I'm creating a gauge using matplotlib pie as the foundation:
import matplotlib.pyplot as plt
import math
theta = 0.2
group_size=[10,10,10,10,10,50]
mid = [18,54,90,126,162]
from textwrap import wrap
labels=['1','2','3','4','5','']
labels = [ '\n'.join(wrap(l, 9)) for l in labels ]
fig, ax = plt.subplots()
ax.axis('equal')
pie3 = ax.pie(group_size, radius=2.2, colors=['k'] ,startangle=180,counterclock=False)
my_circle=plt.Circle( (0,0), 0.4, color='white')
p=plt.gcf()
p.gca().add_artist(my_circle)
pie4 = ax.pie([10,10,10,10,10,50], radius=2, labeldistance=0.9, labels=labels,
startangle=180,rotatelabels =True,counterclock=False)
plt.setp(pie4[1], rotation_mode="anchor", ha="center", va="center")
for tx in pie4[1]:
font = tx.get_fontsize()
tx.set_fontsize(12)
rot = tx.get_rotation()
tx.set_rotation(rot+90+(1-rot//180)*180)
for pie_wedge in pie3[0]:
pie_wedge.set_edgecolor('white')
for pie_wedge in pie4[0]:
pie_wedge.set_edgecolor('white')
pie_wedge.set_linewidth(4)
#arrow bottom circle
ax.add_patch(Circle((0, 0), radius=0.15, facecolor='k',zorder=12))
ax.add_patch(Circle((0, 0), radius=0.13, facecolor='w',zorder=13))
ax.arrow(0, 0, 1.7 * np.sin(math.radians(theta*180-90)), 1.7 * np.cos(math.radians(theta*180-90)), \
width=0.15, head_width=0.15, head_length=0.2, fc='k', ec='k')
theta2 = 0.45
ax.arrow(0, 0, 1.7 * np.sin(math.radians(theta2*180-90)), 1.7 * np.cos(math.radians(theta2*180-90)), \
width=0.15, head_width=0.15, head_length=0.2, fc='k', ec='k',zorder=20)
Now the problem is my gauge arrow (in red) seems to get cut off at the top if it is sitting between 2 and 4. Almost as if there is an imaginary line between the left corner of the 2 wedge and the right corner of the 4 wedge. As you can see with the black arrow, no issue there.
Does anyone know what is happening here? I suspect a possible figsize issue?
I think you're basically right in assuming it's a figsize issue, or at least, a frame size issue. As you have it, you are plotting your pie chart beyond the borders of the figure (this border is the "imaginary line" that you speak of in your question). The arrows don't know how to deal with this, and just get cut off where the frame would be. One way to fix this is to plot your pie graph with a radius of 1 (instead of 2, as you had it), so that it is all within the limits of the matplotlib frame, and then just divide the arrow lengths and other arrow parameters by 2 or thereabouts, to scale everything accordingly. Here is basically what I did to modify your code, to get you going (I put in comments in #### CAPS LOCK ####
where I changed things):
from matplotlib.patches import Circle
import matplotlib.pyplot as plt
import math
theta = 0.2
group_size=[10,10,10,10,10,50]
mid = [18,54,90,126,162]
from textwrap import wrap
labels=['1','2','3','4','5','']
labels = [ '\n'.join(wrap(l, 9)) for l in labels ]
fig, ax = plt.subplots()
ax.axis('equal')
### CHANGED RADIUS HERE ###
pie3 = ax.pie(group_size,radius=1, colors=['k'] ,startangle=180,counterclock=False)
my_circle=plt.Circle( (0,0), 0.4, color='white')
p=plt.gcf()
p.gca().add_artist(my_circle)
### CHANGED RADIUS HERE ###
pie4 = ax.pie([10,10,10,10,10,50], radius=0.9, labeldistance=0.85, labels=labels,
startangle=180,rotatelabels =True,counterclock=False)
plt.setp(pie4[1], rotation_mode="anchor", ha="center", va="center")
for tx in pie4[1]:
font = tx.get_fontsize()
tx.set_fontsize(12)
rot = tx.get_rotation()
tx.set_rotation(rot+90+(1-rot//180)*180)
for pie_wedge in pie3[0]:
pie_wedge.set_edgecolor('white')
### DIVIDED LINEWIDTH BY 2 FOR SCALING ###
for pie_wedge in pie4[0]:
pie_wedge.set_edgecolor('white')
pie_wedge.set_linewidth(2)
#arrow bottom circle
### DIVIDED RADIUS BY 2 FOR SCALING ###
ax.add_patch(Circle((0, 0), radius=0.15/2, facecolor='k',zorder=12))
ax.add_patch(Circle((0, 0), radius=0.13/2, facecolor='w',zorder=13))
### DIVIDED SOME PARAMETERS BY 2.2 FOR SCALING ####
ax.arrow(0, 0, 1.7/2.2 * np.sin(math.radians(theta*180-90)), 1.7/2.2 * np.cos(math.radians(theta*180-90)), \
width=0.15/2, head_width=0.15/2, head_length=0.2/2, fc='k', ec='k')
theta2 = 0.45
### DIVIDED SOME PARAMETERS BY 2.2 FOR SCALING ####
ax.arrow(0, 0, 1.7/2.2 * np.sin(math.radians(theta2*180-90)), 1.7/2.2 * np.cos(math.radians(theta2*180-90)), \
width=0.15/2, head_width=0.15/2, head_length=0.2/2, fc='k', ec='k')
#### TIGHT LAYOUT MAKES SENSE HERE ####
plt.tight_layout()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With