vitessce / vitessce-python

Python API and Jupyter widget for Vitessce
https://python-docs.vitessce.io
MIT License
40 stars 7 forks source link

`layout.to_dict()` throwing: `TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'` #366

Open ivirshup opened 2 months ago

ivirshup commented 2 months ago

Hey, ran into what I think is a small bug in to_dict:

import zarr
from vitessce import (
    VitessceWidget,
    VitessceConfig,
    Component as cm,
    CoordinationType as ct,
    AnnDataWrapper,
)
TEST_ANNDATA_URI = "s3://tmp-census-zarr/v1/homo_sapiens/0041b9c3-6a49-4bf7-8514-9bc7190067a7.zarr"

vc = VitessceConfig(schema_version="1.0.15")
dataset = vc.add_dataset().add_object(
        AnnDataWrapper(
                adata_store=z.store,
                obs_embedding_paths=["obsm/X_umap"],
                obs_embedding_names=["UMAP"],
                obs_set_paths=["obs/cell_type"],
                obs_set_names=["cell_type"],
                obs_feature_matrix_path="X",
                # feature_filter_path="var/top_highly_variable"
        )
)
scatterplot = vc.add_view(cm.SCATTERPLOT, dataset=dataset, mapping="UMAP")
layout = vc.layout(scatterplot)

layout.to_dict()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[12], line 26
     23 scatterplot = vc.add_view(cm.SCATTERPLOT, dataset=dataset, mapping="UMAP")
     24 layout = vc.layout(scatterplot)
---> 26 layout.to_dict()

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/config.py:1488, in VitessceConfig.to_dict(self, base_url)
   1477 def to_dict(self, base_url=None):
   1478     """
   1479     Convert the view config instance to a dict object.
   1480 
   (...)
   1484     :rtype: dict
   1485     """
   1486     return {
   1487         **self.config,
-> 1488         "datasets": [d.to_dict(base_url) for d in self.config["datasets"]],
   1489         "coordinationSpace": dict([
   1490             (c_type, dict([
   1491                 (c_scope_name, c_scope.c_value) for c_scope_name, c_scope in c_scopes.items()
   1492             ])) for c_type, c_scopes in self.config["coordinationSpace"].items()
   1493         ]),
   1494         # TODO: compute the x,y,w,h values if not explicitly defined
   1495         "layout": [c.to_dict() for c in self.config["layout"]]
   1496     }

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/config.py:1488, in <listcomp>(.0)
   1477 def to_dict(self, base_url=None):
   1478     """
   1479     Convert the view config instance to a dict object.
   1480 
   (...)
   1484     :rtype: dict
   1485     """
   1486     return {
   1487         **self.config,
-> 1488         "datasets": [d.to_dict(base_url) for d in self.config["datasets"]],
   1489         "coordinationSpace": dict([
   1490             (c_type, dict([
   1491                 (c_scope_name, c_scope.c_value) for c_scope_name, c_scope in c_scopes.items()
   1492             ])) for c_type, c_scopes in self.config["coordinationSpace"].items()
   1493         ]),
   1494         # TODO: compute the x,y,w,h values if not explicitly defined
   1495         "layout": [c.to_dict() for c in self.config["layout"]]
   1496     }

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/config.py:224, in VitessceConfigDataset.to_dict(self, base_url)
    222 obj_file_defs = []
    223 for obj in self.objs:
--> 224     obj_file_defs += obj.get_file_defs(base_url)
    226 return {
    227     **self.dataset,
    228     "files": [f.to_dict() for f in self.dataset["files"]] + obj_file_defs,
    229 }

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/wrappers.py:102, in AbstractWrapper.get_file_defs(self, base_url)
    100 file_defs_with_base_url = []
    101 for file_def_creator in self.file_def_creators:
--> 102     file_def = file_def_creator(base_url)
    103     if file_def is not None:
    104         file_defs_with_base_url.append(file_def)

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/wrappers.py:1183, in AnnDataWrapper.make_file_def_creator.<locals>.get_anndata_zarr(base_url)
   1178 if self.is_h5ad:
   1179     options["refSpecUrl"] = self.get_ref_url(base_url, dataset_uid, obj_i)
   1181 obj_file_def = {
   1182     "fileType": ft.ANNDATA_ZARR.value if not self.is_h5ad else ft.ANNDATA_H5AD.value,
-> 1183     "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),
   1184     "options": options
   1185 }
   1186 if self._request_init is not None:
   1187     obj_file_def['requestInit'] = self._request_init

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/wrappers.py:1087, in AnnDataWrapper.get_zarr_url(self, base_url, dataset_uid, obj_i)
   1085     return self._adata_url
   1086 else:
-> 1087     return self.get_local_dir_url(base_url, dataset_uid, obj_i, self._adata_path, self.local_dir_uid)

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/wrappers.py:133, in AbstractWrapper.get_local_dir_url(self, base_url, dataset_uid, obj_i, local_dir_path, local_dir_uid)
    131 def get_local_dir_url(self, base_url, dataset_uid, obj_i, local_dir_path, local_dir_uid):
    132     # Logic for files and directories is the same for this function.
--> 133     return self.get_local_file_url(base_url, dataset_uid, obj_i, local_dir_path, local_dir_uid)

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/wrappers.py:129, in AbstractWrapper.get_local_file_url(self, base_url, dataset_uid, obj_i, local_file_path, local_file_uid)
    127 if not self.is_remote and self.base_dir is not None:
    128     return self._get_url_simple(base_url, file_path_to_url_path(local_file_path, prepend_slash=False))
--> 129 return self._get_url(base_url, dataset_uid, obj_i, local_file_uid)

File ~/miniforge3/envs/cellxgene-census-dev-new/lib/python3.11/site-packages/vitessce/wrappers.py:200, in AbstractWrapper._get_url(self, base_url, dataset_uid, obj_i, *args)
    199 def _get_url(self, base_url, dataset_uid, obj_i, *args):
--> 200     return base_url + self._get_route_str(dataset_uid, obj_i, *args)

TypeError: unsupported operand type(s) for +: 'NoneType' and 'str'

This is using Vitessce 3.3.3