How to use matplotlib save multiple plots to a file in loop - python

x = [1 2 5 6 3 .....]
n = len(x)//34
i = 0
while i < n*34:
fig, axs = plt.subplots(2)
axs[0].plot(x[i:34+i],y[i:34+i],x_l[i:34+i],y_l[i:34+i]) #knee
axs[1].plot(x_a[i:34+i],y_a[i:34+i],color = 'red') #ank
axs[1].plot(x_l_a[i:34+i],y_l_a[i:34+i],color = 'green')
axs[0].axis('off')
axs[1].axis('off')
plt.savefig('test')
i = i + 17
The code above will only save the last plot in my file, but I would like to generate and save the multiple plots for different values of i.

Currently, you are overwriting the same "test" file on every iteration; as such, when your program completes, you are left with only the last figure saved to disk. If you want to save multiple files, you need to use a different filename on every iteration in your call to savefig.
For example, you may use the iteration variable i and change your call to:
plt.savefig("test{}".format(i))

Related

Weird "demonic" xtick in matplotlib (jpeg artifacts? No way...)

So I'm comparing NBA betting lines between different sportsbooks over time
Procedure:
Open pickle file of scraped data
Plot the scraped data
The pickle file is a dictionary of NBA betting lines over time. Each of the two teams are their own nested dictionary. Each key in these team-specific dictionaries represents a different sportsbook. The values for these sportsbook keys are lists of tuples, representing timeseries data. It looks roughly like this:
dicto = {
'Time': <time that the game starts>,
'Team1': {
Market1: [ (time1, value1), (time2, value2), etc...],
Market2: [ (time1, value1), (time2, value2), etc...],
etc...
}
'Team2': {
<SAME FORM AS TEAM1>
}
}
There are no issues with scraping or manipulating this data. The issue comes when I plot it. Here is the code for the script that unpickles and plots these dictionaries:
import matplotlib.pyplot as plt
import pickle, datetime, os, time, re
IMAGEPATH = 'Images'
reg = re.compile(r'[A-Z]+#[A-Z]+[0-9|-]+')
noDate = re.compile(r'[A-Z]+#[A-Z]+')
# Turn 1 into '01'
def zeroPad(num):
if num < 10:
return '0' + str(num)
else:
return num
# Turn list of time-series tuples into an x list and y list
def unzip(lst):
x = []
y = []
for i in lst:
x.append(f'{i[0].hour}:{zeroPad(i[0].minute)}')
y.append(i[1])
return x, y
# Make exactly 5, evenly spaced xticks
def prune(xticks):
last = len(xticks)
first = 0
mid = int(len(xticks) / 2) - 1
upMid = int( mid + (last - mid) / 2)
downMid = int( (mid - first) / 2)
out = []
count = 0
for i in xticks:
if count in [last, first, mid, upMid, downMid]:
out.append(i)
else:
out.append('')
count += 1
return out
def plot(filename, choice):
IMAGEPATH = 'Images'
IMAGEPATH = os.path.join(IMAGEPATH, choice)
with open(filename, 'rb') as pik:
dicto = pickle.load(pik)
fig, axs = plt.subplots(2)
gameID = noDate.search(filename).group(0)
tm = dicto['Time']
fig.suptitle(gameID + '\n' + str(tm))
i = 0
for team in dicto.keys():
axs[i].set_title(team)
if team == 'Time':
continue
for market in dicto[team].keys():
lst = dicto[team][market]
x, y = unzip(lst)
axs[i].plot(x, y, label= market)
axs[i].set_xticks(prune(x))
axs[i].set_xticklabels(rotation=45, labels = x)
i += 1
plt.tight_layout()
#Finish
outputFile = reg.search(filename).group(0)
date = (datetime.datetime.today() - datetime.timedelta(hours = 6)).date()
fig.savefig(os.path.join(IMAGEPATH, str(date), f'{outputFile}.png'))
plt.close()
Here is the image that results from calling the plot function on one of the dictionaries that I described above. It is pretty much exactly as I intended it, except for one very strange and bothersome problem.
You will notice that the bottom right tick looks haunted, demonic, jpeggy, whatever you want to call it. I am highly suspicious that this problem occurs in the prune function, which I use to set the xtick values of the plot.
The reason that I prune the values with a function like this is because these dictionaries are continuously updated, so setting a static number of xticks would not work. And if I don't prune the xticks, they end up becoming unreadable due to overlapping one another.
I am quite confused as to what could cause an xtick to look like this. It happens consistently, for every dictionary, every time. Before I added the prune function (when the xticks unbound, overlapping one another), this issue did not occur. So when I say I'm suspicious that the prune function is the cause, I am really quite certain.
I will be happy to share an instance of one of these dictionaries, but they are saved as .pickle files, and I'm pretty sure it's bad practice to share pickle files over the internet. I have been warned about potential malware, so I'll just stay away from that. But if you need to see the dictionary, I can take the time to prettily print one and share a screenshot. Any help is greatly appreciated!
Matplotlib does this when there are many xticks or yticks which are plotted on the same value. It is normal. If you can limit the number of times the specific value is plotted - you can make it appear indistinguishable from the rest of the xticks.
Plot a simple example to test this out and you will see for yourself.

How to append numpy x and y values into a text file

I have some code which creates an x variable (frames) and a y variable (pixel intensity) in an infinite loop until the program ends. I would like to append these values every loop into a txt.file so that I can later work with the data. The data comes out as numpy arrays.
Say for example after 5 loops(5 frames) I get these values
1 2 3 4 5 (x values)
0 0 8 0 0 (y values)
I would like it to append these into a file every loop so I get after closing the program this:
1, 0
2, 0
3, 8
4, 0
5, 0
What would be the fastest way to implement this?
So far I have tried np.savetxt('data.txt', x) but this only saves the last value in the loop and doesn't add the data each loop. Is there a way to change this function or another function I could use that adds the data into the txt document.
First I will zip the values into (x,y) coordinate form and put them into a list so it is easier to append them to a text file, in your program you won't need to do this since you will have generated the x and y already within the loop prior.
x = [1, 2, 3, 4 ,5] #(x values)
y = [0, 0, 8, 0, 0] #(y values)
coordinate = list(zip(x,y))
print(coordinate)
So I used the Zip function, to store the sample results as (x_n, y_n) to a list for later.
Here is what I am appending to the text file with the below for loop (in the terminal display)
With in the loop itself you can use:
for element in coordinate: #you wouldn't need to write this since you are already in a loop
file1 = open("file.txt","a")
file1.write(f"{element} \n")
file1.close()
Output:
You can do something like this -- it is not complete because it will just append to the old file. The other issue with this is that it will not actually write the file until you close it. If you really need the file saved each time in the loop, then another solution is required.
import numpy as np
variable_to_ID_file = 3.
file_name_str = 'Foo_Var{0:.0f}.txt'.format(variable_to_ID_file)
# Need code here to delete old file if it is there
# with proper error checking, or write a blank file, then open it in append mode.
f_id = open(file_name_str, 'a')
for ii in range(4):
# Pick the delimiter you desire. I prefer tab '/t'
np.savetxt(f_id, np.column_stack((ii, 3*ii/4)), delimiter=', ', newline ='\n')
f_id.close()
If you do not need to write the file for each step in the loop, I recommend this option. It requires the Numpy arrays to be the same size.
import numpy as np
array1 = np.arange(1,5,1)
array2 = np.zeros(array1.size)
variable_to_ID_file = 3.
file_name_str = 'Foo_Var{0:.0f}.txt'.format(variable_to_ID_file)
# Pick the delimiter you desire. I prefer tab '/t'
np.savetxt(file_name_str, np.column_stack((array1, array2)), delimiter=', ')

for loop in for loop sumation is overwriting data values python

I have a question concering my code for a data evaluation of an experiment:
in a first for loop I am opening file after file which I want to analyze. inside this for loop, so inside one file, I want to create a second for loop to evaluate the some specific paramters for evaluation. when I do it just for one file, the parameters are correct, but when I loop over all files, it looks like in the second for loop these paramteres are summed up. so the normal value should be in the range of ar= 0.0001, for one file perfectly working. when I loop over the files I then get 0.0001 for the first one, 0.0002 for the second, 0.0003 for the thrid, etc.
update:
ok so here is the whole part of the code. for each file I want after fitting the data to get the sum over the difference between two datapoints in the first column (x[j]) inside the file multiplicated by the coressponding value in the second columnn (y[j]) (each file has two columns with a length of 720 datapoints) and the result of this should then be stored in AR for each file.
def sum_list(l):
sum = 0
for k in l:
sum += k
return sum
INV= []
DIFFS= []
AR= []
for i in range(0,len(fnames)):
data= np.loadtxt(fnames[i])
x= data[:,0]
y=data[:,1]
gmod=lm.Model(linmod)
result= gmod.fit(y, x=x, p=0.003, bg=0.001)
plt.plot(x, y)
plt.plot(x, result.best_fit, 'r-')
plt.show()
print result.best_values['bg']
print result.best_values['p']
p= result.best_values['p']
bg1= result.best_values['bg']
for j in range(0, 719):
diffs = ((x[j+1]- x[j])*y[j])
DIFFS.append(diffs)
ar= sum_list(DIFFS)
AR.append(ar)
inr= (x[0]-bg1)*(y[0]**3)/3 + ar
INV[i]= inr
If you are working with files (e.g opening them), I suggest to use os module, maybe a construct like this will help you to avoid the nested for loop:
for root,dirs,files in os.walk(os.getcwd()):
for i in files:
with open(os.path.join(root,i)) as f:
#do your summation

pandas plot - plot specific lines in file

I am using the following code for pandas plot. It takes in a file, and makes plots for specific lines (locus ID's: i.e. 'loc.27404').
However, this code manually specifies the lines which I want to plot.
I have a another file containing all the lines (there are 100s) that I want to plot - how can I write a script that will allow me to input this file such that so that these specific lines are plotted using the below code. I can't seem to write anything that makes sense.
data = {}
for line in File:
cols = line.strip().split('\t')
vals = map(float,cols[6:])
data[cols[3]] = vals
fig,ax = plt.subplots(4,figsize=[15,20])
l1= 'loc.27404'
l2= 'loc.37387'
l3 = 'loc.05134'
l4 = 'loc.10034'
pd.Series(data[l1],index=xticks).plot(ax=ax[0])
pd.Series(data[l2],index=xticks).plot(ax=ax[1])
pd.Series(data[l3],index=xticks).plot(ax=ax[2])
pd.Series(data[l4],index=xticks).plot(ax=ax[3])
A potential solution would be to read the 100s of lines and store results in a list, like: ['loc.27404','loc.37387','loc.05134','loc.10034'] to be used in a for-loop:
for i,line_to_plot in enumerate(['loc.27404','loc.37387','loc.05134','loc.10034']):
pd.Series(data[line_to_plot],index=xticks).plot(ax=ax[i])

Python add text to matplotlib.image.AxesImage instance

i have this code for creating a series of image from a series of matrixes, and in each image i want to add a specific text. this is my typical code :
ax = axes([0,0,1,1])
for i in range(0,5):
text(1,1,str(i))
ax.imshow(a[:,:,i],origin='lower')
savefig(str("%04d" % int(i))+'.png',format="png")
del ax.texts[-1]
but the problem is that as the number of iteration increases, the speed decease and it becomes so so slow. It seems that there is something wrong with opening a lot of windows in background.
Any suggestion?
Instead of creating a new image and text objects every loop reuse the objects.
ax = axes([0,0,1,1])
t = text(1,1,str(0))
img = ax.imshow(a[:,:,0],origin='lower')
for i in range(0,5):
t.set_text(str(i)
img.set_data(a[:,:,i])
savefig(str("%04d" % int(i))+'.png',format="png")
also see
Visualization of 3D-numpy-array frame by frame
I just added this single line at the end of the loop and it works fine now. It was simply the problem of accumulating previuosly opened figures in the memory.
ax = axes([0,0,1,1])
for i in range(0,5):
text(1,1,str(i))
ax.imshow(a[:,:,i],origin='lower')
savefig(str("%04d" % int(i))+'.png',format="png")
del ax.texts[-1]
close(gcf())

Categories

Resources