How to change axes direction to ImageJ standard
ghianda opened this issue · 3 comments
Hi
i use this package for simple cardiac stack visualization. i'm writing a 3d analysis script for orientation and volumetric estimation of cardiac cells.
The issue is the rotation and the direction of the axes.
I explain it with an example:
I have a stack with M images if NxN pixels. If i plot one slice with Imagej (or matplotlib.imshow) i see correct orientation, when i create a Nibabel image with
my_stack_nib = nib.Nifti1Image(my_stack, affine) # with affine = numpy.eye(4) from your example
and plot it with
widget = niwidgets.NiftiWidget(my_stack_nib)
widget.nifti_plotter()
i see :
- the xy plane rotated by 90' clockwise.
- the z and y axex inverted respect to numpy stack information ( z = 0 on bottom and z = zmax in up, y = 0 in bottom and y = ymax in up).
To fix it , i tried to change
nifti_plotter(plotting_func=...)
i tried numpy.rotate on xy plan (OK) and flip on z axe (but this breaks correct reference from data to plot)
i tried to change affine matrix, but it seems not to works.
I search only a simple way to change axes direction without corrupt my data, please someone can help me?
thanks a lot
Dr. Francesco Giardini, LENS, Florence
Hi Francesco,
good points to raise. I think this is some hard-coded transformations in this package to move the data from the standard neuroimaging storage format to the standard way to display that data.
This happens on this line:
https://github.com/nipy/niwidgets/blob/master/niwidgets/niwidget_volume.py#L194
You could simply change that line to:
imh.set_data(
data[slice_obj]
)
This would make your widget plot exactly the data in the array you describe, with no transformations.
However, I'm not particularly satisfied with that solution. I might add some controls in the widget or some keyword arguments to the plotting functions to fix this.
Let me know if that solution works for you.
Hi Jan!
thanks a lot for your quick reply!
I try you solutions, but it not works.. i make some screenshots for you:
-
My Numpy nd array saved in tiff and open by ImageJ (FIJI) (first slice, z = 0)
-
same array plotted with matplotlib.imshow (first slice, z = 0)
-
Nibabel image created from same array (data) and plotted with nifti_plotter
code:
affine = np.eye(4)
data_nii = nib.Nifti1Image(data, affine)
widget = NiftiWidget(data_nii)
widget.nifti_plotter()
I tried to modify affine matrix for create a rotation matrix that resolves the problem, but this not works.. this is my code, i not understand where is my error
Affine matrix for rotate volume
https://scipython.com/book/chapter-6-numpy/examples/creating-a-rotation-matrix-in-numpy/
rot_xy_90 = np.array([[0, 1, 0], [-1, 0, 0], [0, 0, 1]])
trasl = np.array([[0], [0], [0]])
affine = np.vstack((np.hstack((rot_xy_90, trasl)), np.array([0, 0, 0, 1])))
data_nii_rotated = nib.Nifti1Image(data, affine)
Thank You very much for you support, have a nice day
Francesco
Hi Jan
This is the little code:
def _select_ImageJ_trasformations(self, data, slice_obj, views, ii):
if views[ii] == views[0]:
return np.rot90(data[slice_obj], k=1) # coronal
elif views[ii] == views[1]:
return np.fliplr(np.rot90(data[slice_obj])) # sagittal
else:
return np.flipud(data[slice_obj]) # axial
and inside _plot_slices function:
views = ['Coronal XZ', 'Sagittal YZ', 'Axial XY']
[...]
imh.set_data(
# original
# np.flipud(np.rot90(data[slice_obj], k=1))
# if views[ii] != views[0] else
# np.fliplr(np.flipud(np.rot90(data[slice_obj], k=1)))
# modified
self._select_ImageJ_trasformations(data, slice_obj, views, ii)
)
i'm not able to solve Sagittal views, i'm not understand how you create orthogonal views:
Another probem is axes direction:
z low fiji:
i think this is little harder to solve ;)
Thanks for you help and sorry for my bad english
Francesco