mirror of
https://github.com/fjosw/pyerrors.git
synced 2025-05-15 20:13:41 +02:00
correlator class cleaned up
This commit is contained in:
parent
c5c673bdb6
commit
311b0bf91a
1 changed files with 189 additions and 264 deletions
|
@ -1,15 +1,12 @@
|
|||
import numpy as np
|
||||
import autograd.numpy as anp
|
||||
#from scipy.special.orthogonal import _IntegerType
|
||||
from .pyerrors import *
|
||||
import scipy.linalg
|
||||
from .pyerrors import Obs, dump_object
|
||||
from .fits import standard_fit
|
||||
from .linalg import *
|
||||
from .linalg import eigh, mat_mat_op
|
||||
from .roots import find_root
|
||||
from matplotlib import pyplot as plt
|
||||
from matplotlib.ticker import NullFormatter # useful for `logit` scale
|
||||
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
|
||||
#import PySimpleGUI as sg
|
||||
import matplotlib
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
class Corr:
|
||||
"""The class for a correlator (time dependent sequence of pe.Obs).
|
||||
|
@ -37,7 +34,7 @@ class Corr:
|
|||
self.N = 1 # number of smearings
|
||||
|
||||
# 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 is None for item in data_input]) and any([isinstance(item, np.ndarray) for item in 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
|
||||
|
@ -105,6 +102,7 @@ class Corr:
|
|||
|
||||
def sum(self):
|
||||
return np.sqrt(self.N) * self.projected(np.ones(self.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):
|
||||
if self.N == 1:
|
||||
|
@ -112,15 +110,14 @@ class Corr:
|
|||
newcontent = [None if(item is None) else item[i, j] for item in self.content]
|
||||
return Corr(newcontent)
|
||||
|
||||
|
||||
# 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
|
||||
def plottable(self):
|
||||
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.
|
||||
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_err_list = [y[0].dvalue for y in self.content if (not y is None)]
|
||||
y_list = [y[0].value for y in self.content if (y is not None)]
|
||||
y_err_list = [y[0].dvalue for y in self.content if (y is not None)]
|
||||
|
||||
return x_list, y_list, y_err_list
|
||||
|
||||
|
@ -142,7 +139,6 @@ class Corr:
|
|||
raise Exception("Corr could not be symmetrized: No redundant values")
|
||||
return Corr(newcontent, prange=self.prange)
|
||||
|
||||
|
||||
def anti_symmetric(self):
|
||||
|
||||
if self.T % 2 != 0:
|
||||
|
@ -158,7 +154,6 @@ class Corr:
|
|||
raise Exception("Corr could not be symmetrized: No redundant values")
|
||||
return Corr(newcontent, prange=self.prange)
|
||||
|
||||
|
||||
# This method will symmetrice the matrices and therefore make them positive definit.
|
||||
def smearing_symmetric(self):
|
||||
if self.N > 1:
|
||||
|
@ -167,7 +162,6 @@ class Corr:
|
|||
if self.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
|
||||
def GEVP(self, t0, ts, state=1):
|
||||
if (self.content[t0] is None) or (self.content[ts] is None):
|
||||
|
@ -179,11 +173,10 @@ class Corr:
|
|||
Gt[i, j] = self.content[ts][i, j].value
|
||||
|
||||
sp_val, sp_vec = scipy.linalg.eig(Gt, G0)
|
||||
sp_vec=sp_vec[:,np.argsort(sp_val)[-state]] #we only want the eigenvector belonging to the selected state
|
||||
sp_vec = sp_vec[:, np.argsort(sp_val)[-state]] # We only want the eigenvector belonging to the selected state
|
||||
sp_vec = sp_vec / np.sqrt(sp_vec @ sp_vec)
|
||||
return sp_vec
|
||||
|
||||
|
||||
def Eigenvalue(self, t0, state=1):
|
||||
G = self.smearing_symmetric()
|
||||
G0 = G.content[t0]
|
||||
|
@ -196,16 +189,13 @@ class Corr:
|
|||
Gt = G.content[t]
|
||||
M = Li @ Gt @ LTi
|
||||
eigenvalues = eigh(M)[0]
|
||||
#print(eigenvalues)
|
||||
eigenvalue = eigenvalues[-state]
|
||||
newcontent.append(eigenvalue)
|
||||
return Corr(newcontent)
|
||||
|
||||
|
||||
def roll(self, dt):
|
||||
return Corr(list(np.roll(np.array(self.content, dtype=object), dt)))
|
||||
|
||||
|
||||
def deriv(self, symmetric=True): # Defaults to symmetric derivative
|
||||
if not symmetric:
|
||||
newcontent = []
|
||||
|
@ -228,7 +218,6 @@ class Corr:
|
|||
raise Exception('Derivative is undefined at all timeslices')
|
||||
return Corr(newcontent, padding_back=1, padding_front=1)
|
||||
|
||||
|
||||
def second_deriv(self):
|
||||
newcontent = []
|
||||
for t in range(1, self.T - 1):
|
||||
|
@ -240,7 +229,6 @@ class Corr:
|
|||
raise Exception("Derivative is undefined at all timeslices")
|
||||
return Corr(newcontent, padding_back=1, padding_front=1)
|
||||
|
||||
|
||||
def m_eff(self, variant='log', guess=1.0):
|
||||
"""Returns the effective mass of the correlator as correlator object
|
||||
|
||||
|
@ -252,7 +240,7 @@ class Corr:
|
|||
"""
|
||||
if self.N != 1:
|
||||
raise Exception('Correlator must be projected before getting m_eff')
|
||||
if variant is 'log':
|
||||
if variant == 'log':
|
||||
newcontent = []
|
||||
for t in range(self.T - 1):
|
||||
if (self.content[t] is None) or (self.content[t + 1] is None):
|
||||
|
@ -264,7 +252,7 @@ class Corr:
|
|||
|
||||
return np.log(Corr(newcontent, padding_back=1))
|
||||
|
||||
elif variant is 'periodic':
|
||||
elif variant == 'periodic':
|
||||
newcontent = []
|
||||
for t in range(self.T - 1):
|
||||
if (self.content[t] is None) or (self.content[t + 1] is None):
|
||||
|
@ -276,7 +264,8 @@ class Corr:
|
|||
raise Exception('m_eff is undefined at all timeslices')
|
||||
|
||||
return Corr(newcontent, padding_back=1)
|
||||
elif variant is 'arccosh':
|
||||
|
||||
elif variant == 'arccosh':
|
||||
newcontent = []
|
||||
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):
|
||||
|
@ -300,7 +289,6 @@ class Corr:
|
|||
# if none is provided, use the range of the corr
|
||||
# if this is also not set, use the whole length of the corr (This could come with a warning!)
|
||||
|
||||
|
||||
if fitrange is None:
|
||||
if self.prange:
|
||||
fitrange = self.prange
|
||||
|
@ -318,8 +306,6 @@ class Corr:
|
|||
raise Exception('Unexpected fit result.')
|
||||
return result
|
||||
|
||||
|
||||
#we want to quickly get a plateau
|
||||
def plateau(self, plateau_range=None, method="fit"):
|
||||
if not plateau_range:
|
||||
if self.prange:
|
||||
|
@ -335,7 +321,7 @@ class Corr:
|
|||
return a[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]
|
||||
elif method in ["avg", "average", "mean"]:
|
||||
returnvalue= np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1]+1] if not item is None])
|
||||
returnvalue = np.mean([item[0] for item in self.content[plateau_range[0]:plateau_range[1] + 1] if item is not None])
|
||||
returnvalue.gamma_method()
|
||||
return returnvalue
|
||||
|
||||
|
@ -408,8 +394,8 @@ class Corr:
|
|||
if fit_res:
|
||||
x_samples = np.arange(x_range[0], x_range[1] + 1, 0.05)
|
||||
ax1.plot(x_samples,
|
||||
fit_res['fit_function']([o.value for o in fit_res['fit_parameters']], x_samples)
|
||||
, ls='-', marker=',', lw=2)
|
||||
fit_res['fit_function']([o.value for o in fit_res['fit_parameters']], x_samples),
|
||||
ls='-', marker=',', lw=2)
|
||||
|
||||
ax1.set_xlabel(r'$x_0 / a$')
|
||||
if ylabel:
|
||||
|
@ -418,7 +404,7 @@ class Corr:
|
|||
|
||||
handles, labels = ax1.get_legend_handles_labels()
|
||||
if labels:
|
||||
legend = ax1.legend()
|
||||
ax1.legend()
|
||||
plt.draw()
|
||||
|
||||
if save:
|
||||
|
@ -449,9 +435,9 @@ class Corr:
|
|||
content_string += '\t' + element.__repr__()[4:-1]
|
||||
content_string += '\n'
|
||||
return content_string
|
||||
|
||||
def __str__(self):
|
||||
return self.__repr__()
|
||||
#return ("Corr[T="+str(self.T)+" , N="+str(self.N)+" , content="+str([o[0] for o in [o for o in self.content]])+"]")
|
||||
|
||||
# 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.
|
||||
|
@ -524,14 +510,11 @@ class Corr:
|
|||
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Division returns completely undefined correlator")
|
||||
|
||||
|
||||
|
||||
return Corr(newcontent)
|
||||
|
||||
elif isinstance(y, Obs):
|
||||
if y.value == 0:
|
||||
raise Exception("Division by Zero will return undefined correlator")
|
||||
raise Exception('Division by zero will return undefined correlator')
|
||||
newcontent = []
|
||||
for t in range(self.T):
|
||||
if (self.content[t] is None):
|
||||
|
@ -542,16 +525,16 @@ class Corr:
|
|||
|
||||
elif isinstance(y, int) or isinstance(y, float):
|
||||
if y == 0:
|
||||
raise Exception("Division by Zero will return undefined correlator")
|
||||
raise Exception('Division by zero will return undefined correlator')
|
||||
newcontent = []
|
||||
for t in range(self.T):
|
||||
if (self.content[t] is None):
|
||||
newcontent.append(None)
|
||||
else:
|
||||
newcontent.append(self.content[t] / y)
|
||||
return Corr(newcontent,prange= self.prange if hasattr(self,"prange") else None)
|
||||
return Corr(newcontent, prange=self.prange)
|
||||
else:
|
||||
raise TypeError("Corr / wrong type")
|
||||
raise TypeError('Corr / wrong type')
|
||||
|
||||
def __neg__(self):
|
||||
newcontent = [None if (item is None) else -1. * item for item in self.content]
|
||||
|
@ -565,11 +548,11 @@ class Corr:
|
|||
newcontent = [None if (item is None) else item**y for item in self.content]
|
||||
return Corr(newcontent, prange=self.prange)
|
||||
else:
|
||||
raise TypeError("type of exponent not supported")
|
||||
raise TypeError('Type of exponent not supported')
|
||||
|
||||
def __abs__(self):
|
||||
newcontent = [None if (item is None) else np.abs(item) for item in self.content]
|
||||
return Corr(newcontent,prange= self.prange if hasattr(self,"prange") else None)
|
||||
return Corr(newcontent, prange=self.prange)
|
||||
|
||||
# The numpy functions:
|
||||
def sqrt(self):
|
||||
|
@ -577,123 +560,65 @@ class Corr:
|
|||
|
||||
def log(self):
|
||||
newcontent = [None if (item is None) else np.log(item) for item in self.content]
|
||||
return Corr(newcontent,prange= self.prange if hasattr(self,"prange") else None)
|
||||
return Corr(newcontent, prange=self.prange)
|
||||
|
||||
def exp(self):
|
||||
newcontent = [None if (item is None) else np.exp(item) for item in self.content]
|
||||
return Corr(newcontent,prange= self.prange if hasattr(self,"prange") else None)
|
||||
return Corr(newcontent, prange=self.prange)
|
||||
|
||||
def _apply_func_to_corr(self, func):
|
||||
newcontent = [None if (item is None) else func(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t] = None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception('Operation returns undefined correlator')
|
||||
return Corr(newcontent)
|
||||
|
||||
def sin(self):
|
||||
newcontent=[None if (item is None) else np.sin(item) for item in self.content]
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.sin)
|
||||
|
||||
def cos(self):
|
||||
newcontent=[None if (item is None) else np.cos(item) for item in self.content]
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.cos)
|
||||
|
||||
def tan(self):
|
||||
newcontent=[None if (item is None) else np.tan(item) for item in self.content]
|
||||
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.tan)
|
||||
|
||||
def sinh(self):
|
||||
newcontent=[None if (item is None) else np.sinh(item) for item in self.content]
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.sinh)
|
||||
|
||||
def cosh(self):
|
||||
newcontent=[None if (item is None) else np.cosh(item) for item in self.content]
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.cosh)
|
||||
|
||||
def tanh(self):
|
||||
newcontent=[None if (item is None) else np.tanh(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.tanh)
|
||||
|
||||
def arcsin(self):
|
||||
newcontent=[None if (item is None) else np.arcsin(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.arcsin)
|
||||
|
||||
def arccos(self):
|
||||
newcontent=[None if (item is None) else np.arccos(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.arccos)
|
||||
|
||||
def arctan(self):
|
||||
newcontent=[None if (item is None) else np.arctan(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.arctan)
|
||||
|
||||
def arcsinh(self):
|
||||
newcontent=[None if (item is None) else np.arcsinh(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.arcsinh)
|
||||
|
||||
def arccosh(self):
|
||||
newcontent=[None if (item is None) else np.arccosh(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.arccosh)
|
||||
|
||||
def arctanh(self):
|
||||
newcontent=[None if (item is None) else np.arctanh(item) for item in self.content]
|
||||
for t in range(self.T):
|
||||
if newcontent[t] is None:
|
||||
continue
|
||||
if np.isnan(np.sum(newcontent[t]).value):
|
||||
newcontent[t]=None
|
||||
if all([item is None for item in newcontent]):
|
||||
raise Exception("Operation returns completely undefined correlator")
|
||||
return Corr(newcontent)
|
||||
return self._apply_func_to_corr(np.arctanh)
|
||||
|
||||
|
||||
#right hand side operations (require tweak in main module to work)
|
||||
# Right hand side operations (require tweak in main module to work)
|
||||
def __rsub__(self, y):
|
||||
return -self + y
|
||||
|
||||
def __rmul__(self, y):
|
||||
return self * y
|
||||
|
||||
def __radd__(self, y):
|
||||
return self + y
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue