Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(feat): SpatialData wrapper #333

Closed
wants to merge 63 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
3158ce8
(refactor): separate out schema creation
ilan-gold Apr 2, 2024
9bef112
(feat): initial pass at spatial data
ilan-gold Apr 2, 2024
7cb5e8d
(feat): working notebook minus spots (maybe a vitessce bug?)
ilan-gold Apr 2, 2024
6da2952
(fix): try to get spots to appear
ilan-gold Apr 3, 2024
44f3834
(chore): comment out other stuff to make widget show more
ilan-gold Apr 3, 2024
4df1092
Fix visium config
keller-mark Apr 3, 2024
74f8c38
(feat): firstt pass at `from_spatialdata_object`
ilan-gold Apr 4, 2024
bd298cc
(refactor): refactor `from_spatialdata_object` and util funcs from st…
ilan-gold Apr 16, 2024
fdfcc20
(feat): add url capability
ilan-gold Apr 19, 2024
aeb19e9
(temp): spatial data fixes
ilan-gold May 6, 2024
9668ea5
Merge branch 'ig/anndata_api_cleanup' into ig/spatial_data
ilan-gold May 7, 2024
daec711
(chore): more clean ups and fixes
ilan-gold May 7, 2024
7ffc5e1
Merge branch 'ig/anndata_api_cleanup' into ig/spatial_data
ilan-gold May 7, 2024
b07a72a
Create module for plugin JS (#337)
keller-mark May 15, 2024
431d180
Merge branch 'ig/anndata_api_cleanup' into ig/spatial_data
ilan-gold May 16, 2024
07c1db2
(fix): adapt to api
ilan-gold May 16, 2024
933d6de
(chore): remove erroneous notebook
ilan-gold May 16, 2024
596c420
(fix): add type support
ilan-gold May 24, 2024
50ce52b
(chore): add test
ilan-gold May 24, 2024
c8c93aa
(fix): automatic lint
ilan-gold May 24, 2024
f906eb3
(fix): add default for `obsEmbedding`
ilan-gold May 24, 2024
eaf63a7
(fix): redefinition
ilan-gold May 24, 2024
ba10f0e
(fix): `path` and `embeddingType` swapped
ilan-gold May 24, 2024
6ea8c33
(fix): add annotattions to `utils.py`
ilan-gold May 24, 2024
c43845f
(chore): add `spatialdata` dep
ilan-gold May 24, 2024
91f27b6
(fix): oops, comma for `toml`
ilan-gold May 24, 2024
7be038e
(fix): no more python3.8 bc of spatialdata
ilan-gold May 24, 2024
eb12a00
(fix): remove whitespace
ilan-gold May 24, 2024
8d6472a
(api): small api cleanups
ilan-gold May 24, 2024
779d4a1
(fix): args bug
ilan-gold May 27, 2024
05c8dbd
(fix): try spatialdata from master
ilan-gold May 27, 2024
3862c70
(chore): lint
ilan-gold May 27, 2024
5ae1dae
NickAkhmetov/Cap `numpy` under v2 (#349)
NickAkhmetov Jun 17, 2024
559e6c5
(chore): try `spatialdata` update
ilan-gold Jun 25, 2024
31bd2cc
NickAkhmetov/Copy `requestInit` when using `from_dict` (#352)
NickAkhmetov Jul 19, 2024
2e36cb2
Plugin class (#350)
keller-mark Jul 24, 2024
c88eb37
Update fill_template.py (#353)
keller-mark Jul 29, 2024
bc7b353
Plugin for SpatialQuery (#354)
keller-mark Aug 2, 2024
55b3f57
Unit test for to_dict output following .add_object(AnnDataWrapper(...…
keller-mark Aug 31, 2024
06a04e7
Misc: Spatial-query, kerchunk, and OME helper functions (#360)
keller-mark Aug 31, 2024
94501cc
Support for H5AD-based AnnData in AnnDataWrapper (#361)
keller-mark Sep 9, 2024
c48fdd8
Fix binder example (#363)
keller-mark Sep 11, 2024
b02d767
Fix bug (#367)
keller-mark Sep 19, 2024
bf5853b
(fix): `image_elem` usage + table key
ilan-gold Sep 24, 2024
73b8f52
(chore): update SpatialData
ilan-gold Sep 24, 2024
6dc8779
(fix): `shapes_elem`
ilan-gold Sep 24, 2024
d8db5e0
(fix): capitalize name of obs set
ilan-gold Sep 24, 2024
76a6652
(fix): use table for spots
ilan-gold Sep 24, 2024
5f8cfca
(fix): capitalization
ilan-gold Sep 24, 2024
f7cba04
(fix): first letter only
ilan-gold Sep 24, 2024
b5e1a19
(fix): check `self._coordination_values`
ilan-gold Sep 24, 2024
dc021eb
Add notebook (#369)
keller-mark Oct 2, 2024
f267084
Added utility functions to update and remove a view (#368)
tkakar Oct 2, 2024
6bac2c2
Keller mark/more exports (#370)
keller-mark Oct 2, 2024
d4ebe79
(chore): add `obsSets` check
ilan-gold Oct 4, 2024
bc5e21c
Allow passing artifacts as data in addition to paths, urls, and zarr …
keller-mark Oct 4, 2024
f64bd51
Merge
keller-mark Oct 4, 2024
eb22344
SpatialData changes into original SpatialData branch (#374)
keller-mark Oct 7, 2024
0b04e15
Update pyproject.toml
keller-mark Oct 7, 2024
0a4a4b0
Keller mark/spatial data2 (#375)
keller-mark Oct 7, 2024
5da19a8
SpatialDataWrapper v2 (#373)
keller-mark Oct 15, 2024
ffce2a4
Fix spatialdata nb
keller-mark Oct 15, 2024
4043489
Merge branch 'main' into ig/spatial_data
keller-mark Oct 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .coveragerc_omit
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
omit =
vitessce/config.py
vitessce/export.py
vitessce/file_def_utils.py
vitessce/routes.py
vitessce/widget.py
vitessce/wrappers.py
Expand All @@ -10,4 +11,6 @@ omit =
vitessce/data_utils/anndata.py
vitessce/data_utils/ome.py
vitessce/data_utils/entities.py
vitessce/data_utils/multivec.py
vitessce/data_utils/multivec.py
vitessce/widget_plugins/demo_plugin.py
vitessce/widget_plugins/spatial_query.py
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
version: ['3.8', '3.12']
version: ['3.9', '3.12']
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
Expand Down
2 changes: 1 addition & 1 deletion demos/fill_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def render_json(dir_name, version_str, url_type, port):

BASE_URL = {
'local': f'http://localhost:{port}/{dir_name}/data/processed',
'remote': f'https://s3.amazonaws.com/vitessce-data/{version_str}/main/{dir_name}'
'remote': f'https://data-1.vitessce.io/{version_str}/main/{dir_name}'
}
BASE_URL_GCP = {
'local': f'http://localhost:{port}/{dir_name}/data/processed',
Expand Down
3 changes: 2 additions & 1 deletion docs/data_examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ Data preparation examples

notebooks/data_export_s3
notebooks/data_export_files
notebooks/widget_brain_with_base_dir
notebooks/widget_brain_with_base_dir
notebooks/widget_brain_h5ad
39 changes: 39 additions & 0 deletions docs/data_options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,44 @@ Jupyter process: remote service like Colab/Binder; Files: remote & accessed via

Unfortunately, this will not work because the remote server cannot access the files that are on another machine behind SSH.

========================================================================
Jupyter process: anywhere; Files: anywhere that can be accessed via Zarr
========================================================================

If the data is readable via Zarr (i.e., `zarr.storage.*Store`) and the Jupyter process can access the store contents, then the Vitessce widget can access the data by specifying the Zarr store as the data source for Vitessce data wrapper class instances.
This is currently supported for the ``AnnDataWrapper`` class using the ``adata_store`` parameter (as opposed to ``adata_path`` or ``adata_url``).

.. code-block:: python

from vitessce import VitessceConfig, AnnDataWrapper

# ...
adata.write_zarr("my_store.adata.zarr")

vc = VitessceConfig(name="My Vitessce Configuration")
vc.add_dataset(name="My Dataset").add_object(AnnDataWrapper(
adata_store="my_store.adata.zarr",
# ...
))
# ...
vc.widget()


Or, with a Zarr store instance (instead of a local string path to a DirectoryStore):

.. code-block:: python

import zarr
from vitessce import VitessceConfig, AnnDataWrapper

# ...
store = zarr.storage.FSStore("s3://my_bucket/path/to/my_store.adata.zarr")

vc = VitessceConfig(name="My Vitessce Configuration")
vc.add_dataset(name="My Dataset").add_object(AnnDataWrapper(
adata_store=store,
# ...
))
# ...
vc.widget()

1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ The Vitessce widget is compatible with the following interactive Python platform
api_config
api_data
data_options
widget_plugins
screenshots


Expand Down
203 changes: 203 additions & 0 deletions docs/notebooks/spatial_data.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"nbsphinx": "hidden"
},
"source": [
"# Vitessce Widget Tutorial"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Visualization of SpatialData Object"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Import dependencies\n",
"\n",
"We need to import the classes and functions that we will be using from the corresponding packages."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2\n",
"\n",
"from pathlib import Path\n",
"from urllib.request import urlretrieve\n",
"import dask\n",
"\n",
"dask.config.set({'dataframe.query-planning-warning': False})\n",
"\n",
"from spatialdata import read_zarr\n",
"import scanpy as sc\n",
"\n",
"from vitessce import (\n",
" VitessceConfig,\n",
" Component as cm,\n",
" CoordinationType as ct,\n",
" CoordinationLevel as CL,\n",
" AbstractWrapper,\n",
" SpatialDataWrapper,\n",
" get_initial_coordination_scope_prefix\n",
")\n",
"from vitessce.data_utils import (\n",
" optimize_adata,\n",
" VAR_CHUNK_SIZE,\n",
")\n",
"import zipfile\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"zip_filepath = Path(\"data/visium.spatialdata.zarr.zip\")\n",
"spatialdata_filepath = zip_filepath.with_suffix('')\n",
"if not zip_filepath.exists():\n",
" spatialdata_filepath.parent.mkdir(exist_ok=True)\n",
" urlretrieve('https://s3.embl.de/spatialdata/spatialdata-sandbox/visium_associated_xenium_io.zip', zip_filepath)\n",
"if not spatialdata_filepath.exists():\n",
" with zipfile.ZipFile(zip_filepath,\"r\") as zip_ref:\n",
" zip_ref.extractall(spatialdata_filepath.parent)\n",
" (spatialdata_filepath.parent / \"data.zarr\").rename(spatialdata_filepath)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Load the data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"spatialdata = read_zarr(spatialdata_filepath)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"spatialdata"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Create the Vitessce widget configuration\n",
"\n",
"Vitessce needs to know which pieces of data we are interested in visualizing, the visualization types we would like to use, and how we want to coordinate (or link) the views."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vc = VitessceConfig(\n",
" schema_version=\"1.0.16\",\n",
" name='Visium SpatialData Demo (visium_associated_xenium_io)',\n",
" description='From https://spatialdata.scverse.org/en/latest/tutorials/notebooks/datasets/README.html'\n",
")\n",
"# Add data to the configuration:\n",
"wrapper = SpatialDataWrapper(\n",
" sdata_path=spatialdata_filepath,\n",
" # The following paths are relative to the root of the SpatialData zarr store on-disk.\n",
" image_path=\"images/CytAssist_FFPE_Human_Breast_Cancer_full_image\",\n",
" table_path=\"table/table\",\n",
" obs_feature_matrix_path=\"table/table/X\",\n",
" obs_spots_path=\"shapes/CytAssist_FFPE_Human_Breast_Cancer\",\n",
" region=\"CytAssist_FFPE_Human_Breast_Cancer\",\n",
" coordinate_system=\"global\",\n",
" coordination_values={\n",
" # The following tells Vitessce to consider each observation as a \"spot\"\n",
" \"obsType\": \"spot\",\n",
" }\n",
")\n",
"dataset = vc.add_dataset(name='Breast Cancer Visium').add_object(wrapper)\n",
"\n",
"# Add views (visualizations) to the configuration:\n",
"spatial = vc.add_view(\"spatialBeta\", dataset=dataset)\n",
"feature_list = vc.add_view(cm.FEATURE_LIST, dataset=dataset)\n",
"layer_controller = vc.add_view(\"layerControllerBeta\", dataset=dataset)\n",
"vc.link_views_by_dict([spatial, layer_controller], {\n",
" 'imageLayer': CL([{\n",
" 'photometricInterpretation': 'RGB',\n",
" }]),\n",
"}, scope_prefix=get_initial_coordination_scope_prefix(\"A\", \"image\"))\n",
"obs_sets = vc.add_view(cm.OBS_SETS, dataset=dataset)\n",
"vc.link_views([spatial, layer_controller, feature_list, obs_sets], ['obsType'], [wrapper.obs_type_label])\n",
"\n",
"# Layout the views\n",
"vc.layout(spatial | (feature_list / layer_controller / obs_sets));"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4. Render the widget"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vw = vc.widget()\n",
"vw"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Loading
Loading