pyerrors.input.misc

  1import os
  2import fnmatch
  3import re
  4import struct
  5import warnings
  6import numpy as np  # Thinly-wrapped numpy
  7import matplotlib.pyplot as plt
  8from matplotlib import gridspec
  9from ..obs import Obs
 10from ..fits import fit_lin
 11
 12
 13def fit_t0(t2E_dict, fit_range, plot_fit=False, observable='t0'):
 14    """Compute the root of (flow-based) data based on a dictionary that contains
 15    the necessary information in key-value pairs a la (flow time: observable at flow time).
 16
 17    It is assumed that the data is monotonically increasing and passes zero from below.
 18    No exception is thrown if this is not the case (several roots, no monotonic increase).
 19    An exception is thrown if no root can be found in the data.
 20
 21    A linear fit in the vicinity of the root is performed to exctract the root from the
 22    two fit parameters.
 23
 24    Parameters
 25    ----------
 26    t2E_dict : dict
 27        Dictionary with pairs of (flow time: observable at flow time) where the flow times
 28        are of type float and the observables of type Obs.
 29    fit_range : int
 30        Number of data points left and right of the zero
 31        crossing to be included in the linear fit.
 32    plot_fit : bool
 33        If true, the fit for the extraction of t0 is shown together with the data. (Default: False)
 34    observable: str
 35        Keyword to identify the observable to print the correct ylabel (if plot_fit is True)
 36        for the observables 't0' and 'w0'. No y label is printed otherwise. (Default: 't0')
 37
 38    Returns
 39    -------
 40    root : Obs
 41        The root of the data series.
 42    """
 43
 44    zero_crossing = np.argmax(np.array(
 45        [o.value for o in t2E_dict.values()]) > 0.0)
 46
 47    if zero_crossing == 0:
 48        raise Exception('Desired flow time not in data')
 49
 50    x = list(t2E_dict.keys())[zero_crossing - fit_range:
 51                              zero_crossing + fit_range]
 52    y = list(t2E_dict.values())[zero_crossing - fit_range:
 53                                zero_crossing + fit_range]
 54    [o.gamma_method() for o in y]
 55
 56    if len(x) < 2 * fit_range:
 57        warnings.warn('Fit range smaller than expected! Fitting from %1.2e to %1.2e' % (x[0], x[-1]))
 58
 59    fit_result = fit_lin(x, y)
 60
 61    if plot_fit is True:
 62        plt.figure()
 63        gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1], wspace=0.0, hspace=0.0)
 64        ax0 = plt.subplot(gs[0])
 65        xmore = list(t2E_dict.keys())[zero_crossing - fit_range - 2: zero_crossing + fit_range + 2]
 66        ymore = list(t2E_dict.values())[zero_crossing - fit_range - 2: zero_crossing + fit_range + 2]
 67        [o.gamma_method() for o in ymore]
 68        ax0.errorbar(xmore, [yi.value for yi in ymore], yerr=[yi.dvalue for yi in ymore], fmt='x')
 69        xplot = np.linspace(np.min(x), np.max(x))
 70        yplot = [fit_result[0] + fit_result[1] * xi for xi in xplot]
 71        [yi.gamma_method() for yi in yplot]
 72        ax0.fill_between(xplot, y1=[yi.value - yi.dvalue for yi in yplot], y2=[yi.value + yi.dvalue for yi in yplot])
 73        retval = (-fit_result[0] / fit_result[1])
 74        retval.gamma_method()
 75        ylim = ax0.get_ylim()
 76        ax0.fill_betweenx(ylim, x1=retval.value - retval.dvalue, x2=retval.value + retval.dvalue, color='gray', alpha=0.4)
 77        ax0.set_ylim(ylim)
 78        if observable == 't0':
 79            ax0.set_ylabel(r'$t^2 \langle E(t) \rangle - 0.3 $')
 80        elif observable == 'w0':
 81            ax0.set_ylabel(r'$t d(t^2 \langle E(t) \rangle)/dt - 0.3 $')
 82        xlim = ax0.get_xlim()
 83
 84        fit_res = [fit_result[0] + fit_result[1] * xi for xi in x]
 85        residuals = (np.asarray([o.value for o in y]) - [o.value for o in fit_res]) / np.asarray([o.dvalue for o in y])
 86        ax1 = plt.subplot(gs[1])
 87        ax1.plot(x, residuals, 'ko', ls='none', markersize=5)
 88        ax1.tick_params(direction='out')
 89        ax1.tick_params(axis="x", bottom=True, top=True, labelbottom=True)
 90        ax1.axhline(y=0.0, ls='--', color='k')
 91        ax1.fill_between(xlim, -1.0, 1.0, alpha=0.1, facecolor='k')
 92        ax1.set_xlim(xlim)
 93        ax1.set_ylabel('Residuals')
 94        ax1.set_xlabel(r'$t/a^2$')
 95
 96        plt.draw()
 97    return -fit_result[0] / fit_result[1]
 98
 99
100def read_pbp(path, prefix, **kwargs):
101    """Read pbp format from given folder structure.
102
103    Parameters
104    ----------
105    r_start : list
106        list which contains the first config to be read for each replicum
107    r_stop : list
108        list which contains the last config to be read for each replicum
109
110    Returns
111    -------
112    result : list[Obs]
113        list of observables read
114    """
115
116    ls = []
117    for (dirpath, dirnames, filenames) in os.walk(path):
118        ls.extend(filenames)
119        break
120
121    if not ls:
122        raise Exception('Error, directory not found')
123
124    # Exclude files with different names
125    for exc in ls:
126        if not fnmatch.fnmatch(exc, prefix + '*.dat'):
127            ls = list(set(ls) - set([exc]))
128    if len(ls) > 1:
129        ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0]))
130    replica = len(ls)
131
132    if 'r_start' in kwargs:
133        r_start = kwargs.get('r_start')
134        if len(r_start) != replica:
135            raise Exception('r_start does not match number of replicas')
136        # Adjust Configuration numbering to python index
137        r_start = [o - 1 if o else None for o in r_start]
138    else:
139        r_start = [None] * replica
140
141    if 'r_stop' in kwargs:
142        r_stop = kwargs.get('r_stop')
143        if len(r_stop) != replica:
144            raise Exception('r_stop does not match number of replicas')
145    else:
146        r_stop = [None] * replica
147
148    print(r'Read <bar{psi}\psi> from', prefix[:-1], ',', replica, 'replica', end='')
149
150    print_err = 0
151    if 'print_err' in kwargs:
152        print_err = 1
153        print()
154
155    deltas = []
156
157    for rep in range(replica):
158        tmp_array = []
159        with open(path + '/' + ls[rep], 'rb') as fp:
160
161            t = fp.read(4)  # number of reweighting factors
162            if rep == 0:
163                nrw = struct.unpack('i', t)[0]
164                for k in range(nrw):
165                    deltas.append([])
166            else:
167                if nrw != struct.unpack('i', t)[0]:
168                    raise Exception('Error: different number of factors for replicum', rep)
169
170            for k in range(nrw):
171                tmp_array.append([])
172
173            # This block is necessary for openQCD1.6 ms1 files
174            nfct = []
175            for i in range(nrw):
176                t = fp.read(4)
177                nfct.append(struct.unpack('i', t)[0])
178            print('nfct: ', nfct)  # Hasenbusch factor, 1 for rat reweighting
179
180            nsrc = []
181            for i in range(nrw):
182                t = fp.read(4)
183                nsrc.append(struct.unpack('i', t)[0])
184
185            # body
186            while True:
187                t = fp.read(4)
188                if len(t) < 4:
189                    break
190                if print_err:
191                    config_no = struct.unpack('i', t)
192                for i in range(nrw):
193                    tmp_nfct = 1.0
194                    for j in range(nfct[i]):
195                        t = fp.read(8 * nsrc[i])
196                        t = fp.read(8 * nsrc[i])
197                        tmp_rw = struct.unpack('d' * nsrc[i], t)
198                        tmp_nfct *= np.mean(np.asarray(tmp_rw))
199                        if print_err:
200                            print(config_no, i, j, np.mean(np.asarray(tmp_rw)), np.std(np.asarray(tmp_rw)))
201                            print('Sources:', np.asarray(tmp_rw))
202                            print('Partial factor:', tmp_nfct)
203                    tmp_array[i].append(tmp_nfct)
204
205            for k in range(nrw):
206                deltas[k].append(tmp_array[k][r_start[rep]:r_stop[rep]])
207
208    rep_names = []
209    for entry in ls:
210        truncated_entry = entry.split('.')[0]
211        idx = truncated_entry.index('r')
212        rep_names.append(truncated_entry[:idx] + '|' + truncated_entry[idx:])
213    print(',', nrw, r'<bar{psi}\psi> with', nsrc, 'sources')
214    result = []
215    for t in range(nrw):
216        result.append(Obs(deltas[t], rep_names))
217
218    return result
def fit_t0(t2E_dict, fit_range, plot_fit=False, observable='t0'):
14def fit_t0(t2E_dict, fit_range, plot_fit=False, observable='t0'):
15    """Compute the root of (flow-based) data based on a dictionary that contains
16    the necessary information in key-value pairs a la (flow time: observable at flow time).
17
18    It is assumed that the data is monotonically increasing and passes zero from below.
19    No exception is thrown if this is not the case (several roots, no monotonic increase).
20    An exception is thrown if no root can be found in the data.
21
22    A linear fit in the vicinity of the root is performed to exctract the root from the
23    two fit parameters.
24
25    Parameters
26    ----------
27    t2E_dict : dict
28        Dictionary with pairs of (flow time: observable at flow time) where the flow times
29        are of type float and the observables of type Obs.
30    fit_range : int
31        Number of data points left and right of the zero
32        crossing to be included in the linear fit.
33    plot_fit : bool
34        If true, the fit for the extraction of t0 is shown together with the data. (Default: False)
35    observable: str
36        Keyword to identify the observable to print the correct ylabel (if plot_fit is True)
37        for the observables 't0' and 'w0'. No y label is printed otherwise. (Default: 't0')
38
39    Returns
40    -------
41    root : Obs
42        The root of the data series.
43    """
44
45    zero_crossing = np.argmax(np.array(
46        [o.value for o in t2E_dict.values()]) > 0.0)
47
48    if zero_crossing == 0:
49        raise Exception('Desired flow time not in data')
50
51    x = list(t2E_dict.keys())[zero_crossing - fit_range:
52                              zero_crossing + fit_range]
53    y = list(t2E_dict.values())[zero_crossing - fit_range:
54                                zero_crossing + fit_range]
55    [o.gamma_method() for o in y]
56
57    if len(x) < 2 * fit_range:
58        warnings.warn('Fit range smaller than expected! Fitting from %1.2e to %1.2e' % (x[0], x[-1]))
59
60    fit_result = fit_lin(x, y)
61
62    if plot_fit is True:
63        plt.figure()
64        gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1], wspace=0.0, hspace=0.0)
65        ax0 = plt.subplot(gs[0])
66        xmore = list(t2E_dict.keys())[zero_crossing - fit_range - 2: zero_crossing + fit_range + 2]
67        ymore = list(t2E_dict.values())[zero_crossing - fit_range - 2: zero_crossing + fit_range + 2]
68        [o.gamma_method() for o in ymore]
69        ax0.errorbar(xmore, [yi.value for yi in ymore], yerr=[yi.dvalue for yi in ymore], fmt='x')
70        xplot = np.linspace(np.min(x), np.max(x))
71        yplot = [fit_result[0] + fit_result[1] * xi for xi in xplot]
72        [yi.gamma_method() for yi in yplot]
73        ax0.fill_between(xplot, y1=[yi.value - yi.dvalue for yi in yplot], y2=[yi.value + yi.dvalue for yi in yplot])
74        retval = (-fit_result[0] / fit_result[1])
75        retval.gamma_method()
76        ylim = ax0.get_ylim()
77        ax0.fill_betweenx(ylim, x1=retval.value - retval.dvalue, x2=retval.value + retval.dvalue, color='gray', alpha=0.4)
78        ax0.set_ylim(ylim)
79        if observable == 't0':
80            ax0.set_ylabel(r'$t^2 \langle E(t) \rangle - 0.3 $')
81        elif observable == 'w0':
82            ax0.set_ylabel(r'$t d(t^2 \langle E(t) \rangle)/dt - 0.3 $')
83        xlim = ax0.get_xlim()
84
85        fit_res = [fit_result[0] + fit_result[1] * xi for xi in x]
86        residuals = (np.asarray([o.value for o in y]) - [o.value for o in fit_res]) / np.asarray([o.dvalue for o in y])
87        ax1 = plt.subplot(gs[1])
88        ax1.plot(x, residuals, 'ko', ls='none', markersize=5)
89        ax1.tick_params(direction='out')
90        ax1.tick_params(axis="x", bottom=True, top=True, labelbottom=True)
91        ax1.axhline(y=0.0, ls='--', color='k')
92        ax1.fill_between(xlim, -1.0, 1.0, alpha=0.1, facecolor='k')
93        ax1.set_xlim(xlim)
94        ax1.set_ylabel('Residuals')
95        ax1.set_xlabel(r'$t/a^2$')
96
97        plt.draw()
98    return -fit_result[0] / fit_result[1]

Compute the root of (flow-based) data based on a dictionary that contains the necessary information in key-value pairs a la (flow time: observable at flow time).

It is assumed that the data is monotonically increasing and passes zero from below. No exception is thrown if this is not the case (several roots, no monotonic increase). An exception is thrown if no root can be found in the data.

A linear fit in the vicinity of the root is performed to exctract the root from the two fit parameters.

Parameters
  • t2E_dict (dict): Dictionary with pairs of (flow time: observable at flow time) where the flow times are of type float and the observables of type Obs.
  • fit_range (int): Number of data points left and right of the zero crossing to be included in the linear fit.
  • plot_fit (bool): If true, the fit for the extraction of t0 is shown together with the data. (Default: False)
  • observable (str): Keyword to identify the observable to print the correct ylabel (if plot_fit is True) for the observables 't0' and 'w0'. No y label is printed otherwise. (Default: 't0')
Returns
  • root (Obs): The root of the data series.
def read_pbp(path, prefix, **kwargs):
101def read_pbp(path, prefix, **kwargs):
102    """Read pbp format from given folder structure.
103
104    Parameters
105    ----------
106    r_start : list
107        list which contains the first config to be read for each replicum
108    r_stop : list
109        list which contains the last config to be read for each replicum
110
111    Returns
112    -------
113    result : list[Obs]
114        list of observables read
115    """
116
117    ls = []
118    for (dirpath, dirnames, filenames) in os.walk(path):
119        ls.extend(filenames)
120        break
121
122    if not ls:
123        raise Exception('Error, directory not found')
124
125    # Exclude files with different names
126    for exc in ls:
127        if not fnmatch.fnmatch(exc, prefix + '*.dat'):
128            ls = list(set(ls) - set([exc]))
129    if len(ls) > 1:
130        ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0]))
131    replica = len(ls)
132
133    if 'r_start' in kwargs:
134        r_start = kwargs.get('r_start')
135        if len(r_start) != replica:
136            raise Exception('r_start does not match number of replicas')
137        # Adjust Configuration numbering to python index
138        r_start = [o - 1 if o else None for o in r_start]
139    else:
140        r_start = [None] * replica
141
142    if 'r_stop' in kwargs:
143        r_stop = kwargs.get('r_stop')
144        if len(r_stop) != replica:
145            raise Exception('r_stop does not match number of replicas')
146    else:
147        r_stop = [None] * replica
148
149    print(r'Read <bar{psi}\psi> from', prefix[:-1], ',', replica, 'replica', end='')
150
151    print_err = 0
152    if 'print_err' in kwargs:
153        print_err = 1
154        print()
155
156    deltas = []
157
158    for rep in range(replica):
159        tmp_array = []
160        with open(path + '/' + ls[rep], 'rb') as fp:
161
162            t = fp.read(4)  # number of reweighting factors
163            if rep == 0:
164                nrw = struct.unpack('i', t)[0]
165                for k in range(nrw):
166                    deltas.append([])
167            else:
168                if nrw != struct.unpack('i', t)[0]:
169                    raise Exception('Error: different number of factors for replicum', rep)
170
171            for k in range(nrw):
172                tmp_array.append([])
173
174            # This block is necessary for openQCD1.6 ms1 files
175            nfct = []
176            for i in range(nrw):
177                t = fp.read(4)
178                nfct.append(struct.unpack('i', t)[0])
179            print('nfct: ', nfct)  # Hasenbusch factor, 1 for rat reweighting
180
181            nsrc = []
182            for i in range(nrw):
183                t = fp.read(4)
184                nsrc.append(struct.unpack('i', t)[0])
185
186            # body
187            while True:
188                t = fp.read(4)
189                if len(t) < 4:
190                    break
191                if print_err:
192                    config_no = struct.unpack('i', t)
193                for i in range(nrw):
194                    tmp_nfct = 1.0
195                    for j in range(nfct[i]):
196                        t = fp.read(8 * nsrc[i])
197                        t = fp.read(8 * nsrc[i])
198                        tmp_rw = struct.unpack('d' * nsrc[i], t)
199                        tmp_nfct *= np.mean(np.asarray(tmp_rw))
200                        if print_err:
201                            print(config_no, i, j, np.mean(np.asarray(tmp_rw)), np.std(np.asarray(tmp_rw)))
202                            print('Sources:', np.asarray(tmp_rw))
203                            print('Partial factor:', tmp_nfct)
204                    tmp_array[i].append(tmp_nfct)
205
206            for k in range(nrw):
207                deltas[k].append(tmp_array[k][r_start[rep]:r_stop[rep]])
208
209    rep_names = []
210    for entry in ls:
211        truncated_entry = entry.split('.')[0]
212        idx = truncated_entry.index('r')
213        rep_names.append(truncated_entry[:idx] + '|' + truncated_entry[idx:])
214    print(',', nrw, r'<bar{psi}\psi> with', nsrc, 'sources')
215    result = []
216    for t in range(nrw):
217        result.append(Obs(deltas[t], rep_names))
218
219    return result

Read pbp format from given folder structure.

Parameters
  • r_start (list): list which contains the first config to be read for each replicum
  • r_stop (list): list which contains the last config to be read for each replicum
Returns
  • result (list[Obs]): list of observables read