Skip to content

Error attempting to transform xenium transcript coordinate using transform() #1105

Closed

Description

@rached-97

Describe the bug

I am getting "ValueError: The number of items in 'lengths' does not match the number of partitions. 4 != 13" when attempting to transform xenium transcript coordinates using spatialdata (sd) sd.transform()

I noticed a similar error reported previously (issue #1064) but I am under the impression that it was resolved and closed.

Thank you for your help.

>>> sdata = xenium(xenDataDir, cells_as_circles=False)

>>> get_transformation(sdata["transcripts"])
Scale (x, y)
    [4.70588235 4.70588235]

>>> sd.transform(sdata["transcripts"], to_coordinate_system = "global")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[23], line 1
----> 1 sd.transform(sdata["transcripts"], to_coordinate_system = "global")

File /opt/homebrew/Cellar/[email protected]/3.14.3_1/Frameworks/Python.framework/Versions/3.14/lib/python3.14/functools.py:982, in singledispatch.<locals>.wrapper(*args, **kw)
    979 if not args:
    980     raise TypeError(f'{funcname} requires at least '
    981                     '1 positional argument')
--> 982 return dispatch(args[0].__class__)(*args, **kw)

File .venv/lib/python3.14/site-packages/spatialdata/_core/operations/transform.py:443, in _(data, transformation, maintain_positioning, to_coordinate_system)
    441 arrays = []
    442 for ax in axes:
--> 443     arrays.append(data[ax].to_dask_array(lengths=True).reshape(-1, 1))
    444 xdata = DataArray(da.concatenate(arrays, axis=1), coords={"points": range(len(data)), "dim": list(axes)})
    445 xtransformed = transformation._transform_coordinates(xdata)

File .venv/lib/python3.14/site-packages/dask/dataframe/dask_expr/_collection.py:1422, in FrameBase.to_dask_array(self, lengths, meta, optimize, **optimize_kwargs)
   1418     lengths = tuple(self.map_partitions(len).compute())
   1420 arr = self.values
-> 1422 chunks = self._validate_chunks(arr, lengths)
   1423 arr._chunks = chunks
   1425 if meta is not None:

File .venv/lib/python3.14/site-packages/dask/dataframe/dask_expr/_collection.py:2471, in FrameBase._validate_chunks(self, arr, lengths)
   2468 lengths = tuple(lengths)
   2470 if len(lengths) != self.npartitions:
-> 2471     raise ValueError(
   2472         "The number of items in 'lengths' does not match the number of "
   2473         f"partitions. {len(lengths)} != {self.npartitions}"
   2474     )
   2476 if self.ndim == 1:
   2477     chunks = normalize_chunks((lengths,))

ValueError: The number of items in 'lengths' does not match the number of partitions. 4 != 13

To Reproduce

pip freeze | grep spatialdata
napari-spatialdata==0.7.0
spatialdata==0.7.2
spatialdata-io==0.6.0
spatialdata-plot==0.3.2

pip freeze | grep dask       
dask==2026.1.1
dask-image==2025.11.0

Expected behavior
I expected the transcript data to be scaled to the global coordinate system (more specifically the coordinates of the Images in the spatialdata object) by the scaling factor returned by get_transformation()

Desktop (optional):

  • OS: MacOS running on Apple M1 Max
  • Version: Tahoe 26.2

Activity

  1. LucaMarconato commented on Apr 4, 2026

    @LucaMarconato
    Member

    Hi, thanks for reporting. Seems to be related to #1095. @melonora do you have updates regarding the issue? Thanks!

  2. rached-97 commented on May 8, 2026

    @rached-97
    Author

    Dear dev team,

    I attempted the operation again in spatialdata v0.7.3 and received a different error "ValueError: cannot reindex on an axis with duplicate labels"

    ---------------------------------------------------------------------------
    ValueError                                Traceback (most recent call last)
    Cell In[7], line 1
    ----> 1 sd.transform(sdata["transcripts"], to_coordinate_system = "global")
    
    File /opt/homebrew/Cellar/[email protected]/3.14.4_1/Frameworks/Python.framework/Versions/3.14/lib/python3.14/functools.py:982, in singledispatch.<locals>.wrapper(*args, **kw)
        979 if not args:
        980     raise TypeError(f'{funcname} requires at least '
        981                     '1 positional argument')
    --> 982 return dispatch(args[0].__class__)(*args, **kw)
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/spatialdata/_core/operations/transform.py:466, in _(data, transformation, maintain_positioning, to_coordinate_system)
        462     new_ax = xtransformed[:, indices]
        463     # TODO: discuss with dask team
        464     # This is not nice, but otherwise there is a problem with the joint graph of new_ax and transformed, causing
        465     # a getattr missing dependency of dependent from_dask_array.
    --> 466     new_col = pd.Series(new_ax.data.flatten().compute(), index=transformed.index)
        467     transformed[ax] = new_col
        469 old_transformations = cast(dict[str, Any], get_transformation(data, get_all=True))
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/pandas/core/series.py:493, in Series.__init__(self, data, index, dtype, name, copy, fastpath)
        490 name = ibase.maybe_extract_name(name, data, type(self))
        492 if index is not None:
    --> 493     index = ensure_index(index)
        495 if dtype is not None:
        496     dtype = self._validate_dtype(dtype)
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/pandas/core/indexes/base.py:7715, in ensure_index(index_like, copy)
       7713         return Index(index_like, copy=copy, tupleize_cols=False)
       7714 else:
    -> 7715     return Index(index_like, copy=copy)
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/pandas/core/indexes/base.py:529, in Index.__new__(cls, data, dtype, copy, name, tupleize_cols)
        527     raise cls._raise_scalar_data_error(data)
        528 elif hasattr(data, "__array__"):
    --> 529     return cls(np.asarray(data), dtype=dtype, copy=copy, name=name)
        530 elif not is_list_like(data) and not isinstance(data, memoryview):
        531     # 2022-11-16 the memoryview check is only necessary on some CI
        532     #  builds, not clear why
        533     raise cls._raise_scalar_data_error(data)
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/dask/dataframe/dask_expr/_collection.py:460, in FrameBase.__array__(self, dtype, **kwargs)
        459 def __array__(self, dtype=None, **kwargs):
    --> 460     return np.array(self.compute())
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/spatialdata/models/_accessor.py:72, in wrap_method_with_attrs.<locals>.wrapper(self, *args, **kwargs)
         64     raise RuntimeError(
         65         "Invalid .attrs: expected an accessor (`AttrsAccessor`), "
         66         f"got {type(self.attrs).__name__}. A common cause is assigning a dict, e.g. "
         67         "my_dd_object.attrs = {...}. Do not assign to 'attrs'; use "
         68         "my_dd_object.attrs.update(...) instead."
         69     )
         71 old_attrs = self.attrs.copy()
    ---> 72 result = original_method(self, *args, **kwargs)
         73 # the pandas Index do not have attrs, but dd.Index, since they are a subclass of dd.Series, do have attrs
         74 # thanks to our accessor. Here we ensure that we do not assign attrs to pd.Index objects.
         75 if hasattr(result, "attrs"):
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/dask/base.py:377, in DaskMethodsMixin.compute(self, **kwargs)
        353 def compute(self, **kwargs):
        354     """Compute this dask collection
        355 
        356     This turns a lazy Dask collection into its in-memory equivalent.
       (...)    375     dask.compute
        376     """
    --> 377     (result,) = compute(self, traverse=False, **kwargs)
        378     return result
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/dask/base.py:685, in compute(traverse, optimize_graph, scheduler, get, *args, **kwargs)
        682     expr = expr.optimize()
        683     keys = list(flatten(expr.__dask_keys__()))
    --> 685     results = schedule(expr, keys, **kwargs)
        687 return repack(results)
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/dask/dataframe/dask_expr/_expr.py:1957, in assign(df, *pairs)
       1955         if isinstance(val, Callable):
       1956             val = val(df)
    -> 1957         df[name] = val
       1958 return df
    
    File ~/Documents/python_virtual_environments/py3env_spatialAnalysis_20260508/lib/python3.14/site-packages/pandas/core/indexes/base.py:4436, in Index.reindex(self, target, method, level, limit, tolerance)
       4433     raise ValueError("cannot handle a non-unique multi-index!")
       4434 elif not self.is_unique:
       4435     # GH#42568
    -> 4436     raise ValueError("cannot reindex on an axis with duplicate labels")
       4437 else:
       4438     indexer, _ = self.get_indexer_non_unique(target)
    
    ValueError: cannot reindex on an axis with duplicate labels
    
    dask==2026.1.1
    dask-image==2025.11.0
    multiscale_spatial_image==2.0.3
    napari-spatialdata==0.7.1
    spatial_image==1.2.3
    spatialdata==0.7.3
    spatialdata-io==0.7.0
    spatialdata-plot==0.3.3
    xarray-spatial==0.9.9
    

    Thank you for your help and effort!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions