# pyerrors.input.misc

View Source

      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'): View Source

    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): View Source

    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