plotly / dash-slicer

A volume slicer for Dash
https://dash.plotly.com/slicer
MIT License
24 stars 8 forks source link

Add option to display brain images in neurological orientation #43

Open surchs opened 3 years ago

surchs commented 3 years ago

Human brain MRI volumes are generally organized in the R-A-S orientation in voxel space, i.e. moving along the volume axes moves through the "real world" image in Right-Left, Anterior-Posterior, Superior-Inferior directions respectively. And if the data were not oriented as expected, nilearn offers a way to try to get them there.

To display slices from these volumes in the expected display conventions (that differ somewhat between radiologists and neurologists): , we need to flip them by 90 degrees. Here is a short example to show this:

import numpy as np
from nilearn import datasets, plotting
import nibabel as nib
import matplotlib.pyplot as plt

# Get the commonly used MNI152 brain template
mni152 = datasets.fetch_icbm152_2009()
print(mni152.description.decode())

# Load the Nibabel image object
# And the volume as a numpy array
mni152_t1_img = nib.load(mni152.t1)
mni152_t1 = mni152_t1_img.get_fdata()

# Check that the data are in RAS orientation
nib.aff2axcodes(mni152_t1_img.affine)

# Display a slice
a_slice = mni152_t1[:, :, 90]
fig, axes = plt.subplots(1, 2)
axes[0].imshow(a_slice, cmap="gray")
axes[1].imshow(np.rot90(a_slice), cmap="gray")

This looks like so: image

This "flip the slice by 90 degrees before displaying" is also what nilearn does in it's plotting tools:

# Note that nilearn displays slice indices in MNI/real-world coordinates
plotting.plot_anat(mni152_t1_img)

image

Since we aren't displaying static images of single slices, I think it'd be best to allow the user to ask us to flip the slices before displaying on the dash-slicer side of things.

almarklein commented 3 years ago

This is a bit similar to the reverse_y option. Maybe we can generalize this. I wonder if it's possible (and sensible) to do the flip by configuring the axii.

almarklein commented 3 years ago

AFAICT there is no way to "just flip the x and y axii". So I think the best way to go about this is to flip the images at the server side (right before encoding it to base64). This also means that we need to take this into account in a couple of places.

Also, people adding additional traces to the figure (with the new extra_traces property) should take into account that it is flipped. But this is probably fine.

surchs commented 3 years ago

I think that would be a good solution. Would you add this as a flag for only this specific case (i.e. rotate 90 degrees) or more generally and let the users pick (e.g. let users pick the in plane rotation or pass a function that does it)?

almarklein commented 3 years ago

Good question. If we only allow a 90 degree rotation, someone else is bound to ask for a rotation of -90 at some point. A function is probably to general, since we must take the rotation into account internally.

What about an argument rotate that can be -1, 0 or 1. Together with the reverse_y, that gives 6 possible configurations, and I think, all possible configurations that people could reasonably want.

almarklein commented 3 years ago

Or maybe orientation? Or another name?

surchs commented 3 years ago

I think a keyword like pre-rotate or rotation is great. It'd be great if the acceptable values can be human readable, but as we are handling 3D volumes, maybe words like "left", or "clockwise" aren't super intuitive? I guess we could just say in the docstring: "allows in-plane rotations by 90 degrees, either clockwise or counterclockwise" would be pretty straightforward. What do you think?

almarklein commented 3 years ago

Well, this orientation is in the 2D plane, so words like that should be fine. So one of:

@emmanuelle opinions?