My script works, but when running I receive the error that is displayed in the heading. I do not understand why bc I use plt.clf() after every plot that I open and save. Below is an example of one of the instances I open (and close) a figure
...
roi1 = img[700:830, 730:835]
roiStats1(roi1)
plt.imshow(roi1)
plt.colorbar()
plt.savefig('roi1_'+file[:20]+'.tif')
plt.clf()
###### Make ROI sequential to be able to "bin" the axes #############
roi1y =roi1.reshape(13650, 1)
roi1y_df = pd.DataFrame(roi1y).reset_index().rename(columns= {0: 'Intensity'})
###### Plot Y axis variation of ROI for edge or lane gradient ###########
inlet_bins = np.linspace(-1, 13650, num=10, endpoint=True)
y_binlabels = [1,2,3,4,5,6,7,8,9]
roi1y_df['bins'] = pd.cut(roi1y_df['index'], inlet_bins, labels = y_binlabels)
roi1y_df['Intensity'] = roi1y_df['Intensity'].astype(float)
fig, ax = plt.subplots()
sns.boxplot(x='bins', y='Intensity', data=roi1y_df, ax = ax).set_title('Y-Axis Variation'+file[:20])
plt.savefig('YvarPlot_Inlet_'+file[:20]+'.tif')
plt.clf()
...
So I plt.clf() each time I open and save a figure, but I still get the memory warning
try plt.close() instead of plt.clf()
Related
I'm making Terror Attacks analysis using Python. And I wanted make an animation. I made it but I have a problem the text above the animation overlaps in every frame. How can I fix it?
fig = plt.figure(figsize = (7,4))
def animate(Year):
ax = plt.axes()
ax.clear()
ax.set_title('Terrorism In Turkey\n'+ str(Year))
m5 = Basemap(projection='lcc',resolution='l' ,width=1800000, height=900000 ,lat_0=38.9637, lon_0=35.2433)
lat_gif=list(terror_turkey[terror_turkey['Year']==Year].Latitude)
long_gif=list(terror_turkey[terror_turkey['Year']==Year].Longitude)
x_gif,y_gif=m5(long_gif,lat_gif)
m5.scatter(x_gif, y_gif,s=[Death+Injured for Death,Injured in zip(terror_turkey[terror_turkey['Year']==Year].Death,terror_turkey[terror_turkey['Year']==Year].Injured)],color = 'r')
m5.drawcoastlines()
m5.drawcountries()
m5.fillcontinents(color='coral',lake_color='aqua', zorder = 1,alpha=0.4)
m5.drawmapboundary(fill_color='aqua')
ani = animation.FuncAnimation(fig,animate, list(terror_turkey.Year.unique()), interval = 1500)
ani.save('animation_tr.gif', writer='imagemagick', fps=1)
plt.close(1)
filename = 'animation_tr.gif'
video = io.open(filename, 'r+b').read()
encoded = base64.b64encode(video)
HTML(data='''<img src="data:image/gif;base64,{0}" type="gif" />'''.format(encoded.decode('ascii')))
Output:
#JohanC's recommendation in comments resolved my problem:
Did you consider creating the axes the usual way, as in fig, ax = plt.subplots(figsize = (7,4)) (in the main code, not inside the animate function)? And leaving out the call to plt.axes()?
This is the structure of my data:
print("test_data: " + str(test_data))
#test_data: [[-1.3869276 0.76189806]
# [-1.3870304 0.76177611]
# [-1.38695643 0.76194005]
# ...,
# [-1.38663699 0.76174211]
# [-1.38670514 0.76161662]
# [-1.3865974 0.76163099]]
It is a numpy array of lat/lng coordinates converted to radians.
I have problems setting the x and y limits/bounds of the matplot-figure. I have tried both set_xlim()/set_ylim() and set_xbound()/set_ybound(), but the results are not satisfactory:
set_xlim() and set_ylim() result in a distorted view of my data:
.. while set_xbound() and set_ybound() zooms in too much (and further crops labels of the y-axis):
This is my code:
test_data = np.radians(points)
#get max data extent
limXMin = np.max(test_data[0])
limXMax = np.max(test_data[1])
limYMax = np.min(test_data[0])
limYMin = np.min(test_data[1])
#print max data extent:
print(limXMin)
print(limXMax)
print(limYMin)
print(limYMax)
#0.761924200543
#0.761882818787
#-1.38701148104
#-1.3868174877
#create figure
fig = plt.figure(figsize=(11, 8), dpi=80)
#print current extent
print(str(plt.xlim()))
print(str(plt.ylim()))
#(0.0, 1.0)
#(0.0, 1.0)
ax = fig.add_subplot(1,1,1) # 1 Row, 1 Column and the first axes in this grid
plt.scatter(test_data.T[0], test_data.T[1], color='b', **plot_kwds)
#modify extent (Fig.1)
ax.set_xlim([limXMin, limXMax])
ax.set_ylim([limYMin, limYMax])
#modify extent (Fig.2)
ax.set_xbound(limXMin, limXMax)
ax.set_ybound(limYMin, limYMax)
ax.figure.savefig(pathname + '/graph_1.png')
Instead, if I do this:
plt.figure(figsize=(11, 8), dpi=80)
plt.autoscale(enable=True)
fig = plt.scatter(test_data.T[0], test_data.T[1], color='b', **plot_kwds)
fig.figure.savefig(pathname + '/graph_1.png')
I get the full extent but with too much border. Almost half of the plot area is not showing data:
Something went wrong with your definition of min and max values. Additionally you probably also forgot to transpose your data. It should probably be
limXMin = np.min(test_data.T[0])
limXMax = np.max(test_data.T[0])
limYMin = np.min(test_data.T[1])
limYMax = np.max(test_data.T[1])
Using the provided data,
set_xlim()/set_ylim and set_xbound()/set_ybound() both produce the same figure:
After realizing that I need to transpose my numpy array, I managed to get the correct results:
limYMin = np.min(test_data.T[1])
limYMax = np.max(test_data.T[1])
limXMin = np.min(test_data.T[0])
limXMax = np.max(test_data.T[0])
fig = plt.figure(figsize=(11, 11), dpi=80)
plt.gca().set_xlim([limXMin, limXMax])
plt.gca().set_ylim([limYMin, limYMax])
fig = plt.scatter(test_data.T[0], test_data.T[1], color='b', **plot_kwds)
fig.figure.savefig(pathname + 'graph_01.png')
The .T somehow turns the array around, so it is accessible in rows and not columns. Further, by using plt.gca().set_xlim and plt.gca().set_ylim I could avoid creating axes and sub_plots (e.g. ax1 = plt.subplot(131) and then ax.set_xlim(left=limXMin,right=limXMax)).
Many thanks to ImportanceOfBeingErnest for pointing me in the right direction (see answer above)!
I want to draw a 3D volume using Matplotlib, slice by slice.
Mouse scroll to change the index. My program is given below:
#Mouse scroll event.
def mouse_scroll(event):
fig = event.canvas.figure
ax = fig.axes[0]
if event.button == 'down':
next_slice(ax)
fig.canvas.draw()
#Next slice func.
def previous_slice(ax):
volume = ax.volume
ax.index = (ax.index - 1) % volume.shape[0]
#ax.imshow(volume[ax.index])
ax.images[0].set_array(volume[ax.index])
Figure is initialized in the main function. like:
fig, ax = plt.subplots()
ax.volume = volume # volume is a 3D data, a 3d np array.
ax.index = 1
ax.imshow(volume[ax.index])
fig.canvas.mpl_connect('scroll_event', mouse_scroll)
Everything worked pretty well even I don't understand what is the ax.images. However, problem occurred when I replace the ax.volume with a new volume data. It suddenly stop to render! Debug into the code, the ax.image[0] is correctly set at each event callback.
But, if change the image set_array method to ax.show(). Figure begins to render again. But axes imshow function is really slow comparing to the ax.images[0].set_array() method.
How can I fix this problem? really want to use set_array() method. Thank you very much.
A simple executable script is attached.
plot.py#googledrive
You need to work on the same image all the time. Best give this a name
img = ax.imshow(volume[ax.index])
You can then set the data for it using set_data.
import numpy as np
import matplotlib.pyplot as plt
#Mouse scroll event.
def mouse_scroll(event):
fig = event.canvas.figure
ax = fig.axes[0]
if event.button == 'down':
next_slice(ax)
fig.canvas.draw()
#Next slice func.
def next_slice(ax):
volume = ax.volume
ax.index = (ax.index - 1) % volume.shape[0]
img.set_array(volume[ax.index])
def mouse_click(event):
fig = event.canvas.figure
ax = fig.axes[0]
volume = np.random.rand(10, 10, 10)
ax.volume = volume
ax.index = (ax.index - 1) % volume.shape[0]
img.set_array(volume[ax.index])
fig.canvas.draw_idle()
if __name__ == '__main__':
fig, ax = plt.subplots()
volume = np.random.rand(40, 40, 40)
ax.volume = volume # volume is a 3D data, a 3d np array.
ax.index = 1
img = ax.imshow(volume[ax.index])
fig.canvas.mpl_connect('scroll_event', mouse_scroll)
fig.canvas.mpl_connect('button_press_event', mouse_click)
plt.show()
Edit 3/15/2017 12:00 PM CDT: I have managed to fix the error in the program and complete the program as it was designed. I would like to thank berna1111 and TigerhawkT3 for their answer submissions, as they allowed me to complete this program. Thanks again, Stack Overflow!
I am attempting to save a series of array-built histograms (arrays made with numpy and histograms using matplotlib) to .png type files. I am receiving the following error message:
Traceback (most recent call last):
File "C:/Users/Ryan/PycharmProjects/NWS/weather_data.py", line 475, in <module>
figure1.savefig("{}_temperature.png".format(filename))
AttributeError: 'tuple' object has no attribute 'savefig'
The section the error refers to is below:
figure1 = plt.hist(temperature_graph_array, color="blue")
figure2 = plt.hist(feelslike_graph_array, color="blue")
figure3 = plt.hist(windspeed_graph_array, color="blue")
figure4 = plt.hist(windgustspeed_graph_array, color="blue")
figure5 = plt.hist(pressure_graph_array, color="blue")
figure6 = plt.hist(humidity_graph_array, color="blue")
figure1.savefig("{}_temperature.png".format(filename), format='png')
figure2.savefig("{}_feelslike.png".format(filename), format='png')
figure3.savefig("{}_windspeed.png".format(filename), format='png')
figure4.savefig("{}_windgustspeed.png".format(filename), format='png')
figure5.savefig("{}_pressure.png".format(filename), format='png')
figure6.savefig("{}_humidity.png".format(filename), format='png')
Why am I receiving this error, and how can I fix it? If someone could let me know I would greatly appreciate it.
Notes:
I have done some google searching and found a few similar errors, but none where the figure was interpreted as a tuple. I do not understand where the tuple part is coming from.
The "_graph_array" items in the histogram creation steps are arrays of dimensions 10 long, 1 tall. 10 total items inside, designated as type Float.
The "filename" variable in the saving step represents a string containing the date and time.
From the documentation for matplotlib.pyplot.hist:
The return value is a tuple (n, bins, patches) or ([n0, n1, ...], bins, [patches0, patches1,...]) if the input contains multiple data.
From the documentation for matplotlib.pyplot.savefig:
Save the current figure.
It looks like you should call savefig in the same way you call hist, not on the result of the hist call.
plt.savefig("{}_temperature.png".format(filename), format='png')
...
I've adapted your code and took the liberty to change the several lines creating a figure by list in comprehension of for loops:
import matplotlib.pyplot as plt
# should be equal when using .pylab
import numpy.random as rnd
# generate_data
n_points = 1000
temperature_graph_array = rnd.random(n_points)
feelslike_graph_array = rnd.random(n_points)
windspeed_graph_array = rnd.random(n_points)
windgustspeed_graph_array = rnd.random(n_points)
pressure_graph_array = rnd.random(n_points)
humidity_graph_array = rnd.random(n_points)
list_of_data = [temperature_graph_array,
feelslike_graph_array,
windspeed_graph_array,
windgustspeed_graph_array,
pressure_graph_array,
humidity_graph_array]
list_of_names = ['temperature',
'feelslike',
'windspeed',
'windgustspeed',
'pressure',
'humidity']
# create the figures:
#figure1 = plt.figure()
#figure2 = plt.figure()
#figure3 = plt.figure()
#figure4 = plt.figure()
#figure5 = plt.figure()
#figure6 = plt.figure()
#list_of_figs = [figure1, figure2, figure3, figure4, figure5, figure6]
## could be:
list_of_figs = [plt.figure() for i in range(6)]
# create the axis:
#ax1 = figure1.add_subplot(111)
#ax2 = figure2.add_subplot(111)
#ax3 = figure3.add_subplot(111)
#ax4 = figure4.add_subplot(111)
#ax5 = figure5.add_subplot(111)
#ax6 = figure6.add_subplot(111)
#list_of_axis = [ax1, ax2, ax3, ax4, ax5, ax6]
## could be:
list_of_axis = [fig.add_subplot(111) for fig in list_of_figs]
# plot the histograms
# notice `plt.hist` returns a tuple (n, bins, patches) or
# ([n0, n1, ...], bins, [patches0, patches1,...]) if the input
# contains multiple data
#hist1 = ax1.hist(temperature_graph_array, color="blue")
#hist2 = ax2.hist(feelslike_graph_array, color="blue")
#hist3 = ax3.hist(windspeed_graph_array, color="blue")
#hist4 = ax4.hist(windgustspeed_graph_array, color="blue")
#hist5 = ax5.hist(pressure_graph_array, color="blue")
#hist6 = ax6.hist(humidity_graph_array, color="blue")
#list_of_hists = [hist1, hist2, hist3, hist4, hist5, hist6]
## could be:
list_of_hists = []
for i, ax in enumerate(list_of_axis):
list_of_hists.append(ax.hist(list_of_data[i], color="blue"))
filename = 'output_graph'
for i, fig in enumerate(list_of_figs):
name = list_of_names[i].capitalize()
list_of_axis[i].set_title(name)
fig.tight_layout()
fig.savefig("{}_{}.png".format(filename,name), format='png')
Will not post the resulting figures, but this gives me 6 little .png files in the same folder as the script.
Even better, you can use a function to do all that to your data:
def save_hist(data, name, filename):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.hist(data, color="blue")
ax.set_title(name)
fig.tight_layout()
fig.savefig("{}_{}.png".format(filename,name), format='png')
plt.close(fig)
filename = 'output_graph_2'
for data, name in zip(list_of_data, list_of_names):
save_hist(data, name, filename)
Here is my program in python and I am trying to save multiple plots in a single folder but it doesn't seem to work. How could I do this please?
for i in range(0:244):
plt.figure()
y = numpy.array(Data_EMG[i,:])
x = pylab.linspace(EMG_start, EMG_stop, Amount_samples)
plt.xlabel('Time(ms)')
plt.ylabel('EMG voltage(microV)')
pylab.plot(x, y)
pylab.show(block=True)
You can use the savefig function.
for i in range(0:244):
plt.figure()
y = numpy.array(Data_EMG[i,:])
x = pylab.linspace(EMG_start, EMG_stop, Amount_samples)
plt.xlabel('Time(ms)')
plt.ylabel('EMG voltage(microV)')
plt.savefig('EMG {0}.jpg'.format(i))
plt.close()
First of all check the identation. Hopefully your code actually reads
for i in range(0:244):
plt.figure()
y = numpy.array(Data_EMG[i,:])
x = pylab.linspace(EMG_start, EMG_stop, Amount_samples)
plt.xlabel('Time(ms)')
plt.ylabel('EMG voltage(microV)')
pylab.plot(x, y)
pylab.show(block=True)
At each iteration you completely generate a new figure. That´s very ineffective. Also you just plot your figure on the screen and not actually save it. Better is
from os import path
data = numpy.array(Data_EMG) # convert complete dataset into numpy-array
x = pylab.linspace(EMG_start, EMG_stop, Amount_samples) # doesn´t change in loop anyway
outpath = "path/of/your/folder/"
fig, ax = plt.subplots() # generate figure with axes
image, = ax.plot(x,data[0]) # initialize plot
ax.xlabel('Time(ms)')
ax.ylabel('EMG voltage(microV)')
plt.draw()
fig.savefig(path.join(outpath,"dataname_0.png")
for i in range(1, len(data)):
image.set_data(x,data[i])
plt.draw()
fig.savefig(path.join(outpath,"dataname_{0}.png".format(i))
Should be much faster.