vitessce 3.5.9__py3-none-any.whl → 3.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
vitessce/constants.py CHANGED
@@ -164,6 +164,7 @@ class FileType(DocEnum):
164
164
  ANNDATA_ZARR = "anndata.zarr", "Joint file type for AnnData objects"
165
165
  SPATIALDATA_ZARR = "spatialdata.zarr", "Joint file type for SpatialData objects"
166
166
  ANNDATA_H5AD = "anndata.h5ad", "Joint file type for AnnData objects"
167
+ ANNDATA_ZARR_ZIP = "anndata.zarr.zip", "Joint file type for AnnData object in a Zarr directory store that has been zipped"
167
168
  OBS_EMBEDDING_CSV = 'obsEmbedding.csv', "File type for obsEmbedding values stored in a CSV file"
168
169
  OBS_LOCATIONS_CSV = 'obsLocations.csv', "File type for obsLocations values stored in a CSV file"
169
170
  OBS_LABELS_CSV = 'obsLabels.csv', "File type for obsLabels values stored in a CSV file"
vitessce/responses.py ADDED
@@ -0,0 +1,11 @@
1
+ import ujson
2
+ from starlette.responses import JSONResponse
3
+
4
+ # References:
5
+ # - https://www.starlette.io/responses/#custom-json-serialization
6
+ # - https://github.com/encode/starlette/releases/tag/0.14.1
7
+
8
+
9
+ class UJSONResponse(JSONResponse):
10
+ def render(self, content):
11
+ return ujson.dumps(content, ensure_ascii=False).encode("utf-8")
vitessce/widget.py CHANGED
@@ -233,6 +233,7 @@ async function render(view) {
233
233
  const remountOnUidChange = view.model.get('remount_on_uid_change');
234
234
  const storeUrls = view.model.get('store_urls');
235
235
  const invokeTimeout = view.model.get('invoke_timeout');
236
+ const invokeBatched = view.model.get('invoke_batched');
236
237
 
237
238
  const pageMode = view.model.get('page_mode');
238
239
  const pageEsm = view.model.get('page_esm');
@@ -319,23 +320,25 @@ async function render(view) {
319
320
  storeUrl,
320
321
  {
321
322
  async get(key) {
322
- return enqueue([storeUrl, key]);
323
- /*
324
- const [data, buffers] = await view.experimental.invoke("_zarr_get", [storeUrl, key], {
325
- signal: AbortSignal.timeout(invokeTimeout),
326
- });
327
- if (!data.success) return undefined;
328
-
329
- if (key.includes("spatialdata_attrs") && key.endsWith("0") && !ArrayBuffer.isView(buffers[0].buffer)) {
330
- // For some reason, the Zarrita.js UnicodeStringArray does not seem to work with
331
- // ArrayBuffers (throws a TypeError), so here we convert to Uint8Array if needed.
332
- // This error is occurring specifically for the arr.getChunk call within the AnnDataSource._loadString function.
333
- // TODO: figure out a more long-term solution.
334
- return new Uint8Array(buffers[0].buffer);
335
- }
323
+ if (invokeBatched) {
324
+ return enqueue([storeUrl, key]);
325
+ } else {
326
+ // Do not submit zarr gets in batches. Instead, submit individually.
327
+ const [data, buffers] = await view.experimental.invoke("_zarr_get", [storeUrl, key], {
328
+ signal: AbortSignal.timeout(invokeTimeout),
329
+ });
330
+ if (!data.success) return undefined;
331
+
332
+ if (key.includes("spatialdata_attrs") && key.endsWith("0") && !ArrayBuffer.isView(buffers[0].buffer)) {
333
+ // For some reason, the Zarrita.js UnicodeStringArray does not seem to work with
334
+ // ArrayBuffers (throws a TypeError), so here we convert to Uint8Array if needed.
335
+ // This error is occurring specifically for the arr.getChunk call within the AnnDataSource._loadString function.
336
+ // TODO: figure out a more long-term solution.
337
+ return new Uint8Array(buffers[0].buffer);
338
+ }
336
339
 
337
- return buffers[0].buffer;
338
- */
340
+ return buffers[0].buffer;
341
+ }
339
342
  },
340
343
  }
341
344
  ])),
@@ -413,7 +416,7 @@ async function render(view) {
413
416
  }
414
417
 
415
418
  function VitessceWidget(props) {
416
- const { model } = props;
419
+ const { model, styleContainer } = props;
417
420
 
418
421
  const [config, setConfig] = React.useState(prependBaseUrl(model.get('config'), model.get('proxy'), model.get('has_host_name')));
419
422
  const [validateConfig, setValidateConfig] = React.useState(true);
@@ -477,7 +480,7 @@ async function render(view) {
477
480
  height, theme, config, onConfigChange, validateConfig,
478
481
  pluginViewTypes, pluginCoordinationTypes,
479
482
  pluginFileTypes,pluginJointFileTypes, pluginAsyncFunctions,
480
- remountOnUidChange, stores, pageMode,
483
+ remountOnUidChange, stores, pageMode, styleContainer,
481
484
  };
482
485
 
483
486
  return e('div', { ref: divRef, style: { height: height + 'px' } },
@@ -492,7 +495,10 @@ async function render(view) {
492
495
  }
493
496
 
494
497
  const root = createRoot(view.el);
495
- root.render(e(VitessceWidget, { model: view.model }));
498
+ // Marimo puts AnyWidgets in a Shadow Root, so we need to tell Emotion to
499
+ // insert styles within the Shadow DOM.
500
+ const styleContainer = view.el.getRootNode();
501
+ root.render(e(VitessceWidget, { model: view.model, styleContainer }));
496
502
 
497
503
  return () => {
498
504
  // Re-enable scrolling.
@@ -603,10 +609,11 @@ class VitessceWidget(anywidget.AnyWidget):
603
609
  page_mode = Bool(False).tag(sync=True)
604
610
  page_esm = Unicode('').tag(sync=True)
605
611
  invoke_timeout = Int(300000).tag(sync=True)
612
+ invoke_batched = Bool(True).tag(sync=True)
606
613
 
607
614
  store_urls = List(trait=Unicode(''), default_value=[]).tag(sync=True)
608
615
 
609
- def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=False, js_package_version='3.5.12', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, prefer_local=True, invoke_timeout=300000, page_mode=False, page_esm=None):
616
+ def __init__(self, config, height=600, theme='auto', uid=None, port=None, proxy=False, js_package_version='3.5.12', js_dev_mode=False, custom_js_url='', plugins=None, remount_on_uid_change=True, prefer_local=True, invoke_timeout=300000, invoke_batched=True, page_mode=False, page_esm=None):
610
617
  """
611
618
  Construct a new Vitessce widget.
612
619
 
@@ -623,6 +630,7 @@ class VitessceWidget(anywidget.AnyWidget):
623
630
  :param bool remount_on_uid_change: Passed to the remountOnUidChange prop of the <Vitessce/> React component. By default, True.
624
631
  :param bool prefer_local: Should local data be preferred (only applies to `*_artifact` data objects)? By default, True.
625
632
  :param int invoke_timeout: The timeout in milliseconds for invoking Python functions from JavaScript. By default, 300000.
633
+ :param bool invoke_batched: Should invocations (Zarr gets) be submitted in batch, or individually? By default, True.
626
634
  :param bool page_mode: Whether to render the <Vitessce/> component in grid-mode or page-mode. By default, False.
627
635
  :param str page_esm: The ES module string for the page component creation function. Optional.
628
636
 
@@ -658,7 +666,7 @@ class VitessceWidget(anywidget.AnyWidget):
658
666
  js_package_version=js_package_version, js_dev_mode=js_dev_mode, custom_js_url=custom_js_url,
659
667
  plugin_esm=plugin_esm, remount_on_uid_change=remount_on_uid_change,
660
668
  page_mode=page_mode, page_esm=('' if page_esm is None else page_esm),
661
- invoke_timeout=invoke_timeout,
669
+ invoke_timeout=invoke_timeout, invoke_batched=invoke_batched,
662
670
  uid=uid_str, store_urls=list(self._stores.keys())
663
671
  )
664
672
 
@@ -763,6 +771,7 @@ def ipython_display(config, height=600, theme='auto', base_url=None, host_name=N
763
771
  "page_esm": ('' if page_esm is None else page_esm),
764
772
  "remount_on_uid_change": remount_on_uid_change,
765
773
  "invoke_timeout": 30000,
774
+ "invoke_batched": False,
766
775
  "proxy": proxy,
767
776
  "has_host_name": host_name is not None,
768
777
  "height": height,
vitessce/wrappers.py CHANGED
@@ -390,8 +390,8 @@ class OmeTiffWrapper(AbstractWrapper):
390
390
  else:
391
391
  # TODO: Move imports back to top when this is factored out.
392
392
  from .routes import range_repsonse, JsonRoute, FileRoute
393
+ from .responses import UJSONResponse
393
394
  from generate_tiff_offsets import get_offsets
394
- from starlette.responses import UJSONResponse
395
395
 
396
396
  offsets = get_offsets(self._img_path)
397
397
 
@@ -533,8 +533,8 @@ class ImageOmeTiffWrapper(AbstractWrapper):
533
533
  else:
534
534
  # TODO: Move imports back to top when this is factored out.
535
535
  from .routes import range_repsonse, JsonRoute, FileRoute
536
+ from .responses import UJSONResponse
536
537
  from generate_tiff_offsets import get_offsets
537
- from starlette.responses import UJSONResponse
538
538
 
539
539
  offsets = get_offsets(self._img_path)
540
540
 
@@ -666,8 +666,8 @@ class ObsSegmentationsOmeTiffWrapper(AbstractWrapper):
666
666
  else:
667
667
  # TODO: Move imports back to top when this is factored out.
668
668
  from .routes import range_repsonse, JsonRoute, FileRoute
669
+ from .responses import UJSONResponse
669
670
  from generate_tiff_offsets import get_offsets
670
- from starlette.responses import UJSONResponse
671
671
 
672
672
  offsets = get_offsets(self._img_path)
673
673
 
@@ -1192,7 +1192,7 @@ def raise_error_if_more_than_one(inputs):
1192
1192
 
1193
1193
 
1194
1194
  class AnnDataWrapper(AbstractWrapper):
1195
- def __init__(self, adata_path=None, adata_url=None, adata_store=None, adata_artifact=None, ref_path=None, ref_url=None, ref_artifact=None, obs_feature_matrix_path=None, feature_filter_path=None, initial_feature_filter_path=None, obs_set_paths=None, obs_set_names=None, obs_locations_path=None, obs_segmentations_path=None, obs_embedding_paths=None, obs_embedding_names=None, obs_embedding_dims=None, obs_spots_path=None, obs_points_path=None, feature_labels_path=None, obs_labels_path=None, convert_to_dense=True, coordination_values=None, obs_labels_paths=None, obs_labels_names=None, **kwargs):
1195
+ def __init__(self, adata_path=None, adata_url=None, adata_store=None, adata_artifact=None, ref_path=None, ref_url=None, ref_artifact=None, obs_feature_matrix_path=None, feature_filter_path=None, initial_feature_filter_path=None, obs_set_paths=None, obs_set_names=None, obs_locations_path=None, obs_segmentations_path=None, obs_embedding_paths=None, obs_embedding_names=None, obs_embedding_dims=None, obs_spots_path=None, obs_points_path=None, feature_labels_path=None, obs_labels_path=None, convert_to_dense=True, coordination_values=None, obs_labels_paths=None, obs_labels_names=None, is_zip=None, **kwargs):
1196
1196
  """
1197
1197
  Wrap an AnnData object by creating an instance of the ``AnnDataWrapper`` class.
1198
1198
 
@@ -1220,6 +1220,7 @@ class AnnDataWrapper(AbstractWrapper):
1220
1220
  :param list[str] obs_labels_names: The optional display names of columns containing observation labels (e.g., alternate cell IDs), instead of the default index in `obs` of the AnnData store.
1221
1221
  :param bool convert_to_dense: Whether or not to convert `X` to dense the zarr store (dense is faster but takes more disk space).
1222
1222
  :param coordination_values: Coordination values for the file definition.
1223
+ :param is_zip: Boolean indicating whether the Zarr store is in a zipped format.
1223
1224
  :type coordination_values: dict or None
1224
1225
  :param \\*\\*kwargs: Keyword arguments inherited from :class:`~vitessce.wrappers.AbstractWrapper`
1225
1226
  """
@@ -1229,6 +1230,7 @@ class AnnDataWrapper(AbstractWrapper):
1229
1230
  self._adata_url = adata_url
1230
1231
  self._adata_store = adata_store
1231
1232
  self._adata_artifact = adata_artifact
1233
+ self.is_zip = is_zip
1232
1234
 
1233
1235
  # For reference spec JSON with .h5ad files
1234
1236
  self._ref_path = ref_path
@@ -1250,11 +1252,14 @@ class AnnDataWrapper(AbstractWrapper):
1250
1252
  self.is_remote = False
1251
1253
  self.is_store = False
1252
1254
  self.zarr_folder = 'anndata.zarr'
1255
+ if is_zip is None and '.zip' in str(adata_path):
1256
+ self.is_zip = True
1253
1257
  elif adata_url is not None or adata_artifact is not None:
1254
1258
  self.is_remote = True
1255
1259
  self.is_store = False
1256
1260
  self.zarr_folder = None
1257
-
1261
+ if is_zip is None and '.zip' in str(adata_url):
1262
+ self.is_zip = True
1258
1263
  # Store artifacts on AbstractWrapper.artifacts for downstream access,
1259
1264
  # e.g. in lamindb.save_vitessce_config
1260
1265
  if adata_artifact is not None:
@@ -1356,9 +1361,8 @@ class AnnDataWrapper(AbstractWrapper):
1356
1361
  if len(options.keys()) > 0:
1357
1362
  if self.is_h5ad:
1358
1363
  options["refSpecUrl"] = self.get_ref_url(base_url, dataset_uid, obj_i)
1359
-
1360
1364
  obj_file_def = {
1361
- "fileType": ft.ANNDATA_ZARR.value if not self.is_h5ad else ft.ANNDATA_H5AD.value,
1365
+ "fileType": ft.ANNDATA_ZARR_ZIP.value if self.is_zip else ft.ANNDATA_H5AD.value if self.is_h5ad else ft.ANNDATA_ZARR.value,
1362
1366
  "url": self.get_zarr_url(base_url, dataset_uid, obj_i) if not self.is_h5ad else self.get_h5ad_url(base_url, dataset_uid, obj_i),
1363
1367
  "options": options
1364
1368
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vitessce
3
- Version: 3.5.9
3
+ Version: 3.6.0
4
4
  Summary: Jupyter widget facilitating interactive visualization of spatial single-cell data with Vitessce
5
5
  Project-URL: repository, https://github.com/vitessce/vitessce-python
6
6
  Author-email: Mark Keller <mark_keller@hms.harvard.edu>
@@ -37,7 +37,7 @@ Classifier: Programming Language :: Python :: 3.11
37
37
  Classifier: Programming Language :: Python :: 3.12
38
38
  Classifier: Topic :: Multimedia :: Graphics
39
39
  Requires-Python: >=3.10
40
- Requires-Dist: anndata<0.11.0,>=0.7.8
40
+ Requires-Dist: anndata>=0.7.8
41
41
  Requires-Dist: black>=21.11b1
42
42
  Requires-Dist: jsonschema>=3.2
43
43
  Requires-Dist: negspy>=0.2.24
@@ -58,7 +58,7 @@ Requires-Dist: generate-tiff-offsets>=0.1.9; extra == 'all'
58
58
  Requires-Dist: jupyter-server-proxy>=1.5.2; extra == 'all'
59
59
  Requires-Dist: kerchunk>=0.2.6; extra == 'all'
60
60
  Requires-Dist: oxc-py>=0.1.1; extra == 'all'
61
- Requires-Dist: starlette==0.14.0; extra == 'all'
61
+ Requires-Dist: starlette>=0.14.0; extra == 'all'
62
62
  Requires-Dist: ujson>=4.0.1; extra == 'all'
63
63
  Requires-Dist: uvicorn>=0.17.0; extra == 'all'
64
64
  Provides-Extra: building
@@ -68,9 +68,9 @@ Requires-Dist: pyyaml; extra == 'demos'
68
68
  Requires-Dist: snakemake; extra == 'demos'
69
69
  Provides-Extra: dev
70
70
  Provides-Extra: docs
71
- Requires-Dist: jinja2==3.0.3; extra == 'docs'
71
+ Requires-Dist: jinja2; extra == 'docs'
72
72
  Requires-Dist: nbclean==0.3.2; extra == 'docs'
73
- Requires-Dist: nbconvert==5.6.1; extra == 'docs'
73
+ Requires-Dist: nbconvert>=6.2; extra == 'docs'
74
74
  Requires-Dist: nbsphinx==0.8.8; extra == 'docs'
75
75
  Requires-Dist: sphinx-rtd-theme==1.0.0; extra == 'docs'
76
76
  Requires-Dist: sphinx==4.2.0; extra == 'docs'
@@ -83,6 +83,10 @@ Requires-Dist: sphinxcontrib-serializinghtml==1.1.5; extra == 'docs'
83
83
  Requires-Dist: sqlalchemy==1.3.24; extra == 'docs'
84
84
  Provides-Extra: linting
85
85
  Provides-Extra: notebook
86
+ Requires-Dist: dask[dataframe]==2024.11.1; extra == 'notebook'
87
+ Requires-Dist: marimo; extra == 'notebook'
88
+ Requires-Dist: spatialdata>=0.3.0; extra == 'notebook'
89
+ Requires-Dist: starlette>=0.42.0; extra == 'notebook'
86
90
  Provides-Extra: testing
87
91
  Description-Content-Type: text/markdown
88
92
 
@@ -1,14 +1,15 @@
1
1
  vitessce/__init__.py,sha256=03pAJROyDfo6EErBx8Oqb9Emqol1QKQ_9zKhkwuQ36Q,1781
2
2
  vitessce/config.py,sha256=vZX4k-kS3zspYVT08PRuLSBeB-tU4GJgbN93z1Ed1iY,81228
3
3
  vitessce/config_converter.py,sha256=IRPnGPGaETvJbYZNUv2pe54SHHHsDY9VWo3JRjSI5FM,14681
4
- vitessce/constants.py,sha256=NTir8PzJAGX6a5Q3Ike0qy2n75WyFAezMP05PZ4mgWA,15233
4
+ vitessce/constants.py,sha256=nBMH55TcnSavcpvYE-epyx3cJ0iDS31eHsL_1e9qb9M,15360
5
5
  vitessce/export.py,sha256=L7j5sVC0nBSqGocFWQyyHImSiAF4IjXhmqV1QtpuNc4,3874
6
6
  vitessce/file_def_utils.py,sha256=RM9Hj1uwPY-Y37JLOHiKA_acGY40p8C9WsDk8iVjDz8,6692
7
7
  vitessce/repr.py,sha256=qMmefmZ3E-3sRVxeI5q1DTZnfuwbXKiA85eyqk5MCT4,2287
8
+ vitessce/responses.py,sha256=Z6Wo4AXN-RyzmxMPhSuhpIsHTItHM4GyIgMLGoVEYcU,339
8
9
  vitessce/routes.py,sha256=U8T-L-3QCD_tAbPF8LsUlSMhPWNbyzbLNUnxP9Z9s9o,2140
9
10
  vitessce/utils.py,sha256=obzjj65qsagu60_yuhGc-0jmHO-BW0Y-bDs0FgrBqLY,981
10
- vitessce/widget.py,sha256=-8zK7h3AeFU8VWncuPWR2vAA8StHWYNjbrwVm5ld03w,32418
11
- vitessce/wrappers.py,sha256=kVqXFcpbuIb8MtZQSB4F7k32JM8bwCgMBrOkcAAhmvc,74676
11
+ vitessce/widget.py,sha256=TJjpOBCSS9EBd-klEStvd_NCWejHG0QUROmI3b_7lrQ,33146
12
+ vitessce/wrappers.py,sha256=3ZNldH2uDhOzUl8ahil7GxnPcr0nKwqfrjjbgS2IL0Y,75010
12
13
  vitessce/data_utils/__init__.py,sha256=3mWi1lMjoj4_dNbhMOvyE-HEJu0qpMzcmkhfz_5T6n8,361
13
14
  vitessce/data_utils/anndata.py,sha256=iLa5-bRezHgBzL_XCHO7w0pc0RQ4urzZbDsqJbBYeCk,10668
14
15
  vitessce/data_utils/entities.py,sha256=X8enC_TQbgwBzjgD1x53IPS6aVr9wyP0s-NLuYBeMeU,11705
@@ -17,7 +18,7 @@ vitessce/data_utils/ome.py,sha256=aK-iGNgjUmUMsWgdZhW78VrtMBKMW_jIQDYnsupq6BE,54
17
18
  vitessce/widget_plugins/__init__.py,sha256=lto2GXnc7KwjIoT-jvzyRYLj0XTJG3uxoX45Hc9EcWA,82
18
19
  vitessce/widget_plugins/demo_plugin.py,sha256=14S7nOxdlKSxIHw9DUcNCN83NE_U1EMPy2D4k0FDues,1797
19
20
  vitessce/widget_plugins/spatial_query.py,sha256=CYxvmMT1Je_jguikPROQxlegkPgIIzemKGbZSJfZMyI,12314
20
- vitessce-3.5.9.dist-info/METADATA,sha256=g_LIqo1wtjJamdEcoUuyv7di45t_X0MhleRnSianTTQ,9558
21
- vitessce-3.5.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
- vitessce-3.5.9.dist-info/licenses/LICENSE,sha256=sNNpI0PQ57AW8_XnTAjU5Yw8YBA_DRNkVHrHYpCIhRU,1067
23
- vitessce-3.5.9.dist-info/RECORD,,
21
+ vitessce-3.6.0.dist-info/METADATA,sha256=LHEQzRra80wKjvCJnln_yQMvmULNcZsbsohcmaUlKL0,9756
22
+ vitessce-3.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
23
+ vitessce-3.6.0.dist-info/licenses/LICENSE,sha256=sNNpI0PQ57AW8_XnTAjU5Yw8YBA_DRNkVHrHYpCIhRU,1067
24
+ vitessce-3.6.0.dist-info/RECORD,,