mirror of
https://github.com/fjosw/pyerrors.git
synced 2025-03-15 14:50:25 +01:00
correlators module cleaned up, GUI_range_finder commented out for now
This commit is contained in:
parent
44cd3d52bd
commit
c09a56b9c0
3 changed files with 348 additions and 371 deletions
File diff suppressed because one or more lines are too long
|
@ -15,240 +15,237 @@ class Corr:
|
||||||
One often wants to add or multiply correlators of the same length at every timeslice and it is inconvinient
|
One often wants to add or multiply correlators of the same length at every timeslice and it is inconvinient
|
||||||
to iterate over all timeslices for every operation. This is especially true, when dealing with smearing matrices.
|
to iterate over all timeslices for every operation. This is especially true, when dealing with smearing matrices.
|
||||||
|
|
||||||
The correlator can have two types of content: An Obs at every timeslice OR a GEVP
|
The correlator can have two types of content: An Obs at every timeslice OR a GEVP
|
||||||
smearing matrix at every timeslice. Other dependency (eg. spacial) are not supported.
|
smearing matrix at every timeslice. Other dependency (eg. spacial) are not supported.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, data_input,padding_front=0,padding_back=0):
|
def __init__(self, data_input,padding_front=0,padding_back=0):
|
||||||
#All data_input should be a list of things at different timeslices. This needs to be verified
|
#All data_input should be a list of things at different timeslices. This needs to be verified
|
||||||
|
|
||||||
if not isinstance(data_input,list):
|
if not isinstance(data_input,list):
|
||||||
raise TypeError('Corr__init__ expects a list of timeslices.')
|
raise TypeError('Corr__init__ expects a list of timeslices.')
|
||||||
# data_input can have multiple shapes. The simplest one is a list of Obs.
|
# data_input can have multiple shapes. The simplest one is a list of Obs.
|
||||||
#We check, if this is the case
|
#We check, if this is the case
|
||||||
if all([isinstance(item,Obs) for item in data_input]):
|
if all([isinstance(item,Obs) for item in data_input]):
|
||||||
self.content=[np.asarray([item]) for item in data_input]
|
self.content=[np.asarray([item]) for item in data_input]
|
||||||
#Wrapping the Obs in an array ensures that the data structure is consistent with smearing matrices.
|
#Wrapping the Obs in an array ensures that the data structure is consistent with smearing matrices.
|
||||||
self.N=1 # number of smearings
|
self.N = 1 # number of smearings
|
||||||
|
|
||||||
#data_input in the form [np.array(Obs,NxN)]
|
#data_input in the form [np.array(Obs,NxN)]
|
||||||
elif all([isinstance(item,np.ndarray) or item==None for item in data_input]) and any([isinstance(item,np.ndarray)for item in data_input]):
|
elif all([isinstance(item,np.ndarray) or item==None for item in data_input]) and any([isinstance(item,np.ndarray)for item in data_input]):
|
||||||
self.content= data_input
|
self.content = data_input
|
||||||
|
|
||||||
noNull=[a for a in self.content if not (a is None)] #To check if the matrices are correct for all undefined elements
|
noNull=[a for a in self.content if not (a is None)] #To check if the matrices are correct for all undefined elements
|
||||||
self.N= noNull[0].shape[0]
|
self.N = noNull[0].shape[0]
|
||||||
# The checks are now identical to the case above
|
# The checks are now identical to the case above
|
||||||
if self.N>1 and noNull[0].shape[0]!=noNull[0].shape[1]:
|
if self.N > 1 and noNull[0].shape[0] != noNull[0].shape[1]:
|
||||||
raise Exception("Smearing matrices are not NxN")
|
raise Exception("Smearing matrices are not NxN")
|
||||||
if (not all([item.shape==noNull[0].shape for item in noNull])):
|
if (not all([item.shape == noNull[0].shape for item in noNull])):
|
||||||
raise Exception("Items in data_input are not of identical shape."+str(noNull))
|
raise Exception("Items in data_input are not of identical shape." + str(noNull))
|
||||||
|
|
||||||
else: # In case its a list of something else.
|
else: # In case its a list of something else.
|
||||||
raise Exception ("data_input contains item of wrong type")
|
raise Exception ("data_input contains item of wrong type")
|
||||||
|
|
||||||
#We now apply some padding to our list. In case that our list represents a correlator of length T but is not defined at every value.
|
#We now apply some padding to our list. In case that our list represents a correlator of length T but is not defined at every value.
|
||||||
#An undefined timeslice is represented by the None object
|
#An undefined timeslice is represented by the None object
|
||||||
self.content=[None]*padding_front+self.content+[None]*padding_back
|
self.content = [None] * padding_front + self.content + [None] * padding_back
|
||||||
self.T=len(self.content) #for convenience: will be used a lot
|
self.T = len(self.content) #for convenience: will be used a lot
|
||||||
|
|
||||||
|
|
||||||
self.gamma_method()
|
self.gamma_method()
|
||||||
|
|
||||||
|
|
||||||
def gamma_method(self):
|
def gamma_method(self):
|
||||||
for item in self.content:
|
for item in self.content:
|
||||||
if not(item is None):
|
if not(item is None):
|
||||||
if self.N==1:
|
if self.N == 1:
|
||||||
item[0].gamma_method()
|
item[0].gamma_method()
|
||||||
else:
|
else:
|
||||||
for i in range(self.N):
|
for i in range(self.N):
|
||||||
for j in range(self.N):
|
for j in range(self.N):
|
||||||
item[i,j].gamma_method()
|
item[i,j].gamma_method()
|
||||||
|
|
||||||
|
#We need to project the Correlator with a Vector to get a single value at each timeslice.
|
||||||
|
#The method can use one or two vectors.
|
||||||
|
|
||||||
#We need to project the Correlator with a Vector to get a single value at each timeslice.
|
|
||||||
#The method can use one or two vectors.
|
|
||||||
#If two are specified it returns v1@G@v2 (the order might be very important.)
|
#If two are specified it returns v1@G@v2 (the order might be very important.)
|
||||||
#By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
|
#By default it will return the lowest source, which usually means unsmeared-unsmeared (0,0), but it does not have to
|
||||||
def projected(self,vector_l=None,vector_r=None):
|
def projected(self,vector_l=None,vector_r=None):
|
||||||
if self.N==1:
|
if self.N == 1:
|
||||||
raise Exception("Trying to project a Corr, that already has N=1.")
|
raise Exception("Trying to project a Corr, that already has N=1.")
|
||||||
#This Exception is in no way necessary. One could just return self
|
#This Exception is in no way necessary. One could just return self
|
||||||
#But there is no scenario, where a user would want that to happen and the error message might be more informative.
|
#But there is no scenario, where a user would want that to happen and the error message might be more informative.
|
||||||
|
|
||||||
self.gamma_method()
|
self.gamma_method()
|
||||||
|
|
||||||
if vector_l is None:
|
if vector_l is None:
|
||||||
vector_l,vector_r=np.asarray( [1.]+(self.N-1)*[0.]),np.asarray( [1.]+(self.N-1)*[0.])
|
vector_l,vector_r=np.asarray([1.] + (self.N - 1) * [0.]),np.asarray([1.] + (self.N - 1) * [0.])
|
||||||
elif(vector_r is None):
|
elif(vector_r is None):
|
||||||
vector_r=vector_l
|
vector_r=vector_l
|
||||||
|
|
||||||
if not vector_l.shape==vector_r.shape==(self.N,):
|
|
||||||
raise Exception("Vectors are of wrong shape!")
|
|
||||||
|
|
||||||
#We always normalize before projecting! But we only raise a warning, when it is clear, they where not meant to be normalized.
|
|
||||||
if (not(0.95<vector_r@vector_r<1.05)) or (not(0.95<vector_l@vector_l<1.05)):
|
|
||||||
print("Vectors are normalized before projection!")
|
|
||||||
|
|
||||||
vector_l,vector_r=vector_l/np.sqrt((vector_l@vector_l)),vector_r/np.sqrt(vector_r@vector_r)
|
|
||||||
|
|
||||||
newcontent=[None if (item is None) else np.asarray([vector_l.T@item@vector_r]) for item in self.content]
|
if not vector_l.shape == vector_r.shape == (self.N,):
|
||||||
|
raise Exception("Vectors are of wrong shape!")
|
||||||
|
|
||||||
|
#We always normalize before projecting! But we only raise a warning, when it is clear, they where not meant to be normalized.
|
||||||
|
if (not(0.95 < vector_r@vector_r < 1.05)) or (not(0.95 < vector_l@vector_l < 1.05)):
|
||||||
|
print("Vectors are normalized before projection!")
|
||||||
|
|
||||||
|
vector_l,vector_r = vector_l / np.sqrt((vector_l@vector_l)), vector_r / np.sqrt(vector_r@vector_r)
|
||||||
|
|
||||||
|
newcontent = [None if (item is None) else np.asarray([vector_l.T@item@vector_r]) for item in self.content]
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
#For purposes of debugging and verification, one might want to see a single smearing level. smearing will return a Corr at the specified i,j. where both are integers 0<=i,j<N.
|
#For purposes of debugging and verification, one might want to see a single smearing level. smearing will return a Corr at the specified i,j. where both are integers 0<=i,j<N.
|
||||||
def smearing(self,i,j):
|
def smearing(self, i, j):
|
||||||
if self.N==1:
|
if self.N == 1:
|
||||||
raise Exception("Trying to pick smearing from projected Corr")
|
raise Exception("Trying to pick smearing from projected Corr")
|
||||||
newcontent=[None if(item is None) else item[i,j] for item in self.content]
|
newcontent=[None if(item is None) else item[i, j] for item in self.content]
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
|
|
||||||
#Obs and Matplotlib do not play nicely
|
#Obs and Matplotlib do not play nicely
|
||||||
#We often want to retrieve x,y,y_err as lists to pass them to something like pyplot.errorbar
|
#We often want to retrieve x,y,y_err as lists to pass them to something like pyplot.errorbar
|
||||||
def plottable(self):
|
def plottable(self):
|
||||||
if self.N!=1:
|
if self.N != 1:
|
||||||
raise Exception("Can only make Corr[N=1] plottable") #We could also autoproject to the groundstate or expect vectors, but this is supposed to be a super simple function.
|
raise Exception("Can only make Corr[N=1] plottable") #We could also autoproject to the groundstate or expect vectors, but this is supposed to be a super simple function.
|
||||||
x_list=[x for x in range(self.T) if (not self.content[x] is None)]
|
x_list = [x for x in range(self.T) if (not self.content[x] is None)]
|
||||||
y_list=[y[0].value for y in self.content if (not y is None)]
|
y_list = [y[0].value for y in self.content if (not y is None)]
|
||||||
y_err_list=[y[0].dvalue for y in self.content if (not y is None)]
|
y_err_list = [y[0].dvalue for y in self.content if (not y is None)]
|
||||||
|
|
||||||
return x_list, y_list, y_err_list
|
return x_list, y_list, y_err_list
|
||||||
|
|
||||||
#symmetric returns a Corr, that has been symmetrized.
|
#symmetric returns a Corr, that has been symmetrized.
|
||||||
#A symmetry checker is still to be implemented
|
#A symmetry checker is still to be implemented
|
||||||
#The method will not delete any redundant timeslices (Bad for memory, Great for convenience)
|
#The method will not delete any redundant timeslices (Bad for memory, Great for convenience)
|
||||||
def symmetric(self):
|
def symmetric(self):
|
||||||
|
|
||||||
if self.T%2!=0:
|
if self.T%2 != 0:
|
||||||
raise Exception("Can not symmetrize odd T")
|
raise Exception("Can not symmetrize odd T")
|
||||||
|
|
||||||
newcontent=[self.content[0]]
|
newcontent = [self.content[0]]
|
||||||
for t in range(1,self.T):
|
for t in range(1, self.T):
|
||||||
if (self.content[t] is None) or (self.content[self.T-t] is None):
|
if (self.content[t] is None) or (self.content[self.T - t] is None):
|
||||||
newcontent.append(None)
|
newcontent.append(None)
|
||||||
else:
|
else:
|
||||||
newcontent.append(0.5*(self.content[t]+self.content[self.T-t]))
|
newcontent.append(0.5 * (self.content[t] + self.content[self.T - t]))
|
||||||
if(all([x is None for x in newcontent])):
|
if(all([x is None for x in newcontent])):
|
||||||
raise Exception("Corr could not be symmetrized: No redundant values")
|
raise Exception("Corr could not be symmetrized: No redundant values")
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
def anti_symmetric(self):
|
def anti_symmetric(self):
|
||||||
|
|
||||||
if self.T%2!=0:
|
if self.T%2 != 0:
|
||||||
raise Exception("Can not symmetrize odd T")
|
raise Exception("Can not symmetrize odd T")
|
||||||
|
|
||||||
newcontent=[self.content[0]]
|
newcontent=[self.content[0]]
|
||||||
for t in range(1,self.T):
|
for t in range(1, self.T):
|
||||||
if (self.content[t] is None) or (self.content[self.T-t] is None):
|
if (self.content[t] is None) or (self.content[self.T - t] is None):
|
||||||
newcontent.append(None)
|
newcontent.append(None)
|
||||||
else:
|
else:
|
||||||
newcontent.append(0.5*(self.content[t]-self.content[self.T-t]))
|
newcontent.append(0.5 * (self.content[t] - self.content[self.T - t]))
|
||||||
if(all([x is None for x in newcontent])):
|
if(all([x is None for x in newcontent])):
|
||||||
raise Exception("Corr could not be symmetrized: No redundant values")
|
raise Exception("Corr could not be symmetrized: No redundant values")
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#This method will symmetrice the matrices and therefore make them positive definit.
|
#This method will symmetrice the matrices and therefore make them positive definit.
|
||||||
def smearing_symmetric(self):
|
def smearing_symmetric(self):
|
||||||
if self.N>1:
|
if self.N > 1:
|
||||||
transposed=[None if (G is None) else G.T for G in self.content]
|
transposed = [None if (G is None) else G.T for G in self.content]
|
||||||
return 0.5*(Corr(transposed)+self)
|
return 0.5 * (Corr(transposed)+self)
|
||||||
if self.N==1:
|
if self.N == 1:
|
||||||
raise Exception("Trying to symmetrize a smearing matrix, that already has N=1.")
|
raise Exception("Trying to symmetrize a smearing matrix, that already has N=1.")
|
||||||
|
|
||||||
|
|
||||||
#We also include a simple GEVP method based on Scipy.linalg
|
#We also include a simple GEVP method based on Scipy.linalg
|
||||||
def GEVP(self,t0,ts):
|
def GEVP(self, t0, ts):
|
||||||
if (self.content[t0] is None) or (self.content[ts] is None):
|
if (self.content[t0] is None) or (self.content[ts] is None):
|
||||||
raise Exception("Corr not defined at t0/ts")
|
raise Exception("Corr not defined at t0/ts")
|
||||||
G0, Gt=np.empty([self.N,self.N],dtype="double"),np.empty([self.N,self.N],dtype="double")
|
G0, Gt = np.empty([self.N, self.N], dtype="double"), np.empty([self.N, self.N], dtype="double")
|
||||||
for i in range(self.N):
|
for i in range(self.N):
|
||||||
for j in range(self.N):
|
for j in range(self.N):
|
||||||
G0[i,j]=self.content[t0][i,j].value
|
G0[i, j] = self.content[t0][i, j].value
|
||||||
Gt[i,j]=self.content[ts][i,j].value
|
Gt[i, j] = self.content[ts][i, j].value
|
||||||
|
|
||||||
sp_val,sp_vec=scipy.linalg.eig(Gt,G0)
|
sp_val,sp_vec = scipy.linalg.eig(Gt, G0)
|
||||||
sp_vec=sp_vec[:,np.argmax(sp_val)] #we only want the eigenvector belonging to the biggest eigenvalue.
|
sp_vec = sp_vec[:,np.argmax(sp_val)] #we only want the eigenvector belonging to the biggest eigenvalue.
|
||||||
sp_vec=sp_vec/np.sqrt(sp_vec@sp_vec)
|
sp_vec = sp_vec/np.sqrt(sp_vec@sp_vec)
|
||||||
return sp_vec
|
return sp_vec
|
||||||
|
|
||||||
def deriv(self,symmetric=False): #Defaults to forward derivative f'(t)=f(t+1)-f(t)
|
def deriv(self, symmetric=False): #Defaults to forward derivative f'(t)=f(t+1)-f(t)
|
||||||
if not symmetric:
|
if not symmetric:
|
||||||
newcontent=[]
|
newcontent = []
|
||||||
for t in range(self.T-1):
|
for t in range(self.T - 1):
|
||||||
if (self.content[t] is None) or (self.content[t+1] is None):
|
if (self.content[t] is None) or (self.content[t+1] is None):
|
||||||
newcontent.append(None)
|
newcontent.append(None)
|
||||||
else:
|
else:
|
||||||
newcontent.append(self.content[t+1]-self.content[t])
|
newcontent.append(self.content[t + 1] - self.content[t])
|
||||||
if(all([x is None for x in newcontent])):
|
if(all([x is None for x in newcontent])):
|
||||||
raise Exception("Derivative is undefined at all timeslices")
|
raise Exception("Derivative is undefined at all timeslices")
|
||||||
return Corr(newcontent, padding_back=1)
|
return Corr(newcontent, padding_back=1)
|
||||||
if symmetric:
|
if symmetric:
|
||||||
newcontent=[]
|
newcontent = []
|
||||||
for t in range(1,self.T-1):
|
for t in range(1, self.T-1):
|
||||||
if (self.content[t-1] is None) or (self.content[t+1] is None):
|
if (self.content[t-1] is None) or (self.content[t+1] is None):
|
||||||
newcontent.append(None)
|
newcontent.append(None)
|
||||||
else:
|
else:
|
||||||
newcontent.append(0.5*(self.content[t+1]-self.content[t-1]))
|
newcontent.append(0.5 * (self.content[t + 1] - self.content[t - 1]))
|
||||||
if(all([x is None for x in newcontent])):
|
if(all([x is None for x in newcontent])):
|
||||||
raise Exception("Derivative is undefined at all timeslices")
|
raise Exception("Derivative is undefined at all timeslices")
|
||||||
return Corr(newcontent, padding_back=1,padding_front=1)
|
return Corr(newcontent, padding_back=1, padding_front=1)
|
||||||
|
|
||||||
#effective mass at every timeslice
|
#effective mass at every timeslice
|
||||||
def m_eff(self, periodic=False):
|
def m_eff(self, periodic=False):
|
||||||
if self.N!=1:
|
if self.N != 1:
|
||||||
raise Exception("Correlator must be projected before getting m_eff")
|
raise Exception("Correlator must be projected before getting m_eff")
|
||||||
if not periodic:
|
if not periodic:
|
||||||
newcontent=[]
|
newcontent = []
|
||||||
for t in range(self.T-1):
|
for t in range(self.T - 1):
|
||||||
if (self.content[t] is None) or (self.content[t+1] is None):
|
if (self.content[t] is None) or (self.content[t + 1] is None):
|
||||||
newcontent.append(None)
|
newcontent.append(None)
|
||||||
else:
|
else:
|
||||||
newcontent.append(self.content[t]/self.content[t+1])
|
newcontent.append(self.content[t] / self.content[t + 1])
|
||||||
if(all([x is None for x in newcontent])):
|
if(all([x is None for x in newcontent])):
|
||||||
raise Exception("m_eff is undefined at all timeslices")
|
raise Exception("m_eff is undefined at all timeslices")
|
||||||
|
|
||||||
return np.log(Corr(newcontent,padding_back=1))
|
return np.log(Corr(newcontent, padding_back=1))
|
||||||
|
|
||||||
else: #This is usually not very stable. One could default back to periodic=False.
|
else: #This is usually not very stable. One could default back to periodic=False.
|
||||||
newcontent=[]
|
newcontent = []
|
||||||
for t in range(1,self.T-1):
|
for t in range(1, self.T - 1):
|
||||||
if (self.content[t] is None) or (self.content[t+1] is None)or (self.content[t-1] is None):
|
if (self.content[t] is None) or (self.content[t + 1] is None)or (self.content[t - 1] is None):
|
||||||
newcontent.append(None)
|
newcontent.append(None)
|
||||||
else:
|
else:
|
||||||
newcontent.append((self.content[t+1]+self.content[t-1])/(2*self.content[t]))
|
newcontent.append((self.content[t + 1] + self.content[t - 1]) / (2 * self.content[t]))
|
||||||
if(all([x is None for x in newcontent])):
|
if(all([x is None for x in newcontent])):
|
||||||
raise Exception("m_eff is undefined at all timeslices")
|
raise Exception("m_eff is undefined at all timeslices")
|
||||||
return np.arccosh(Corr(newcontent,padding_back=1,padding_front=1))
|
return np.arccosh(Corr(newcontent,padding_back=1, padding_front=1))
|
||||||
|
|
||||||
|
|
||||||
#We want to apply a pe.standard_fit directly to the Corr using an arbitrary function and range.
|
#We want to apply a pe.standard_fit directly to the Corr using an arbitrary function and range.
|
||||||
def fit(self,function,fitrange=None):
|
def fit(self, function, fitrange=None):
|
||||||
if self.N!=1:
|
if self.N != 1:
|
||||||
raise Exception("Correlator must be projected before fitting")
|
raise Exception("Correlator must be projected before fitting")
|
||||||
|
|
||||||
if fitrange is None:
|
if fitrange is None:
|
||||||
fitrange=[0,self.T]
|
fitrange=[0, self.T]
|
||||||
|
|
||||||
xs = [x for x in range(fitrange[0],fitrange[1]) if not self.content[x] is None]
|
xs = [x for x in range(fitrange[0], fitrange[1]) if not self.content[x] is None]
|
||||||
ys = [self.content[x][0] for x in range(fitrange[0],fitrange[1]) if not self.content[x] is None]
|
ys = [self.content[x][0] for x in range(fitrange[0], fitrange[1]) if not self.content[x] is None]
|
||||||
result = standard_fit(xs, ys,function,silent=(True))
|
result = standard_fit(xs, ys, function, silent=True)
|
||||||
[item.gamma_method() for item in result if isinstance(item,Obs)]
|
[item.gamma_method() for item in result if isinstance(item,Obs)]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
#we want to quickly get a plateau
|
#we want to quickly get a plateau
|
||||||
def plateau(self,plateau_range,method="fit"):
|
def plateau(self, plateau_range, method="fit"):
|
||||||
if self.N!=1:
|
if self.N != 1:
|
||||||
raise Exception("Correlator must be projected before getting a plateau")
|
raise Exception("Correlator must be projected before getting a plateau.")
|
||||||
if(all([self.content[t] is None for t in range(plateau_range[0],plateau_range[1])])):
|
if(all([self.content[t] is None for t in range(plateau_range[0], plateau_range[1])])):
|
||||||
raise Exception("plateau is undefined at all timeslices in plateaurange")
|
raise Exception("plateau is undefined at all timeslices in plateaurange.")
|
||||||
if method=="fit":
|
if method == "fit":
|
||||||
def const_func(a,t):
|
def const_func(a, t):
|
||||||
return a[0]+a[1]*0 # At some point pe.standard fit had an issue with single parameter fits. Being careful does not hurt
|
return a[0] + a[1] * 0 # At some point pe.standard fit had an issue with single parameter fits. Being careful does not hurt
|
||||||
return self.fit(const_func,plateau_range)[0]
|
return self.fit(const_func,plateau_range)[0]
|
||||||
elif method in ["avg","average","mean"]:
|
elif method in ["avg","average","mean"]:
|
||||||
returnvalue= np.mean([item[0] for item in self.content if not item is None])
|
returnvalue= np.mean([item[0] for item in self.content if not item is None])
|
||||||
|
@ -256,57 +253,55 @@ class Corr:
|
||||||
return returnvalue
|
return returnvalue
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Unsupported plateau method: "+method)
|
raise Exception("Unsupported plateau method: " + method)
|
||||||
|
|
||||||
#quick and dirty plotting function to view Correlator inside Jupyter
|
#quick and dirty plotting function to view Correlator inside Jupyter
|
||||||
#If one would not want to import pyplot, this could easily be replaced by a call to pe.plot_corrs
|
#If one would not want to import pyplot, this could easily be replaced by a call to pe.plot_corrs
|
||||||
#This might be a bit more flexible later
|
#This might be a bit more flexible later
|
||||||
def show(self,xrange=None,logscale=False):
|
def show(self,xrange=None,logscale=False):
|
||||||
if self.N!=1:
|
if self.N!=1:
|
||||||
raise Exception("Correlator must be projected before plotting")
|
raise Exception("Correlator must be projected before plotting")
|
||||||
if xrange is None:
|
if xrange is None:
|
||||||
xrange=[0,self.T]
|
xrange=[0,self.T]
|
||||||
|
|
||||||
x,y,y_err=self.plottable()
|
x,y,y_err=self.plottable()
|
||||||
plt.errorbar(x,y,y_err,fmt="o-")
|
plt.errorbar(x,y,y_err,fmt="o-")
|
||||||
if logscale:
|
if logscale:
|
||||||
plt.yscale("log")
|
plt.yscale("log")
|
||||||
else:
|
else:
|
||||||
# we generate ylim instead of using autoscaling.
|
# we generate ylim instead of using autoscaling.
|
||||||
y_min=min([ (x[0].value-x[0].dvalue) for x in self.content[xrange[0]:xrange[1]] if(not x is None)])
|
y_min=min([ (x[0].value-x[0].dvalue) for x in self.content[xrange[0]:xrange[1]] if(not x is None)])
|
||||||
y_max=max([ (x[0].value+x[0].dvalue) for x in self.content[xrange[0]:xrange[1]] if(not x is None)])
|
y_max=max([ (x[0].value+x[0].dvalue) for x in self.content[xrange[0]:xrange[1]] if(not x is None)])
|
||||||
plt.ylim([y_min-0.1*(y_max-y_min),y_max+0.1*(y_max-y_min)])
|
plt.ylim([y_min-0.1*(y_max-y_min),y_max+0.1*(y_max-y_min)])
|
||||||
|
|
||||||
plt.xlabel(r"$n_t$ [a]")
|
plt.xlabel(r"$n_t$ [a]")
|
||||||
plt.xlim(xrange)
|
plt.xlim(xrange)
|
||||||
plt.title("Quickplot")
|
plt.title("Quickplot")
|
||||||
plt.grid()
|
plt.grid()
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
plt.clf()
|
plt.clf()
|
||||||
return
|
return
|
||||||
|
|
||||||
def dump(self,filename):
|
def dump(self,filename):
|
||||||
dump_object(self,filename)
|
dump_object(self,filename)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return("Corr[T="+str(self.T)+" , N="+str(self.N)+" , content="+str(self.content)+"]")
|
return("Corr[T="+str(self.T)+" , N="+str(self.N)+" , content="+str(self.content)+"]")
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ("Corr[T="+str(self.T)+" , N="+str(self.N)+" , content="+str(self.content)+"]")
|
return ("Corr[T="+str(self.T)+" , N="+str(self.N)+" , content="+str(self.content)+"]")
|
||||||
|
|
||||||
#We define the basic operations, that can be performed with correlators.
|
#We define the basic operations, that can be performed with correlators.
|
||||||
#While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
|
#While */+- get defined here, they only work for Corr*Obs and not Obs*Corr.
|
||||||
#This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
|
#This is because Obs*Corr checks Obs.__mul__ first and does not catch an exception.
|
||||||
#One could try and tell Obs to check if the y in __mul__ is a Corr and
|
#One could try and tell Obs to check if the y in __mul__ is a Corr and
|
||||||
|
|
||||||
def __add__(self, y):
|
def __add__(self, y):
|
||||||
if isinstance(y, Corr):
|
if isinstance(y, Corr):
|
||||||
if ((self.N!=y.N) or (self.T!=y.T) ):
|
if ((self.N!=y.N) or (self.T!=y.T) ):
|
||||||
raise Exception("Addition of Corrs with different shape")
|
raise Exception("Addition of Corrs with different shape")
|
||||||
newcontent=[]
|
newcontent=[]
|
||||||
for t in range(self.T):
|
for t in range(self.T):
|
||||||
if (self.content[t] is None) or (y.content[t] is None):
|
if (self.content[t] is None) or (y.content[t] is None):
|
||||||
|
@ -325,7 +320,7 @@ class Corr:
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
else:
|
else:
|
||||||
raise TypeError("Corr + wrong type")
|
raise TypeError("Corr + wrong type")
|
||||||
|
|
||||||
def __mul__(self,y):
|
def __mul__(self,y):
|
||||||
if isinstance(y,Corr):
|
if isinstance(y,Corr):
|
||||||
if not((self.N==1 or y.N==1 or self.N==y.N) and self.T==y.T):
|
if not((self.N==1 or y.N==1 or self.N==y.N) and self.T==y.T):
|
||||||
|
@ -371,7 +366,7 @@ class Corr:
|
||||||
raise Exception("Division returns completely undefined correlator")
|
raise Exception("Division returns completely undefined correlator")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
elif isinstance(y, Obs):
|
elif isinstance(y, Obs):
|
||||||
|
@ -401,7 +396,7 @@ class Corr:
|
||||||
def __neg__(self):
|
def __neg__(self):
|
||||||
newcontent=[None if (item is None) else -1.*item for item in self.content]
|
newcontent=[None if (item is None) else -1.*item for item in self.content]
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
def __sub__(self,y):
|
def __sub__(self,y):
|
||||||
return self +(-y)
|
return self +(-y)
|
||||||
|
|
||||||
|
@ -411,10 +406,10 @@ class Corr:
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
else:
|
else:
|
||||||
raise TypeError("type of exponent not supported")
|
raise TypeError("type of exponent not supported")
|
||||||
|
|
||||||
#The numpy functions:
|
#The numpy functions:
|
||||||
def sqrt(self):
|
def sqrt(self):
|
||||||
return self**0.5
|
return self**0.5
|
||||||
|
|
||||||
def log(self):
|
def log(self):
|
||||||
newcontent=[None if (item is None) else np.log(item) for item in self.content]
|
newcontent=[None if (item is None) else np.log(item) for item in self.content]
|
||||||
|
@ -423,7 +418,7 @@ class Corr:
|
||||||
def exp(self):
|
def exp(self):
|
||||||
newcontent=[None if (item is None) else np.exp(item) for item in self.content]
|
newcontent=[None if (item is None) else np.exp(item) for item in self.content]
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
def sin(self):
|
def sin(self):
|
||||||
newcontent=[None if (item is None) else np.sin(item) for item in self.content]
|
newcontent=[None if (item is None) else np.sin(item) for item in self.content]
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
@ -463,7 +458,7 @@ class Corr:
|
||||||
if all([item is None for item in newcontent]):
|
if all([item is None for item in newcontent]):
|
||||||
raise Exception("Operation returns completely undefined correlator")
|
raise Exception("Operation returns completely undefined correlator")
|
||||||
return Corr(newcontent)
|
return Corr(newcontent)
|
||||||
|
|
||||||
def arcsin(self):
|
def arcsin(self):
|
||||||
newcontent=[None if (item is None) else np.arcsin(item) for item in self.content]
|
newcontent=[None if (item is None) else np.arcsin(item) for item in self.content]
|
||||||
for t in range(self.T):
|
for t in range(self.T):
|
||||||
|
@ -537,117 +532,117 @@ class Corr:
|
||||||
def __rmul__(self, y):
|
def __rmul__(self, y):
|
||||||
return self * y
|
return self * y
|
||||||
def __radd__(self,y):
|
def __radd__(self,y):
|
||||||
return self + y
|
return self + y
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#One of the most common tasks is to select a range for a plateau or a fit. This is best done visually.
|
##One of the most common tasks is to select a range for a plateau or a fit. This is best done visually.
|
||||||
def GUI_range_finder(corr, current_range=None):
|
#def GUI_range_finder(corr, current_range=None):
|
||||||
T=corr.T
|
# T=corr.T
|
||||||
if corr.N!=1:
|
# if corr.N!=1:
|
||||||
raise Exception("The Corr needs to be projected to select a range.")
|
# raise Exception("The Corr needs to be projected to select a range.")
|
||||||
#We need to define few helper functions for the Gui
|
# #We need to define few helper functions for the Gui
|
||||||
def get_figure(corr,values):
|
# def get_figure(corr,values):
|
||||||
fig = matplotlib.figure.Figure(figsize=(7, 4), dpi=100)
|
# fig = matplotlib.figure.Figure(figsize=(7, 4), dpi=100)
|
||||||
fig.clf()
|
# fig.clf()
|
||||||
x,y,err=corr.plottable()
|
# x,y,err=corr.plottable()
|
||||||
ax=fig.add_subplot(111,label="main")#.plot(t, 2 * np.sin(2 * np.pi * t))
|
# ax=fig.add_subplot(111,label="main")#.plot(t, 2 * np.sin(2 * np.pi * t))
|
||||||
end=int(max(values["range_start"],values["range_end"]))
|
# end=int(max(values["range_start"],values["range_end"]))
|
||||||
start=int(min(values["range_start"],values["range_end"]))
|
# start=int(min(values["range_start"],values["range_end"]))
|
||||||
db=[0.1,0.2,0.8]
|
# db=[0.1,0.2,0.8]
|
||||||
ax.errorbar(x,y,err, fmt="-o",color=[0.4,0.6,0.8])
|
# ax.errorbar(x,y,err, fmt="-o",color=[0.4,0.6,0.8])
|
||||||
ax.errorbar(x[start:end],y[start:end],err[start:end], fmt="-o",color=db)
|
# ax.errorbar(x[start:end],y[start:end],err[start:end], fmt="-o",color=db)
|
||||||
offset=int(0.3*(end-start))
|
# offset=int(0.3*(end-start))
|
||||||
xrange=[max(min(start-1,int(start-offset)),0),min(max(int(end+offset),end+1),T-1)]
|
# xrange=[max(min(start-1,int(start-offset)),0),min(max(int(end+offset),end+1),T-1)]
|
||||||
ax.grid()
|
# ax.grid()
|
||||||
if values["Plateau"]:
|
# if values["Plateau"]:
|
||||||
plateau=corr.plateau([start,end])
|
# plateau=corr.plateau([start,end])
|
||||||
ax.hlines(plateau.value,0,T+1,lw=plateau.dvalue,color="red",alpha=0.5)
|
# ax.hlines(plateau.value,0,T+1,lw=plateau.dvalue,color="red",alpha=0.5)
|
||||||
ax.hlines(plateau.value,0,T+1,lw=1,color="red")
|
# ax.hlines(plateau.value,0,T+1,lw=1,color="red")
|
||||||
ax.set_title(r"Current Plateau="+str(plateau)[4:-1])
|
# ax.set_title(r"Current Plateau="+str(plateau)[4:-1])
|
||||||
if(values["Crop X"]):
|
# if(values["Crop X"]):
|
||||||
ax.set_xlim(xrange)
|
# ax.set_xlim(xrange)
|
||||||
ax.set_xticks([x for x in ax.get_xticks() if (x-int(x)==0) and (0<=x<T)])
|
# ax.set_xticks([x for x in ax.get_xticks() if (x-int(x)==0) and (0<=x<T)])
|
||||||
if(values["Crop Y"]):
|
# if(values["Crop Y"]):
|
||||||
y_min=min([ (x[0].value-x[0].dvalue) for x in corr.content[xrange[0]:xrange[1]] if(not x is None)])
|
# y_min=min([ (x[0].value-x[0].dvalue) for x in corr.content[xrange[0]:xrange[1]] if(not x is None)])
|
||||||
y_max=max([ (x[0].value+x[0].dvalue) for x in corr.content[xrange[0]:xrange[1]] if(not x is None)])
|
# y_max=max([ (x[0].value+x[0].dvalue) for x in corr.content[xrange[0]:xrange[1]] if(not x is None)])
|
||||||
ax.set_ylim([y_min-0.1*(y_max-y_min),y_max+0.1*(y_max-y_min)])
|
# ax.set_ylim([y_min-0.1*(y_max-y_min),y_max+0.1*(y_max-y_min)])
|
||||||
else:
|
# else:
|
||||||
y_min=min([ (x[0].value-x[0].dvalue) for x in corr.content if(not x is None)])
|
# y_min=min([ (x[0].value-x[0].dvalue) for x in corr.content if(not x is None)])
|
||||||
y_max=max([ (x[0].value+x[0].dvalue) for x in corr.content if(not x is None)])
|
# y_max=max([ (x[0].value+x[0].dvalue) for x in corr.content if(not x is None)])
|
||||||
ax.set_ylim([y_min-0.1*(y_max-y_min),y_max+0.1*(y_max-y_min)])
|
# ax.set_ylim([y_min-0.1*(y_max-y_min),y_max+0.1*(y_max-y_min)])
|
||||||
ax.vlines(values["range_start"]-0.5,-2*abs(y_min),2*y_max,color=db)
|
# ax.vlines(values["range_start"]-0.5,-2*abs(y_min),2*y_max,color=db)
|
||||||
ax.vlines(values["range_end"]-0.5,-2*abs(y_min),2*y_max,color=db)
|
# ax.vlines(values["range_end"]-0.5,-2*abs(y_min),2*y_max,color=db)
|
||||||
return fig
|
# return fig
|
||||||
|
#
|
||||||
def draw_figure(canvas, figure):
|
# def draw_figure(canvas, figure):
|
||||||
#matplotlib.use('TkAgg')
|
# #matplotlib.use('TkAgg')
|
||||||
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
|
# figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
|
||||||
figure_canvas_agg.draw()
|
# figure_canvas_agg.draw()
|
||||||
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
|
# figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
|
||||||
return figure_canvas_agg
|
# return figure_canvas_agg
|
||||||
|
#
|
||||||
def delete_figure_agg(figure_agg):
|
# def delete_figure_agg(figure_agg):
|
||||||
figure_agg.get_tk_widget().forget()
|
# figure_agg.get_tk_widget().forget()
|
||||||
plt.close('all')
|
# plt.close('all')
|
||||||
|
#
|
||||||
#We change settings for mpl only inside the function
|
# #We change settings for mpl only inside the function
|
||||||
#matplotlib.use('TkAgg')
|
# #matplotlib.use('TkAgg')
|
||||||
|
#
|
||||||
#now we can call our gui
|
# #now we can call our gui
|
||||||
# define window layout
|
# # define window layout
|
||||||
default_values={}
|
# default_values={}
|
||||||
default_values["Crop X"]=False
|
# default_values["Crop X"]=False
|
||||||
default_values["Crop Y"]=False
|
# default_values["Crop Y"]=False
|
||||||
default_values["Plateau"]=False
|
# default_values["Plateau"]=False
|
||||||
if current_range is None:
|
# if current_range is None:
|
||||||
default_values["range_start"]=1
|
# default_values["range_start"]=1
|
||||||
default_values["range_end"]=int(T/2)
|
# default_values["range_end"]=int(T/2)
|
||||||
else:
|
# else:
|
||||||
default_values["range_start"]=current_range[0]
|
# default_values["range_start"]=current_range[0]
|
||||||
default_values["range_end"]=current_range[1]
|
# default_values["range_end"]=current_range[1]
|
||||||
|
#
|
||||||
|
#
|
||||||
layout = [
|
# layout = [
|
||||||
[sg.Canvas(key='-CANVAS-')],
|
# [sg.Canvas(key='-CANVAS-')],
|
||||||
[sg.Slider(range=(0,T),default_value=default_values["range_start"],size=(40,15),orientation='horizontal',key="range_start",enable_events = True)],
|
# [sg.Slider(range=(0,T),default_value=default_values["range_start"],size=(40,15),orientation='horizontal',key="range_start",enable_events = True)],
|
||||||
[sg.Slider(range=(0,T),default_value=default_values["range_end"],size=(40,15),orientation='horizontal',key="range_end",enable_events = True)],
|
# [sg.Slider(range=(0,T),default_value=default_values["range_end"],size=(40,15),orientation='horizontal',key="range_end",enable_events = True)],
|
||||||
[sg.Checkbox('Crop X',key="Crop X",default=default_values["Crop X"],enable_events = True),sg.Checkbox('Crop Y',key="Crop Y",default=default_values["Crop Y"],enable_events = True),sg.Checkbox('Plateau', key="Plateau",default=default_values["Plateau"],enable_events = True),sg.Button('Return')]]
|
# [sg.Checkbox('Crop X',key="Crop X",default=default_values["Crop X"],enable_events = True),sg.Checkbox('Crop Y',key="Crop Y",default=default_values["Crop Y"],enable_events = True),sg.Checkbox('Plateau', key="Plateau",default=default_values["Plateau"],enable_events = True),sg.Button('Return')]]
|
||||||
|
#
|
||||||
#Calling a theme after the layout is set, preserves default sliders and Buttons
|
# #Calling a theme after the layout is set, preserves default sliders and Buttons
|
||||||
|
#
|
||||||
window = sg.Window('Range Finder', layout, finalize=True, element_justification='center', font='Helvetica 18',return_keyboard_events=True)
|
# window = sg.Window('Range Finder', layout, finalize=True, element_justification='center', font='Helvetica 18',return_keyboard_events=True)
|
||||||
|
#
|
||||||
# add the plot to the window
|
# # add the plot to the window
|
||||||
fig = get_figure(corr,default_values)
|
# fig = get_figure(corr,default_values)
|
||||||
fig_canvas_agg =draw_figure(window['-CANVAS-'].TKCanvas, fig)
|
# fig_canvas_agg =draw_figure(window['-CANVAS-'].TKCanvas, fig)
|
||||||
while True:
|
# while True:
|
||||||
event, values = window.read()
|
# event, values = window.read()
|
||||||
if event is None or event=="Return" or event=="\r":
|
# if event is None or event=="Return" or event=="\r":
|
||||||
break
|
# break
|
||||||
else:
|
# else:
|
||||||
if values["range_end"]<=values["range_start"]+2:
|
# if values["range_end"]<=values["range_start"]+2:
|
||||||
if values["range_start"]+3<T:
|
# if values["range_start"]+3<T:
|
||||||
window["range_end"].update(values["range_start"]+3)
|
# window["range_end"].update(values["range_start"]+3)
|
||||||
else:
|
# else:
|
||||||
window["range_start"].update(T-3)
|
# window["range_start"].update(T-3)
|
||||||
window["range_end"].update(values["range_start"]+3)
|
# window["range_end"].update(values["range_start"]+3)
|
||||||
# we need a distance of 2 fo a plateau
|
# # we need a distance of 2 fo a plateau
|
||||||
if values["range_end"]<=values["range_start"]+1:
|
# if values["range_end"]<=values["range_start"]+1:
|
||||||
values["Plateau"]=False
|
# values["Plateau"]=False
|
||||||
window["Plateau"].update(False)
|
# window["Plateau"].update(False)
|
||||||
if fig_canvas_agg:
|
# if fig_canvas_agg:
|
||||||
delete_figure_agg(fig_canvas_agg)
|
# delete_figure_agg(fig_canvas_agg)
|
||||||
fig = get_figure(corr,values)
|
# fig = get_figure(corr,values)
|
||||||
fig_canvas_agg =draw_figure(window['-CANVAS-'].TKCanvas, fig)
|
# fig_canvas_agg =draw_figure(window['-CANVAS-'].TKCanvas, fig)
|
||||||
|
#
|
||||||
|
#
|
||||||
window.close()
|
# window.close()
|
||||||
#It is easier to read the last event, that occurred
|
# #It is easier to read the last event, that occurred
|
||||||
if event=="Return" or event=="\r":
|
# if event=="Return" or event=="\r":
|
||||||
end=int(max(values["range_start"],values["range_end"]))
|
# end=int(max(values["range_start"],values["range_end"]))
|
||||||
start=int(min(values["range_start"],values["range_end"]))
|
# start=int(min(values["range_start"],values["range_end"]))
|
||||||
window.close()
|
# window.close()
|
||||||
return [start,end]
|
# return [start,end]
|
||||||
else:
|
# else:
|
||||||
return
|
# return
|
||||||
|
|
4
setup.py
4
setup.py
|
@ -3,11 +3,11 @@
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
|
|
||||||
setup(name='pyerrors',
|
setup(name='pyerrors',
|
||||||
version='1.0.1_forked_JN',
|
version='1.1.0',
|
||||||
description='Error analysis for lattice QCD',
|
description='Error analysis for lattice QCD',
|
||||||
author='Fabian Joswig',
|
author='Fabian Joswig',
|
||||||
author_email='fabian.joswig@wwu.de',
|
author_email='fabian.joswig@wwu.de',
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
python_requires='>=3.5.0',
|
python_requires='>=3.5.0',
|
||||||
install_requires=['numpy>=1.16', 'autograd>=1.2', 'numdifftools', 'matplotlib', 'scipy', 'iminuit','PySimpleGUI']
|
install_requires=['numpy>=1.16', 'autograd>=1.2', 'numdifftools', 'matplotlib', 'scipy', 'iminuit']
|
||||||
)
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue