scverse / spatialdata-plot

Static plotting for spatialdata
BSD 3-Clause "New" or "Revised" License
38 stars 14 forks source link

Bug when trying to plot Visium HD bins as points #299

Open LucaMarconato opened 4 months ago

LucaMarconato commented 4 months ago

While updating the Visium HD notebook I have tried converting the bins to points and plotting them, and I found that this leads to an error in spatialdata-plot.

Here is how to reproduce (I also copy-paste some markdown text as a note to myself; I am removing it from the notebook now and I'll restore it when the bug is fixed).

from spatialdata.models import points_geopandas_to_dask_dataframe

sdata["points_016um"] = points_geopandas_to_dask_dataframe(sdata["Visium_HD_Mouse_Small_Intestine_square_016um"])
# gives the error:
sdata.pl.render_points("points_016um").pl.show()

Traceback:

[/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/anndata.py:430](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/anndata.py#line=429): FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
  warnings.warn(
[/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/aligned_df.py:67](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/aligned_df.py#line=66): ImplicitModificationWarning: Transforming to str index.
  warnings.warn("Transforming to str index.", ImplicitModificationWarning)
[/Users/macbook/embl/projects/basel/spatialdata/src/spatialdata/_core/_elements.py:106](http://localhost:8888/Users/macbook/embl/projects/basel/spatialdata/src/spatialdata/_core/_elements.py#line=105): UserWarning: Key `points_016um` already exists. Overwriting it in-memory.
  self._check_key(key, self.keys(), self._shared_keys)
[/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/anndata.py:430](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/anndata.py#line=429): FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
  warnings.warn(
[/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/aligned_df.py:67](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/aligned_df.py#line=66): ImplicitModificationWarning: Transforming to str index.
  warnings.warn("Transforming to str index.", ImplicitModificationWarning)
[/Users/macbook/embl/projects/basel/spatialdata/src/spatialdata/_core/_elements.py:106](http://localhost:8888/Users/macbook/embl/projects/basel/spatialdata/src/spatialdata/_core/_elements.py#line=105): UserWarning: Key `points_016um` already exists. Overwriting it in-memory.
  self._check_key(key, self.keys(), self._shared_keys)
[/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/anndata.py:430](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/anndata.py#line=429): FutureWarning: The dtype argument is deprecated and will be removed in late 2024.
  warnings.warn(
[/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/aligned_df.py:67](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/anndata/_core/aligned_df.py#line=66): ImplicitModificationWarning: Transforming to str index.
  warnings.warn("Transforming to str index.", ImplicitModificationWarning)
[/Users/macbook/embl/projects/basel/spatialdata/src/spatialdata/_core/_elements.py:106](http://localhost:8888/Users/macbook/embl/projects/basel/spatialdata/src/spatialdata/_core/_elements.py#line=105): UserWarning: Key `points_016um` already exists. Overwriting it in-memory.
  self._check_key(key, self.keys(), self._shared_keys)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[28], line 1
----> 1 sdata.pl.render_points("points_016um").pl.show()

File [~/embl/projects/basel/spatialdata-plot/src/spatialdata_plot/pl/basic.py:906](http://localhost:8888/~/embl/projects/basel/spatialdata-plot/src/spatialdata_plot/pl/basic.py#line=905), in PlotAccessor.show(self, coordinate_systems, legend_fontsize, legend_fontweight, legend_loc, legend_fontoutline, na_in_legend, colorbar, wspace, hspace, ncols, frameon, figsize, dpi, fig, title, share_extent, pad_extent, ax, return_ax, save)
    901     wanted_elements, wanted_points_on_this_cs, wants_points = _get_wanted_render_elements(
    902         sdata, wanted_elements, params_copy, cs, "points"
    903     )
    905     if wanted_points_on_this_cs:
--> 906         _render_points(
    907             sdata=sdata,
    908             render_params=params_copy,
    909             coordinate_system=cs,
    910             ax=ax,
    911             fig_params=fig_params,
    912             scalebar_params=scalebar_params,
    913             legend_params=legend_params,
    914         )
    916 elif cmd == "render_labels" and has_labels:
    917     wanted_elements, wanted_labels_on_this_cs, wants_labels = _get_wanted_render_elements(
    918         sdata, wanted_elements, params_copy, cs, "labels"
    919     )

File [~/embl/projects/basel/spatialdata-plot/src/spatialdata_plot/pl/render.py:459](http://localhost:8888/~/embl/projects/basel/spatialdata-plot/src/spatialdata_plot/pl/render.py#line=458), in _render_points(sdata, render_params, coordinate_system, ax, fig_params, scalebar_params, legend_params)
    452 else:
    453     ds_result = ds.tf.shade(
    454         ds.tf.spread(agg, px=px),
    455         rescale_discrete_levels=True,
    456         cmap=render_params.cmap_params.cmap,
    457     )
--> 459 rbga_image = np.transpose(ds_result.to_numpy().base, (0, 1, 2))
    460 cax = ax.imshow(rbga_image, zorder=render_params.zorder, alpha=render_params.alpha)
    461 if aggregate_with_sum is not None:

File [/opt/miniconda3/envs/ome/lib/python3.10/site-packages/numpy/core/fromnumeric.py:655](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/numpy/core/fromnumeric.py#line=654), in transpose(a, axes)
    588 @array_function_dispatch(_transpose_dispatcher)
    589 def transpose(a, axes=None):
    590     """
    591     Returns an array with axes transposed.
    592 
   (...)
    653 
    654     """
--> 655     return _wrapfunc(a, 'transpose', axes)

File [/opt/miniconda3/envs/ome/lib/python3.10/site-packages/numpy/core/fromnumeric.py:56](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/numpy/core/fromnumeric.py#line=55), in _wrapfunc(obj, method, *args, **kwds)
     54 bound = getattr(obj, method, None)
     55 if bound is None:
---> 56     return _wrapit(obj, method, *args, **kwds)
     58 try:
     59     return bound(*args, **kwds)

File [/opt/miniconda3/envs/ome/lib/python3.10/site-packages/numpy/core/fromnumeric.py:45](http://localhost:8888/opt/miniconda3/envs/ome/lib/python3.10/site-packages/numpy/core/fromnumeric.py#line=44), in _wrapit(obj, method, *args, **kwds)
     43 except AttributeError:
     44     wrap = None
---> 45 result = getattr(asarray(obj), method)(*args, **kwds)
     46 if wrap:
     47     if not isinstance(result, mu.ndarray):

ValueError: axes don't match array
LucaMarconato commented 4 months ago

I post as a note to myself also the markdown description that I wanted to add to the notebook. I'll remove it now, and


- Plotting circles vs points. In an hypotetic scenario where the user is working with hundreds of Visium HD datasets and where performance is even more important, switching to a point representation may be considered. Points have no radius so visualization would be less accurate, but this may be acceptable in favor of performance.

...

### Plotting the geometries as points

When making plots where the correct bin size (e.g. circle diameter) can be sacrified in favor of performance, and wish the rasterized approach not to be used, the user can choose to convert the geometries to points. Here is an example of converting the data.
Vector-based plotting is now faster than if plotting circles, but the rasterized-based version shown above is the fastest. Therefore we recommend it over the current one.