scanpy
scanpy copied to clipboard
Scanpy.pl.embedding throws error when projection='3d' and all values are the same for coloring
- [x] I have checked that this issue has not already been reported.
- [x] I have confirmed this bug exists on the latest version of scanpy.
- [ ] (optional) I have confirmed this bug exists on the master branch of scanpy.
Note: Please read this guide detailing how to provide the necessary information for us to reproduce your bug.
Minimal code sample (that we can copy&paste without having any data)
# NOTE: This throws error
sc.pl.embedding(
adata, basis='X_emb', color=de_genes[:10], sort_order=True, vmin=0, color_map='magma',
projection='3d'
)
# NOTE: This doesn't throw error
sc.pl.embedding(
adata, basis='X_emb', color=de_genes[:10], sort_order=True, vmin=0, color_map='magma',
projection='2d'
)
# NOTE: the error is that one of the genes in `de_genes` has almost the value for all cells
np.unique(adata.X[:, de_genes.index('KRT1')])
> array([-0.09614931, -0.09614931, -0.09614931, -0.09614931, -0.09614931,
-0.09614931, -0.09614931, -0.09614931, -0.09614931, -0.09614931,
-0.09614931, -0.09614931, -0.09614931, -0.09614931, -0.09614931,
-0.09614931, -0.09614931, -0.09614931, -0.09614931, -0.09614931,
-0.09614931, -0.09614931, -0.09614931, -0.09614931, -0.09614931,
-0.09614931, -0.09614931, -0.09614931, -0.09614931, -0.09614931,
-0.09614931, -0.09614931, -0.09614931, -0.09614931])
# Thus this is a combination of projection 3d and rounding. This should not throw an error and just plot all points same color
[Paste the error output produced by the above code here]
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Input In [403], in <cell line: 1>()
----> 1 sc.pl.embedding(
2 adata, basis='X_phate_alone', color=de_genes[:10], sort_order=True, vmin=0, color_map='magma',
3 projection='3d'
4 )
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/scanpy/plotting/_tools/scatterplots.py:325, in embedding(adata, basis, color, gene_symbols, use_raw, sort_order, edges, edges_width, edges_color, neighbors_key, arrows, arrows_kwds, groups, components, dimensions, layer, projection, scale_factor, color_map, cmap, palette, na_color, na_in_legend, size, frameon, legend_fontsize, legend_fontweight, legend_loc, legend_fontoutline, colorbar_loc, vmax, vmin, vcenter, norm, add_outline, outline_width, outline_color, ncols, hspace, wspace, title, show, save, ax, return_fig, **kwargs)
323 # make the scatter plot
324 if projection == '3d':
--> 325 cax = ax.scatter(
326 coords[:, 0],
327 coords[:, 1],
328 coords[:, 2],
329 marker=".",
330 c=color_vector,
331 rasterized=settings._vector_friendly,
332 norm=normalize,
333 **kwargs,
334 )
335 else:
336 scatter = (
337 partial(ax.scatter, s=size, plotnonfinite=True)
338 if scale_factor is None
(...)
341 ) # size in circles is radius
342 )
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/mpl_toolkits/mplot3d/axes3d.py:2417, in Axes3D.scatter(self, xs, ys, zs, zdir, s, c, depthshade, *args, **kwargs)
2414 zs = zs.copy()
2416 patches = super().scatter(xs, ys, s=s, c=c, *args, **kwargs)
-> 2417 art3d.patch_collection_2d_to_3d(patches, zs=zs, zdir=zdir,
2418 depthshade=depthshade)
2420 if self._zmargin < 0.05 and xs.size > 0:
2421 self.set_zmargin(0.05)
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/mpl_toolkits/mplot3d/art3d.py:674, in patch_collection_2d_to_3d(col, zs, zdir, depthshade)
672 col._depthshade = depthshade
673 col._in_draw = False
--> 674 col.set_3d_properties(zs, zdir)
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/mpl_toolkits/mplot3d/art3d.py:542, in Path3DCollection.set_3d_properties(self, zs, zdir)
539 def set_3d_properties(self, zs, zdir):
540 # Force the collection to initialize the face and edgecolors
541 # just in case it is a scalarmappable with a colormap.
--> 542 self.update_scalarmappable()
543 offsets = self.get_offsets()
544 if len(offsets) > 0:
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/collections.py:926, in Collection.update_scalarmappable(self)
924 # pcolormesh, scatter, maybe others flatten their _A
925 self._alpha = self._alpha.reshape(self._A.shape)
--> 926 self._mapped_colors = self.to_rgba(self._A, self._alpha)
928 if self._face_is_mapped:
929 self._facecolors = self._mapped_colors
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/cm.py:359, in ScalarMappable.to_rgba(self, x, alpha, bytes, norm)
357 x = ma.asarray(x)
358 if norm:
--> 359 x = self.norm(x)
360 rgba = self.cmap(x, alpha=alpha, bytes=bytes)
361 return rgba
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/colors.py:1193, in Normalize.__call__(self, value, clip)
1191 result.fill(0) # Or should it be all masked? Or 0.5?
1192 elif vmin > vmax:
-> 1193 raise ValueError("minvalue must be less than or equal to maxvalue")
1194 else:
1195 if clip:
ValueError: minvalue must be less than or equal to maxvalue
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/IPython/core/formatters.py:339, in BaseFormatter.__call__(self, obj)
337 pass
338 else:
--> 339 return printer(obj)
340 # Finally look for special method names
341 method = get_real_method(obj, self.print_method)
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/IPython/core/pylabtools.py:151, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
148 from matplotlib.backend_bases import FigureCanvasBase
149 FigureCanvasBase(fig)
--> 151 fig.canvas.print_figure(bytes_io, **kw)
152 data = bytes_io.getvalue()
153 if fmt == 'svg':
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/backend_bases.py:2230, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
2226 ctx = (renderer._draw_disabled()
2227 if hasattr(renderer, '_draw_disabled')
2228 else suppress())
2229 with ctx:
-> 2230 self.figure.draw(renderer)
2232 if bbox_inches:
2233 if bbox_inches == "tight":
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/artist.py:74, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
72 @wraps(draw)
73 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 74 result = draw(artist, renderer, *args, **kwargs)
75 if renderer._rasterizing:
76 renderer.stop_rasterizing()
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/artist.py:51, in allow_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
48 if artist.get_agg_filter() is not None:
49 renderer.start_filter()
---> 51 return draw(artist, renderer, *args, **kwargs)
52 finally:
53 if artist.get_agg_filter() is not None:
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/figure.py:2790, in Figure.draw(self, renderer)
2787 # ValueError can occur when resizing a window.
2789 self.patch.draw(renderer)
-> 2790 mimage._draw_list_compositing_images(
2791 renderer, self, artists, self.suppressComposite)
2793 for sfig in self.subfigs:
2794 sfig.draw(renderer)
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/image.py:132, in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
130 if not_composite or not has_images:
131 for a in artists:
--> 132 a.draw(renderer)
133 else:
134 # Composite any adjacent images together
135 image_group = []
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/artist.py:51, in allow_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
48 if artist.get_agg_filter() is not None:
49 renderer.start_filter()
---> 51 return draw(artist, renderer, *args, **kwargs)
52 finally:
53 if artist.get_agg_filter() is not None:
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/mpl_toolkits/mplot3d/axes3d.py:485, in Axes3D.draw(self, renderer)
480 # Calculate projection of collections and patches and zorder them.
481 # Make sure they are drawn above the grids.
482 zorder_offset = max(axis.get_zorder()
483 for axis in self._get_axis_list()) + 1
484 for i, col in enumerate(
--> 485 sorted(self.collections,
486 key=do_3d_projection,
487 reverse=True)):
488 col.zorder = zorder_offset + i
489 for i, patch in enumerate(
490 sorted(self.patches,
491 key=do_3d_projection,
492 reverse=True)):
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/mpl_toolkits/mplot3d/axes3d.py:471, in Axes3D.draw.<locals>.do_3d_projection(artist)
458 """
459 Call `do_3d_projection` on an *artist*, and warn if passing
460 *renderer*.
(...)
464 *renderer* and raise a warning.
465 """
467 if artist.__module__ == 'mpl_toolkits.mplot3d.art3d':
468 # Our 3D Artists have deprecated the renderer parameter, so
469 # avoid passing it to them; call this directly once the
470 # deprecation has expired.
--> 471 return artist.do_3d_projection()
473 _api.warn_deprecated(
474 "3.4",
475 message="The 'renderer' parameter of "
476 "do_3d_projection() was deprecated in Matplotlib "
477 "%(since)s and will be removed %(removal)s.")
478 return artist.do_3d_projection(renderer)
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/matplotlib/_api/deprecation.py:431, in delete_parameter.<locals>.wrapper(*inner_args, **inner_kwargs)
421 deprecation_addendum = (
422 f"If any parameter follows {name!r}, they should be passed as "
423 f"keyword, not positionally.")
424 warn_deprecated(
425 since,
426 name=repr(name),
(...)
429 else deprecation_addendum,
430 **kwargs)
--> 431 return func(*inner_args, **inner_kwargs)
File ~/anaconda3/envs/ml/lib/python3.9/site-packages/mpl_toolkits/mplot3d/art3d.py:599, in Path3DCollection.do_3d_projection(self, renderer)
597 @_api.delete_parameter('3.4', 'renderer')
598 def do_3d_projection(self, renderer=None):
--> 599 xs, ys, zs = self._offsets3d
600 vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs,
601 self.axes.M)
602 # Sort the points based on z coordinates
603 # Performance optimization: Create a sorted index array and reorder
604 # points and point properties according to the index array
AttributeError: 'Path3DCollection' object has no attribute '_offsets3d'
Versions
[Paste the output of scanpy.logging.print_versions() leaving a blank line after the details tag]
anndata 0.8.0 scanpy 1.9.1
PIL 9.1.1 aa8f2297d25b4dc6fd3d98411eb3ba53823c4f42 NA absl NA asttokens NA astunparse 1.6.3 backcall 0.2.0 batchglm v0.7.4 beta_ufunc NA binom_ufunc NA bottleneck 1.3.4 certifi 2022.05.18.1 cffi 1.15.0 charset_normalizer 2.0.12 cloudpickle 2.1.0 colorama 0.4.5 cycler 0.10.0 cython_runtime NA dask 2022.6.1 dateutil 2.8.2 debugpy 1.6.0 decorator 5.1.1 defusedxml 0.7.1 deprecated 1.2.13 diffxpy v0.7.4 entrypoints 0.4 executing 0.8.3 flatbuffers NA fsspec 2022.5.0 future 0.18.2 gast NA google NA graphtools 1.5.2 h5py 3.7.0 hypergeom_ufunc NA idna 3.3 ipykernel 6.15.0 ipython_genutils 0.2.0 ipywidgets 7.7.0 jedi 0.18.1 jinja2 3.1.2 joblib 1.1.0 keras 2.9.0 kiwisolver 1.4.3 llvmlite 0.38.1 magic 3.0.0 markupsafe 2.1.1 matplotlib 3.4.3 matplotlib_inline NA mkl 2.4.0 mpl_toolkits NA natsort 8.1.0 nbinom_ufunc NA numba 0.55.2 numexpr 2.8.1 numpy 1.22.3 opt_einsum v3.3.0 packaging 21.3 pandas 1.4.2 parso 0.8.3 patsy 0.5.2 pcurve NA pexpect 4.8.0 phate 1.0.7 pickleshare 0.7.5 pkg_resources NA prompt_toolkit 3.0.29 psutil 5.9.1 ptyprocess 0.7.0 pure_eval 0.2.2 pydev_ipython NA pydevconsole NA pydevd 2.8.0 pydevd_file_utils NA pydevd_plugins NA pydevd_tracing NA pygments 2.12.0 pygsp 0.5.1 pyparsing 3.0.9 pytz 2022.1 requests 2.28.0 s_gd2 1.8 scipy 1.8.1 scprep 1.2.0 seaborn 0.11.2 session_info 1.0.0 setuptools 62.6.0 six 1.16.0 sklearn 1.1.1 slingshot NA sparse 0.13.0 stack_data 0.3.0 statsmodels 0.13.2 swig_runtime_data4 NA tasklogger 1.1.2 tensorboard 2.9.1 tensorflow 2.9.1 termcolor 1.1.0 threadpoolctl 3.1.0 tlz 0.11.2 toolz 0.11.2 torch 1.11.0 tornado 6.1 tqdm 4.64.0 traitlets 5.3.0 typing_extensions NA unicodedata2 NA urllib3 1.26.9 wcwidth 0.2.5 wrapt 1.14.1 yaml 6.0 zipp NA zmq 23.1.0
IPython 8.4.0 jupyter_client 7.3.4 jupyter_core 4.10.0 notebook 6.4.12
Python 3.9.12 | packaged by conda-forge | (main, Mar 24 2022, 23:25:59) [GCC 10.3.0] Linux-5.10.16.3-microsoft-standard-WSL2-x86_64-with-glibc2.31
Session information updated at 2022-06-28 16:19