-
Notifications
You must be signed in to change notification settings - Fork 75
Transfert functions for reorient #1295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
frheault
wants to merge
35
commits into
scilus:dev_3.0.x
Choose a base branch
from
frheault:fix_init_strides
base: dev_3.0.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,058
−140
Open
Changes from 26 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
3a30883
Add maximum operation in volume_math
CHrlS98 40bbc7a
Merge branch 'master' into volume-operation
CHrlS98 e83596a
Transfert functions for reorient
frheault c55dd1b
Add pathspec==0.12.* to dependencies
arnaudbore 0588741
Update paper figures with better resolution
EmmaRenauld d2558c1
Merge branch 'master' into volume-operation
CHrlS98 b4555cc
Merge pull request #1296 from EmmaRenauld/update_figs
arnaudbore 30304ea
Small fix in checking files in explore_bundleseg
EmmaRenauld 5bcba00
Option -v did nothing in compute_density_map. Added loggings
EmmaRenauld ecc0388
Verify dir exists in bundleseg
EmmaRenauld f950a6f
Value args.tractogram_clustering_thr was never used in recobundles
EmmaRenauld c6a8a5e
Merge pull request #1293 from CHrlS98/volume-operation
arnaudbore ff44804
Merge pull request #1297 from EmmaRenauld/small_changes_from_my_tests
arnaudbore 97b440b
Merge branch 'master' of https://github.com/scilus/scilpy into fix_in…
frheault 60e5dbb
Conversion to to state class
frheault dc30357
New attribtutes
frheault d4485fe
Fix tests 3.12
frheault bda03f4
fix install and tests
arnaudbore 0ba0902
Merge pull request #1299 from arnaudbore/fix_test_
arnaudbore c7c26d2
Merge branch 'master' of https://github.com/scilus/scilpy into fix_in…
frheault c260249
Added basic tests to verify SFI behaves normally
frheault efd61de
Improved tests
frheault 7eb3311
Additionnal tests and flake8
frheault a23efeb
Update src/scilpy/io/tests/test_stateful_image.py
frheault 9d420b9
Update src/scilpy/io/tests/test_stateful_image.py
frheault 917901e
Copilot comments
frheault a6c4fae
Remove hasattr check
frheault 26e4ff5
Incorporation to scripts
frheault cc1ff82
Fix conflict
frheault 262c527
Fix conflict
frheault 52d5617
allequal to allclose
frheault 44e4d3a
New voxels order modification script
frheault efbd0a8
feat: Add 4D support for voxel order modification
frheault 4cc1860
Fixes due to switch to static functions and changes apply_transform s…
frheault 37ae49b
Last fixes for comments and full testing with Arnaud
frheault File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,192 @@ | ||
| # -*- coding: utf-8 -*- | ||
|
|
||
| import nibabel as nib | ||
| from dipy.io.utils import get_reference_info | ||
| from scilpy.utils.orientation import validate_axcodes | ||
|
|
||
|
|
||
| class StatefulImage(nib.Nifti1Image): | ||
| """ | ||
| A class that extends nib.Nifti1Image to manage image orientation state. | ||
|
|
||
| This class ensures that image data loaded into memory is always in a | ||
| consistent orientation (RAS by default), while preserving the original | ||
| on-disk orientation information. When saving, the image is automatically | ||
| reverted to its original orientation, ensuring non-destructive operations. | ||
| """ | ||
|
|
||
| def __init__(self, dataobj, affine, header=None, extra=None, | ||
| file_map=None, original_affine=None, | ||
| original_dimensions=None, original_voxel_sizes=None, | ||
| original_axcodes=None): | ||
| """ | ||
| Initialize a StatefulImage object. | ||
|
|
||
| Extends the Nifti1Image constructor to store original orientation info. | ||
| """ | ||
| super().__init__(dataobj, affine, header, extra, file_map) | ||
|
|
||
| # Store original image information | ||
| self._original_affine = original_affine | ||
| self._original_dimensions = original_dimensions | ||
| self._original_voxel_sizes = original_voxel_sizes | ||
| self._original_axcodes = original_axcodes | ||
|
|
||
| @classmethod | ||
| def load(cls, filename, to_orientation="RAS"): | ||
| """ | ||
| Load a NIfTI image, store its original orientation, and reorient it. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| filename : str | ||
| Path to the NIfTI file. | ||
| to_orientation : str or tuple, optional | ||
| The target orientation for the in-memory data. Default is "RAS". | ||
|
|
||
| Returns | ||
| ------- | ||
| StatefulImage | ||
| An instance of StatefulImage with data in the target orientation. | ||
| """ | ||
| img = nib.load(filename) | ||
|
|
||
| original_affine = img.affine.copy() | ||
| original_axcodes = nib.orientations.aff2axcodes(img.affine) | ||
| original_dims = img.header.get_data_shape() | ||
| original_voxel_sizes = img.header.get_zooms() | ||
|
|
||
| if to_orientation: | ||
| validate_axcodes(to_orientation) | ||
| start_ornt = nib.orientations.io_orientation(img.affine) | ||
| target_ornt = nib.orientations.axcodes2ornt(to_orientation) | ||
| transform = nib.orientations.ornt_transform(start_ornt, | ||
| target_ornt) | ||
| reoriented_img = img.as_reoriented(transform) | ||
| else: | ||
| reoriented_img = img | ||
|
|
||
| return cls(reoriented_img.dataobj, reoriented_img.affine, | ||
| reoriented_img.header, original_affine=original_affine, | ||
| original_dimensions=original_dims, | ||
| original_voxel_sizes=original_voxel_sizes, | ||
| original_axcodes=original_axcodes) | ||
|
|
||
| def save(self, filename): | ||
| """ | ||
| Save the image to a file, reverting to its original orientation. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| filename : str | ||
| Path to save the NIfTI file. | ||
| """ | ||
frheault marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if not hasattr(self, "_original_axcodes") or \ | ||
frheault marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| self._original_axcodes is None: | ||
| raise ValueError( | ||
| "Unknown original orientation. Ensure the image was loaded" | ||
| "with StatefulImage.load() or that original_axcodes was" | ||
| "provided when creating the StatefulImage instance.") | ||
|
|
||
| self.reorient_to_original() | ||
| nib.save(self, filename) | ||
|
|
||
| def reorient_to_original(self): | ||
| """ | ||
| Reorient the in-memory image to its original orientation. | ||
| This method modifies the image in place. It does not return a new | ||
| Nifti1Image instance. | ||
|
|
||
| Raises | ||
| ------ | ||
| ValueError | ||
| If the original axis codes are not set. | ||
| """ | ||
frheault marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if self._original_axcodes is None: | ||
| raise ValueError( | ||
| "Original axis codes are not set cannot reorient to original" | ||
| "orientation.") | ||
| self.reorient(self._original_axcodes) | ||
|
|
||
| def reorient(self, target_axcodes): | ||
| """ | ||
| Reorient the in-memory image to a target orientation. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| target_axcodes : str or tuple | ||
| The target orientation axis codes (e.g., "LPS", ("R", "A", "S")). | ||
| """ | ||
| validate_axcodes(target_axcodes) | ||
|
|
||
| current_axcodes = nib.orientations.aff2axcodes(self.affine) | ||
| if current_axcodes == tuple(target_axcodes): | ||
| return | ||
|
|
||
| start_ornt = nib.orientations.axcodes2ornt(current_axcodes) | ||
| target_ornt = nib.orientations.axcodes2ornt(target_axcodes) | ||
| transform = nib.orientations.ornt_transform(start_ornt, target_ornt) | ||
|
|
||
| reoriented_img = self.as_reoriented(transform) | ||
| self.__init__(reoriented_img.dataobj, reoriented_img.affine, | ||
| reoriented_img.header, | ||
| original_affine=self._original_affine, | ||
| original_dimensions=self._original_dimensions, | ||
| original_voxel_sizes=self._original_voxel_sizes, | ||
| original_axcodes=self._original_axcodes) | ||
|
|
||
| def to_ras(self): | ||
| """Convenience method to reorient in-memory data to RAS.""" | ||
| self.reorient(("R", "A", "S")) | ||
|
|
||
| def to_lps(self): | ||
| """Convenience method to reorient in-memory data to LPS.""" | ||
| self.reorient(("L", "P", "S")) | ||
|
|
||
| def to_reference(self, obj): | ||
| """ | ||
| Reorient the in-memory image to match the orientation of a reference | ||
| object. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| obj : object | ||
| Reference object from which orientation information can be obtained. | ||
| Must not be an instance of ``StatefulImage``. | ||
|
|
||
| Raises | ||
| ------ | ||
| TypeError | ||
| If ``obj`` is an instance of ``StatefulImage``. | ||
| """ | ||
|
|
||
| if isinstance(obj, StatefulImage): | ||
| raise TypeError("Reference object cannot be a StatefulImage.") | ||
frheault marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| _, _, _, voxel_order = get_reference_info(obj) | ||
| self.reorient(voxel_order) | ||
|
|
||
| @property | ||
| def axcodes(self): | ||
| """Get the axis codes for the current image orientation.""" | ||
| return nib.orientations.aff2axcodes(self.affine) | ||
|
|
||
| @property | ||
| def original_axcodes(self): | ||
| """Get the axis codes for the original image orientation.""" | ||
| return self._original_axcodes | ||
|
|
||
| def __str__(self): | ||
| """Return a string representation of the image, including orientation.""" | ||
| base_str = super().__str__() | ||
| current_axcodes = self.axcodes | ||
| reoriented = current_axcodes != self._original_axcodes | ||
|
|
||
| orientation_info = ( | ||
| f"Reorientation Information:\n" | ||
| f" Original axis codes: {self._original_axcodes}\n" | ||
| f" Current axis codes: {current_axcodes}\n" | ||
| f" Reoriented from original: {reoriented}" | ||
| ) | ||
|
|
||
| return f"{base_str}\n{orientation_info}" | ||
Empty file.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.