Plotly is Super Slow When Visualizing Volume Slices in Python

Hi! I am new to Plotly. I have been trying to replicate creating a plotly animation with slider that cycles through MRI cross-sections of a human brain (Visualizing mri volume slices in Python). However, I am using my own data which is a nifti file containing the CT scan of the lung s of a mouse. Running the code does not display any errors. However, Jupiter Notebook takes a long time when I run the line of code that starts with “fig.add_trace(go.Surface…” and the line of code that starts with “fig.update_layout…” and at the end when I run “fig.show()” no visualization or error is displayed. Can anyone help me know what is going on? Is there something I am missing or doing wrong? Your help will be highly appreciate it.

I am working with a nifti file which has 267 slices.


import time
import numpy as np
from skimage import io
import plotly.graph_objects as go

# Loading Data and transposing
vol = io.imread("data/B6-0355_406_Day_21_095951/nifti/lung_test.nii")
volume = vol.T # The .T tranposes the numpy array to make it easy to get x and y coords
r, c = volume[0].shape #(512, 277)

# Define frames
nb_frames = 267

fig = go.Figure(frames=[go.Frame(data=go.Surface(
   z=(26.6 - k * 0.1) * np.ones((r, c)),
   surfacecolor=np.flipud(volume[266 - k]),
   cmin=0, cmax=200
   ),
   name=str(k) # you need to name the frame for the animation to behave properly
   )
   for k in range(nb_frames)])

# Add data to be displayed before animation starts
fig.add_trace(go.Surface(
   z=26.6 * np.ones((r, c)),
   surfacecolor=np.flipud(volume[266]),
   colorscale='Gray',
   cmin=0, cmax=200,
   colorbar=dict(thickness=20, ticklen=4)
   ))

# Define frames
import plotly.graph_objects as go
nb_frames = 68

fig = go.Figure(frames=[go.Frame(data=go.Surface(
   z=(6.7 - k * 0.1) * np.ones((r, c)),
   surfacecolor=np.flipud(volume[67 - k]),
   cmin=0, cmax=200
   ),
   name=str(k) # you need to name the frame for the animation to behave properly
   )
   for k in range(nb_frames)])

# Add data to be displayed before animation starts
fig.add_trace(go.Surface(
   z=6.7 * np.ones((r, c)),
   surfacecolor=np.flipud(volume[67]),
   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(k),
                       "method": "animate",
                   }
                   for k, f in enumerate(fig.frames)
               ],
           }
       ]

# Layout
fig.update_layout(
        title='Slices in volumetric data',
        width=600,
        height=600,
        scene=dict(
                   zaxis=dict(range=[-0.1, 6.8], 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()

Hi, I’m wondering if this is splicing of two pieces of code. Because I noticed that you call the Figure constructor twice and assign it to the same variable.

You can print out the fig before calling fig.show(): print(fig)

This will show you the content of the figure, which might help you locate an issue (e.g. way too many data making your code slow).

@numam The example you followed to aproach your case has a particular implementation for the case with 68 MRI images . It should be removed from Plotly tutorials.
Here is a version for an arbitrary stack of MRI images: