ENH: Reimplement GDCMSeriesFileNames on gdcm::IPPSorter/Scanner (drop deprecated SerieHelper) - #6469
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
19dc745 to
0e85890
Compare
|
@malaterre I have been looking at removing the "SerieHelper" dependency that is only kept around for ITK (according to the GDCM comments for SerieHelper). Your insights into the implications of the proposed change would be helpful. |
…twareConsortium#6467) Pin the observable contract of itk::GDCMSeriesFileNames before migrating its backend off the deprecated gdcm::SerieHelper onto gdcm::Scanner + gdcm::IPPSorter: single-series enumeration / grouping, geometric ordering that reconstructs a valid uniformly-spaced volume, GetInputFileNames returning the first series, and the Recursive flag controlling descent (which must be set before SetInputDirectory triggers the scan). These tests are backend-agnostic and must remain green across the swap.
Replace the deprecated gdcm::SerieHelper backend ("DO NOT USE ... temporary
solution for ITK migration from GDCM 1.x to 2.x") with the supported modern
API: gdcm::Directory for enumeration, gdcm::Scanner for series grouping, and
gdcm::IPPSorter for geometric (ImagePositionPatient on the slice normal)
ordering.
Behavior preserved on the in-tree suite (all 89 ITKIOGDCM tests pass,
including the series-reader and direction-cosine tests) and pinned by the
GDCMSeriesFileNames characterization tests added in the previous commit:
single-series enumeration / grouping, geometric ordering, GetInputFileNames
returning the first series, Recursive descent.
Intentional behavior changes:
- IPPSorter is strict: duplicate-IPP and gantry-tilt acquisitions FAIL to
sort; the input order is then left unchanged rather than fabricated.
Whether these need first-class support (and whether SerieHelper's permissive
strategy was correct) is tracked for discussion in InsightSoftwareConsortium#6468.
- AddSeriesRestriction now refines the series identifier (the documented and
example intent, e.g. "0008|0021"), instead of delegating to SerieHelper's
largely-inert file restriction list.
Part of InsightSoftwareConsortium#6467.
0e85890 to
50dfb13
Compare
|
@greptileai re: the P2 "LoadSequences/LoadPrivateTags are silently dead" (outside-diff comment) — addressed in |
|
Thanks for the pointer to
Documenting them as intentional no-ops rather than either silently dropping behavior or fabricating emulation is the right call. The |
thewtex
left a comment
There was a problem hiding this comment.
LGTM but it would be good to get @malaterre 's review.
There may be additional SerieHelper tests in GDCM to port, check for behavior changes, and augment our interface to reduce changes in behavior.
gdcm::IPPSorter failure now throws by default (FailOnAmbiguousOrdering, default true). When disabled, the legacy SerieHelper heuristics apply for determinism and backward compatibility: Instance Number (0020,0013, read by the existing scan) when unique, else lexicographic filename order. Series are ordered lazily per request, so enumerating a directory that contains an unsortable series does not throw. Addresses PR InsightSoftwareConsortium#6469 review feedback from thewtex.
Scan Rows (0028,0010) unconditionally and skip files lacking it (SR, RTSTRUCT, DICOMDIR, presentation states), restoring SerieHelper's ImageReader-based image-only acceptance. Addresses PR InsightSoftwareConsortium#6469 review feedback from thewtex.
A directory holding an image series plus an SR-like object (same SeriesInstanceUID, no Rows/PixelData), a DICOMDIR-like object (no SeriesInstanceUID), and a non-DICOM text file must enumerate exactly one series with only the image slices, and still reconstruct a valid volume. Addresses PR InsightSoftwareConsortium#6469 review feedback from thewtex.
|
Thanks @thewtex! I checked upstream GDCM for portable Short answer on tests: GDCM's Behavior deltas found by diffing Ordering fallback chain (7cb3bbe)
Non-image DICOM objects (debb566)
New contract tests (7cb3bbe, debb566, 04c142f)Four new GTests pin the behaviors above: duplicate-IPP series throws by default and enumeration doesn't; Migration guide and class docs updated to match. Update: the interface-ordering hazard ( Update 2: |
SetUseSeriesDetails(true) cleared previously added restriction tags. Keep user tags (m_UserRefineTags) separate from the constant default detail tags; SetUseSeriesDetails now only toggles whether both are applied, matching SerieHelper's append-only Refine list. Addresses PR InsightSoftwareConsortium#6469 review feedback from thewtex.
The class documentation has always presented SetUseSeriesDetails(true) as an explicit opt-in for splitting multi-volume series. The previous backend behaved accordingly (detail tags were seeded only by that call) while GetUseSeriesDetails() misreported true. Default the flag to false so behavior and reporting match the documentation and DICOM series identity: series group by raw SeriesInstanceUID (0020,000e) and GetFileNames(<raw UID>) matches out of the box. Addresses PR InsightSoftwareConsortium#6469 review feedback from thewtex.
|
@thewtex requesting a re-review: your review prompted follow-up commits that go a bit beyond the original scope — the deltas are summarized in the comment above. In short: ambiguous slice ordering now throws by default ( |
thewtex
left a comment
There was a problem hiding this comment.
Thanks, Hans. These details are tricky. I am glad the further analysis / updates were made.
|
@hjmjohnson If I set FailOnAmbiguousOrdering=false (in order for my app to continue opening files I've thus far supported) is there any way to know if the fallback was actually used? That would allow me to maintain backwards compatibility, but show a message to the user telling them the DICOM files are suspect. |
Here's my patch for that: #6766 |
Reimplement
itk::GDCMSeriesFileNameson the supported modern GDCM API (gdcm::Directory+gdcm::Scanner+gdcm::IPPSorter), dropping the deprecatedgdcm::SerieHelper. Part of #6467.Why
gdcm::SerieHelperis documented by GDCM as deprecated backward-compat code — "DO NOT USE this class, it is only a temporary solution for ITK migration from GDCM 1.x to GDCM 2.x … Instead see ImageHelper or IPPSorter." This PR movesGDCMSeriesFileNamesto the supported API.What changed
gdcm::Directory(enumerate, honoring Recursive) →gdcm::Scanner(group by SeriesInstanceUID + detail tags; the series identifier replicatesSerieHelper::CreateUniqueSeriesIdentifier) →gdcm::IPPSorter(geometric ImagePositionPatient-on-normal ordering, applied lazily per requested series). Lazy parse with aTimeStampcache, so repeatedGetSeriesUIDs/GetFileNames/GetInputFileNamescalls no longer re-scan.(0028,0010)is scanned unconditionally and files lacking it (SR, RTSTRUCT, DICOMDIR, presentation states) are skipped, matching SerieHelper'sImageReader-based image-only acceptance.GetInputFileNamesreturns the first series, Recursive descent. Green on both backends. Follow-on commits add contract tests for ambiguous-ordering failure, the legacy fallbacks, and mixed-content directories.Intentional behavior changes
FailOnAmbiguousOrderingflag (defaulttrue) throws an exception in that case. Setting itfalseopts into the legacy SerieHelper heuristics — Instance Number(0020,0013)when unique, else lexicographic filename order — retained only for determinism and backward compatibility; the fallback is not DICOM-standards conforming and its output should not be trusted. Enumeration (GetSeriesUIDs) never orders, so it never throws. First-class support for these acquisitions is tracked in Discussion: GDCMSeriesFileNames ordering edge cases (duplicate IPP, gantry tilt) and whether SerieHelper's permissive strategy is correct #6468.AddSeriesRestrictionnow refines the series identifier (the documented and example intent, e.g."0008|0021"), instead of delegating to SerieHelper's largely-inert file-restriction list.Testing
All 92 ITKIOGDCM tests pass locally (series-reader, direction-cosine, compliance suites), including 7 contract GTests (ambiguous-ordering throw, Instance-Number/lexicographic fallbacks, non-image exclusion, mixed-content directory). Downstream
GDCMSeriesFileNamesconsumers (itkAccumulateImageFilterTest,itkGetAverageSliceImageFilterTest,itkImageSeriesWriterTest) pass.pre-commit run --all-filesclean. The vendoredgdcm::SerieHelperis untouched (still used by GDCM's own code); a follow-up may remove it once upstream GDCM drops it.