体积数据中的Plotly离线切片

时间:2018-06-18 18:53:56

标签: python plotly

我尝试按照"Visualizing MRI Volume Slices"示例进行绘图,但是在离线模式下。我运行的代码与示例中的代码相同,但我做了一些更改以避免使用网格,因为这些代码仅适用于在线图。每当我运行脚本时,我都会得到一个带滑块和所有内容的交互式网格,但是图表是空的(没有MRI切片或任何东西)。我已经验证MRI数据正在被正确下载和格式化。这是我的完整源代码:

import plotly
import plotly.plotly  as py
from plotly.grid_objs import Grid, Column
import numpy as np
from skimage import io
import time

vol = io.imread("https://s3.amazonaws.com/assets.datacamp.com/blog_assets/attention-mri.tif")
volume = vol.T
r, c = volume[0].shape

# Set the color scale

pl_bone = [
    [0.0, 'rgb(0, 0, 0)'],
    [0.05, 'rgb(10, 10, 14)'],
    [0.1, 'rgb(21, 21, 30)'],
    [0.15, 'rgb(33, 33, 46)'],
    [0.2, 'rgb(44, 44, 62)'],
    [0.25, 'rgb(56, 55, 77)'],
    [0.3, 'rgb(66, 66, 92)'],
    [0.35, 'rgb(77, 77, 108)'],
    [0.4, 'rgb(89, 92, 121)'],
    [0.45, 'rgb(100, 107, 132)'],
    [0.5, 'rgb(112, 123, 143)'],
    [0.55, 'rgb(122, 137, 154)'],
    [0.6, 'rgb(133, 153, 165)'],
    [0.65, 'rgb(145, 169, 177)'],
    [0.7, 'rgb(156, 184, 188)'],
    [0.75, 'rgb(168, 199, 199)'],
    [0.8, 'rgb(185, 210, 210)'],
    [0.85, 'rgb(203, 221, 221)'],
    [0.9, 'rgb(220, 233, 233)'],
    [0.95, 'rgb(238, 244, 244)'],
    [1.0, 'rgb(255, 255, 255)']
]

# Create the grid


my_columns  = []
z_source = []
surface_color_source = []
nr_frames = 68
for k in range(nr_frames):
  z_source.append((6.7 - k * 0.1) * np.ones((r, c)))
  surface_color_source.append(np.flipud(volume[67 - k]))

# Create the chart

data=[
    dict(
        type='surface',
        zsrc=z_source[0],
        surfacecolorsrc=surface_color_source[0],
        colorscale=pl_bone,
        colorbar=dict(thickness=20, ticklen=4)
    )
]

frames=[]
for k in range(nr_frames):
    frames.append(
        dict(
            data=[dict(zsrc=z_source[k], surfacecolorsrc=surface_color_source[k])],
            name='frame{}'.format(k + 1)
        )
    )

sliders=[
    dict(
        steps=[dict(method='animate',
                    args= [['frame{}'.format(k + 1)],
                            dict(mode='immediate',
                                 frame= dict(duration=70, redraw= False),
                                 transition=dict(duration=0))],
                    label='{:d}'.format(k+1)) for k in range(68)],
        transition= dict(duration=0),
        x=0,
        y=0,
        currentvalue=dict(font=dict(size=12),
                          prefix='slice: ',
                          visible=True,
                          xanchor='center'
                         ),
        len=1.0
    )
]

axis3d = dict(
    showbackground=True,
    backgroundcolor="rgb(230, 230,230)",
    gridcolor="rgb(255, 255, 255)",
    zerolinecolor="rgb(255, 255, 255)",
)

layout3d = dict(
         title='Slices in volumetric data',
         font=dict(family='Balto'),
         width=600,
         height=600,
         scene=dict(xaxis=(axis3d),
                    yaxis=(axis3d),
                    zaxis=dict(axis3d, **dict(range=[-0.1, 6.8], autorange=False)),
                    aspectratio=dict(x=1, y=1, z=1),
                    ),
         updatemenus=[
             dict(type='buttons',
                  showactive=False,
                  y=1,
                  x=1.3,
                  xanchor='right',
                  yanchor='top',
                  pad=dict(t=0, r=10),
                  buttons=[dict(label='Play',
                                method='animate',
                                args=[
                                    None,
                                    dict(frame=dict(duration=70, redraw=False),
                                         transition=dict(duration=0),
                                         fromcurrent=True,
                                         mode='immediate')
                                ])])
         ],
        sliders=sliders
)


fig=dict(data=data, layout=layout3d, frames=frames)
plotly.offline.plot(fig)

1 个答案:

答案 0 :(得分:0)

我简化了您的代码以显示可能的错误:

import os
import pickle
import plotly
import numpy as np
from skimage import io

filename = 'data.pickle' 
url = ('https://s3.amazonaws.com/assets.datacamp.com/blog_assets/'
       'attention-mri.tif')
if not os.path.exists(filename):
    vol = io.imread(url)    
    with open(filename, 'wb') as f:
        pickle.dump(vol, f)
else:
    with open(filename, 'rb') as f:
        vol = pickle.load(f)
volume = vol.T
r, c = volume[0].shape

# Set the color scale

pl_bone = [
    [0.0, 'rgb(0, 0, 0)'],
    [0.05, 'rgb(10, 10, 14)'],
    [0.1, 'rgb(21, 21, 30)'],
    [0.15, 'rgb(33, 33, 46)'],
    [0.2, 'rgb(44, 44, 62)'],
    [0.25, 'rgb(56, 55, 77)'],
    [0.3, 'rgb(66, 66, 92)'],
    [0.35, 'rgb(77, 77, 108)'],
    [0.4, 'rgb(89, 92, 121)'],
    [0.45, 'rgb(100, 107, 132)'],
    [0.5, 'rgb(112, 123, 143)'],
    [0.55, 'rgb(122, 137, 154)'],
    [0.6, 'rgb(133, 153, 165)'],
    [0.65, 'rgb(145, 169, 177)'],
    [0.7, 'rgb(156, 184, 188)'],
    [0.75, 'rgb(168, 199, 199)'],
    [0.8, 'rgb(185, 210, 210)'],
    [0.85, 'rgb(203, 221, 221)'],
    [0.9, 'rgb(220, 233, 233)'],
    [0.95, 'rgb(238, 244, 244)'],
    [1.0, 'rgb(255, 255, 255)']
]

# Create the grid
my_columns  = []
z_source = []
surface_color_source = []
nr_frames = 68
for k in range(nr_frames):
  z_source.append((6.7 - k * 0.1) * np.ones((r, c)))
  surface_color_source.append(np.flipud(volume[67 - k]))

# Create the chart

data=[
    dict(
        type='surface',
        zsrc=z_source[0],
        surfacecolorsrc=surface_color_source[0],
        colorscale=pl_bone,
        colorbar=dict(thickness=20, ticklen=4)
    )
]

fig=dict(data=data)
plotly.offline.plot(fig)

这将导致以下错误:

plotly.offline.plot(fig)

PlotlyError: Invalid 'figure_or_data' argument. Plotly will not be able to properly parse the resulting JSON. If you want to send this 'figure_or_data' to Plotly anyway (not recommended), you can set 'validate=False' as a plot option.
Here's why you're seeing this error:

zsrc does not have an `id` property. [[6.7 6.7 6.7 ... 6.7 6.7 6.7]
 [6.7 6.7 6.7 ... 6.7 6.7 6.7]
 [6.7 6.7 6.7 ... 6.7 6.7 6.7]
 ...
 [6.7 6.7 6.7 ... 6.7 6.7 6.7]
 [6.7 6.7 6.7 ... 6.7 6.7 6.7]
 [6.7 6.7 6.7 ... 6.7 6.7 6.7]] needs to be assigned to either an object with an `id` (like a plotly.grid_objs.Column) or a string. The `id` is a unique identifier assigned by the Plotly webserver to this grid column.

也许在消化fig=dict(data=data, layout=layout3d, frames=frames)时阴谋认为它是'validate = False'情况,因此什么也没画。