Redesign batch construction and schema - #1501
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
📖 Docs PreviewPreview of the documentation for this PR: 🔗 https://smokeshow.helpmanual.io/4m5h0u6o3q4814110637/ Built from a40aeac |
There was a problem hiding this comment.
Pull request overview
This PR refactors TorchIO’s batching internals to support lossless batch construction (via private per-element prototypes) and centralized schema validation for images/subjects, while also introducing explicit annotation handling (Points/BoundingBoxes) and guarding spatial transforms from silently producing stale annotations.
Changes:
- Add
ImagesBatch.from_tensor()and reworkImagesBatch.from_images()/SubjectsBatch.from_subjects()to use validated schemas and per-element prototypes for round-tripping payload. - Expose
ImagesBatch.image_class/ImagesBatch.is_labeland update transforms to use these public APIs instead of private fields. - Preserve and move annotation payload (and their affines) on
.to(), and reject spatial transforms when annotations are present (until spatial annotation support exists), with expanded test coverage.
Reviewed changes
Copilot reviewed 25 out of 25 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/test_transforms_base.py | Updates subject fixtures used by transform base tests to include both scalar and label images. |
| tests/test_device.py | Adds tests ensuring .to() moves annotation affines and image-attached annotations. |
| tests/test_batch.py | Adds extensive tests for new batch factories, schema validation, and annotation/metadata round-trips. |
| src/torchio/transforms/transform.py | Adds annotation detection + spatial rejection guard; switches intensity filtering to public image_class. |
| src/torchio/transforms/spatial/spatial.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/spatial/resize.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/spatial/crop_or_pad.py | Ensures annotation guard is applied on the lazy Subject/Image path. |
| src/torchio/transforms/spatial/anisotropy.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/lambda_transform.py | Uses public image_class when deciding applicability. |
| src/torchio/transforms/label/sequential_labels.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/label/remove_labels.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/label/remap_labels.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/label/one_hot.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/label/keep_largest.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/label/contour.py | Replaces private image-class checks with img_batch.is_label. |
| src/torchio/transforms/intensity/swap.py | Uses img_batch.is_label for label-map warning detection. |
| src/torchio/transforms/intensity/standardize.py | Uses mask_batch.is_label for label-mask validation. |
| src/torchio/transforms/intensity/normalize.py | Uses mask_batch.is_label for label-mask validation. |
| src/torchio/transforms/intensity/mask.py | Uses mask_batch.is_label for label-mask validation. |
| src/torchio/transforms/intensity/labels_to_image.py | Uses img_batch.is_label for auto-detecting label batches. |
| src/torchio/data/points.py | Extends Points.to() to also move/cast the stored affine. |
| src/torchio/data/image.py | Extends Image.to() to move/cast attached points and bounding boxes. |
| src/torchio/data/bboxes.py | Extends BoundingBoxes.to() to also move/cast the stored affine. |
| src/torchio/data/batch.py | Major batch redesign: factories, prototypes, subject field stores, schema validation, annotation support. |
| src/torchio/data/batch_schema.py | New schema module centralizing compatibility checks for subjects/images/annotations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 25 out of 25 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
src/torchio/data/batch.py:214
ImagesBatch.from_images()stores each source image'sapplied_transformsin the private prototypes (_make_image_prototype), butImagesBatch.__getitem__overwritesimage.applied_transformswith only the batch-level history. This drops any transform history that existed on the original images, so a lossless round-trip throughfrom_images(...).unbatch()will not preserveapplied_transformsas intended.
)
image._metadata = _copy.deepcopy(prototype.metadata)
image.applied_transforms = [
*prototype.applied_transforms,
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: baf5f11a-f67c-44dc-804e-6be849fa9160
[Generated by a coding agent]
What
Redesign batch construction around lossless factories, mandatory private image prototypes, and typed subject/image schemas.
Why
The previous implementation had optional template state, exposed private image-class fields to transforms, silently dropped metadata/annotations, and derived batch structure incidentally from the first image. Batching should have one reconstruction path and one explicit schema invariant.
How
ImagesBatch.from_tensor()and losslessfrom_images()image_classandis_labelinstead of_image_classbatch_schema.pyValidation
Replacement stack