{ "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 }