/
analyze.py
244 lines (203 loc) · 8 KB
/
analyze.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
from spectrum import DFSpec
import time
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['figure.subplot.hspace']=0.5
mpl.rcParams['backend']='TkAgg'
import Tkinter as tk
import tkFileDialog as tkf
import re
import os.path
from uncertainties import ufloat
from uncertainties.umath import sqrt
#an example function, if the spectrum class doesn't contain a
#needed method
def Slope(spec):
return spec.getSlope(spec.lockPointX()[0])
#a list with the properties of interest. entries are from the DFSpec methods
#or other supported functions
#supported functions have to take one DFSpec argument and return either a value or
#a list of the form [value, error]
global prop
prop=[DFSpec.lockPointX, DFSpec.lockPointY, Slope, DFSpec.lockPrecision, DFSpec.meanPeakWidth, DFSpec.getChiSquareRed]
global fitstyle
fitstyle='simplevoigt'
global noise
noise=0
#if multiple measurement points shall be averaged for one property point
#set this to something greater than 1
numPoints=0
#prevent plt from blocking
plt.ion()
#------------------UTILITY FUNCTIONS---------------------------
def analyzation(dateien):
#list with names of the fitted files
files=[]
#list with names of the evaluated properties
propNames=[]
for p in prop:
propNames.append(p.__name__)
#list containing lists of every spectrums parameters
params=[]
#list containing lists of every spectrums parameters' errors
paramErrs=[]
#list with lists of every evaluated poperty's values
propVals=[]
#list containing errors of the evaluated properties
propErrs=[]
#list containing the Spectrum objects
specs=[]
for i in xrange(21):
params.append([])
paramErrs.append([])
for i in prop:
propVals.append([])
propErrs.append([])
#index for deciding when to begin a new plot
j=0
#variable to store noise level
noise=0
for datei in dateien:
print datei
if datei.endswith('.npy'):
data=np.load(datei)
elif datei.endswith('.csv') or datei.endswith('.txt'):
try:
data=np.loadtxt(datei)
except:
print 'could not open file '+datei
continue
else:
print 'unknown format '+ datei
continue
s=DFSpec([data[3],data[1]])
s.setAlpha(0.01)
if j==0 and not noise:
s.fit()
s.noisefit1()
noise=s.noise_level
s.setStyle(fitstyle)
s.noise_level=noise
s.fit()
if not s.isValid():
print 'invalid spectrum, skipped: '+datei[-15:]
continue
files.append('...'+datei[-15:-4])
specs.append(s)
for i in xrange(len(s.params)):
params[i].append(s.params[i])
paramErrs[i].append(s.errors[i])
#now get the desired properties
for i in xrange(len(prop)):
#prop[i] is a function or class method taking s as an argument
r=prop[i](s)
#maybe prop[i] returns a tuple of value and error or only one value without error
if type(r)==list or type(r) == tuple:
propVals[i].append(r[0])
propErrs[i].append(r[1])
else:
#there is no error for this value so set it to zero
propVals[i].append(r)
propErrs[i].append(0)
#create a new figure for the spectra if the current is full
if j%20 == 0:
plt.figure(figsize=(20,20))
plt.subplot(5,4,j%20+1)
s.plot()
plt.draw()
j+=1
#get the folder of the files
folder=os.path.dirname(dateien[0])+'/'
filename=folder+'_'.join([str(x) for x in time.localtime()[:6]])+'.log'
#write the results to file
saveLog(files, propNames, params, paramErrs, propVals, propErrs, filename)
return files, propNames, params, paramErrs, propVals, propErrs
def saveLog(files, propNames, params, paramErrs, propVals, propErrs, filename=None, listsep='\n', valsep=' '):
''' this function saves the data contained in the arguments. files and propnames must be lists of values,
the other arguments lists of lists of values. listsep and valsep are the seperation characters for lists and values.
if no filename is given, the date and time is taken.'''
#header for the logfile.
log='This is a logfile generated by analyze.py - lines containing the following: 1. filenames of the fitted spectra 2. names of the evaluated parameters 3. fitparameters of the spectra (one line for every parameter, in order of the filenames, this applies to the rest of the file) 4. errors of the fitparameters 5. evaluated properties 6. errors of the properties\n'
#the lists are seperated by listsep, the values are seperated by valsep
for x in files, propNames:
log+=valsep.join([str(y) for y in x])
log+=listsep
for x in params, paramErrs, propVals, propErrs:
for y in x:
log+=valsep.join([str(z) for z in y])
log+=listsep
#remove the last listsep
log=log[:-(len(listsep))]
if not filename:
filename='_'.join([str(x) for x in time.localtime()[:6]])+'.log'
f=open(filename,'w')
f.write(log)
f.close()
def loadLog(filename, listsep='\n', valsep=' '):
f=open(filename, 'r')
header=f.readline()
print header
raw_data=f.read()
lists=[x.split(valsep) for x in raw_data.split(listsep)]
numlists=len(lists)
files, propNames = lists[:2]
numprops=len(propNames)
numparams=(numlists-2*numprops-2)/2
params=[[float(x) for x in l] for l in lists[2:numparams+2]]
paramErrs=[[float(x) for x in l] for l in lists[numparams+2:2*numparams+2]]
propVals=[[float(x) for x in l] for l in lists[-2*numprops:-numprops]]
propErrs=[[float(x) for x in l] for l in lists[-numprops:]]
return files, propNames, params, paramErrs, propVals, propErrs
#-----------------PROGRAM START------------------------
root=tk.Tk()
root.title("data analysis")
dateien=unicode(tkf.askopenfilenames())
dateien=re.findall('{.*?}',dateien)
root.destroy()
for i in xrange(len(dateien)):
dateien[i]=dateien[i].replace('{','')
dateien[i]=dateien[i].replace('}','')
if len(dateien) == 1 and dateien[0].endswith('.log'):
files, propNames, params, paramErrs, propVals, propErrs = loadLog(dateien[0])
else:
files, propNames, params, paramErrs, propVals, propErrs = analyzation(dateien)
#this part is for the case multiple measurements have been performed
#with the same parameters -> set numpoints to this value
if numPoints>1:
newpropVals=[]
newpropErrs=[]
#construct an array with values and errors using the uncertainties package
valNerr=[[ufloat(propVals[i][j],propErrs[i][j]) for j in xrange(len(propVals[i]))] for i in xrange(len(propVals))]
valNerr=np.array(valNerr)
for line in valNerr:
valtemp=[]
errtemp=[]
for i in xrange(len(line)/numPoints):
#temporary, this should be checked for correct propagation of errors!
l=line[numPoints*i:numPoints*(i+1)]
mean=l.mean()
std=sqrt(l.var())
valtemp.append(mean.n)
errtemp.append(std.n)
newpropVals.append(valtemp)
newpropErrs.append(errtemp)
propVals=newpropVals
propErrs=newpropErrs
#create a figure for the parameters
plt.figure(figsize=(20,20))
#plot the parameters
for i in xrange(len(params)):
plt.subplot(5,5,i+1)
plt.errorbar(range(len(params[i])),params[i],paramErrs[i])
#set the function name as plot title
plt.title('Parameter %d' % (i))
#create a figure for the evaluation of the given properties
plt.figure(figsize=(20,20))
#plot the properties
for i in xrange(len(propVals)):
plt.subplot(5,len(propVals)/5+1,i+1)
plt.errorbar(range(len(propVals[i])),propVals[i],propErrs[i])
#set the function name as plot title
plt.title(propNames[i])
plt.show()