nipy/niwidgets

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:

  1. My Numpy nd array saved in tiff and open by ImageJ (FIJI) (first slice, z = 0)
    1 - imagej orthogonal views

  2. same array plotted with matplotlib.imshow (first slice, z = 0)
    2 - matplotlib_pyplot_imshow_numpy_ndarray

  3. 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()
3 - niftiwidget nifti_plotter

  1. same plot, but with niwidget_volume.py modified with your suggestion
    4 - nifti_plotter_modified

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

i finded a solutions!
risolto

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:
quasi

Another probem is axes direction:
z low fiji:
z_high

z high in fiji:
z_low

i think this is little harder to solve ;)

Thanks for you help and sorry for my bad english
Francesco