pyplot barchart is plotted, but saved to empty file - python

I have a strange behaviour in my python code, where I plot a bar-chart and it will be showed in a window, but pressing the "save"-button does nothing and .savefig() creates an empty file with 0KB.
Even more strange, I have a for-loop before the barchart, which is creating several complicated plots and all of them are capable to be plotted and then saved, except the barchart, which is only plotted.
I do not receive any errors from the python-console.
This is my code from the plot-loop before the bar-chart:
for l in range(NumberOfResults):
plottitle=groupLimits[0][l+1]+' - Result Width and Probability Distribution of ' + str(numberCombinations) + ' possible Combinations'
fig=plt.figure(plottitle,figsize=(GetSystemMetrics(0)/96,GetSystemMetrics(1)/96),dpi=96)
plt.clf()
ax=fig.add_subplot(1,1,1)
ResultColumn=range(NumberOfInputs,NumberOfInputs+NumberOfResults)[l]
positions=range(len(groupResults))
#positions=list(map(int, np.array(groupLimits[1:])[:,0]))
#plt.grid(1)
y1=[]
x1=[]
for i in range(len(groupResults)):
y1.append(groupResults[i][:,ResultColumn])
x1.append([positions[i]]*len(groupResults[i]))
y=list(np.array(y1).flatten())
s=[]
for i in range(len(groupResults)):
smin=min(groupResults[i][:,ProbabilityColumn])
smax=max(groupResults[i][:,ProbabilityColumn])
s.append((groupResults[i][:,ProbabilityColumn]-smin)/(smax-smin)*25000)
plt.scatter(x1,y1,s=s,marker='_',color='cyan',alpha=0.45)
bp=plt.boxplot(y1, positions=positions, widths=0.5,
labels=list(np.array(groupLimits[1:])[:,0]),
patch_artist=True,whis=[0,100])
#plt.xlim(min(positions)*0.9,max(positions)*1.1)
ax.xaxis.set_tick_params(labelsize=24)
ax.xaxis.grid(True,'major',color='k', linestyle='-', linewidth=0.75)
ax.xaxis.grid(True,'minor',color='k', linestyle=':', linewidth=0.25)
ax.xaxis.set_minor_locator(MultipleLocator(50));
ax.yaxis.set_tick_params(labelsize=24)
ax.yaxis.grid(True,'major',color='k', linestyle='-', linewidth=0.25)
ax.yaxis.grid(True,'minor',color='k', linestyle=':', linewidth=0.25)
ax.yaxis.set_minor_locator(MultipleLocator(0.1));
ax.yaxis.set_ticks(np.arange(int(min(y)),int(max(y))*1.1,0.5))
## change outline color, fill color and linewidth of the boxes
for box in bp['boxes']:
# change outline color
box.set( color='blue', linewidth=3)
# change fill color
box.set( facecolor = 'None')
## change color and linewidth of the whiskers
for whisker in bp['whiskers']:
whisker.set(color='blue', linewidth=3)
## change color and linewidth of the caps
for cap in bp['caps']:
cap.set(color='blue', linewidth=3,alpha=0.8)
## change color and linewidth of the medians
for median in bp['medians']:
median.set(color='magenta', linewidth=3)
y2=[]
x2=[]
for i in range(1,len(groupResults)+1):
if groupLimits[i][l+1]=='-':
pass
else:
y2.append(float(groupLimits[i][l+1]))
if FailedCombinations[i-1][l] is None:
failureString = 'No Results below the Limit'
else:
failureString= str(len(FailedCombinations[i-1][l]))+' failed # ' + "{:.3g}".format(FailureProbability[i-1][l]*100) + '%'
plt.text(positions[i-1],float(groupLimits[i][l+1])*0.9,
failureString,fontsize=18,horizontalalignment='center',
bbox=dict(facecolor='yellow', edgecolor='black'))
x2.append(positions[i-1])
plt.plot(x2,y2,marker='x',color='red', mew=4,ms=15,linestyle='None')
blue_patch = mpatches.Patch(color='blue', label='Result width')
red_patch = mlines.Line2D([],[],marker='x',color='red', mew=4,ms=15,linestyle='None', label='Limit')
magenta_patch = mpatches.Patch(color='magenta', label='Median')
cyan_patch = mpatches.Patch(color='cyan', label='Probability of Result')
plt.legend(handles=[blue_patch, red_patch, magenta_patch, cyan_patch],
loc='upper left',ncol=1,fontsize=24)
plt.title(plottitle,fontsize=24)
plt.xlabel('Engine Rotation Speed [rpm]',fontsize=24)
plt.ylabel('Absolute Pressure [bar]',fontsize=24)
labelsize = 24
rcParams['xtick.labelsize'] = labelsize
rcParams['ytick.labelsize'] = labelsize
plt.savefig(plottitle)
plt.show()
In between I run some calculations to prepare data for the bar-chart plot. However, the code for the bar-chart is:
# Plot group-wise combined failures with all-combined failures at end
plottitle = 'Failed combinations per group - and engine-all combined - TOTAL combinations: ' + str(len(groupResults[0]))
plt.figure(plottitle,figsize=(GetSystemMetrics(0)/96,GetSystemMetrics(1)/96),dpi=96)
plt.clf()
ax=plt.subplot(1,1,1)
y=[]
ind = np.arange(len(groupFailureProbabilities))
for i in range(len(groupFailures)):
y.append(len(groupFailures[i]))
y=tuple(y)
for i in range(len(y)):
if y[i]==0:
pass
else:
string=str(y[i])+' failed # ' + "{:.3g}".format(groupFailureProbabilities[i]*100)+' %'
plt.text(ind[i],y[i]+100,
string,fontsize=18, horizontalalignment='center',
bbox=dict(facecolor='yellow', edgecolor='black'))
width = 0.35
y=list(y)
plt.bar(ind, y, align='center', color='b')
labels=list(np.array(groupLimits[1:])[:,0])
labels.append('engine \n complete')
ax.set_xticks(ind)
ax.set_xticklabels(tuple(labels))
ax.yaxis.set_tick_params(labelsize=24)
ax.yaxis.grid(True,'major',color='k', linestyle='-', linewidth=0.25)
ax.yaxis.grid(True,'minor',color='k', linestyle=':', linewidth=0.25)
ax.yaxis.set_ticks(np.arange(int(min(y)),int(max(y))*1.1,500))
plt.title(plottitle,fontsize=24)
plt.xlabel('Engine Rotation Speed [rpm]',fontsize=24)
plt.ylabel('Number of Failed Combinations',fontsize=24)
plt.savefig(plottitle)
plt.show()
What is the reason why I cannot save my bar-chart ?

It's kinda difficult to write the shortest code necessary to reproduce the problem, if I have no idea why it happened in the first place.
However, I managed to get it working with a rearrangement of the code lines:
plottitle = 'Failed combinations per group - TOTAL combinations ' + str(len(groupResults[0]))
plt.figure(plottitle,figsize=(GetSystemMetrics(0)/96,GetSystemMetrics(1)/96),dpi=96)
plt.clf()
ax=plt.subplot(1,1,1)
plt.bar(ind, y, align='center')
labels=list(np.array(groupLimits[1:])[:,0])
labels.append('engine \n complete')
ax.set_xticks(ind)
ax.set_xticklabels(tuple(labels))
ax.yaxis.set_tick_params(labelsize=24)
ax.yaxis.grid(True,'major',color='k', linestyle='-', linewidth=0.25)
ax.yaxis.grid(True,'minor',color='k', linestyle=':', linewidth=0.25)
ax.yaxis.set_ticks(np.arange(int(min(y)),int(max(y))*1.1,500))
plt.title(plottitle,fontsize=24)
plt.xlabel('Engine Rotation Speed [rpm]',fontsize=24)
plt.ylabel('Number of Failed Combinations',fontsize=24)
plt.savefig(plottitle+'.png')
plt.show()

Related

Offset in Vertical Alignment of Legend Text and Symbol (Matplotlib)

I was trying to plot some data and include linear trends. I wanted the legend to include the function of the trend but somehow the legend always shows a weird vertical offset of the symbol relative to the text (see Screenshot marked with light blue). Does anybody know why and could maybe also include a fix?
Thank you!
l_y1_1 = ax.plot(x, y1, 'ro', label='Lithium', markersize=10)
l_y1_2 = ax.plot(x_extrapolate, y1_extrapolate,'r:', label = "%s" % poly1)
l_y2_1 = ax.plot(x, y2, 'bx', label='Chlor', markersize=10)
l_y2_2 = ax.plot(x_extrapolate, y2_extrapolate,'b:', label = "%s" % poly2)
ax2 = ax.twinx()
l_y3_1 = ax2.plot(x, y3, 'gD', label='Fluor', markersize=10)
l_y3_2 = ax2.plot(x_extrapolate, y3_extrapolate,'g:',label = "%s" % poly3)
l_y_tot = l_y1_1 + l_y1_2 + l_y2_1 + l_y2_2 + l_y3_1 + l_y3_2
y_labs = [l.get_label() for l in l_y_tot]
legend = ax.legend(l_y_tot, y_labs, loc = 'upper left')

Matplotlib/Pandas - Plot not reflective of data

Trying to work out what is going wrong. I am using pandas to generate dataframes and matplotlib to plot a figure with 5 subplots.
Datasets are large xlsx sheets, all data is relative to depth below ground surface, duplicate depths have been removed, all number as text errors have been removed, although depth is shown between 0 - 60 ft data is not continuous over entire interval.
What I am going for
Current issue, x-axis not reflecting trends of data, line plotted straight through data
#Import libraries
import matplotlib.pyplot as plt
import pandas as pd
#Import Excel Data
df1 = pd.read_excel (r'017_FLD_and_FLS.xlsx')
df2 = pd.read_excel (r'017_SUMD_SUMS.xlsx')
#Sort data for plotting
gam = list(df2['Natural Gamma'])
cal_Pre = list(df2['Caliper (pre-pumping)'])
cal_post = list(df2['Caliper (post-pumping)'])
fc = list(df2['Formation Conductivity'])
fr = list(df2['Formation Resistivity'])
neu = list(df2['Neutron'])
den = list(df2['Spherical Density (long-S)'])
htp = list(df1['Heat Pulse Flow'])
tp = list(df1['Static Fluid Temperature'])
t1 = list(df1['Pumping Temperature Run 1'])
t2 = list(df1['Pumping Temperature Run 2'])
t3 = list(df1['Pumping Temperature Run 3'])
depth = list(df2['Depth'])
depth_t = list(df1['Depth'])
#Test to verify subset
#print(gam)
#print (tp)
#Plot space
fig = plt.figure(figsize=(15,20))
# Caliper
ax01 = plt.subplot(151)
plt.plot(cal_Pre, depth, color="black")
ax01 = plt.gca()
ax01.invert_yaxis()
ax01.set_xlabel('Caliper (Inches)', color="black")
ax01.set_ylabel('Depth (Feet)', color="black")
plt.grid(True)
ax11 = ax01.twiny()
ax11.plot(cal_post, depth, color = 'green')
ax11.set_xlabel('Gamma (counts)', color="green")
ax11.tick_params(axis='x', labelcolor="green")
plt.grid(True, linestyle='--')
# Gamma
ax02 = plt.subplot(152)
plt.plot(cal_Pre, depth, color="black")
ax02 = plt.gca()
ax02.invert_yaxis()
ax02.set_xlabel('Caliper (Inches)', color="black")
plt.grid(True)
# Neutron Density
ax03 = plt.subplot(153, sharey=ax01)
plt.plot(den, depth, color = 'red')
ax03 = plt.gca()
ax03.invert_yaxis()
ax03.set_xlabel('Density (counts)', color = 'red')
ax03.tick_params(axis='x', labelcolor="red")
plt.grid(True)
ax13 = ax03.twiny()
ax13.plot(neu, depth, color = 'blue')
ax13.invert_xaxis()
ax13.set_xlabel('Neutron (counts)', color="blue")
ax13.tick_params(axis='x', labelcolor="blue")
plt.grid(True, linestyle='--')
# Conductivity and Resistivity
ax04 = plt.subplot(154, sharey=ax01)
plt.plot(fc, depth, color="black")
ax04 = plt.gca()
ax04.invert_yaxis()
ax04.set_xlabel('Formation Conductivity(mS/cm)', color="black")
ax04.tick_params(axis='x', labelcolor="black")
plt.grid(True)
ax14 = ax04.twiny()
ax14.plot(fr, depth, color = 'blue')
ax14.invert_xaxis()
ax14.set_xlabel('Formation Resistivity (ohm-m)', color="blue")
ax14.tick_params(axis='x', labelcolor="blue")
plt.grid(True, linestyle='--')
# Temperature and heat pulse
ax05 = plt.subplot(155)
plt.plot(htp, depth_t, color="black")
ax05 = plt.gca()
ax05.invert_yaxis()
ax05.set_xlabel('Heat Pulse Flow (gpm)', color="black")
ax05.set_ylabel('Depth (Feet)', color="black")
plt.grid(True)
ax15 = ax05.twiny()
ax15.plot(tp, depth_t, color = 'blue')
ax15.invert_xaxis()
ax15.set_xlabel('Formation Resistivity (ohm-m)', color="blue")
ax15.tick_params(axis='x', labelcolor="blue")
ax15 = ax05.twiny()
ax15.plot(t3, depth_t, color = 'blue')
ax15.invert_xaxis()
ax15.set_xlabel('Formation Resistivity (ohm-m)', color="blue")
ax15.tick_params(axis='x', labelcolor="blue")
plt.grid(True, linestyle='--')
fig.suptitle('GB017', fontsize=30, x=0.5, y=1.01)
fig.tight_layout()
plt.show()
Open to suggestions on making code more elegant but maintaining ease of figure modification.

For loop to create multiple histogram png files

I am not sure as to why this happens. Maybe it is just a simple mistake that I cannot see, but by using this code:
for filename in glob.glob('/Users/jacob/Desktop/MERS/new/NOT COAL/gensets/statistics_per_lgu/per_lgu_files/*.csv'):
base = os.path.basename(filename)
name = os.path.splitext(base)[0]
df = pd.read_csv(filename)
# Show 4 different binwidths
for i, binwidth in enumerate([10, 20, 30, 40]):
# Set up the plot
ax = plt.subplot(2, 2, i + 1)
plt.subplots_adjust( wspace=0.5, hspace=0.5)
# Draw the plot
ax.hist(df['New Capacity based on 0.8 PF'], bins=binwidth,
color='red', edgecolor='black',alpha=0.5)
# Title and labels
ax.set_title('Histogram with Binwidth = %d' % binwidth, size=10)
ax.set_xlabel('Capacity', size=11)
ax.set_ylabel('Frequency count', size=11)
ax.axvline(x=df['New Capacity based on 0.8 PF'].median(), linestyle='dashed', alpha=0.3, color='blue')
min_ylim, max_ylim = plt.ylim()
ax.text(x=df['New Capacity based on 0.8 PF'].median(),y= max_ylim*0.9, s='Median', alpha=0.7, color='blue',fontsize = 12)
ax.axvline(x=df['New Capacity based on 0.8 PF'].mean(), linestyle='dashed', alpha=0.9, color='green')
min_ylim, max_ylim = plt.ylim()
ax.text(x=df['New Capacity based on 0.8 PF'].mean(),y= max_ylim*0.5, s='Mean', alpha=0.9, color='green',fontsize = 12)
plt.tight_layout()
plt.grid(True)
plt.savefig('/Users/jacob/Documents/Gensets_gis/historgrams/per_lgu_files/{}.png'.format(name))
I get all files created like this attached photo here.
Any ideas as to what I've done wrong?
Thanks in advance.
attached photo of one histogram output
My desired result would be something like this.
Desired output
It doesn't create new subplots but it use previous ones and then it draw new plots on old plots so you have to use clear subplot before you draw new histogram.
ax = plt.subplot(2, 2, i + 1)
ax.clear()
Example code. It gives desired output but if you remove `ax.clear() then first image will be OK but you get new plot with old plots on second and third image.
import os
import pandas as pd
import matplotlib.pyplot as plt
import random
for n in range(3):
filename = f'example_data_{n}.csv'
base = os.path.basename(filename)
name = os.path.splitext(base)[0]
df = pd.DataFrame({'New Capacity based on 0.8 PF': random.choices(list(range(1000)), k=100)})
data = df['New Capacity based on 0.8 PF']
median = data.median()
mean = data.mean()
# Show 4 different binwidths
for i, binwidth in enumerate([10, 20, 30, 40]):
# Set up the plot
ax = plt.subplot(2,2,i+1)
ax.clear() # <--- it removes previous histogram
plt.subplots_adjust( wspace=0.5, hspace=0.5)
# Draw the plot
ax.hist(data , bins=binwidth, color='red', edgecolor='black',alpha=0.5)
# Title and labels
ax.set_title('Histogram with Binwidth = %d' % binwidth, size=10)
ax.set_xlabel('Capacity', size=11)
ax.set_ylabel('Frequency count', size=11)
min_ylim, max_ylim = plt.ylim()
ax.axvline(x=median, linestyle='dashed', alpha=0.3, color='blue')
ax.text(x=median, y= max_ylim*0.9, s='Median', alpha=0.7, color='blue',fontsize = 12)
ax.axvline(x=mean, linestyle='dashed', alpha=0.9, color='green')
ax.text(x=mean, y= max_ylim*0.5, s='Mean', alpha=0.9, color='green',fontsize = 12)
plt.tight_layout()
plt.grid(True)
plt.savefig('{}.png'.format(name))

Increasing the space between the plot and the title with matplotlib

I am using the following script to generate some plots. The problem is sometimes the scientific notation is overlapping with the title.
Is there a way to fix this like moving the plot a little bit down?
# init
u = {}
o = {}
# create figure
fig = plt.figure()
# x-Axis (timesteps)
i = np.array(i)
for key in urbs_values.keys():
# y-Axis (values)
u[key] = np.array(urbs_values[key])
o[key] = np.array(oemof_values[key])
# draw plots
plt.plot(i, u[key], label='urbs_'+str(key), linestyle='None', marker='x')
plt.ticklabel_format(axis='y', style='sci', scilimits=(0, 0))
plt.plot(i, o[key], label='oemof_'+str(key), linestyle='None', marker='.')
plt.ticklabel_format(axis='y', style='sci', scilimits=(0, 0))
# plot specs
plt.xlabel('Timesteps [h]')
plt.ylabel('Flow [MWh]')
plt.title(site+' '+name)
plt.grid(True)
plt.tight_layout(rect=[0,0,0.7,1])
plt.legend(bbox_to_anchor=(1.025, 1), loc=2, borderaxespad=0)
# plt.show()
Example:
You can change the position of the title by providing a value for the y parameter in plt.title(...), e.g., plt.title(site+' '+name, y=1.1).
You can edit the tittle position this way:
# plot specs
plt.xlabel('Timesteps [h]')
plt.ylabel('Flow [MWh]')
plt.title(site+' '+name)
ttl = plt.title
ttl.set_position([.5, 1.02])
plt.grid(True)
plt.tight_layout(rect=[0,0,0.7,1])
plt.legend(bbox_to_anchor=(1.025, 1), loc=2, borderaxespad=0)
# plt.show()
tuning the '1.02' should do the trick

Does anyone know how to get rid of the black 'y' axis to the left in Matplotlib plot?

After moving all of my 'y' axes to subplots I get an unwanted axis. It's the black one on the left. Does anyone know how to get rid of it? I'm sure it's getting plotted when I call the figure, however I'm not sure how to get rid of it.
def mpl_plot(self, plot_page, replot = 0): #Data stored in lists
if plot_page == 1: #Plot 1st Page
#plt0 = self.mplwidget.axes
fig = self.mplwidget.figure #Add a figure
if plot_page == 2: #Plot 2nd Page
#plt0 = self.mplwidget_2.axes
fig = self.mplwidget_2.figure #Add a figure
if plot_page == 3: #Plot 3rd Page
#plt0 = self.mplwidget_3.axes
fig = self.mplwidget_3.figure #Add a figure
#Clears Figure if data is roplotted
if replot == 1:
fig.clf()
par0 = fig.add_subplot(111)
par1 = fig.add_subplot(111)
par2 = fig.add_subplot(111)
#Add Axes
plt = par0.twinx()
ax1 = par1.twinx()
ax2 = par2.twinx()
impeller = str(self.comboBox_impellers.currentText()) #Get Impeller
fac_curves = self.mpl_factory_specs(impeller)
fac_lift = fac_curves[0]
fac_power = fac_curves[1]
fac_flow = fac_curves[2]
fac_eff = fac_curves[3]
fac_max_eff = fac_curves[4]
fac_max_eff_bpd = fac_curves[5]
fac_ranges = self.mpl_factory_ranges()
min_range = fac_ranges[0]
max_range = fac_ranges[1]
#Plot Chart
plt.hold(True)
plt.plot(fac_flow, fac_lift, 'b', linestyle = "dashed", linewidth = 1)
ax1.plot(fac_flow, fac_power, 'r', linestyle = "dashed", linewidth = 1)
ax2.plot(fac_flow, fac_eff, 'g', linestyle = "dashed", linewidth = 1)
#Move spines
ax2.spines["right"].set_position(("outward", 25))
self.make_patch_spines_invisible(ax2)
ax2.spines["right"].set_visible(True)
#Plot x axis minor tick marks
minorLocatorx = AutoMinorLocator()
ax1.xaxis.set_minor_locator(minorLocatorx)
ax1.tick_params(which='both', width= 0.5)
ax1.tick_params(which='major', length=7)
ax1.tick_params(which='minor', length=4, color='k')
#Plot y axis minor tick marks
minorLocatory = AutoMinorLocator()
plt.yaxis.set_minor_locator(minorLocatory)
plt.tick_params(which='both', width= 0.5)
plt.tick_params(which='major', length=7)
plt.tick_params(which='minor', length=4, color='k')
#Make Border of Chart White
fig.set_facecolor('white')
#Plot Grid
plt.grid(b=True, which='both', color='k', linestyle='-')
#set shaded Area
plt.axvspan(min_range, max_range, facecolor='#9BE2FA', alpha=0.5) #Yellow rectangular shaded area
#Set Vertical Lines
plt.axvline(fac_max_eff_bpd, color = '#69767A')
#BEP MARKER *** Can change marker style if needed
bep = fac_max_eff * 0.90 #bep is 90% of maximum efficiency point
bep_corrected = bep * 0.90 # We knock off another 10% to place the arrow correctly on chart
ax2.annotate('BEP', xy=(fac_max_eff_bpd, bep_corrected), xycoords='data', #Subtract 2.5 shows up correctly on chart
xytext=(-50, 30), textcoords='offset points',
bbox=dict(boxstyle="round", fc="0.8"),
arrowprops=dict(arrowstyle="-|>",
shrinkA=0, shrinkB=10,
connectionstyle="angle,angleA=0,angleB=90,rad=10"),
)
#Set Scales
plt.set_ylim(0,max(fac_lift) + (max(fac_lift) * 0.40)) #Pressure
#plt.set_xlim(0,max(fac_flow))
ax1.set_ylim(0,max(fac_power) + (max(fac_power) * 0.40)) #Power
ax2.set_ylim(0,max(fac_eff) + (max(fac_eff) * 0.40)) #Effiency
plt.yaxis.tick_left()
# Set Axes Colors
plt.tick_params(axis='y', colors='b')
ax1.tick_params(axis='y', colors='r')
ax2.tick_params(axis='y', colors='g')
# Set Chart Labels
plt.yaxis.set_label_position("left")
plt.set_xlabel("BPD")
plt.set_ylabel("Feet" , color = 'b')
#ax1.set_ylabel("BHP", color = 'r')
#ax1.set_ylabel("Effiency", color = 'g')
# Set tight layout
fig.set_tight_layout
# Since we moved Feet Axis to subplot, extra unneeded axis was created. This Removes it
# Refresh
fig.canvas.update()
fig.canvas.draw()
Well it looks like you have three y-axes, referencing the one you want to not be shown, you could try adding:
ax.yaxis.set_tick_params(labelsize=0, length=0, which='major')
to just make invisible the labels and ticks. I think it's ax2 you want gone?

Categories