{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Left ventricle bullseye\n\nThis example demonstrates how to create the 17 segment model for the left\nventricle recommended by the American Heart Association (AHA).\n\n.. redirect-from:: /gallery/specialty_plots/leftventricle_bulleye\n\nSee also the :doc:`/gallery/pie_and_polar_charts/nested_pie` example.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nimport matplotlib as mpl\n\n\ndef bullseye_plot(ax, data, seg_bold=None, cmap=\"viridis\", norm=None):\n \"\"\"\n Bullseye representation for the left ventricle.\n\n Parameters\n ----------\n ax : Axes\n data : list[float]\n The intensity values for each of the 17 segments.\n seg_bold : list[int], optional\n A list with the segments to highlight.\n cmap : colormap, default: \"viridis\"\n Colormap for the data.\n norm : Normalize or None, optional\n Normalizer for the data.\n\n Notes\n -----\n This function creates the 17 segment model for the left ventricle according\n to the American Heart Association (AHA) [1]_\n\n References\n ----------\n .. [1] M. D. Cerqueira, N. J. Weissman, V. Dilsizian, A. K. Jacobs,\n S. Kaul, W. K. Laskey, D. J. Pennell, J. A. Rumberger, T. Ryan,\n and M. S. Verani, \"Standardized myocardial segmentation and\n nomenclature for tomographic imaging of the heart\",\n Circulation, vol. 105, no. 4, pp. 539-542, 2002.\n \"\"\"\n\n data = np.ravel(data)\n if seg_bold is None:\n seg_bold = []\n if norm is None:\n norm = mpl.colors.Normalize(vmin=data.min(), vmax=data.max())\n\n r = np.linspace(0.2, 1, 4)\n\n ax.set(ylim=[0, 1], xticklabels=[], yticklabels=[])\n ax.grid(False) # Remove grid\n\n # Fill segments 1-6, 7-12, 13-16.\n for start, stop, r_in, r_out in [\n (0, 6, r[2], r[3]),\n (6, 12, r[1], r[2]),\n (12, 16, r[0], r[1]),\n (16, 17, 0, r[0]),\n ]:\n n = stop - start\n dtheta = 2*np.pi / n\n ax.bar(np.arange(n) * dtheta + np.pi/2, r_out - r_in, dtheta, r_in,\n color=cmap(norm(data[start:stop])))\n\n # Now, draw the segment borders. In order for the outer bold borders not\n # to be covered by inner segments, the borders are all drawn separately\n # after the segments have all been filled. We also disable clipping, which\n # would otherwise affect the outermost segment edges.\n # Draw edges of segments 1-6, 7-12, 13-16.\n for start, stop, r_in, r_out in [\n (0, 6, r[2], r[3]),\n (6, 12, r[1], r[2]),\n (12, 16, r[0], r[1]),\n ]:\n n = stop - start\n dtheta = 2*np.pi / n\n ax.bar(np.arange(n) * dtheta + np.pi/2, r_out - r_in, dtheta, r_in,\n clip_on=False, color=\"none\", edgecolor=\"k\", linewidth=[\n 4 if i + 1 in seg_bold else 2 for i in range(start, stop)])\n # Draw edge of segment 17 -- here; the edge needs to be drawn differently,\n # using plot().\n ax.plot(np.linspace(0, 2*np.pi), np.linspace(r[0], r[0]), \"k\",\n linewidth=(4 if 17 in seg_bold else 2))\n\n\n# Create the fake data\ndata = np.arange(17) + 1\n\n\n# Make a figure and Axes with dimensions as desired.\nfig = plt.figure(figsize=(10, 5), layout=\"constrained\")\nfig.get_layout_engine().set(wspace=.1, w_pad=.2)\naxs = fig.subplots(1, 3, subplot_kw=dict(projection='polar'))\nfig.canvas.manager.set_window_title('Left Ventricle Bulls Eyes (AHA)')\n\n\n# Set the colormap and norm to correspond to the data for which\n# the colorbar will be used.\ncmap = mpl.cm.viridis\nnorm = mpl.colors.Normalize(vmin=1, vmax=17)\n# Create an empty ScalarMappable to set the colorbar's colormap and norm.\n# The following gives a basic continuous colorbar with ticks and labels.\nfig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm),\n cax=axs[0].inset_axes([0, -.15, 1, .1]),\n orientation='horizontal', label='Some units')\n\n\n# And again for the second colorbar.\ncmap2 = mpl.cm.cool\nnorm2 = mpl.colors.Normalize(vmin=1, vmax=17)\nfig.colorbar(mpl.cm.ScalarMappable(cmap=cmap2, norm=norm2),\n cax=axs[1].inset_axes([0, -.15, 1, .1]),\n orientation='horizontal', label='Some other units')\n\n\n# The second example illustrates the use of a ListedColormap, a\n# BoundaryNorm, and extended ends to show the \"over\" and \"under\"\n# value colors.\ncmap3 = (mpl.colors.ListedColormap(['r', 'g', 'b', 'c'])\n .with_extremes(over='0.35', under='0.75'))\n# If a ListedColormap is used, the length of the bounds array must be\n# one greater than the length of the color list. The bounds must be\n# monotonically increasing.\nbounds = [2, 3, 7, 9, 15]\nnorm3 = mpl.colors.BoundaryNorm(bounds, cmap3.N)\nfig.colorbar(mpl.cm.ScalarMappable(cmap=cmap3, norm=norm3),\n cax=axs[2].inset_axes([0, -.15, 1, .1]),\n extend='both',\n ticks=bounds, # optional\n spacing='proportional',\n orientation='horizontal',\n label='Discrete intervals, some other units')\n\n\n# Create the 17 segment model\nbullseye_plot(axs[0], data, cmap=cmap, norm=norm)\naxs[0].set_title('Bulls Eye (AHA)')\n\nbullseye_plot(axs[1], data, cmap=cmap2, norm=norm2)\naxs[1].set_title('Bulls Eye (AHA)')\n\nbullseye_plot(axs[2], data, seg_bold=[3, 5, 6, 11, 12, 16],\n cmap=cmap3, norm=norm3)\naxs[2].set_title('Segments [3, 5, 6, 11, 12, 16] in bold')\n\nplt.show()" ] } ], "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.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }