Skip to content

NGFF v06 transformations - #1182

Open
Tomaz-Vieira wants to merge 30 commits into
transformation_managerfrom
feature/ngff_v06_transforms
Open

Tomaz-Vieira wants to merge 30 commits into
transformation_managerfrom
feature/ngff_v06_transforms

Conversation

@Tomaz-Vieira

@Tomaz-Vieira Tomaz-Vieira commented Aug 19, 2026

Copy link
Copy Markdown
Collaborator

Mirrors Ngff* classes in the graph module, parses ome-zarr-models-py classes.

CoordSystem (based on NgffCoordinateSystem)

  • Made immutable, so we can __hash__ (needed for usage in graph, but we might still have the identity issue when searching for verts)
  • Can be marked "virtual" so that we know not to serialize it (that is, it has been created for the sake of putting it in a graph and maintaining the invariant of always having an input and output, but it should not show up in the zarr metadata)

*Edge (based on NgffTransformation)

  • All transformations always have input and output, which diverge from the raw NGFF
  • Don't do serialization to raw JSON anymore, but rather convert to and from omz-models-py classes
  • Stronger invariants; checked in __init__ and nowhere else
  • A few corner cases fixed

io_raster.py

  • Adds function to read multiscales from v06, applying the scale/translation transformations as a RangeIndex to the resulting xarrays

Next steps

Roundtripping

This PR only does input dfor now; The full roundtrip is showing some issues that would delay this further, so I've removed all output for now and will submit it in another PR

Using unorderd axes in coordinate systems

Since our arrays are labeled, we probably shouldn't be using a Sequence of axes in our coordinate systems. This will probably simplify runtime quit a lot, but might create some more work during IO

@Tomaz-Vieira
Tomaz-Vieira force-pushed the feature/ngff_v06_transforms branch from 0dfccb5 to f57dc1d Compare August 21, 2026 11:33
@codecov

codecov Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.18519% with 88 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (transformation_manager@b0ff71c). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/spatialdata/transformations/graph/edge.py 87.29% 53 Missing ⚠️
src/spatialdata/transformations/graph/vert.py 77.10% 19 Missing ⚠️
src/spatialdata/_io/io_raster.py 68.62% 16 Missing ⚠️
Additional details and impacted files
@@                    Coverage Diff                    @@
##             transformation_manager    #1182   +/-   ##
=========================================================
  Coverage                          ?   92.22%           
=========================================================
  Files                             ?       55           
  Lines                             ?     8654           
  Branches                          ?        0           
=========================================================
  Hits                              ?     7981           
  Misses                            ?      673           
  Partials                          ?        0           
Files with missing lines Coverage Δ
...ialdata/_core/transformation_manager/exceptions.py 100.00% <100.00%> (ø)
src/spatialdata/transformations/__init__.py 100.00% <100.00%> (ø)
src/spatialdata/_io/io_raster.py 85.44% <68.62%> (ø)
src/spatialdata/transformations/graph/vert.py 77.10% <77.10%> (ø)
src/spatialdata/transformations/graph/edge.py 87.29% <87.29%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread pyproject.toml Outdated
Comment thread src/spatialdata/_io/io_raster.py
Comment thread src/spatialdata/_io/io_raster.py
Comment thread src/spatialdata/_io/io_raster.py Outdated
Comment thread src/spatialdata/_io/io_raster.py
Comment thread src/spatialdata/transformations/graph/vert.py
Comment thread src/spatialdata/transformations/graph/vert.py Outdated
Comment thread src/spatialdata/transformations/graph/vert.py
Comment thread src/spatialdata/transformations/graph/vert.py Outdated
Comment thread src/spatialdata/transformations/graph/vert.py Outdated
Comment thread src/spatialdata/transformations/graph/vert.py Outdated
Comment thread src/spatialdata/transformations/graph/vert.py Outdated
Comment thread src/spatialdata/transformations/graph/vert.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment on lines +310 to +313
def __repr__(self) -> str:
s = super().__repr__() + "\n"
s += "\n".join(f" {out} <- {inp}\n" for out, inp in self.output_to_input.items())
return s

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rough edge: MapAxis is basically an affine (made of zeros and a few ones to permute the data). When we do repr on the affine we print the matrix and not the axes (which will be handled by the coordinate systems). Here we do the opposite, we print the axes and don't care about the affine.

It's not incorrect, but I see that this goes more towards the philosophy of spatialdata transformations, while the affine stays "true" to the NGFF transformations.

For clarify we could actually always print both: the "index-based/matrix representation" (in this case index 0 goes to 1, index 3 goes to 4 etc; in the affine case the matrix); and then the axes annotation (x -> y, y -> z here; in the case of affine the input and output axes, as we do when we print spatialdata Affine transformations).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'd rather avoid the indexed output since we have everything labeled (axes have names, arrays have dims), and hopefully we eventually completely hide the fact that indices have any meaning for us

Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py Outdated
Comment thread src/spatialdata/transformations/graph/edge.py
@ajkswamy
ajkswamy force-pushed the feature/ngff_v06_transforms branch from 84e3669 to 3a42bef Compare September 15, 2026 20:35
Comment thread src/spatialdata/_core/transformation_manager/exceptions.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants