Hi all,
I am trying to visualize slices in a 3d volume similar to the MRI example.
I was able to alter the code such that also vertical slices can be displayed and added a second slider for those slices.
The point where Iām getting stuck is that when a horizontal slice is shown, the vertical one disappears and vice versa. If anyone has an Idea how to display a horizontal and a vertical slide at the same time (e.g. using two separate traces), your help would be very much appreciated.
Here is the modified MRI example as far a I got:
# Import data
import time
import numpy as np
from skimage import io
vol = io.imread("https://s3.amazonaws.com/assets.datacamp.com/blog_assets/attention-mri.tif")
volume = vol.T
nz,ny,nx = volume.shape
print('volume dimensions:', nz, ny, nx)
x = np.linspace(0,nx*0.1, nx)
y = np.linspace(0,ny*0.1, ny)
z = np.linspace(0,nz*0.1, nz)
# Define frames
import plotly.graph_objects as go
nb_frames = nz
# add z-frames
X, Y = np.meshgrid(x,y)
zFrames = [go.Frame(data=go.Surface(
x=X, y=Y, z=(6.7 - k * 0.1) * np.ones((ny, nz)),
surfacecolor=np.flipud(volume[nz-1 - k,:,:]),
cmin=0, cmax=200
),
name=str(k)
)
for k in range(nb_frames)]
# add y-frames
X, Z = np.meshgrid(x,z)
yFrames = [go.Frame(data=go.Surface(
x=X, y = (18.9 - k * 0.1) * np.ones((nz, nx)), z=Z,
surfacecolor=volume[:, ny-1 - k, :],
cmin=0, cmax=200,
name='ySlices'
),
name=str(k+nz)
)
for k in range(ny)]
frames = zFrames + yFrames
fig = go.Figure(frames = frames)
# Add data to be displayed before animation starts
# z-plane
X, Y = np.meshgrid(x,y)
fig.add_trace(go.Surface(
x=X, y=Y, z=6.7 * np.ones((ny, nx)),
surfacecolor=np.flipud(volume[nz-1,:,:]),
colorscale='Gray',
cmin=0, cmax=200,
colorbar=dict(thickness=20, ticklen=4)
))
# y-plane
#fig.add_trace(go.Surface(
# z=18.9 * np.ones((nz, nx)),
# surfacecolor=np.flipud(volume[:,ny-1,:]),
# colorscale='Gray',
# cmin=0, cmax=200,
# colorbar=dict(thickness=20, ticklen=4)
# ))
def frame_args(duration):
return {
"frame": {"duration": duration},
"mode": "immediate",
"fromcurrent": True,
"transition": {"duration": duration, "easing": "linear"},
}
sliders = [
{
"pad": {"b": 10, "t": 60},
"len": 0.9,
"x": 0.1,
"y": 0,
"steps": [
{
"args": [[f.name], frame_args(0)],
"label": str(iz),
"method": "animate",
}
for iz, f in enumerate(fig.frames[:nz])
],
},
{
"pad": {"b": 10, "t": 60},
"len": 0.9,
"x": 0.1,
"y": 0.2,
"steps": [
{
"args": [[f.name], frame_args(0)],
"label": str(iy),
"method": "animate",
}
for iy, f in enumerate(fig.frames[nz:])
],
}
]
# Layout
fig.update_layout(
title='Slices in volumetric data',
width=600,
height=600,
scene=dict(
zaxis=dict(range=[-0.1, 6.8], autorange=False),
yaxis=dict(range=[-0.1, 18.9], autorange=False),
aspectratio=dict(x=1, y=1, z=1),
),
updatemenus = [
{
"buttons": [
{
"args": [None, frame_args(50)],
"label": "▶", # play symbol
"method": "animate",
},
{
"args": [[None], frame_args(0)],
"label": "◼", # pause symbol
"method": "animate",
},
],
"direction": "left",
"pad": {"r": 10, "t": 70},
"type": "buttons",
"x": 0.1,
"y": 0,
}
],
sliders=sliders
)
fig.show()