7
7
ventricle recommended by the American Heart Association (AHA).
8
8
9
9
.. redirect-from:: /gallery/specialty_plots/leftventricle_bulleye
10
+
11
+ See also the :doc:`/gallery/pie_and_polar_charts/nested_pie` example.
10
12
"""
11
13
12
14
import numpy as np
13
15
import matplotlib as mpl
14
16
import matplotlib .pyplot as plt
15
17
16
18
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 ):
18
20
"""
19
21
Bullseye representation for the left ventricle.
20
22
21
23
Parameters
22
24
----------
23
25
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.
30
32
norm : Normalize or None, optional
31
- Optional argument to normalize data into the [0.0, 1.0] range
33
+ Normalizer for the data.
32
34
33
35
Notes
34
36
-----
@@ -43,93 +45,49 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None):
43
45
nomenclature for tomographic imaging of the heart",
44
46
Circulation, vol. 105, no. 4, pp. 539-542, 2002.
45
47
"""
46
- if seg_bold is None :
47
- seg_bold = []
48
48
49
- linewidth = 2
50
49
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 = []
55
52
if norm is None :
56
53
norm = mpl .colors .Normalize (vmin = data .min (), vmax = data .max ())
57
54
58
- theta = np .linspace (0 , 2 * np .pi , 768 )
59
55
r = np .linspace (0.2 , 1 , 4 )
60
56
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 ))
133
91
134
92
135
93
# Create the fake data
@@ -151,7 +109,7 @@ def bullseye_plot(ax, data, seg_bold=None, cmap=None, norm=None):
151
109
# The following gives a basic continuous colorbar with ticks and labels.
152
110
fig .colorbar (mpl .cm .ScalarMappable (cmap = cmap , norm = norm ),
153
111
cax = axs [0 ].inset_axes ([0 , - .15 , 1 , .1 ]),
154
- orientation = 'horizontal' , label = 'Some Units ' )
112
+ orientation = 'horizontal' , label = 'Some units ' )
155
113
156
114
157
115
# And again for the second colorbar.
0 commit comments