Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5259594

Browse files
committed
Merge pull request #4550 from tacaswell/doc_aha_bullseye
Doc: AHA bullseye example
2 parents b57e014 + 1b831cb commit 5259594

File tree

2 files changed

+209
-0
lines changed

2 files changed

+209
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,5 @@ examples/tests/*
6767
texput.log
6868
texput.aux
6969
result_images
70+
71+
*.swp
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
#!/usr/bin/env python
2+
"""
3+
This example demonstrates how to create the 17 segment model for the left
4+
ventricle recommended by the American Heart Association (AHA).
5+
"""
6+
7+
import numpy as np
8+
import matplotlib as mpl
9+
import matplotlib.pyplot as plt
10+
11+
12+
def bullseye_plot(ax, data, segBold=None, cmap=None, norm=None):
13+
"""
14+
Bullseye representation for the left ventricle.
15+
16+
Parameters
17+
----------
18+
ax : axes
19+
data : list of int and float
20+
The intensity values for each of the 17 segments
21+
segBold: list of int, optional
22+
A list with the segments to highlight
23+
cmap : ColorMap or None, optional
24+
Optional argument to set the desired colormap
25+
norm : Normalize or None, optional
26+
Optional argument to normalize data into the [0.0, 1.0] range
27+
28+
29+
Notes
30+
-----
31+
This function create the 17 segment model for the left ventricle according
32+
to the American Heart Association (AHA) [1]_
33+
34+
References
35+
----------
36+
.. [1] M. D. Cerqueira, N. J. Weissman, V. Dilsizian, A. K. Jacobs,
37+
S. Kaul, W. K. Laskey, D. J. Pennell, J. A. Rumberger, T. Ryan,
38+
and M. S. Verani, "Standardized myocardial segmentation and
39+
nomenclature for tomographic imaging of the heart",
40+
Circulation, vol. 105, no. 4, pp. 539-542, 2002.
41+
"""
42+
if segBold is None:
43+
segBold = []
44+
45+
linewidth = 2
46+
data = np.array(data).ravel()
47+
48+
if cmap is None:
49+
cmap = plt.cm.jet
50+
51+
if norm is None:
52+
norm = mpl.colors.Normalize(vmin=data.min(), vmax=data.max())
53+
54+
theta = np.linspace(0, 2*np.pi, 768)
55+
r = np.linspace(0.2, 1, 4)
56+
57+
# Create the bound for the segment 17
58+
for i in range(r.shape[0]):
59+
ax.plot(theta, np.repeat(r[i], theta.shape), '-k', lw=linewidth)
60+
61+
# Create the bounds for the segments 1-12
62+
for i in range(6):
63+
theta_i = i*60*np.pi/180
64+
ax.plot([theta_i, theta_i], [r[1], 1], '-k', lw=linewidth)
65+
66+
# Create the bounds for the segmentss 13-16
67+
for i in range(4):
68+
theta_i = i*90*np.pi/180 - 45*np.pi/180
69+
ax.plot([theta_i, theta_i], [r[0], r[1]], '-k', lw=linewidth)
70+
71+
# Fill the segments 1-6
72+
r0 = r[2:4]
73+
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
74+
for i in range(6):
75+
# First segment start at 60 degrees
76+
theta0 = theta[i*128:i*128+128] + 60*np.pi/180
77+
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
78+
z = np.ones((128, 2))*data[i]
79+
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
80+
if i+1 in segBold:
81+
ax.plot(theta0, r0, '-k', lw=linewidth+2)
82+
ax.plot(theta0[0], [r[2], r[3]], '-k', lw=linewidth+1)
83+
ax.plot(theta0[-1], [r[2], r[3]], '-k', lw=linewidth+1)
84+
85+
# Fill the segments 7-12
86+
r0 = r[1:3]
87+
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
88+
for i in range(6):
89+
# First segment start at 60 degrees
90+
theta0 = theta[i*128:i*128+128] + 60*np.pi/180
91+
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
92+
z = np.ones((128, 2))*data[i+6]
93+
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
94+
if i+7 in segBold:
95+
ax.plot(theta0, r0, '-k', lw=linewidth+2)
96+
ax.plot(theta0[0], [r[1], r[2]], '-k', lw=linewidth+1)
97+
ax.plot(theta0[-1], [r[1], r[2]], '-k', lw=linewidth+1)
98+
99+
# Fill the segments 13-16
100+
r0 = r[0:2]
101+
r0 = np.repeat(r0[:, np.newaxis], 192, axis=1).T
102+
for i in range(4):
103+
# First segment start at 45 degrees
104+
theta0 = theta[i*192:i*192+192] + 45*np.pi/180
105+
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
106+
z = np.ones((192, 2))*data[i+12]
107+
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
108+
if i+13 in segBold:
109+
ax.plot(theta0, r0, '-k', lw=linewidth+2)
110+
ax.plot(theta0[0], [r[0], r[1]], '-k', lw=linewidth+1)
111+
ax.plot(theta0[-1], [r[0], r[1]], '-k', lw=linewidth+1)
112+
113+
# Fill the segments 17
114+
if data.size == 17:
115+
r0 = np.array([0, r[0]])
116+
r0 = np.repeat(r0[:, np.newaxis], theta.size, axis=1).T
117+
theta0 = np.repeat(theta[:, np.newaxis], 2, axis=1)
118+
z = np.ones((theta.size, 2))*data[16]
119+
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm)
120+
if 17 in segBold:
121+
ax.plot(theta0, r0, '-k', lw=linewidth+2)
122+
123+
ax.set_ylim([0, 1])
124+
ax.set_yticklabels([])
125+
ax.set_xticklabels([])
126+
127+
128+
# Create the fake data
129+
data = np.array(range(17)) + 1
130+
131+
132+
# Make a figure and axes with dimensions as desired.
133+
fig, ax = plt.subplots(figsize=(12, 8), nrows=1, ncols=3,
134+
subplot_kw=dict(projection='polar'))
135+
fig.canvas.set_window_title('Left Ventricle Bulls Eyes (AHA)')
136+
137+
# Create the axis for the colorbars
138+
axl = fig.add_axes([0.14, 0.15, 0.2, 0.05])
139+
axl2 = fig.add_axes([0.41, 0.15, 0.2, 0.05])
140+
axl3 = fig.add_axes([0.69, 0.15, 0.2, 0.05])
141+
142+
143+
# Set the colormap and norm to correspond to the data for which
144+
# the colorbar will be used.
145+
cmap = mpl.cm.jet
146+
norm = mpl.colors.Normalize(vmin=1, vmax=17)
147+
148+
# ColorbarBase derives from ScalarMappable and puts a colorbar
149+
# in a specified axes, so it has everything needed for a
150+
# standalone colorbar. There are many more kwargs, but the
151+
# following gives a basic continuous colorbar with ticks
152+
# and labels.
153+
cb1 = mpl.colorbar.ColorbarBase(axl, cmap=cmap, norm=norm,
154+
orientation='horizontal')
155+
cb1.set_label('Some Units')
156+
157+
158+
# Set the colormap and norm to correspond to the data for which
159+
# the colorbar will be used.
160+
cmap2 = mpl.cm.cool
161+
norm2 = mpl.colors.Normalize(vmin=1, vmax=17)
162+
163+
# ColorbarBase derives from ScalarMappable and puts a colorbar
164+
# in a specified axes, so it has everything needed for a
165+
# standalone colorbar. There are many more kwargs, but the
166+
# following gives a basic continuous colorbar with ticks
167+
# and labels.
168+
cb2 = mpl.colorbar.ColorbarBase(axl2, cmap=cmap2, norm=norm2,
169+
orientation='horizontal')
170+
cb2.set_label('Some other units')
171+
172+
173+
# The second example illustrates the use of a ListedColormap, a
174+
# BoundaryNorm, and extended ends to show the "over" and "under"
175+
# value colors.
176+
cmap3 = mpl.colors.ListedColormap(['r', 'g', 'b', 'c'])
177+
cmap3.set_over('0.35')
178+
cmap3.set_under('0.75')
179+
180+
# If a ListedColormap is used, the length of the bounds array must be
181+
# one greater than the length of the color list. The bounds must be
182+
# monotonically increasing.
183+
bounds = [2, 3, 7, 9, 15]
184+
norm3 = mpl.colors.BoundaryNorm(bounds, cmap3.N)
185+
cb3 = mpl.colorbar.ColorbarBase(axl3, cmap=cmap3, norm=norm3,
186+
# to use 'extend', you must
187+
# specify two extra boundaries:
188+
boundaries=[0]+bounds+[18],
189+
extend='both',
190+
ticks=bounds, # optional
191+
spacing='proportional',
192+
orientation='horizontal')
193+
cb3.set_label('Discrete intervals, some other units')
194+
195+
196+
# Create the 17 segment model
197+
bullseye_plot(ax[0], data, cmap=cmap, norm=norm)
198+
ax[0].set_title('Bulls Eye (AHA)')
199+
200+
bullseye_plot(ax[1], data, cmap=cmap2, norm=norm2)
201+
ax[1].set_title('Bulls Eye (AHA)')
202+
203+
bullseye_plot(ax[2], data, segBold=[3, 5, 6, 11, 12, 16],
204+
cmap=cmap3, norm=norm3)
205+
ax[2].set_title('Segments [3,5,6,11,12,16] in bold')
206+
207+
plt.show()

0 commit comments

Comments
 (0)