first version of new bookeeping system

This commit is contained in:
Fabian Joswig 2021-11-01 17:14:30 +00:00
parent b86dda2394
commit e4d7d56180
4 changed files with 38 additions and 54 deletions

View file

@ -33,4 +33,4 @@ jobs:
pip install pytest-benchmark
- name: Run tests
run: pytest --cov=pyerrors -v
run: pytest --cov=pyerrors -vv

View file

@ -24,9 +24,6 @@ class Obs:
Attributes
----------
e_tag_global : int
Integer which determines which part of the name belongs
to the ensemble and which to the replicum.
S_global : float
Standard value for S (default 2.0)
S_dict : dict
@ -41,12 +38,11 @@ class Obs:
Standard value for N_sigma (default 1.0)
"""
__slots__ = ['names', 'shape', 'r_values', 'deltas', 'N', '_value', '_dvalue',
'ddvalue', 'reweighted', 'S', 'tau_exp', 'N_sigma', 'e_names',
'e_content', 'e_dvalue', 'e_ddvalue', 'e_tauint', 'e_dtauint',
'ddvalue', 'reweighted', 'S', 'tau_exp', 'N_sigma',
'e_dvalue', 'e_ddvalue', 'e_tauint', 'e_dtauint',
'e_windowsize', 'e_rho', 'e_drho', 'e_n_tauint', 'e_n_dtauint',
'idl', 'is_merged', 'tag', '__dict__']
e_tag_global = 0
S_global = 2.0
S_dict = {}
tau_exp_global = 0.0
@ -141,6 +137,19 @@ class Obs:
def dvalue(self):
return self._dvalue
@property
def e_names(self):
return sorted(set([o.split('|')[0] for o in self.names]))
@property
def e_content(self):
res = {}
for e, e_name in enumerate(self.e_names):
res[e_name] = sorted(filter(lambda x: x.startswith(e_name + '|'), self.names))
if e_name in self.names:
res[e_name].append(e_name)
return res
def expand_deltas(self, deltas, idx, shape):
"""Expand deltas defined on idx to a regular, contiguous range, where holes are filled by 0.
If idx is of type range, the deltas are not changed
@ -202,23 +211,12 @@ class Obs:
N_sigma : float
number of standard deviations from zero until the tail is
attached to the autocorrelation function (default 1)
e_tag : int
number of characters which label the ensemble. The remaining
ones label replica (default 0)
fft : bool
determines whether the fft algorithm is used for the computation
of the autocorrelation function (default True)
"""
if 'e_tag' in kwargs:
e_tag_local = kwargs.get('e_tag')
if not isinstance(e_tag_local, int):
raise TypeError('Error: e_tag is not integer')
else:
e_tag_local = Obs.e_tag_global
self.e_names = sorted(set([o[:e_tag_local] for o in self.names]))
self.e_content = {}
e_content = self.e_content
self.e_dvalue = {}
self.e_ddvalue = {}
self.e_tauint = {}
@ -295,36 +293,26 @@ class Obs:
else:
self.N_sigma = Obs.N_sigma_global
if max([len(x) for x in self.names]) <= e_tag_local:
for e, e_name in enumerate(self.e_names):
self.e_content[e_name] = [e_name]
else:
for e, e_name in enumerate(self.e_names):
if len(e_name) < e_tag_local:
self.e_content[e_name] = [e_name]
else:
self.e_content[e_name] = sorted(filter(lambda x: x.startswith(e_name), self.names))
for e, e_name in enumerate(self.e_names):
r_length = []
for r_name in self.e_content[e_name]:
for r_name in e_content[e_name]:
if self.idl[r_name] is range:
r_length.append(len(self.idl[r_name]))
else:
r_length.append((self.idl[r_name][-1] - self.idl[r_name][0] + 1))
e_N = np.sum([self.shape[r_name] for r_name in self.e_content[e_name]])
e_N = np.sum([self.shape[r_name] for r_name in e_content[e_name]])
w_max = max(r_length) // 2
e_gamma[e_name] = np.zeros(w_max)
self.e_rho[e_name] = np.zeros(w_max)
self.e_drho[e_name] = np.zeros(w_max)
for r_name in self.e_content[e_name]:
for r_name in e_content[e_name]:
e_gamma[e_name] += self.calc_gamma(self.deltas[r_name], self.idl[r_name], self.shape[r_name], w_max, fft)
gamma_div = np.zeros(w_max)
for r_name in self.e_content[e_name]:
for r_name in e_content[e_name]:
gamma_div += self.calc_gamma(np.ones((self.shape[r_name])), self.idl[r_name], self.shape[r_name], w_max, fft)
e_gamma[e_name] /= gamma_div[:w_max]
@ -384,11 +372,11 @@ class Obs:
self.ddvalue += (self.e_dvalue[e_name] * self.e_ddvalue[e_name]) ** 2
self._dvalue = np.sqrt(self.dvalue)
if self.dvalue == 0.0:
if self._dvalue == 0.0:
self.ddvalue = 0.0
else:
self.ddvalue = np.sqrt(self.ddvalue) / self.dvalue
return 0
return
def print(self, level=1):
"""Print basic properties of the Obs."""
@ -400,7 +388,7 @@ class Obs:
else:
percentage = np.abs(self.dvalue / self.value) * 100
print('Result\t %3.8e +/- %3.8e +/- %3.8e (%3.3f%%)' % (self.value, self.dvalue, self.ddvalue, percentage))
if hasattr(self, 'e_names'):
if hasattr(self, 'e_dvalue'):
if len(self.e_names) > 1:
print(' Ensemble errors:')
for e_name in self.e_names:

View file

@ -30,9 +30,8 @@ def test_least_squares():
out = pe.least_squares(x, oy, func)
beta = out.fit_parameters
pe.Obs.e_tag_global = 5
for i in range(2):
beta[i].gamma_method(e_tag=5, S=1.0)
beta[i].gamma_method(S=1.0)
assert math.isclose(beta[i].value, popt[i], abs_tol=1e-5)
assert math.isclose(pcov[i, i], beta[i].dvalue ** 2, abs_tol=1e-3)
assert math.isclose(pe.covariance(beta[0], beta[1]), pcov[0, 1], abs_tol=1e-3)

View file

@ -135,7 +135,7 @@ def test_fft():
test_obs2 = copy.deepcopy(test_obs1)
test_obs1.gamma_method()
test_obs2.gamma_method(fft=False)
assert max(np.abs(test_obs1.e_rho[''] - test_obs2.e_rho[''])) <= 10 * np.finfo(np.float64).eps
assert max(np.abs(test_obs1.e_rho['t'] - test_obs2.e_rho['t'])) <= 10 * np.finfo(np.float64).eps
assert np.abs(test_obs1.dvalue - test_obs2.dvalue) <= 10 * max(test_obs1.dvalue, test_obs2.dvalue) * np.finfo(np.float64).eps
@ -190,22 +190,19 @@ def test_derived_observables():
assert i_am_one.e_ddvalue['t'] <= 2 * np.finfo(np.float64).eps
def test_multi_ens_system():
names = []
for i in range(100 + int(np.random.rand() * 50)):
tmp_string = ''
for _ in range(int(2 + np.random.rand() * 4)):
tmp_string += random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits)
names.append(tmp_string)
names = list(set(names))
samples = [np.random.rand(5)] * len(names)
new_obs = pe.Obs(samples, names)
def test_multi_ens():
names = ['A0', 'A1|r001', 'A1|r002']
test_obs = pe.Obs([np.random.rand(50), np.random.rand(50), np.random.rand(50)], names)
assert test_obs.e_names == ['A0', 'A1']
assert test_obs.e_content['A0'] == ['A0']
assert test_obs.e_content['A1'] == ['A1|r001', 'A1|r002']
for e_tag_length in range(1, 6):
new_obs.gamma_method(e_tag=e_tag_length)
e_names = sorted(set([n[:e_tag_length] for n in names]))
assert e_names == new_obs.e_names
assert sorted(x for y in sorted(new_obs.e_content.values()) for x in y) == sorted(new_obs.names)
my_sum = 0
ensembles = []
for i in range(100):
my_sum += pe.Obs([np.random.rand(50)], [str(i)])
ensembles.append(str(i))
assert my_sum.e_names == sorted(ensembles)
def test_overloaded_functions():