-
Notifications
You must be signed in to change notification settings - Fork 4
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
Refactor and improve affine handling in the viewer. #7
base: main
Are you sure you want to change the base?
Conversation
reorder data axes to RAS before passing onto Napari. This avoids potential issues in affine handling: napari/napari#3410 We also now drop the non-diagonal (rotation, shear) components from the affine, since napari does not currently handle these. oi
patient left will be to the right side of the screen (radiological orientation) verified that for each dimensions, moving the slider to the right moves to S, P or L as expected, depending on the visible dimensions
Here is an example of a 3D view on 3 separate scans, each of which is a single thick slice along a particular axis through a phantom (data here)
|
Will test it on the weekend. Thanks for the effort :) |
I tested your solution with several images now and looked through your code. I realy like your approach to realighn the image origin and to discard the currently still problematic parts of the affine transformation. This is probably the best solution as long as napari does not support non orthogonal slicing. The images should be added in radiological orientation. In my tests the images are all added in the same orientation, but not in the expected. I'm not completely sure why, but I think it might be the wrong approach to direktly use the SPL orientation for the transform. I can produce the wanted outcome with: target_ornt = nibabel.orientations.axcodes2ornt(('S','P','L'))
current_ornt = nibabel.orientations.io_orientation(nifti.affine)
transform_ornt = nibabel.orientations.ornt_transform(current_ornt, target_ornt)
reoriented_fdata = nibabel.orientations.apply_orientation(nii.get_fdata(),transform_ornt)
or:
reoriented_nifti = nifti.as_reoriented(transform_ornt This works without casting to RAS before. I would further suggest to use the nibabel SpatialImage method as_closest_canonical to cast the image to RAS. Thanks for your work :) |
update reorder_axes to take a specified target orientation instead of assuming RAS Use LPS rather than SPL for now so that affine_plumb[:3, :3] will be diagonal. Once appropriate fixes for perfmuted axes have been made to napari, we can switch to SPL Co-authored-by: Christopher Nauroth-Kreß <56394171+ch-n@users.noreply.github.com>
Yeah, I think I messed up that conversion and agree that we should convert things directly as you propose. I added a commit implementing reorientation to a target orientation, but have left this LPS rather than SPL for now until we resolve napari/napari#3410. |
use as_reoriented method as it is more concise and will also update the affine we pass on in the metadata Co-authored-by: Christopher Nauroth-Kreß <56394171+ch-n@users.noreply.github.com>
Codecov Report
@@ Coverage Diff @@
## main #7 +/- ##
==========================================
+ Coverage 83.05% 92.09% +9.04%
==========================================
Files 4 4
Lines 177 215 +38
==========================================
+ Hits 147 198 +51
+ Misses 30 17 -13
Continue to review full report at Codecov.
|
Hi. I tested the new adjustments. That aside, your solution looks good. Like this we can easily set a default orientation or even adjust the orientation later on with a gui plugin, if we like. Some suggestions to handle it more elegant then to simply flip axis 1 after orientation? This problem highly impacted my work on the saving function. I could not find a way to consitently reorient the data in the viewer back to the metadata. |
@grlee77 I'm sorry I had a misunderstanding. My last comment is majorly wrong. I revisited the code and the results and I think I understand now what goes wrong. I tried to tinker a solution starting from the RAS image, but I could not make it work in all cases. Do you have an ideas? |
This PR resorts axes to RAS order to avoid potential errors in affine slicing in Napari (see napari/napari#3410). Also, any rotation/shear elements are discarded so that the napari sliders just correspond to simple slicing of the array. This results is an affine that is diagonal in the upper left 3x3 matrix.
I then swap and flip signs to go from RAS to SPL order (as suggested in #5) so that upon initially opening the viewer, the axial view is displayed in a normal radiological orientation. I hope to revisit orientation of linked orthogonal views in napari itself in the coming months.
One issue not updated in this PR was what metadata we want to pass to the viewer. We were passing the affine and header from the NIFTI, but now this will no longer match after reordering/flip of the dimensions. I don't think we have to address that in this PR, thouth, as that metadata was passed along for convenience, but is not being used by napari itself.
@ch-n: if you get a chance to test this out, does it operate as you expect?