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

Skip to content

Commit 04f12e5

Browse files
committed
Rewrite bullseye example to use bar() instead of pcolormesh().
It is much simpler to take advantage of bar()'s support for polar plots. Also improve z-ordering of various elements so that edges don't get overdrawn (or clipped).
1 parent 6e9a8c4 commit 04f12e5

File tree

2 files changed

+48
-89
lines changed

2 files changed

+48
-89
lines changed

examples/pie_and_polar_charts/nested_pie.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
The following examples show two ways to build a nested pie chart
77
in Matplotlib. Such charts are often referred to as donut charts.
88
9+
See also the :doc:`/gallery/specialty_plots/leftventricle_bullseye` example.
910
"""
1011

1112
import matplotlib.pyplot as plt

examples/specialty_plots/leftventricle_bullseye.py

Lines changed: 47 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,30 @@
77
ventricle recommended by the American Heart Association (AHA).
88
99
.. redirect-from:: /gallery/specialty_plots/leftventricle_bulleye
10+
11+
See also the :doc:`/gallery/pie_and_polar_charts/nested_pie` example.
1012
"""
1113

1214
import numpy as np
1315
import matplotlib as mpl
1416
import matplotlib.pyplot as plt
1517

1618

17-
def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None):
19+
def bullseye_plot(ax, data, seg_bold=None, cmap="viridis", norm=None):
1820
"""
1921
Bullseye representation for the left ventricle.
2022
2123
Parameters
2224
----------
2325
ax : axes
24-
data : list of int and float
25-
The intensity values for each of the 17 segments
26-
seg_bold : list of int, optional
27-
A list with the segments to highlight
28-
cmap : ColorMap or None, optional
29-
Optional argument to set the desired colormap
26+
data : list[float]
27+
The intensity values for each of the 17 segments.
28+
seg_bold : list[int], optional
29+
A list with the segments to highlight.
30+
cmap : colormap, default: "viridis"
31+
Colormap for the data.
3032
norm : Normalize or None, optional
31-
Optional argument to normalize data into the [0.0, 1.0] range
33+
Normalizer for the data.
3234
3335
Notes
3436
-----
@@ -43,93 +45,49 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None):
4345
nomenclature for tomographic imaging of the heart",
4446
Circulation, vol. 105, no. 4, pp. 539-542, 2002.
4547
"""
46-
if seg_bold is None:
47-
seg_bold = []
4848

49-
linewidth = 2
5049
data = np.ravel(data)
51-
52-
if cmap is None:
53-
cmap = plt.cm.viridis
54-
50+
if seg_bold is None:
51+
seg_bold = []
5552
if norm is None:
5653
norm = mpl.colors.Normalize(vmin=data.min(), vmax=data.max())
5754

58-
theta = np.linspace(0, 2 * np.pi, 768)
5955
r = np.linspace(0.2, 1, 4)
6056

61-
# Remove grid
62-
ax.grid(False)
63-
64-
# Create the bound for the segment 17
65-
for i in range(r.shape[0]):
66-
ax.plot(theta, np.repeat(r[i], theta.shape), '-k', lw=linewidth)
67-
68-
# Create the bounds for the segments 1-12
69-
for i in range(6):
70-
theta_i = np.deg2rad(i * 60)
71-
ax.plot([theta_i, theta_i], [r[1], 1], '-k', lw=linewidth)
72-
73-
# Create the bounds for the segments 13-16
74-
for i in range(4):
75-
theta_i = np.deg2rad(i * 90 - 45)
76-
ax.plot([theta_i, theta_i], [r[0], r[1]], '-k', lw=linewidth)
77-
78-
# Fill the segments 1-6
79-
r0 = r[2:4]
80-
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
81-
for i in range(6):
82-
# First segment start at 60 degrees
83-
theta0 = theta[i * 128:i * 128 + 128] + np.deg2rad(60)
84-
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
85-
z = np.ones((128 - 1, 2 - 1)) * data[i]
86-
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm, shading='auto')
87-
if i + 1 in seg_bold:
88-
ax.plot(theta0, r0, '-k', lw=linewidth + 2)
89-
ax.plot(theta0[0], [r[2], r[3]], '-k', lw=linewidth + 1)
90-
ax.plot(theta0[-1], [r[2], r[3]], '-k', lw=linewidth + 1)
91-
92-
# Fill the segments 7-12
93-
r0 = r[1:3]
94-
r0 = np.repeat(r0[:, np.newaxis], 128, axis=1).T
95-
for i in range(6):
96-
# First segment start at 60 degrees
97-
theta0 = theta[i * 128:i * 128 + 128] + np.deg2rad(60)
98-
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
99-
z = np.ones((128 - 1, 2 - 1)) * data[i + 6]
100-
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm, shading='auto')
101-
if i + 7 in seg_bold:
102-
ax.plot(theta0, r0, '-k', lw=linewidth + 2)
103-
ax.plot(theta0[0], [r[1], r[2]], '-k', lw=linewidth + 1)
104-
ax.plot(theta0[-1], [r[1], r[2]], '-k', lw=linewidth + 1)
105-
106-
# Fill the segments 13-16
107-
r0 = r[0:2]
108-
r0 = np.repeat(r0[:, np.newaxis], 192, axis=1).T
109-
for i in range(4):
110-
# First segment start at 45 degrees
111-
theta0 = theta[i * 192:i * 192 + 192] + np.deg2rad(45)
112-
theta0 = np.repeat(theta0[:, np.newaxis], 2, axis=1)
113-
z = np.ones((192 - 1, 2 - 1)) * data[i + 12]
114-
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm, shading='auto')
115-
if i + 13 in seg_bold:
116-
ax.plot(theta0, r0, '-k', lw=linewidth + 2)
117-
ax.plot(theta0[0], [r[0], r[1]], '-k', lw=linewidth + 1)
118-
ax.plot(theta0[-1], [r[0], r[1]], '-k', lw=linewidth + 1)
119-
120-
# Fill the segments 17
121-
if data.size == 17:
122-
r0 = np.array([0, r[0]])
123-
r0 = np.repeat(r0[:, np.newaxis], theta.size, axis=1).T
124-
theta0 = np.repeat(theta[:, np.newaxis], 2, axis=1)
125-
z = np.ones((theta.size - 1, 2 - 1)) * data[16]
126-
ax.pcolormesh(theta0, r0, z, cmap=cmap, norm=norm, shading='auto')
127-
if 17 in seg_bold:
128-
ax.plot(theta0, r0, '-k', lw=linewidth + 2)
129-
130-
ax.set_ylim([0, 1])
131-
ax.set_yticklabels([])
132-
ax.set_xticklabels([])
57+
ax.set(ylim=[0, 1], xticklabels=[], yticklabels=[])
58+
ax.grid(False) # Remove grid
59+
60+
# Fill segments 1-6, 7-12, 13-16.
61+
for start, stop, r_in, r_out in [
62+
(0, 6, r[2], r[3]),
63+
(6, 12, r[1], r[2]),
64+
(12, 16, r[0], r[1]),
65+
(16, 17, 0, r[0]),
66+
]:
67+
n = stop - start
68+
dtheta = 2*np.pi / n
69+
ax.bar(np.arange(n) * dtheta + np.pi/2, r_out - r_in, dtheta, r_in,
70+
color=cmap(norm(data[start:stop])))
71+
72+
# Now, draw the segment borders. In order for the outer bold borders not
73+
# to be covered by inner segments, the borders are all drawn separately
74+
# after the segments have all been filled. We also disable clipping, which
75+
# would otherwise affect the outermost segment edges.
76+
# Draw edges of segments 1-6, 7-12, 13-16.
77+
for start, stop, r_in, r_out in [
78+
(0, 6, r[2], r[3]),
79+
(6, 12, r[1], r[2]),
80+
(12, 16, r[0], r[1]),
81+
]:
82+
n = stop - start
83+
dtheta = 2*np.pi / n
84+
ax.bar(np.arange(n) * dtheta + np.pi/2, r_out - r_in, dtheta, r_in,
85+
clip_on=False, color="none", edgecolor="k", linewidth=[
86+
4 if i + 1 in seg_bold else 2 for i in range(start, stop)])
87+
# Draw edge of segment 17 -- here; the edge needs to be drawn differently,
88+
# using plot().
89+
ax.plot(np.linspace(0, 2*np.pi), np.linspace(r[0], r[0]), "k",
90+
linewidth=(4 if 17 in seg_bold else 2))
13391

13492

13593
# Create the fake data
@@ -151,7 +109,7 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None):
151109
# The following gives a basic continuous colorbar with ticks and labels.
152110
fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
153111
cax=axs[0].inset_axes([0, -.15, 1, .1]),
154-
orientation='horizontal', label='Some Units')
112+
orientation='horizontal', label='Some units')
155113

156114

157115
# And again for the second colorbar.

0 commit comments

Comments
 (0)