diff --git a/docs/notebooks/spatialdata_blobs.ipynb b/docs/notebooks/spatialdata_blobs.ipynb index e25eedb..88d3f4c 100644 --- a/docs/notebooks/spatialdata_blobs.ipynb +++ b/docs/notebooks/spatialdata_blobs.ipynb @@ -29,7 +29,9 @@ "source": [ "import easy_vitessce as ev\n", "import spatialdata\n", - "import spatialdata_plot" + "import spatialdata_plot\n", + "from anndata import AnnData\n", + "import pandas as pd" ] }, { @@ -54,7 +56,7 @@ "metadata": {}, "outputs": [], "source": [ - "# ev.config.set({ 'data.wrapper_param_suffix': '_store' })" + "# ev.config.set({ 'data.wrapper_param_suffix': '_store' }) # Caveat: https://github.com/vitessce/vitessce-python/issues/491" ] }, { @@ -74,6 +76,65 @@ "sdata" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create a Table with a `var` dataframe corresponding to the `genes` column of the Points table" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ddf = sdata.points['blobs_points']\n", + "ddf" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The current `table` element contains a `var` dataframe corresponding\n", + "# to the 3 image channels, rather than the 2 gene IDs.\n", + "print(sdata.tables['table'].var.index.tolist())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# We need to create another table which has a var.index column containing the gene IDs for the points.\n", + "unique_gene_ids = ddf[\"genes\"].unique().compute().tolist()\n", + "points_var_df = pd.DataFrame(index=unique_gene_ids, data=[], columns=[])\n", + "points_table = AnnData(var=points_var_df, obs=None, X=None)\n", + "sdata.tables['table_points'] = points_table" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "unique_gene_ids" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sdata.write('data/blobs.sdata.zarr', overwrite=True)" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -103,14 +164,14 @@ "metadata": {}, "outputs": [], "source": [ - "sdata.pl.render_images(\"blobs_image\").pl.render_labels(\"blobs_labels\", color=\"channel_0_sum\").pl.render_points(\"blobs_points\").pl.show()" + "sdata.pl.render_images(\"blobs_image\").pl.render_labels(\"blobs_labels\", color=\"channel_0_sum\", table_name=\"table\").pl.render_points(\"blobs_points\").pl.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Disable EasyVitessce" + "## Rendering a subset of points" ] }, { @@ -119,7 +180,13 @@ "metadata": {}, "outputs": [], "source": [ - "ev.disable_plots([\"spatialdata-plot\"])" + "vw = (sdata\n", + " .pl.render_images(\"blobs_image\")\n", + " #.pl.render_labels(\"blobs_labels\", color=\"channel_0_sum\", table_name=\"table\")\n", + " .pl.render_points(\"blobs_points\", color=\"genes\", groups=[\"gene_a\", \"gene_b\"], palette=[\"orange\", \"yellow\"], table_name=\"table_points\", alpha=1.0)\n", + " .pl.show()\n", + ")\n", + "vw" ] }, { @@ -135,6 +202,7 @@ "metadata": {}, "outputs": [], "source": [ + "ev.disable_plots([\"spatialdata-plot\"])\n", "sdata.pl.render_images(\"blobs_image\").pl.render_labels(\"blobs_labels\").pl.show()" ] }, @@ -144,9 +212,31 @@ "metadata": {}, "outputs": [], "source": [ - "sdata.pl.render_images(\"blobs_image\").pl.render_labels(\"blobs_labels\", color=\"channel_0_sum\").pl.render_points(\"blobs_points\").pl.show()" + "sdata.pl.render_images(\"blobs_image\").pl.render_labels(\"blobs_labels\", color=\"channel_0_sum\", table_name=\"table\").pl.render_points(\"blobs_points\").pl.show()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "vw = (sdata\n", + " .pl.render_images(\"blobs_image\")\n", + " #.pl.render_labels(\"blobs_labels\", color=\"channel_0_sum\", table_name=\"table\")\n", + " .pl.render_points(\"blobs_points\", color=\"genes\", groups=[\"gene_a\", \"gene_b\"], palette=[\"orange\", \"yellow\"], table_name=\"table_points\", alpha=1.0)\n", + " .pl.show()\n", + ")\n", + "vw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, diff --git a/docs/notebooks/spatialdata_xenium.ipynb b/docs/notebooks/spatialdata_xenium.ipynb new file mode 100644 index 0000000..68e8d01 --- /dev/null +++ b/docs/notebooks/spatialdata_xenium.ipynb @@ -0,0 +1,322 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "013a95d1", + "metadata": {}, + "source": [ + "# EasyVitessce Example: SpatialData-Plot with MERFISH dataset" + ] + }, + { + "cell_type": "markdown", + "id": "40c9b340", + "metadata": {}, + "source": [ + "## Downloading and importing necessary packages" + ] + }, + { + "cell_type": "markdown", + "id": "846b644c", + "metadata": {}, + "source": [ + "By default, interactive plots are enabled upon importing easy_vitessce. This notebook aims to demonstrate the transition between static and interactive plots, so the interactive plots are initially turned off." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1b9e634a", + "metadata": {}, + "outputs": [], + "source": [ + "!pip install easy_vitessce\n", + "!pip install spatialdata\n", + "!pip install spatialdata_plot" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05991a70", + "metadata": {}, + "outputs": [], + "source": [ + "import easy_vitessce as ev \n", + "import spatialdata as sd\n", + "import spatialdata_plot\n", + "from os.path import join" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19bfbe14-2fa3-4d8a-b239-5e1385806bcb", + "metadata": {}, + "outputs": [], + "source": [ + "from vitessce.data_utils import (\n", + " sdata_morton_sort_points,\n", + " sdata_points_process_columns,\n", + " sdata_points_write_bounding_box_attrs,\n", + " sdata_points_modify_row_group_size,\n", + " sdata_morton_query_rect,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "594003c7", + "metadata": {}, + "outputs": [], + "source": [ + "# Disable interactive plots\n", + "ev.configure_plots(enable_plots=[\"spatialdata-plot\"])" + ] + }, + { + "cell_type": "markdown", + "id": "b0fec04c-68a2-4df6-8ec5-093812c98a6d", + "metadata": {}, + "source": [ + "## Download the data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a7f7f9a-2529-41bb-98c5-bbde65867356", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from os.path import join, isfile, isdir\n", + "from urllib.request import urlretrieve\n", + "import zipfile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3016ea87-6388-4f43-8b92-6244d284b4e0", + "metadata": {}, + "outputs": [], + "source": [ + "data_dir = \"data\"\n", + "zip_path = join(data_dir, \"xenium_rep1_io.spatialdata.zarr.zip\")\n", + "sdata_path = join(data_dir, \"xenium_rep1_io.spatialdata.zarr\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b70f4ee6-f6da-49f0-8dba-9042259782b3", + "metadata": {}, + "outputs": [], + "source": [ + "if not isdir(sdata_path):\n", + " if not isfile(zip_path):\n", + " os.makedirs(data_dir, exist_ok=True)\n", + " urlretrieve('https://s3.embl.de/spatialdata/spatialdata-sandbox/xenium_rep1_io.zip', zip_path)\n", + " with zipfile.ZipFile(zip_path,\"r\") as zip_ref:\n", + " zip_ref.extractall(data_dir)\n", + " os.rename(join(data_dir, \"data.zarr\"), sdata_path)" + ] + }, + { + "cell_type": "markdown", + "id": "f7bebbc5", + "metadata": {}, + "source": [ + "## Read the data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e946174", + "metadata": {}, + "outputs": [], + "source": [ + "sdata = sd.read_zarr(sdata_path)\n", + "sdata" + ] + }, + { + "cell_type": "markdown", + "id": "d5fc0fd3-3c35-4851-bc31-375fc89c350c", + "metadata": {}, + "source": [ + "## Make the points ready for tiled access\n", + "\n", + "References:\n", + "- https://vitessce.io/docs/data-troubleshooting/#points\n", + "- https://github.com/vitessce/vitessce-python/blob/main/docs/notebooks/spatial_data_xenium_morton.ipynb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a4cb7c5-1ce2-4573-9c1c-176538ab25f3", + "metadata": {}, + "outputs": [], + "source": [ + "if \"transcripts_with_morton_codes\" not in sdata.points:\n", + " sdata = sdata_morton_sort_points(sdata, \"transcripts\")\n", + " \n", + " # Add feature_index column to dataframe, and reorder columns so that feature_name (dict column) is the rightmost column.\n", + " ddf = sdata_points_process_columns(sdata, \"transcripts\", var_name_col=\"feature_name\", table_name=\"table\")\n", + " \n", + " sdata[\"transcripts_with_morton_codes\"] = ddf\n", + " sdata.write_element(\"transcripts_with_morton_codes\")\n", + " \n", + " sdata_points_write_bounding_box_attrs(sdata, \"transcripts_with_morton_codes\")\n", + " \n", + " sdata_points_modify_row_group_size(sdata, \"transcripts_with_morton_codes\", row_group_size=25_000)" + ] + }, + { + "cell_type": "markdown", + "id": "140217fb", + "metadata": {}, + "source": [ + "## Static plotting" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8383a98f-4090-44e2-b574-3531d3a96dfa", + "metadata": {}, + "outputs": [], + "source": [ + "sdata" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e5a21a04-8b45-4f69-9115-98341bd7a76a", + "metadata": {}, + "outputs": [], + "source": [ + "sdata.points[\"transcripts_with_morton_codes\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1b41a4bb-e552-41c7-a0c4-f9b70847d5cb", + "metadata": {}, + "outputs": [], + "source": [ + "sdata.points[\"transcripts_with_morton_codes\"].attrs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2035d286", + "metadata": {}, + "outputs": [], + "source": [ + "vw = (\n", + " sdata\n", + " .pl.render_images(element=\"morphology_focus\")\n", + " .pl.render_shapes(element=\"cell_boundaries\")\n", + " .pl.render_points(element=\"transcripts_with_morton_codes\", color=\"feature_name\", groups=[\"ERBB2\"], palette=[\"red\"], table_name=\"table\")\n", + " .pl.show()\n", + ")\n", + "vw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5433ec21-e385-4667-a45d-e184611fdde0", + "metadata": {}, + "outputs": [], + "source": [ + "vw.config.to_dict(base_url=\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d69cdee", + "metadata": {}, + "outputs": [], + "source": [ + "# add another code block for the mouse liver dataset? " + ] + }, + { + "cell_type": "markdown", + "id": "27b04c12", + "metadata": {}, + "source": [ + "## Activating interactive plots" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ddf74968", + "metadata": {}, + "outputs": [], + "source": [ + "# Enable interactive plots\n", + "ev.configure_plots(enable_plots=[\"spatialdata-plot\"])" + ] + }, + { + "cell_type": "markdown", + "id": "23ffc21d-92ac-4066-b09a-b7a10307cbe6", + "metadata": {}, + "source": [ + "## Interactive plotting" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63900fe4", + "metadata": {}, + "outputs": [], + "source": [ + "sdata.pl.render_images(element=\"rasterized\").pl.render_shapes(element=\"cells\", color=\"Acta2\").pl.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed91d03f-098b-47b7-a397-4b2003c60a13", + "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.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/pyproject.toml b/pyproject.toml index 45bc711..ca6795c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "easy_vitessce" -version = "0.0.9" +version = "0.0.10" authors = [ {name="HIDIVE Lab"}, {name="Selena Luo"} @@ -24,7 +24,7 @@ dependencies = [ 'numpy>=1.21.2', 'zarr>=2.5.0,<3', 'numcodecs>=0.5.7,<0.16.0', - 'vitessce[all]>=3.7.9', + 'vitessce[all]>=3.8.2', 'scanpy>=1.11.3', 'anndata>=0.11.4', 'spatialdata>=0.3.0', diff --git a/src/easy_vitessce/spatialdata_plot.py b/src/easy_vitessce/spatialdata_plot.py index 375a269..eb8e0d3 100644 --- a/src/easy_vitessce/spatialdata_plot.py +++ b/src/easy_vitessce/spatialdata_plot.py @@ -20,24 +20,19 @@ vconcat, ) -from os.path import join - from spatialdata_plot.pl.basic import PlotAccessor from spatialdata import get_element_annotators -from easy_vitessce.widget import _to_widget, config +from easy_vitessce.widget import _to_widget from easy_vitessce.colors import to_uint8_rgb from easy_vitessce.data import _get_sdata_wrapper_params -# Internal function for shared logic between render_shapes and render_labels. -def _shared_render_shapes_and_labels( - sdata, element, table_name, table_layer, color, cmap, norm, groups, palette, obs_type, feature_type, is_spots, fill_alpha, outline_alpha, outline_width, outline_color, +from matplotlib.colors import is_color_like + +def _shared_table_handling(sdata, element, table_name, table_layer, obs_type, feature_type, # Note: These dict params are modified by this function. wrapper_args, obs_type_to_num_rows, feature_type_to_num_rows, ): - - extra_layer_coordination = {} - if table_name is None: annotating_tables = list(get_element_annotators(sdata, element)) if len(annotating_tables) > 0: @@ -80,6 +75,19 @@ def _shared_render_shapes_and_labels( """ pass +# Internal function for shared logic between render_shapes and render_labels. +def _shared_render_shapes_and_labels( + sdata, element, table_name, table_layer, color, cmap, norm, groups, palette, obs_type, feature_type, is_spots, fill_alpha, outline_alpha, outline_width, outline_color, + # Note: These dict params are modified by this function. + wrapper_args, obs_type_to_num_rows, feature_type_to_num_rows, + ): + + extra_layer_coordination = {} + + _shared_table_handling(sdata, element, table_name, table_layer, obs_type, feature_type, + wrapper_args, obs_type_to_num_rows, feature_type_to_num_rows, + ) + obs_coordination = None feature_coordination = None is_maybe_static_color = False @@ -240,7 +248,7 @@ def _init_params(self): # Tuples of (wrapper_args, spot_layer_coordination, obs_coordination, feature_coordination) ] self.point_layers = [ - # Tuples of (wrapper_args, point_layer_coordination) + # Tuples of (wrapper_args, point_layer_coordination, obs_coordination, feature_coordination) ] # For ensuring that counts of obs/var match if used for multiple layers. @@ -341,12 +349,16 @@ def render_images( # RGB vs. non-RGB logic in spatialdata-plot: # Reference: https://github.com/scverse/spatialdata-plot/blob/010560f7eebdd245693a8c55eede0f895a636f5c/src/spatialdata_plot/pl/render.py#L865 img = self.sdata.images[element] - try: - all_channels = img.coords["c"].values.tolist() - except KeyError: - # TODO: use a better way than try/except of determining whether this is a multi-resolution image. - all_channels = img.scale0.coords["c"].values.tolist() - img_dtype = img.dtype + if hasattr(img, "dtype"): + img_arr = img + else: + # Assume multi-scale (DataTree). + # We use the highest resolution scale, 'scale0'. + # The image data is typically in the 'image' variable of the dataset. + img_arr = img["scale0"]["image"] + + all_channels = img_arr.coords["c"].values.tolist() + img_dtype = img_arr.dtype img_dtype_is_uint8 = img_dtype.kind == 'u' and img_dtype.itemsize == 1 # Not ideal logic. Should ideally only use the OME-NGFF color model metadata. But this is what spatialdata-plot does. @@ -631,7 +643,17 @@ def render_labels(self, # References: # - https://spatialdata.scverse.org/projects/plot/en/latest/plotting.html#spatialdata_plot.pl.basic.PlotAccessor.render_points # - https://github.com/scverse/spatialdata-plot/blob/c9bae235c0521499fb4d1098b15c79619654e5dc/src/spatialdata_plot/pl/basic.py#L338 - def render_points(self, element=None, **kwargs): + def render_points(self, + element=None, + color=None, + alpha=None, + groups=None, + palette=None, + # TODO: size + table_name=None, + table_layer=None, + **kwargs + ): """ Renders points. @@ -639,7 +661,17 @@ def render_points(self, element=None, **kwargs): :returns: Self, allows for chaining. """ if not VitesscePlotAccessor._is_enabled: - return self._pl.render_points(element=element, **kwargs) + return self._pl.render_points( + element=element, + color=color, + alpha=alpha, + groups=groups, + palette=palette, + # TODO: size + table_name=table_name, + table_layer=table_layer, + **kwargs + ) self._maybe_init() @@ -660,14 +692,109 @@ def render_points(self, element=None, **kwargs): } } + _shared_table_handling(self.sdata, element, table_name, table_layer, obs_type, feature_type, + wrapper_args, self.obs_type_to_num_rows, self.feature_type_to_num_rows, + ) + layer_coordination = { "obsType": obs_type, "obsHighlight": None, "fileUid": file_uid, + # TODO: featureSelection: None or list[str] + # TODO: featureFilterMode: None or 'featureSelection' + # TODO: obsColorEncoding: 'geneSelection' or 'spatialLayerColor' or 'randomByFeature' or 'random' + # TODO: featureColor: None or [ { name: str, color: [R, G, B] } ] + # TODO: spatialLayerColor: [R, G, B] + # TODO: spatialLayerOpacity: number } + + # Coloring cases + # color param can be: + # - None (default color) + # - static color like "red" or "#FF0000" + # - name of the "feature_name" column of sdata.points table + + # alpha param can be: + # - None (default opacity) 1.0 + # - float between 0.0 and 1.0 + + # groups param: + # - None (all points) + # - str: a single gene name (when `color` param is the name of the column containing gene names) + # - list[str]: list of gene names (when `color` param is the name of the column containing gene names) + + # palette param: + # - None (default color) + # - str: a single color (when `groups` param is a single gene name) + # - list[str]: list of colors (when `groups` param is a list of gene names) (the length must match the length of `groups`) + + ddf = self.sdata.points[element] + + try: + # Check if the dataframe contains a _codes column. + # Reference: https://github.com/vitessce/vitessce-python/blob/adb066c088307b658a45ca9cf2ab2d63effaa5ef/src/vitessce/data_utils/spatialdata_points_zorder.py#L458 + feature_key_col = ddf.attrs["spatialdata_attrs"]["feature_key"] + # Note: this should be the default behavior on the JS side, so this may be unnecessary to do here. + # Reference: https://github.com/vitessce/vitessce/blob/0ff9f3b43ca28ef9858d3db0ce06417f6dd174a9/packages/file-types/spatial-zarr/src/spatialdata-loaders/SpatialDataObsPointsLoader.js#L126 + codes_col = f"{feature_key_col}_codes" + if codes_col in ddf.columns: + wrapper_args["obs_points_feature_index_column"] = codes_col + except KeyError: + pass + + obs_coordination = None + feature_coordination = None + + if color is not None: + if is_color_like(color): + # static color + layer_coordination["spatialLayerColor"] = to_uint8_rgb(color) + elif color in ddf.columns: + # feature_name column + layer_coordination["obsColorEncoding"] = "randomByFeature" + + # In case the value of `color` does not match spatialdata_attrs.feature_key + codes_col = f"{color}_codes" + if codes_col in ddf.columns: + # Note: this overwrites any existing feature index column value in the dict. + wrapper_args["obs_points_feature_index_column"] = codes_col + + if groups is not None: + if type(groups) is str: + groups = [groups] + if palette is not None: + if type(palette) is str: + # Broadcast single color to all groups. + palette = [palette for _ in groups] + elif type(palette) is list and len(groups) != len(palette): + raise ValueError("The length of 'groups' and 'palette' lists must be equal.") + + feature_color_val = [ + { + "name": groups[i], + "color": to_uint8_rgb(palette[i]), + } for i in range(len(groups)) + ] + + layer_coordination["featureColor"] = feature_color_val + layer_coordination["obsColorEncoding"] = "geneSelection" + layer_coordination["featureSelection"] = groups + layer_coordination["featureFilterMode"] = "featureSelection" + + feature_coordination = { + "obsType": obs_type, + "featureType": feature_type, + "featureSelection": groups if groups is not None else None, + } + + if alpha is not None: + layer_coordination["spatialLayerOpacity"] = alpha + # TODO: perform the necessary operations on the points dataframe (sorting by morton code). + # Perhaps the user will need to opt-in via the global configuration. + self.point_layers.append( - (wrapper_args, layer_coordination) + (wrapper_args, layer_coordination, obs_coordination, feature_coordination) ) return self.sdata @@ -714,7 +841,7 @@ def show(self, coordinate_systems=None, **kwargs): }) dataset = dataset.add_object(spot_wrapper) - for (layer_wrapper_args, _) in self.point_layers: + for (layer_wrapper_args, _, _, _) in self.point_layers: points_wrapper = SpatialDataWrapper(**{ **self.shared_wrapper_args, **({ "coordinate_system": coordinate_systems } if coordinate_systems is not None else {}), @@ -746,6 +873,11 @@ def show(self, coordinate_systems=None, **kwargs): obs_coordination.append(obs_coord) if feature_coord is not None: feature_coordination.append(feature_coord) + for (_, _, obs_coord, feature_coord) in self.point_layers: + if obs_coord is not None: + obs_coordination.append(obs_coord) + if feature_coord is not None: + feature_coordination.append(feature_coord) # Add obsSet and featureList views. for obs_coord in obs_coordination: @@ -851,7 +983,7 @@ def show(self, coordinate_systems=None, **kwargs): **obs_coordination_by_key.get(layer_dict.get("obsType"), {}), **layer_dict, } - for (_, layer_dict) in self.point_layers + for (_, layer_dict, _, _) in self.point_layers ]), }, meta=True, scope_prefix=get_initial_coordination_scope_prefix(dataset_uid, "obsPoints")) diff --git a/uv.lock b/uv.lock index 6fdb3c4..dcc92c4 100644 --- a/uv.lock +++ b/uv.lock @@ -1023,7 +1023,7 @@ wheels = [ [[package]] name = "easy-vitessce" -version = "0.0.8" +version = "0.0.10" source = { editable = "." } dependencies = [ { name = "anndata", version = "0.11.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, @@ -1085,7 +1085,7 @@ requires-dist = [ { name = "sphinx", marker = "extra == 'docs'" }, { name = "sphinx-book-theme", marker = "extra == 'docs'" }, { name = "sphinx-copybutton", marker = "extra == 'docs'" }, - { name = "vitessce", extras = ["all"], specifier = ">=3.7.9" }, + { name = "vitessce", extras = ["all"], specifier = ">=3.8.1" }, { name = "xarray", specifier = ">=2024.10.0,<=2025.3.0" }, { name = "zarr", specifier = ">=2.5.0,<3" }, ] @@ -4904,7 +4904,7 @@ wheels = [ [[package]] name = "vitessce" -version = "3.7.9" +version = "3.8.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "black" }, @@ -4917,8 +4917,9 @@ dependencies = [ { name = "zarr", version = "2.18.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "zarr", version = "2.18.7", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, ] +sdist = { url = "https://files.pythonhosted.org/packages/4a/c8/f5a7928e5521611e1d128d37d336078c9324198929e261524eda15a6559a/vitessce-3.8.1.tar.gz", hash = "sha256:293b99a0b66721368b0500c328f9d7879f6ab08bdce949b749c4a23271d8f397", size = 332200 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b6/79/ef9dcc1dc0ead62e143194606b65a00761f43dbc22df3bca248c1c78115d/vitessce-3.7.9-py3-none-any.whl", hash = "sha256:b54cc4a73991d07b1ccf2617062705ae708508a18fde338790b7fea381ee30ba", size = 79840 }, + { url = "https://files.pythonhosted.org/packages/d0/8d/cfd9eb3fdc3d37ae12ad3aa4e3b01ea7d886e2941adf212d1be1a7085552/vitessce-3.8.1-py3-none-any.whl", hash = "sha256:7a98683da82d5ffa5b1d7aea3f4a687e7a45090fabded8250895c7912230fbfc", size = 80024 }, ] [package.optional-dependencies]