itk.image_from_simpleitk() and itk.simpleitk_from_image() convert between the
two toolkits, and the filter decorator accepts a SimpleITK image wherever it
accepts a NumPy array.
Geometry uses the order-explicit spatial keys from InsightSoftwareConsortium#6710, falling back to the
Get*() accessors. The bare 'spacing' key means (z,y,x) on an itk.Image and
(x,y,z) on a SimpleITK Image, so reading it would reverse the spacing (InsightSoftwareConsortium#6706).
SimpleITK images start at index 0, so the origin moves to the first stored
voxel and the index is carried as ITK_original_index; the inverse restores
both, keeping the pixels in the same physical location.
Supersedes InsightSoftwareConsortium#6021.
Co-Authored-By: Bradley Lowekamp <321061+blowekamp@users.noreply.github.com>
Co-Authored-By: Matt McCormick <25432+thewtex@users.noreply.github.com>
Co-Authored-By: Dzenan Zukic <1792121+dzenanz@users.noreply.github.com>
Adds
(@blowekamp), which stalled on the axis-order conflict that
has since resolved.
itk.image_from_simpleitk()anditk.simpleitk_from_image(), and teaches the filter decorator to accept a SimpleITK image wherever it accepts a NumPy array. SupersedesNo new dependency. SimpleITK is imported lazily inside the functions, so ITK builds and imports without it. The in-tree test uses a duck-typed stub and never imports SimpleITK — SimpleITK's superbuild builds ITK, so a test requiring it would close a cycle in the build graph, and SimpleITK is not present in ITK CI.
Why the bare
spacingkey cannot be usedimage['spacing']means (z, y, x) on anitk.Imageand (x, y, z) on a SimpleITKImage. A converter reading it from one and writing it to the other silently reverses the spacing — the conflict reported in #6706, and what blocked #6021.Geometry is therefore read through the order-explicit
spacing_xyz/origin_xyz/direction_xyzkeys from #6710, falling back toGetSpacing()/GetOrigin()/GetDirection(). Both are unambiguous.Note that SimpleITK exposes no order-explicit keys today, so the accessor fallback carries every conversion; the key path is forward-looking, and starts working by itself if SimpleITK#2531 lands. A test asserts the two bare-key conventions still disagree, so this fails loudly rather than drifting if either toolkit changes.
Concerns from #6021, and how each is resolved
GetSpacing()/GetOrigin()/GetDirection(); SimpleITK exposes methods, not dict keys. Vector images treated as scalar, geometry left at ITK defaults_spatial_from_order_explicit()tries the_xyzkey, then the accessor. Components come fromGetNumberOfComponentsPerPixel();dimfromGetDimension(), notarray.ndimITK_original_indexand restored by the inverse. SimpleITK images always start at 0, so it cannot be represented directlyImageRegion.m_Indexas metadataMetadata: every key is copied in both directions, and
ITK_-prefixed entries are guaranteed to survive — a conversion failure on one of those raises rather than being silently dropped.Testing
macOS 15 arm64, Release.
PythonSimpleITKProtocolTest— Passed via ctest against this commit. Runs with SimpleITK present and with it blocked, confirming no hard dependency.extras.py/helpers.py. Causes are a broken VTK@rpathand a wrapping predating002eebce7c4, neither related to this change.pre-commit run --all-filespasses on the branch tip.Not validated on Linux or Windows.