{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Slice animation in a MRI volumetric data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"A volumetric data set read from a tif image is sliced, and succesive slices are displayed by Plotly animation."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'4.2.0'"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import plotly\n",
"plotly.__version__"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"from skimage import io\n",
"import plotly.graph_objects as go"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"volume = (io.imread(\"https://s3.amazonaws.com/assets.datacamp.com/blog_assets/attention-mri.tif\")).T"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"volume.shape"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"pl_bone=[[0.0, 'rgb(0, 0, 0)'],\n",
" [0.05, 'rgb(10, 10, 14)'],\n",
" [0.1, 'rgb(21, 21, 30)'],\n",
" [0.15, 'rgb(33, 33, 46)'],\n",
" [0.2, 'rgb(44, 44, 62)'],\n",
" [0.25, 'rgb(56, 55, 77)'],\n",
" [0.3, 'rgb(66, 66, 92)'],\n",
" [0.35, 'rgb(77, 77, 108)'],\n",
" [0.4, 'rgb(89, 92, 121)'],\n",
" [0.45, 'rgb(100, 107, 132)'],\n",
" [0.5, 'rgb(112, 123, 143)'],\n",
" [0.55, 'rgb(122, 137, 154)'],\n",
" [0.6, 'rgb(133, 153, 165)'],\n",
" [0.65, 'rgb(145, 169, 177)'],\n",
" [0.7, 'rgb(156, 184, 188)'],\n",
" [0.75, 'rgb(168, 199, 199)'],\n",
" [0.8, 'rgb(185, 210, 210)'],\n",
" [0.85, 'rgb(203, 221, 221)'],\n",
" [0.9, 'rgb(220, 233, 233)'],\n",
" [0.95, 'rgb(238, 244, 244)'],\n",
" [1.0, 'rgb(255, 255, 255)']]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"r, c = volume[0].shape\n",
"n_slices = volume.shape[0]\n",
"height = (volume.shape[0]-1) / 10\n",
"grid = np.linspace(0, height, n_slices)\n",
"slice_step = grid[1] - grid[0]\n",
"height"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"initial_slice = go.Surface(\n",
" z=height*np.ones((r,c)),\n",
" surfacecolor=np.flipud(volume[-1]),\n",
" colorscale=pl_bone,\n",
" showscale=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"frames = [go.Frame(data=[dict(type='surface',\n",
" z=(height-k*slice_step)*np.ones((r,c)),\n",
" surfacecolor=np.flipud(volume[-1-k]))],\n",
" name=f'frame{k+1}') for k in range(1, n_slices)]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sliders = [dict(steps = [dict(method= 'animate',\n",
" args= [[f'frame{k+1}'], \n",
" dict(mode= 'immediate',\n",
" frame= dict(duration=40, redraw= True),\n",
" transition=dict(duration= 0))\n",
" ],\n",
" label=f'{k+1}'\n",
" ) for k in range(n_slices)], \n",
" active=17,\n",
" transition= dict(duration= 0 ),\n",
" x=0, # slider starting position \n",
" y=0, \n",
" currentvalue=dict(font=dict(size=12), \n",
" prefix='slice: ', \n",
" visible=True, \n",
" xanchor= 'center'\n",
" ), \n",
" len=1.0) #slider length\n",
" ]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"layout3d = dict(title_text='Head Scanning', title_x=0.5,\n",
" width=600,\n",
" height=600,\n",
" scene_zaxis_range= [-0.1, 6.8],\n",
" sliders=sliders,\n",
" )\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig = go.Figure(data=[initial_slice], layout=layout3d, frames=frames)\n",
"from plotly.offline import download_plotlyjs, init_notebook_mode, iplot\n",
"init_notebook_mode(connected=True)\n",
"iplot(fig) #wait a few seconds until the plot is displayed"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Moving the slider to right or left we can inspect each slice."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The gif file created from the above animation:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%html\n",
""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}