{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## Slice in volumetric data, via Plotly ##" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A volume included in a parallelepiped is described by the values of a scalar field, $f(x,y,z)$, with $x\\in[a,b]$, $y\\in [c,d]$, $z\\in[e,f]$.\n", "A slice in this volume is visualized by coloring the surface of the slice, according to the values of the function f, restricted to that surface.\n", "\n", "In order to plot a planar or a nonlinear slice of equation z=s(x,y) one proceeds as follows:\n", "\n", "- define a meshgrid in x,y;\n", "- evaluate z=s(x,y)\n", "- define an instance of the Plotly Surface class, that represents the surface z=s(x,y)\n", "- this surface is colored according to the values, f(x,y,z), at its points. More precisely, the normalized values of the function f are mapped to a colormap/colorscale." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "With obvious modications we get slices of equation $x=s(y,z), y=s(z,x)$." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import plotly.graph_objects as go\n", "from IPython" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define a function that returns a slice as a Plotly Surface:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_the_slice(x,y,z, surfacecolor):\n", " return go.Surface(x=x,\n", " y=y,\n", " z=z,\n", " surfacecolor=surfacecolor,\n", " coloraxis='coloraxis')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def get_lims_colors(surfacecolor):# color limits for a slice\n", " return np.min(surfacecolor), np.max(surfacecolor)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us plot the slices z=0 and y=-0.5 in the volume defined by:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "scalar_f = lambda x,y,z: x*np.exp(-x**2-y**2-z**2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-2,2, 50)\n", "y = np.linspace(-2,2, 50)\n", "x, y = np.meshgrid(x,y)\n", "z = np.zeros(x.shape)\n", "surfcolor_z = scalar_f(x,y,z)\n", "sminz, smaxz = get_lims_colors(surfcolor_z)\n", "\n", "slice_z = get_the_slice(x, y, z, surfcolor_z)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x = np.linspace(-2,2, 50)\n", "z = np.linspace(-2,2, 50)\n", "x, z = np.meshgrid(x,y)\n", "y = -0.5 * np.ones(x.shape)\n", "surfcolor_y = scalar_f(x,y,z)\n", "sminy, smaxy = get_lims_colors(surfcolor_y)\n", "vmin = min([sminz, sminy])\n", "vmax = max([smaxz, smaxy])\n", "slice_y = get_the_slice(x, y, z, surfcolor_y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In order to be able to compare the two slices, we choose a unique interval of values to be mapped to the colorscale:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def colorax(vmin, vmax):\n", " return dict(cmin=vmin,\n", " cmax=vmax)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig1 = go.Figure(data=[slice_z, slice_y])\n", "fig1.update_layout(\n", " title_text='Slices in volumetric data', \n", " title_x=0.5,\n", " width=700,\n", " height=700,\n", " scene_zaxis_range=[-2,2], \n", " coloraxis=dict(colorscale='BrBG',\n", " colorbar_thickness=25,\n", " colorbar_len=0.75,\n", " **colorax(vmin, vmax))) \n", " \n", "#fig1.show() " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from IPython.display import IFrame \n", "IFrame('https://chart-studio.plotly.com/~empet/13862', width=700, height=700)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Oblique slice in volumetric data ###" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As an example we plot comparatively two slices: a slice through $z=0$ and an oblique planar slice, that is defined by rotating the plane z=0 by $\\alpha=\\pi/4$, about Oy." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Rotating the plane $z=c$ about Oy (from Oz towards Ox) with $\\alpha$ radians we get the plane of equation\n", "$z=c/\\cos(\\alpha)-x\\tan(\\alpha)$" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "alpha = np.pi/4\n", "x = np.linspace(-2, 2, 50)\n", "y = np.linspace(-2, 2, 50)\n", "x, y = np.meshgrid(x,y)\n", "z = -x * np.tan(alpha)\n", "\n", "surfcolor_obl = scalar_f(x,y,z)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "smino, smaxo = get_lims_colors(surfcolor_obl)\n", "vmin = min([sminz, smino])\n", "vmax = max([smaxz, smaxo])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "slice_obl = get_the_slice(x,y,z, surfcolor_obl)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig2 = go.Figure(data=[slice_z, slice_obl], layout=fig1.layout)\n", "fig2.update_layout( coloraxis=colorax(vmin, vmax))\n", "\n", "#fig2.show() " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "IFrame('https://chart-studio.plotly.com/~empet/13864', width=700, height=700)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.core.display import HTML\n", "def css_styling():\n", " styles = open(\"./custom.css\", \"r\").read()\n", " return HTML(styles)\n", "css_styling()" ] } ], "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": 4 }