sc.tl.dendrogram no longer(?) works in backed mode
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 779
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 27
Description
Please make sure these conditions are met
- I have checked that this issue has not already been reported.
- I have confirmed this bug exists on the latest version of scanpy.
- (optional) I have confirmed this bug exists on the main branch of scanpy.
What happened?
In #3048 we started raising errors for functions that don’t support backed mode, but seems like a tutorial used dendrogram in backed mode: https://scverse-tutorials.readthedocs.io/en/latest/notebooks/scverse_data_backed.html
That was probably a mistake and the data just got loaded to memory, but since dendrogram can be reimplemented using .get.aggregate, we should do that!
Minimal code sample
import scanpy as sc
adata = sc.datasets.pbmc3k()
adata.filename = "test.h5ad"
sc.pl.dotplot(adata, ["FCN1"], groupby="index", dendrogram=True)
Error output
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
Cell In[44], line 1
----> 1 sc.pl.dotplot(mdata["rna"], var_names=["CD2"], groupby="leiden", figsize=(10, 3), dendrogram=True, swap_axes=True)
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/legacy_api_wrap/__init__.py:80, in legacy_api.<locals>.wrapper.<locals>.fn_compatible(*args_all, **kw)
77 @wraps(fn)
78 def fn_compatible(*args_all: P.args, **kw: P.kwargs) -> R:
79 if len(args_all) <= n_positional:
---> 80 return fn(*args_all, **kw)
82 args_pos: P.args
83 args_pos, args_rest = args_all[:n_positional], args_all[n_positional:]
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/scanpy/plotting/_dotplot.py:1046, in dotplot(adata, var_names, groupby, use_raw, log, num_categories, expression_cutoff, mean_only_expressed, cmap, dot_max, dot_min, standard_scale, smallest_dot, title, colorbar_title, size_title, figsize, dendrogram, gene_symbols, var_group_positions, var_group_labels, var_group_rotation, layer, swap_axes, dot_color_df, show, save, ax, return_fig, vmin, vmax, vcenter, norm, **kwds)
1019 dp = DotPlot(
1020 adata,
1021 var_names,
(...)
1042 **kwds,
1043 )
1045 if dendrogram:
-> 1046 dp.add_dendrogram(dendrogram_key=dendrogram)
1047 if swap_axes:
1048 dp.swap_axes()
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/scanpy/plotting/_baseplot_class.py:306, in BasePlot.add_dendrogram(self, show, dendrogram_key, size)
302 self.group_extra_size = size
304 # to correctly plot the dendrogram the categories need to be ordered
305 # according to the dendrogram ordering.
--> 306 self._reorder_categories_after_dendrogram(dendrogram_key)
308 dendro_ticks = np.arange(len(self.categories)) + 0.5
310 self.group_extra_size = size
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/scanpy/plotting/_baseplot_class.py:897, in BasePlot._reorder_categories_after_dendrogram(self, dendrogram)
894 _categories = _categories[:3] + ["etc."]
895 return ", ".join(_categories)
--> 897 key = _get_dendrogram_key(self.adata, dendrogram, self.groupby)
899 dendro_info = self.adata.uns[key]
900 if self.groupby != dendro_info["groupby"]:
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/scanpy/plotting/_anndata.py:2384, in _get_dendrogram_key(adata, dendrogram_key, groupby)
2377 from ..tools._dendrogram import dendrogram
2379 logg.warning(
2380 f"dendrogram data not found (using key={dendrogram_key}). "
2381 "Running `sc.tl.dendrogram` with default parameters. For fine "
2382 "tuning it is recommended to run `sc.tl.dendrogram` independently."
2383 )
-> 2384 dendrogram(adata, groupby, key_added=dendrogram_key)
2386 if "dendrogram_info" not in adata.uns[dendrogram_key]:
2387 raise ValueError(
2388 f"The given dendrogram key ({dendrogram_key!r}) does not contain "
2389 "valid dendrogram information."
2390 )
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/legacy_api_wrap/__init__.py:80, in legacy_api.<locals>.wrapper.<locals>.fn_compatible(*args_all, **kw)
77 @wraps(fn)
78 def fn_compatible(*args_all: P.args, **kw: P.kwargs) -> R:
79 if len(args_all) <= n_positional:
---> 80 return fn(*args_all, **kw)
82 args_pos: P.args
83 args_pos, args_rest = args_all[:n_positional], args_all[n_positional:]
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/scanpy/tools/_dendrogram.py:121, in dendrogram(adata, groupby, n_pcs, use_rep, var_names, use_raw, cor_method, linkage_method, optimal_ordering, key_added, inplace)
25 @old_positionals(
26 "n_pcs",
27 "use_rep",
(...)
49 inplace: bool = True,
50 ) -> dict[str, Any] | None:
51 """\
52 Computes a hierarchical clustering for the given `groupby` categories.
53
(...)
118 >>> sc.pl.dotplot(adata, markers, groupby='bulk_labels', dendrogram=True)
119 """
--> 121 raise_not_implemented_error_if_backed_type(adata.X, "dendrogram")
122 if isinstance(groupby, str):
123 # if not a list, turn into a list
124 groupby = [groupby]
File ~/.local/share/hatch/env/virtual/scverse-tutorials/_YRPCeuX/basic-scrna/lib/python3.12/site-packages/scanpy/_utils/__init__.py:1100, in raise_not_implemented_error_if_backed_type(X, method_name)
1098 def raise_not_implemented_error_if_backed_type(X: object, method_name: str) -> None:
1099 if is_backed_type(X):
-> 1100 raise NotImplementedError(
1101 f"{method_name} is not implemented for matrices of type {type(X)}"
1102 )
NotImplementedError: dendrogram is not implemented for matrices of type <class 'anndata._core.sparse_dataset.CSRDataset'>
Versions
-----
anndata 0.10.8
scanpy 1.10.2
-----
PIL 10.3.0
asttokens NA
comm 0.2.2
cycler 0.12.1
cython_runtime NA
dateutil 2.9.0.post0
debugpy 1.8.1
decorator 5.1.1
executing 2.0.1
h5py 3.11.0
igraph 0.11.4
ipykernel 6.29.4
jedi 0.19.1
joblib 1.4.0
kiwisolver 1.4.5
legacy_api_wrap NA
leidenalg 0.10.2
llvmlite 0.42.0
matplotlib 3.8.4
mpl_toolkits NA
natsort 8.4.0
numba 0.59.1
numpy 1.26.4
packaging 24.0
pandas 2.2.2
parso 0.8.4
platformdirs 4.2.1
prompt_toolkit 3.0.43
psutil 5.9.8
pure_eval 0.2.2
pydev_ipython NA
pydevconsole NA
pydevd 2.9.5
pydevd_file_utils NA
pydevd_plugins NA
pydevd_tracing NA
pygments 2.17.2
pyparsing 3.1.2
pytz 2024.1
scipy 1.13.0
session_info 1.0.0
six 1.16.0
sklearn 1.4.2
stack_data 0.6.3
texttable 1.7.0
threadpoolctl 3.5.0
tornado 6.4
traitlets 5.14.3
vscode NA
wcwidth 0.2.13
zmq 26.0.3
-----
IPython 8.24.0
jupyter_client 8.6.1
jupyter_core 5.7.2
-----
Python 3.12.4 (main, Jun 7 2024, 06:33:07) [GCC 14.1.1 20240522]
Linux-6.10.3-zen1-1-zen-x86_64-with-glibc2.40
-----
Session information updated at 2024-08-06 12:18
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with scanpy/tools/_dendrogram.py and the sc.tl.dendrogram call reached from scanpy/plotting/_anndata.py; reproduce the minimal backed-mode dotplot example. Done means dendrogram computation no longer raises for backed CSRDataset and the dotplot path works in the reported case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- data-visualization
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100