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.
Related
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()
I am trying to make an animation with matplotlib.animation, using the ArtistAnimation function. I have a large matrix and I want to show a different part of this matrix in a colormap using plt.imshow() in each frame. However, only one frame is shown in the animation and I don't know why. I tried to mimic the code in An animated image using a list of images. I have looked at this question and this question, but I could not find a solution there.
This is my code:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
def make_animation(pwv_matrix, length_side):
pwv_shape = pwv_matrix.shape
fig = plt.figure()
num_frames = min(pwv_shape[0], pwv_shape[1])-length_side
y_min = int(np.round(pwv_shape[0]/2) - np.round(length_side/2))
y_max = int(np.round(pwv_shape[0]/2) + np.round(length_side/2))
x_min = 0
x_max = length_side
ims = []
for i in range(0, num_frames):
pwv_frame = pwv_matrix[x_min:x_max, y_min:y_max]
im = plt.imshow(pwv_frame, animated=True, cmap = 'viridis')
ims.append([im])
x_min += 1
x_max += 1
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,
repeat_delay=1000)
plt.show()
x = np.linspace(0, 1, 200)
y = np.linspace(0, 1, 200)
pwv_matrix, yv = np.meshgrid(x, y)
length_side = 20 #m
make_animation(pwv_matrix, length_side)
where self.pwv_matrix is a large matrix obtained from a .dat file. Does anyone see the problem?
Thanks very much in advance!
Try adding a very small delay after the show() function with
matplotlib.pyplot.pause(interval)[source]
function or:
from time import sleep
sleep(0.05)
The actual drawing of the image occurs one you give it some processing time (in a very simplified way of explaining it)
If it does not work there are some other things you might try, let me know if it doesn't work
I want to plot data in matplotlib in real time. I want to open a figure once at the start of the programme, then update the figure when new data is acquired. Despite there being a few similar questions out there, none quite answer my specific question.
I want each set of data points new_data1 and new_data2 to be plotted on the same figure at the end of each while loop i.e. one line after the first while loop, two lines on the same figure after the second while loop etc. Currently they are all plotted together, but only right at the end of the programme, which is no use for real time data acquisition.
import matplotlib.pyplot as plt
import numpy
hl, = plt.plot([], [])
def update_line(hl, new_datax, new_datay):
hl.set_xdata(numpy.append(hl.get_xdata(), new_datax))
hl.set_ydata(numpy.append(hl.get_ydata(), new_datay))
plt.xlim(0, 50)
plt.ylim(0,200)
plt.draw()
x = 1
while x < 5:
new_data1 = []
new_data2 = []
for i in range(500):
new_data1.append(i * x)
new_data2.append(i ** 2 * x)
update_line(hl, new_data1, new_data2)
x += 1
else:
print("DONE")
This programme plots all 5 lines, but at the end of the programme. I want each line to be plotted after one another, after the while loop is completed. I have tried putting in plt.pause(0.001) in the function, but it has not worked.
This programme is different from the one that has been put forward - that programme only plots one graph and does not update with time.
If I correctly understood your specifications, you can modify just a bit your MWE as follows:
import matplotlib.pyplot as plt
import numpy
fig = plt.figure(figsize=(11.69,8.27))
ax = fig.gca()
ax.set_xlim(0, 50)
ax.set_ylim(0,200)
hl, = plt.plot([], [])
def update_line(hl, new_datax, new_datay):
# re initialize line object each time if your real xdata is not contiguous else comment next line
hl, = plt.plot([], [])
hl.set_xdata(numpy.append(hl.get_xdata(), new_datax))
hl.set_ydata(numpy.append(hl.get_ydata(), new_datay))
fig.canvas.draw_idle()
fig.canvas.flush_events()
x = 1
while x < 10:
new_data1 = []
new_data2 = []
for i in range(500):
new_data1.append(i * x)
new_data2.append(i ** 2 * x)
update_line(hl, new_data1, new_data2)
# adjust pause duration here
plt.pause(0.5)
x += 1
else:
print("DONE")
which displays :
Not sure, if I am reading the requirements right but below is a blueprint. Please change it to suit your requirements. You may want to change the function Redraw_Function and edit the frames (keyword parameter, which is np.arange(1,5,1) ) in the FuncAnimation call. Also interval=1000 means 1000 milliseconds of delay.
If you are using Jupyter then comment out the second last line (where it says plt.show()) and uncomment the last line. This will defeat your purpose of real time update but I am sorry I had trouble making it work real time in Jupyter. However if you are using python console or official IDLE please run the code as it is. It should work nicely.
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
plot, = plt.plot([],[])
def init_function():
ax.set_xlim(0,50)
ax.set_ylim(0,250)
return plot,
def Redraw_Function(UpdatedVal):
new_x = np.arange(500)*UpdatedVal
new_y = np.arange(500)**2*UpdatedVal
plot.set_data(new_x,new_y)
return plot,
Animated_Figure = FuncAnimation(fig,Redraw_Function,init_func=init_function,frames=np.arange(1,5,1),interval=1000)
plt.show()
# Animated_Figure.save('MyAnimated.gif',writer='imagemagick')
When you run the code, you obtain the below result. I tried to keep very little code but I am sorry, if your requirement was totally different.
Best Wishes,
I have lists of ~10 corresponding input files containing columns of tab separated data approx 300 lines/datapoints each.
I'm looking to plot the contents of each set of data such that I have a 2 plots for each set of data one is simply of x vs (y1,y2,y3,...) and one which is transformed by a function e.g. x vs (f(y1), f(y2),f(y3),...).
I am not sure of the best way to achieve it, I thought about using a simple array of filenames then couldn't work out how to store them all without overwriting the data - something like this:
import numpy as np
import matplotlib.pyplot as plt
def ReadDataFile(file):
print (file)
x,y = np.loadtxt(file, unpack=True, usecols=(8,9))
return x, y
inputFiles = ['data1.txt','data2.txt','data2.txt',...]
for file in inputFiles:
x1,y1 = ReadDataFile(file) ## ? ##
p1,q1 = function(x1,y1) ## ? ##
plt.figure(1)
plt.plot(x1,y1)
plt.plot(x2,y2)
...
# plt.savefig(...)
plt.figure(2)
plt.plot(p1,q1)
plt.plot(p2,q2)
...
# plt.savefig(...)
plt.show()
I guess my question is how to best read and store all the data and maintain tha ability to access it without needing to put all the code in the readloop. Can I read two data sets into a list of pairs? Is that a thing in Python? if so, how do I access them?
Thanks in advance for any help!
Best regards!
Basically, I think you should put all your code in the readloop, because that will work easily. There's a slightly different way of using matplotlib that makes it easy to use the existing organization of your data AND write shorter code. Here's a toy, but complete, example:
import matplotlib.pyplot as plt
from numpy.random import random
fig, axs = plt.subplots(2)
for c in 'abc': # In your case, for filename in [file-list]:
x, y = random((2, 5))
axs[0].plot(x, y, label=c) # filename instead of c in your case
axs[1].plot(x, y**2, label=c) # Plot p(x,y), q(x,y) in your case
axs[0].legend() # handy to get this from the data list
fig.savefig('two_plots.png')
You can also create two figures and plot into each of them explicitly, if you need them in different files for page layout, etc:
import matplotlib.pyplot as plt
from numpy.random import random
fig1, ax1 = plt.subplots(1)
fig2, ax2 = plt.subplots(1)
for c in 'abc': # or, for filename in [file-list]:
x, y = random((2, 5))
ax1.plot(x, y, label=c)
ax2.plot(x, y**2, label=c)
ax1.legend()
ax2.legend()
fig1.savefig('two_plots_1.png')
fig2.savefig('two_plots_2.png')
I'm trying to go away from matlab and use python + matplotlib instead. However, I haven't really figured out what the matplotlib equivalent of matlab 'handles' is. So here's some matlab code where I return the handles so that I can change certain properties. What is the exact equivalent of this code using matplotlib? I very often use the 'Tag' property of handles in matlab and use 'findobj' with it. Can this be done with matplotlib as well?
% create figure and return figure handle
h = figure();
% add a plot and tag it so we can find the handle later
plot(1:10, 1:10, 'Tag', 'dummy')
% add a legend
my_legend = legend('a line')
% change figure name
set(h, 'name', 'myfigure')
% find current axes
my_axis = gca();
% change xlimits
set(my_axis, 'XLim', [0 5])
% find the plot object generated above and modify YData
set(findobj('Tag', 'dummy'), 'YData', repmat(10, 1, 10))
There is a findobj method is matplotlib too:
import matplotlib.pyplot as plt
import numpy as np
h = plt.figure()
plt.plot(range(1,11), range(1,11), gid='dummy')
my_legend = plt.legend(['a line'])
plt.title('myfigure') # not sure if this is the same as set(h, 'name', 'myfigure')
my_axis = plt.gca()
my_axis.set_xlim(0,5)
for p in set(h.findobj(lambda x: x.get_gid()=='dummy')):
p.set_ydata(np.ones(10)*10.0)
plt.show()
Note that the gid parameter in plt.plot is usually used by matplotlib (only) when the backend is set to 'svg'. It use the gid as the id attribute to some grouping elements (like line2d, patch, text).
I have not used matlab but I think this is what you want
import matplotlib
import matplotlib.pyplot as plt
x = [1,3,4,5,6]
y = [1,9,16,25,36]
fig = plt.figure()
ax = fig.add_subplot(111) # add a plot
ax.set_title('y = x^2')
line1, = ax.plot(x, y, 'o-') #x1,y1 are lists(equal size)
line1.set_ydata(y2) #Use this to modify Ydata
plt.show()
Of course, this is just a basic plot, there is more to it.Go though this to find the graph you want and view its source code.
# create figure and return figure handle
h = figure()
# add a plot but tagging like matlab is not available here. But you can
# set one of the attributes to find it later. url seems harmless to modify.
# plot() returns a list of Line2D instances which you can store in a variable
p = plot(arange(1,11), arange(1,11), url='my_tag')
# add a legend
my_legend = legend(p,('a line',))
# you could also do
# p = plot(arange(1,11), arange(1,11), label='a line', url='my_tag')
# legend()
# or
# p[0].set_label('a line')
# legend()
# change figure name: not sure what this is for.
# set(h, 'name', 'myfigure')
# find current axes
my_axis = gca()
# change xlimits
my_axis.set_xlim(0, 5)
# You could compress the above two lines of code into:
# xlim(start, end)
# find the plot object generated above and modify YData
# findobj in matplotlib needs you to write a boolean function to
# match selection criteria.
# Here we use a lambda function to return only Line2D objects
# with the url property set to 'my_tag'
q = h.findobj(lambda x: isinstance(x, Line2D) and x.get_url() == 'my_tag')
# findobj returns duplicate objects in the list. We can take the first entry.
q[0].set_ydata(ones(10)*10.0)
# now refresh the figure
draw()