scverse / anndata

Annotated data.
http://anndata.readthedocs.io
BSD 3-Clause "New" or "Revised" License
576 stars 152 forks source link

Slicing AnnData changes louvain_colors dtype #114

Closed Marius1311 closed 1 month ago

Marius1311 commented 5 years ago

In AnnData 0.6.18, when I slice an AnnData object via

adata_new = adata[bool_vector].copy()

then the type of 'louvain_colors' in adata.uns is changed from list to array. This throws an error when trying to plot via scanpy or scvelo, like sc.pl.scatter(adata_f, basis='umap', color='louvain') The error is unhashable type: 'numpy.ndarray' Can be solved of course by manually changing the data type again.

ivirshup commented 5 years ago

I can't seem to replicate this. Here's what I ran:

import scanpy as sc
import numpy as np

adata = sc.datasets.pbmc68k_reduced()
print(type(adata.uns["louvain_colors"]))
# <class 'numpy.ndarray'>

bool_array = np.random.randint(0, 2, adata.shape[0]).astype(bool)
adata_new = adata[bool_array].copy()
sc.pl.scatter(adata_new, basis="umap", color="louvain") # This just plotted normally

I also tried setting adata.uns["louvain_colors"] to be a list, but got the same results. Would you mind posting a minimal reproducible example and the traceback?

Marius1311 commented 5 years ago
outliers = ['ODs', 'Fibro']
cluster_subset = np.invert(np.in1d(adata.obs['louvain'], outliers))
adata_f = adata[cluster_subset].copy()
scv.pl.scatter(adata_f, color='louvain', legend_loc='on data')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-110-aa98b9eefe2d> in <module>
      1 # plot the reduced data
      2 
----> 3 scv.pl.scatter(adata_f, color='louvain', legend_loc='on data')

~/anaconda3/envs/reprog/lib/python3.6/site-packages/scvelo/plotting/scatter.py in scatter(adata, x, y, basis, vkey, color, use_raw, layer, color_map, colorbar, palette, size, alpha, perc, sort_order, groups, components, projection, legend_loc, legend_fontsize, legend_fontweight, right_margin, left_margin, xlabel, ylabel, title, fontsize, figsize, dpi, frameon, show, save, ax, zorder, ncols, **kwargs)
     74             from scanpy.api.pl import scatter as scatter_
     75             ax = scatter_(adata, basis=basis, color=color, color_map=color_map, size=size, frameon=frameon, ax=ax,
---> 76                           **scatter_kwargs, **kwargs)
     77 
     78         else:

~/anaconda3/envs/reprog/lib/python3.6/site-packages/scanpy/plotting/_anndata.py in scatter(adata, x, y, color, use_raw, layers, sort_order, alpha, basis, groups, components, projection, legend_loc, legend_fontsize, legend_fontweight, color_map, palette, frameon, right_margin, left_margin, size, title, show, save, ax)
    112             show=show,
    113             save=save,
--> 114             ax=ax)
    115     elif x is not None and y is not None:
    116         if ((x in adata.obs.keys() or x in adata.var.index)

~/anaconda3/envs/reprog/lib/python3.6/site-packages/scanpy/plotting/_anndata.py in _scatter_obs(adata, x, y, color, use_raw, layers, sort_order, alpha, basis, groups, components, projection, legend_loc, legend_fontsize, legend_fontweight, color_map, palette, frameon, right_margin, left_margin, size, title, show, save, ax)
    423         key = keys[ikey]
    424         utils.add_colors_for_categorical_sample_annotation(
--> 425             adata, key, palette, force_update_colors=not palette_was_none)
    426         # actually plot the groups
    427         mask_remaining = np.ones(Y.shape[0], dtype=bool)

~/anaconda3/envs/reprog/lib/python3.6/site-packages/scanpy/plotting/_utils.py in add_colors_for_categorical_sample_annotation(adata, key, palette, force_update_colors)
    289             adata.uns[key + '_colors'] = [
    290                 additional_colors[c] if c in additional_colors else c
--> 291                 for c in adata.uns[key + '_colors']]
    292             return
    293     else:

~/anaconda3/envs/reprog/lib/python3.6/site-packages/scanpy/plotting/_utils.py in <listcomp>(.0)
    289             adata.uns[key + '_colors'] = [
    290                 additional_colors[c] if c in additional_colors else c
--> 291                 for c in adata.uns[key + '_colors']]
    292             return
    293     else:

TypeError: unhashable type: 'numpy.ndarray'
ivirshup commented 5 years ago

Sorry, should have been more clear. I need an example that I can run on my machine, something like what's described here. Ideally, I'd be able to paste it into the REPL and it'd replicate your error. Can you reproduce this with one of the datasets under sc.datasets, or with some dummy data?

Also can you provide version information and the results of print(adata) and print(adata_f)?

flying-sheep commented 5 years ago

@Marius1311 https://stackoverflow.com/help/mcve

ivirshup commented 5 years ago

@Marius1311, just looking at this again. As a heads up, we pretty frequently will convert values in uns from lists to arrays. This will also happen from round-tripping the anndata object to disk.

Is this something that you will be/ have been able to work around?

github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. Please add a comment if you want to keep the issue open. Thank you for your contributions!