# pyerrors.input.hadrons API documentation

# pyerrors.input.hadrons

View Source

      1import os
      2from collections import Counter
      3import h5py
      4from pathlib import Path
      5import numpy as np
      6from ..obs import Obs, CObs
      7from ..correlators import Corr
      8from ..dirac import epsilon_tensor_rank4
      9from .misc import fit_t0
     10
     11
     12def _get_files(path, filestem, idl):
     13    ls = os.listdir(path)
     14
     15    # Clean up file list
     16    files = list(filter(lambda x: x.startswith(filestem + "."), ls))
     17
     18    if not files:
     19        raise Exception('No files starting with', filestem, 'in folder', path)
     20
     21    def get_cnfg_number(n):
     22        return int(n.replace(".h5", "")[len(filestem) + 1:])  # From python 3.9 onward the safer 'removesuffix' method can be used.
     23
     24    # Sort according to configuration number
     25    files.sort(key=get_cnfg_number)
     26
     27    cnfg_numbers = []
     28    filtered_files = []
     29    for line in files:
     30        no = get_cnfg_number(line)
     31        if idl:
     32            if no in list(idl):
     33                filtered_files.append(line)
     34                cnfg_numbers.append(no)
     35        else:
     36            filtered_files.append(line)
     37            cnfg_numbers.append(no)
     38
     39    if idl:
     40        if Counter(list(idl)) != Counter(cnfg_numbers):
     41            raise Exception("Not all configurations specified in idl found, configurations " + str(list(Counter(list(idl)) - Counter(cnfg_numbers))) + " are missing.")
     42
     43    # Check that configurations are evenly spaced
     44    dc = np.unique(np.diff(cnfg_numbers))
     45    if np.any(dc < 0):
     46        raise Exception("Unsorted files")
     47    if len(dc) == 1:
     48        idx = range(cnfg_numbers[0], cnfg_numbers[-1] + dc[0], dc[0])
     49    elif idl:
     50        idx = idl
     51    else:
     52        raise Exception("Configurations are not evenly spaced. Provide an idl if you want to proceed with this set of configurations.")
     53
     54    return filtered_files, idx
     55
     56
     57def read_hd5(filestem, ens_id, group, attrs=None, idl=None, part="real"):
     58    r'''Read hadrons hdf5 file and extract entry based on attributes.
     59
     60    Parameters
     61    -----------------
     62    filestem : str
     63        Full namestem of the files to read, including the full path.
     64    ens_id : str
     65        name of the ensemble, required for internal bookkeeping
     66    group : str
     67        label of the group to be extracted.
     68    attrs : dict or int
     69        Dictionary containing the attributes. For example
     70        ```python
     71        attrs = {"gamma_snk": "Gamma5",
     72                 "gamma_src": "Gamma5"}
     73         ```
     74        Alternatively an integer can be specified to identify the sub group.
     75        This is discouraged as the order in the file is not guaranteed.
     76    idl : range
     77        If specified only configurations in the given range are read in.
     78    part: str
     79        string specifying whether to extract the real part ('real'),
     80        the imaginary part ('imag') or a complex correlator ('complex').
     81        Default 'real'.
     82
     83    Returns
     84    -------
     85    corr : Corr
     86        Correlator of the source sink combination in question.
     87    '''
     88
     89    path_obj = Path(filestem)
     90    path = path_obj.parent.as_posix()
     91    filestem = path_obj.name
     92
     93    files, idx = _get_files(path, filestem, idl)
     94
     95    if isinstance(attrs, dict):
     96        h5file = h5py.File(path + '/' + files[0], "r")
     97        entry = None
     98        for key in h5file[group].keys():
     99            if attrs.items() <= {k: v[0].decode() for k, v in h5file[group][key].attrs.items()}.items():
    100                if entry is None:
    101                    entry = key
    102                else:
    103                    raise ValueError("More than one fitting entry found. More constraint on attributes needed.")
    104        h5file.close()
    105        if entry is None:
    106            raise ValueError(f"Entry with attributes {attrs} not found.")
    107    elif isinstance(attrs, int):
    108        entry = group + f"_{attrs}"
    109    else:
    110        raise TypeError("Invalid type for 'attrs'. Needs to be dict or int.")
    111
    112    corr_data = []
    113    infos = []
    114    for hd5_file in files:
    115        h5file = h5py.File(path + '/' + hd5_file, "r")
    116        if not group + '/' + entry in h5file:
    117            raise Exception("Entry '" + entry + "' not contained in the files.")
    118        raw_data = h5file[group + '/' + entry + '/corr']
    119        real_data = raw_data[:].view("complex")
    120        corr_data.append(real_data)
    121        if not infos:
    122            for k, i in h5file[group + '/' + entry].attrs.items():
    123                infos.append(k + ': ' + i[0].decode())
    124        h5file.close()
    125    corr_data = np.array(corr_data)
    126
    127    if part == "complex":
    128        l_obs = []
    129        for c in corr_data.T:
    130            l_obs.append(CObs(Obs([c.real], [ens_id], idl=[idx]),
    131                              Obs([c.imag], [ens_id], idl=[idx])))
    132    else:
    133        corr_data = getattr(corr_data, part)
    134        l_obs = []
    135        for c in corr_data.T:
    136            l_obs.append(Obs([c], [ens_id], idl=[idx]))
    137
    138    corr = Corr(l_obs)
    139    corr.tag = r", ".join(infos)
    140    return corr
    141
    142
    143def read_meson_hd5(path, filestem, ens_id, meson='meson_0', idl=None, gammas=None):
    144    r'''Read hadrons meson hdf5 file and extract the meson labeled 'meson'
    145
    146    Parameters
    147    -----------------
    148    path : str
    149        path to the files to read
    150    filestem : str
    151        namestem of the files to read
    152    ens_id : str
    153        name of the ensemble, required for internal bookkeeping
    154    meson : str
    155        label of the meson to be extracted, standard value meson_0 which
    156        corresponds to the pseudoscalar pseudoscalar two-point function.
    157    gammas : tuple of strings
    158        Instrad of a meson label one can also provide a tuple of two strings
    159        indicating the gamma matrices at sink and source (gamma_snk, gamma_src).
    160        ("Gamma5", "Gamma5") corresponds to the pseudoscalar pseudoscalar
    161        two-point function. The gammas argument dominateds over meson.
    162    idl : range
    163        If specified only configurations in the given range are read in.
    164
    165    Returns
    166    -------
    167    corr : Corr
    168        Correlator of the source sink combination in question.
    169    '''
    170    if gammas is None:
    171        attrs = int(meson.rsplit('_', 1)[-1])
    172    else:
    173        if len(gammas) != 2:
    174            raise ValueError("'gammas' needs to have exactly two entries")
    175        attrs = {"gamma_snk": gammas[0],
    176                 "gamma_src": gammas[1]}
    177    return read_hd5(filestem=path + "/" + filestem, ens_id=ens_id,
    178                    group=meson.rsplit('_', 1)[0], attrs=attrs, idl=idl,
    179                    part="real")
    180
    181
    182def _extract_real_arrays(path, files, tree, keys):
    183    corr_data = {}
    184    for key in keys:
    185        corr_data[key] = []
    186    for hd5_file in files:
    187        h5file = h5py.File(path + '/' + hd5_file, "r")
    188        for key in keys:
    189            if not tree + '/' + key in h5file:
    190                raise Exception("Entry '" + key + "' not contained in the files.")
    191            raw_data = h5file[tree + '/' + key + '/data']
    192            real_data = raw_data[:].astype(np.double)
    193            corr_data[key].append(real_data)
    194        h5file.close()
    195    for key in keys:
    196        corr_data[key] = np.array(corr_data[key])
    197    return corr_data
    198
    199
    200def extract_t0_hd5(path, filestem, ens_id, obs='Clover energy density', fit_range=5, idl=None, **kwargs):
    201    r'''Read hadrons FlowObservables hdf5 file and extract t0
    202
    203    Parameters
    204    -----------------
    205    path : str
    206        path to the files to read
    207    filestem : str
    208        namestem of the files to read
    209    ens_id : str
    210        name of the ensemble, required for internal bookkeeping
    211    obs : str
    212        label of the observable from which t0 should be extracted.
    213        Options: 'Clover energy density' and 'Plaquette energy density'
    214    fit_range : int
    215        Number of data points left and right of the zero
    216        crossing to be included in the linear fit. (Default: 5)
    217    idl : range
    218        If specified only configurations in the given range are read in.
    219    plot_fit : bool
    220        If true, the fit for the extraction of t0 is shown together with the data.
    221    '''
    222
    223    files, idx = _get_files(path, filestem, idl)
    224    tree = "FlowObservables"
    225
    226    h5file = h5py.File(path + '/' + files[0], "r")
    227    obs_key = None
    228    for key in h5file[tree].keys():
    229        if obs == h5file[tree][key].attrs["description"][0].decode():
    230            obs_key = key
    231            break
    232    h5file.close()
    233    if obs_key is None:
    234        raise Exception(f"Observable {obs} not found.")
    235
    236    corr_data = _extract_real_arrays(path, files, tree, ["FlowObservables_0", obs_key])
    237
    238    if not np.allclose(corr_data["FlowObservables_0"][0], corr_data["FlowObservables_0"][:]):
    239        raise Exception("Not all flow times were equal.")
    240
    241    t2E_dict = {}
    242    for t2, dat in zip(corr_data["FlowObservables_0"][0], corr_data[obs_key].T):
    243        t2E_dict[t2] = Obs([dat], [ens_id], idl=[idx]) - 0.3
    244
    245    return fit_t0(t2E_dict, fit_range, plot_fit=kwargs.get('plot_fit'))
    246
    247
    248def read_DistillationContraction_hd5(path, ens_id, diagrams=["direct"], idl=None):
    249    """Read hadrons DistillationContraction hdf5 files in given directory structure
    250
    251    Parameters
    252    -----------------
    253    path : str
    254        path to the directories to read
    255    ens_id : str
    256        name of the ensemble, required for internal bookkeeping
    257    diagrams : list
    258        List of strings of the diagrams to extract, e.g. ["direct", "box", "cross"].
    259    idl : range
    260        If specified only configurations in the given range are read in.
    261
    262    Returns
    263    -------
    264    result : dict
    265        extracted DistillationContration data
    266    """
    267
    268    res_dict = {}
    269
    270    directories, idx = _get_files(path, "data", idl)
    271
    272    explore_path = Path(path + "/" + directories[0])
    273
    274    for explore_file in explore_path.iterdir():
    275        if explore_file.is_file():
    276            stem = explore_file.with_suffix("").with_suffix("").as_posix().split("/")[-1]
    277        else:
    278            continue
    279
    280        file_list = []
    281        for dir in directories:
    282            tmp_path = Path(path + "/" + dir)
    283            file_list.append((tmp_path / stem).as_posix() + tmp_path.suffix + ".h5")
    284
    285        corr_data = {}
    286
    287        for diagram in diagrams:
    288            corr_data[diagram] = []
    289
    290        try:
    291            for n_file, (hd5_file, n_traj) in enumerate(zip(file_list, list(idx))):
    292                h5file = h5py.File(hd5_file)
    293
    294                if n_file == 0:
    295                    if h5file["DistillationContraction/Metadata"].attrs.get("TimeSources")[0].decode() != "0...":
    296                        raise Exception("Routine is only implemented for files containing inversions on all timeslices.")
    297
    298                    Nt = h5file["DistillationContraction/Metadata"].attrs.get("Nt")[0]
    299
    300                    identifier = []
    301                    for in_file in range(len(h5file["DistillationContraction/Metadata/DmfInputFiles"].attrs.keys()) - 1):
    302                        encoded_info = h5file["DistillationContraction/Metadata/DmfInputFiles"].attrs.get("DmfInputFiles_" + str(in_file))
    303                        full_info = encoded_info[0].decode().split("/")[-1].replace(".h5", "").split("_")
    304                        my_tuple = (full_info[0], full_info[1][1:], full_info[2], full_info[3])
    305                        identifier.append(my_tuple)
    306                    identifier = tuple(identifier)
    307                    # "DistillationContraction/Metadata/DmfSuffix" contains info about different quarks, irrelevant in the SU(3) case.
    308
    309                for diagram in diagrams:
    310
    311                    if diagram == "triangle" and "Identity" not in str(identifier):
    312                        part = "im"
    313                    else:
    314                        part = "re"
    315
    316                    real_data = np.zeros(Nt)
    317                    for x0 in range(Nt):
    318                        raw_data = h5file["DistillationContraction/Correlators/" + diagram + "/" + str(x0)][:][part].astype(np.double)
    319                        real_data += np.roll(raw_data, -x0)
    320                    real_data /= Nt
    321
    322                    corr_data[diagram].append(real_data)
    323                h5file.close()
    324
    325            res_dict[str(identifier)] = {}
    326
    327            for diagram in diagrams:
    328
    329                tmp_data = np.array(corr_data[diagram])
    330
    331                l_obs = []
    332                for c in tmp_data.T:
    333                    l_obs.append(Obs([c], [ens_id], idl=[idx]))
    334
    335                corr = Corr(l_obs)
    336                corr.tag = str(identifier)
    337
    338                res_dict[str(identifier)][diagram] = corr
    339        except FileNotFoundError:
    340            print("Skip", stem)
    341
    342    return res_dict
    343
    344
    345class Npr_matrix(np.ndarray):
    346
    347    def __new__(cls, input_array, mom_in=None, mom_out=None):
    348        obj = np.asarray(input_array).view(cls)
    349        obj.mom_in = mom_in
    350        obj.mom_out = mom_out
    351        return obj
    352
    353    @property
    354    def g5H(self):
    355        """Gamma_5 hermitean conjugate
    356
    357        Uses the fact that the propagator is gamma5 hermitean, so just the
    358        in and out momenta of the propagator are exchanged.
    359        """
    360        return Npr_matrix(self,
    361                          mom_in=self.mom_out,
    362                          mom_out=self.mom_in)
    363
    364    def _propagate_mom(self, other, name):
    365        s_mom = getattr(self, name, None)
    366        o_mom = getattr(other, name, None)
    367        if s_mom is not None and o_mom is not None:
    368            if not np.allclose(s_mom, o_mom):
    369                raise Exception(name + ' does not match.')
    370        return o_mom if o_mom is not None else s_mom
    371
    372    def __matmul__(self, other):
    373        return self.__new__(Npr_matrix,
    374                            super().__matmul__(other),
    375                            self._propagate_mom(other, 'mom_in'),
    376                            self._propagate_mom(other, 'mom_out'))
    377
    378    def __array_finalize__(self, obj):
    379        if obj is None:
    380            return
    381        self.mom_in = getattr(obj, 'mom_in', None)
    382        self.mom_out = getattr(obj, 'mom_out', None)
    383
    384
    385def read_ExternalLeg_hd5(path, filestem, ens_id, idl=None):
    386    """Read hadrons ExternalLeg hdf5 file and output an array of CObs
    387
    388    Parameters
    389    ----------
    390    path : str
    391        path to the files to read
    392    filestem : str
    393        namestem of the files to read
    394    ens_id : str
    395        name of the ensemble, required for internal bookkeeping
    396    idl : range
    397        If specified only configurations in the given range are read in.
    398
    399    Returns
    400    -------
    401    result : Npr_matrix
    402        read Cobs-matrix
    403    """
    404
    405    files, idx = _get_files(path, filestem, idl)
    406
    407    mom = None
    408
    409    corr_data = []
    410    for hd5_file in files:
    411        file = h5py.File(path + '/' + hd5_file, "r")
    412        raw_data = file['ExternalLeg/corr'][0][0].view('complex')
    413        corr_data.append(raw_data)
    414        if mom is None:
    415            mom = np.array(str(file['ExternalLeg/info'].attrs['pIn'])[3:-2].strip().split(), dtype=float)
    416        file.close()
    417    corr_data = np.array(corr_data)
    418
    419    rolled_array = np.rollaxis(corr_data, 0, 5)
    420
    421    matrix = np.empty((rolled_array.shape[:-1]), dtype=object)
    422    for si, sj, ci, cj in np.ndindex(rolled_array.shape[:-1]):
    423        real = Obs([rolled_array[si, sj, ci, cj].real], [ens_id], idl=[idx])
    424        imag = Obs([rolled_array[si, sj, ci, cj].imag], [ens_id], idl=[idx])
    425        matrix[si, sj, ci, cj] = CObs(real, imag)
    426
    427    return Npr_matrix(matrix, mom_in=mom)
    428
    429
    430def read_Bilinear_hd5(path, filestem, ens_id, idl=None):
    431    """Read hadrons Bilinear hdf5 file and output an array of CObs
    432
    433    Parameters
    434    ----------
    435    path : str
    436        path to the files to read
    437    filestem : str
    438        namestem of the files to read
    439    ens_id : str
    440        name of the ensemble, required for internal bookkeeping
    441    idl : range
    442        If specified only configurations in the given range are read in.
    443
    444    Returns
    445    -------
    446    result_dict: dict[Npr_matrix]
    447        extracted Bilinears
    448    """
    449
    450    files, idx = _get_files(path, filestem, idl)
    451
    452    mom_in = None
    453    mom_out = None
    454
    455    corr_data = {}
    456    for hd5_file in files:
    457        file = h5py.File(path + '/' + hd5_file, "r")
    458        for i in range(16):
    459            name = file['Bilinear/Bilinear_' + str(i) + '/info'].attrs['gamma'][0].decode('UTF-8')
    460            if name not in corr_data:
    461                corr_data[name] = []
    462            raw_data = file['Bilinear/Bilinear_' + str(i) + '/corr'][0][0].view('complex')
    463            corr_data[name].append(raw_data)
    464            if mom_in is None:
    465                mom_in = np.array(str(file['Bilinear/Bilinear_' + str(i) + '/info'].attrs['pIn'])[3:-2].strip().split(), dtype=float)
    466            if mom_out is None:
    467                mom_out = np.array(str(file['Bilinear/Bilinear_' + str(i) + '/info'].attrs['pOut'])[3:-2].strip().split(), dtype=float)
    468
    469        file.close()
    470
    471    result_dict = {}
    472
    473    for key, data in corr_data.items():
    474        local_data = np.array(data)
    475
    476        rolled_array = np.rollaxis(local_data, 0, 5)
    477
    478        matrix = np.empty((rolled_array.shape[:-1]), dtype=object)
    479        for si, sj, ci, cj in np.ndindex(rolled_array.shape[:-1]):
    480            real = Obs([rolled_array[si, sj, ci, cj].real], [ens_id], idl=[idx])
    481            imag = Obs([rolled_array[si, sj, ci, cj].imag], [ens_id], idl=[idx])
    482            matrix[si, sj, ci, cj] = CObs(real, imag)
    483
    484        result_dict[key] = Npr_matrix(matrix, mom_in=mom_in, mom_out=mom_out)
    485
    486    return result_dict
    487
    488
    489def read_Fourquark_hd5(path, filestem, ens_id, idl=None, vertices=["VA", "AV"]):
    490    """Read hadrons FourquarkFullyConnected hdf5 file and output an array of CObs
    491
    492    Parameters
    493    ----------
    494    path : str
    495        path to the files to read
    496    filestem : str
    497        namestem of the files to read
    498    ens_id : str
    499        name of the ensemble, required for internal bookkeeping
    500    idl : range
    501        If specified only configurations in the given range are read in.
    502    vertices : list
    503        Vertex functions to be extracted.
    504
    505    Returns
    506    -------
    507    result_dict : dict
    508        extracted fourquark matrizes
    509    """
    510
    511    files, idx = _get_files(path, filestem, idl)
    512
    513    mom_in = None
    514    mom_out = None
    515
    516    vertex_names = []
    517    for vertex in vertices:
    518        vertex_names += _get_lorentz_names(vertex)
    519
    520    corr_data = {}
    521
    522    tree = 'FourQuarkFullyConnected/FourQuarkFullyConnected_'
    523
    524    for hd5_file in files:
    525        file = h5py.File(path + '/' + hd5_file, "r")
    526
    527        for i in range(32):
    528            name = (file[tree + str(i) + '/info'].attrs['gammaA'][0].decode('UTF-8'), file[tree + str(i) + '/info'].attrs['gammaB'][0].decode('UTF-8'))
    529            if name in vertex_names:
    530                if name not in corr_data:
    531                    corr_data[name] = []
    532                raw_data = file[tree + str(i) + '/corr'][0][0].view('complex')
    533                corr_data[name].append(raw_data)
    534                if mom_in is None:
    535                    mom_in = np.array(str(file[tree + str(i) + '/info'].attrs['pIn'])[3:-2].strip().split(), dtype=float)
    536                if mom_out is None:
    537                    mom_out = np.array(str(file[tree + str(i) + '/info'].attrs['pOut'])[3:-2].strip().split(), dtype=float)
    538
    539        file.close()
    540
    541    intermediate_dict = {}
    542
    543    for vertex in vertices:
    544        lorentz_names = _get_lorentz_names(vertex)
    545        for v_name in lorentz_names:
    546            if v_name in [('SigmaXY', 'SigmaZT'),
    547                          ('SigmaXT', 'SigmaYZ'),
    548                          ('SigmaYZ', 'SigmaXT'),
    549                          ('SigmaZT', 'SigmaXY')]:
    550                sign = -1
    551            else:
    552                sign = 1
    553            if vertex not in intermediate_dict:
    554                intermediate_dict[vertex] = sign * np.array(corr_data[v_name])
    555            else:
    556                intermediate_dict[vertex] += sign * np.array(corr_data[v_name])
    557
    558    result_dict = {}
    559
    560    for key, data in intermediate_dict.items():
    561
    562        rolled_array = np.moveaxis(data, 0, 8)
    563
    564        matrix = np.empty((rolled_array.shape[:-1]), dtype=object)
    565        for index in np.ndindex(rolled_array.shape[:-1]):
    566            real = Obs([rolled_array[index].real], [ens_id], idl=[idx])
    567            imag = Obs([rolled_array[index].imag], [ens_id], idl=[idx])
    568            matrix[index] = CObs(real, imag)
    569
    570        result_dict[key] = Npr_matrix(matrix, mom_in=mom_in, mom_out=mom_out)
    571
    572    return result_dict
    573
    574
    575def _get_lorentz_names(name):
    576    lorentz_index = ['X', 'Y', 'Z', 'T']
    577
    578    res = []
    579
    580    if name == "TT":
    581        for i in range(4):
    582            for j in range(i + 1, 4):
    583                res.append(("Sigma" + lorentz_index[i] + lorentz_index[j], "Sigma" + lorentz_index[i] + lorentz_index[j]))
    584        return res
    585
    586    if name == "TTtilde":
    587        for i in range(4):
    588            for j in range(i + 1, 4):
    589                for k in range(4):
    590                    for o in range(k + 1, 4):
    591                        fac = epsilon_tensor_rank4(i, j, k, o)
    592                        if not np.isclose(fac, 0.0):
    593                            res.append(("Sigma" + lorentz_index[i] + lorentz_index[j], "Sigma" + lorentz_index[k] + lorentz_index[o]))
    594        return res
    595
    596    assert len(name) == 2
    597
    598    if 'S' in name or 'P' in name:
    599        if not set(name) <= set(['S', 'P']):
    600            raise Exception("'" + name + "' is not a Lorentz scalar")
    601
    602        g_names = {'S': 'Identity',
    603                   'P': 'Gamma5'}
    604
    605        res.append((g_names[name[0]], g_names[name[1]]))
    606
    607    else:
    608        if not set(name) <= set(['V', 'A']):
    609            raise Exception("'" + name + "' is not a Lorentz scalar")
    610
    611        for ind in lorentz_index:
    612            res.append(('Gamma' + ind + (name[0] == 'A') * 'Gamma5',
    613                        'Gamma' + ind + (name[1] == 'A') * 'Gamma5'))
    614
    615    return res

def read_hd5(filestem, ens_id, group, attrs=None, idl=None, part='real'): View Source

     58def read_hd5(filestem, ens_id, group, attrs=None, idl=None, part="real"):
     59    r'''Read hadrons hdf5 file and extract entry based on attributes.
     60
     61    Parameters
     62    -----------------
     63    filestem : str
     64        Full namestem of the files to read, including the full path.
     65    ens_id : str
     66        name of the ensemble, required for internal bookkeeping
     67    group : str
     68        label of the group to be extracted.
     69    attrs : dict or int
     70        Dictionary containing the attributes. For example
     71        ```python
     72        attrs = {"gamma_snk": "Gamma5",
     73                 "gamma_src": "Gamma5"}
     74         ```
     75        Alternatively an integer can be specified to identify the sub group.
     76        This is discouraged as the order in the file is not guaranteed.
     77    idl : range
     78        If specified only configurations in the given range are read in.
     79    part: str
     80        string specifying whether to extract the real part ('real'),
     81        the imaginary part ('imag') or a complex correlator ('complex').
     82        Default 'real'.
     83
     84    Returns
     85    -------
     86    corr : Corr
     87        Correlator of the source sink combination in question.
     88    '''
     89
     90    path_obj = Path(filestem)
     91    path = path_obj.parent.as_posix()
     92    filestem = path_obj.name
     93
     94    files, idx = _get_files(path, filestem, idl)
     95
     96    if isinstance(attrs, dict):
     97        h5file = h5py.File(path + '/' + files[0], "r")
     98        entry = None
     99        for key in h5file[group].keys():
    100            if attrs.items() <= {k: v[0].decode() for k, v in h5file[group][key].attrs.items()}.items():
    101                if entry is None:
    102                    entry = key
    103                else:
    104                    raise ValueError("More than one fitting entry found. More constraint on attributes needed.")
    105        h5file.close()
    106        if entry is None:
    107            raise ValueError(f"Entry with attributes {attrs} not found.")
    108    elif isinstance(attrs, int):
    109        entry = group + f"_{attrs}"
    110    else:
    111        raise TypeError("Invalid type for 'attrs'. Needs to be dict or int.")
    112
    113    corr_data = []
    114    infos = []
    115    for hd5_file in files:
    116        h5file = h5py.File(path + '/' + hd5_file, "r")
    117        if not group + '/' + entry in h5file:
    118            raise Exception("Entry '" + entry + "' not contained in the files.")
    119        raw_data = h5file[group + '/' + entry + '/corr']
    120        real_data = raw_data[:].view("complex")
    121        corr_data.append(real_data)
    122        if not infos:
    123            for k, i in h5file[group + '/' + entry].attrs.items():
    124                infos.append(k + ': ' + i[0].decode())
    125        h5file.close()
    126    corr_data = np.array(corr_data)
    127
    128    if part == "complex":
    129        l_obs = []
    130        for c in corr_data.T:
    131            l_obs.append(CObs(Obs([c.real], [ens_id], idl=[idx]),
    132                              Obs([c.imag], [ens_id], idl=[idx])))
    133    else:
    134        corr_data = getattr(corr_data, part)
    135        l_obs = []
    136        for c in corr_data.T:
    137            l_obs.append(Obs([c], [ens_id], idl=[idx]))
    138
    139    corr = Corr(l_obs)
    140    corr.tag = r", ".join(infos)
    141    return corr

Read hadrons hdf5 file and extract entry based on attributes.

###### Parameters

- filestem (str): Full namestem of the files to read, including the full path.
- ens_id (str): name of the ensemble, required for internal bookkeeping
- group (str): label of the group to be extracted.

- attrs (dict or int): Dictionary containing the attributes. For example

      attrs = {"gamma_snk": "Gamma5",
               "gamma_src": "Gamma5"}

  Alternatively an integer can be specified to identify the sub group. This is discouraged as the order in the file is not guaranteed.

- idl (range): If specified only configurations in the given range are read in.
- part (str): string specifying whether to extract the real part ('real'), the imaginary part ('imag') or a complex correlator ('complex'). Default 'real'.

###### Returns

- corr (Corr): Correlator of the source sink combination in question.

def read_meson_hd5(path, filestem, ens_id, meson='meson_0', idl=None, gammas=None): View Source

    144def read_meson_hd5(path, filestem, ens_id, meson='meson_0', idl=None, gammas=None):
    145    r'''Read hadrons meson hdf5 file and extract the meson labeled 'meson'
    146
    147    Parameters
    148    -----------------
    149    path : str
    150        path to the files to read
    151    filestem : str
    152        namestem of the files to read
    153    ens_id : str
    154        name of the ensemble, required for internal bookkeeping
    155    meson : str
    156        label of the meson to be extracted, standard value meson_0 which
    157        corresponds to the pseudoscalar pseudoscalar two-point function.
    158    gammas : tuple of strings
    159        Instrad of a meson label one can also provide a tuple of two strings
    160        indicating the gamma matrices at sink and source (gamma_snk, gamma_src).
    161        ("Gamma5", "Gamma5") corresponds to the pseudoscalar pseudoscalar
    162        two-point function. The gammas argument dominateds over meson.
    163    idl : range
    164        If specified only configurations in the given range are read in.
    165
    166    Returns
    167    -------
    168    corr : Corr
    169        Correlator of the source sink combination in question.
    170    '''
    171    if gammas is None:
    172        attrs = int(meson.rsplit('_', 1)[-1])
    173    else:
    174        if len(gammas) != 2:
    175            raise ValueError("'gammas' needs to have exactly two entries")
    176        attrs = {"gamma_snk": gammas[0],
    177                 "gamma_src": gammas[1]}
    178    return read_hd5(filestem=path + "/" + filestem, ens_id=ens_id,
    179                    group=meson.rsplit('_', 1)[0], attrs=attrs, idl=idl,
    180                    part="real")

Read hadrons meson hdf5 file and extract the meson labeled 'meson'

###### Parameters

- path (str): path to the files to read
- filestem (str): namestem of the files to read
- ens_id (str): name of the ensemble, required for internal bookkeeping
- meson (str): label of the meson to be extracted, standard value meson_0 which corresponds to the pseudoscalar pseudoscalar two-point function.
- gammas (tuple of strings): Instrad of a meson label one can also provide a tuple of two strings indicating the gamma matrices at sink and source (gamma_snk, gamma_src). ("Gamma5", "Gamma5") corresponds to the pseudoscalar pseudoscalar two-point function. The gammas argument dominateds over meson.
- idl (range): If specified only configurations in the given range are read in.

###### Returns

- corr (Corr): Correlator of the source sink combination in question.

def extract_t0_hd5( path, filestem, ens_id, obs='Clover energy density', fit_range=5, idl=None, **kwargs): View Source

    201def extract_t0_hd5(path, filestem, ens_id, obs='Clover energy density', fit_range=5, idl=None, **kwargs):
    202    r'''Read hadrons FlowObservables hdf5 file and extract t0
    203
    204    Parameters
    205    -----------------
    206    path : str
    207        path to the files to read
    208    filestem : str
    209        namestem of the files to read
    210    ens_id : str
    211        name of the ensemble, required for internal bookkeeping
    212    obs : str
    213        label of the observable from which t0 should be extracted.
    214        Options: 'Clover energy density' and 'Plaquette energy density'
    215    fit_range : int
    216        Number of data points left and right of the zero
    217        crossing to be included in the linear fit. (Default: 5)
    218    idl : range
    219        If specified only configurations in the given range are read in.
    220    plot_fit : bool
    221        If true, the fit for the extraction of t0 is shown together with the data.
    222    '''
    223
    224    files, idx = _get_files(path, filestem, idl)
    225    tree = "FlowObservables"
    226
    227    h5file = h5py.File(path + '/' + files[0], "r")
    228    obs_key = None
    229    for key in h5file[tree].keys():
    230        if obs == h5file[tree][key].attrs["description"][0].decode():
    231            obs_key = key
    232            break
    233    h5file.close()
    234    if obs_key is None:
    235        raise Exception(f"Observable {obs} not found.")
    236
    237    corr_data = _extract_real_arrays(path, files, tree, ["FlowObservables_0", obs_key])
    238
    239    if not np.allclose(corr_data["FlowObservables_0"][0], corr_data["FlowObservables_0"][:]):
    240        raise Exception("Not all flow times were equal.")
    241
    242    t2E_dict = {}
    243    for t2, dat in zip(corr_data["FlowObservables_0"][0], corr_data[obs_key].T):
    244        t2E_dict[t2] = Obs([dat], [ens_id], idl=[idx]) - 0.3
    245
    246    return fit_t0(t2E_dict, fit_range, plot_fit=kwargs.get('plot_fit'))

Read hadrons FlowObservables hdf5 file and extract t0

###### Parameters

- path (str): path to the files to read
- filestem (str): namestem of the files to read
- ens_id (str): name of the ensemble, required for internal bookkeeping
- obs (str): label of the observable from which t0 should be extracted. Options: 'Clover energy density' and 'Plaquette energy density'
- fit_range (int): Number of data points left and right of the zero crossing to be included in the linear fit. (Default: 5)
- idl (range): If specified only configurations in the given range are read in.
- plot_fit (bool): If true, the fit for the extraction of t0 is shown together with the data.

def read_DistillationContraction_hd5(path, ens_id, diagrams=['direct'], idl=None): View Source

    249def read_DistillationContraction_hd5(path, ens_id, diagrams=["direct"], idl=None):
    250    """Read hadrons DistillationContraction hdf5 files in given directory structure
    251
    252    Parameters
    253    -----------------
    254    path : str
    255        path to the directories to read
    256    ens_id : str
    257        name of the ensemble, required for internal bookkeeping
    258    diagrams : list
    259        List of strings of the diagrams to extract, e.g. ["direct", "box", "cross"].
    260    idl : range
    261        If specified only configurations in the given range are read in.
    262
    263    Returns
    264    -------
    265    result : dict
    266        extracted DistillationContration data
    267    """
    268
    269    res_dict = {}
    270
    271    directories, idx = _get_files(path, "data", idl)
    272
    273    explore_path = Path(path + "/" + directories[0])
    274
    275    for explore_file in explore_path.iterdir():
    276        if explore_file.is_file():
    277            stem = explore_file.with_suffix("").with_suffix("").as_posix().split("/")[-1]
    278        else:
    279            continue
    280
    281        file_list = []
    282        for dir in directories:
    283            tmp_path = Path(path + "/" + dir)
    284            file_list.append((tmp_path / stem).as_posix() + tmp_path.suffix + ".h5")
    285
    286        corr_data = {}
    287
    288        for diagram in diagrams:
    289            corr_data[diagram] = []
    290
    291        try:
    292            for n_file, (hd5_file, n_traj) in enumerate(zip(file_list, list(idx))):
    293                h5file = h5py.File(hd5_file)
    294
    295                if n_file == 0:
    296                    if h5file["DistillationContraction/Metadata"].attrs.get("TimeSources")[0].decode() != "0...":
    297                        raise Exception("Routine is only implemented for files containing inversions on all timeslices.")
    298
    299                    Nt = h5file["DistillationContraction/Metadata"].attrs.get("Nt")[0]
    300
    301                    identifier = []
    302                    for in_file in range(len(h5file["DistillationContraction/Metadata/DmfInputFiles"].attrs.keys()) - 1):
    303                        encoded_info = h5file["DistillationContraction/Metadata/DmfInputFiles"].attrs.get("DmfInputFiles_" + str(in_file))
    304                        full_info = encoded_info[0].decode().split("/")[-1].replace(".h5", "").split("_")
    305                        my_tuple = (full_info[0], full_info[1][1:], full_info[2], full_info[3])
    306                        identifier.append(my_tuple)
    307                    identifier = tuple(identifier)
    308                    # "DistillationContraction/Metadata/DmfSuffix" contains info about different quarks, irrelevant in the SU(3) case.
    309
    310                for diagram in diagrams:
    311
    312                    if diagram == "triangle" and "Identity" not in str(identifier):
    313                        part = "im"
    314                    else:
    315                        part = "re"
    316
    317                    real_data = np.zeros(Nt)
    318                    for x0 in range(Nt):
    319                        raw_data = h5file["DistillationContraction/Correlators/" + diagram + "/" + str(x0)][:][part].astype(np.double)
    320                        real_data += np.roll(raw_data, -x0)
    321                    real_data /= Nt
    322
    323                    corr_data[diagram].append(real_data)
    324                h5file.close()
    325
    326            res_dict[str(identifier)] = {}
    327
    328            for diagram in diagrams:
    329
    330                tmp_data = np.array(corr_data[diagram])
    331
    332                l_obs = []
    333                for c in tmp_data.T:
    334                    l_obs.append(Obs([c], [ens_id], idl=[idx]))
    335
    336                corr = Corr(l_obs)
    337                corr.tag = str(identifier)
    338
    339                res_dict[str(identifier)][diagram] = corr
    340        except FileNotFoundError:
    341            print("Skip", stem)
    342
    343    return res_dict

Read hadrons DistillationContraction hdf5 files in given directory structure

###### Parameters

- path (str): path to the directories to read
- ens_id (str): name of the ensemble, required for internal bookkeeping
- diagrams (list): List of strings of the diagrams to extract, e.g. ["direct", "box", "cross"].
- idl (range): If specified only configurations in the given range are read in.

###### Returns

- result (dict): extracted DistillationContration data

class Npr_matrix(numpy.ndarray): View Source

    346class Npr_matrix(np.ndarray):
    347
    348    def __new__(cls, input_array, mom_in=None, mom_out=None):
    349        obj = np.asarray(input_array).view(cls)
    350        obj.mom_in = mom_in
    351        obj.mom_out = mom_out
    352        return obj
    353
    354    @property
    355    def g5H(self):
    356        """Gamma_5 hermitean conjugate
    357
    358        Uses the fact that the propagator is gamma5 hermitean, so just the
    359        in and out momenta of the propagator are exchanged.
    360        """
    361        return Npr_matrix(self,
    362                          mom_in=self.mom_out,
    363                          mom_out=self.mom_in)
    364
    365    def _propagate_mom(self, other, name):
    366        s_mom = getattr(self, name, None)
    367        o_mom = getattr(other, name, None)
    368        if s_mom is not None and o_mom is not None:
    369            if not np.allclose(s_mom, o_mom):
    370                raise Exception(name + ' does not match.')
    371        return o_mom if o_mom is not None else s_mom
    372
    373    def __matmul__(self, other):
    374        return self.__new__(Npr_matrix,
    375                            super().__matmul__(other),
    376                            self._propagate_mom(other, 'mom_in'),
    377                            self._propagate_mom(other, 'mom_out'))
    378
    379    def __array_finalize__(self, obj):
    380        if obj is None:
    381            return
    382        self.mom_in = getattr(obj, 'mom_in', None)
    383        self.mom_out = getattr(obj, 'mom_out', None)

ndarray(shape, dtype=float, buffer=None, offset=0, strides=None, order=None)

An array object represents a multidimensional, homogeneous array of fixed-size items. An associated data-type object describes the format of each element in the array (its byte-order, how many bytes it occupies in memory, whether it is an integer, a floating point number, or something else, etc.)

Arrays should be constructed using `array`, `zeros` or `empty` (refer to the See Also section below). The parameters given here refer to a low-level method (`ndarray(...)`) for instantiating an array.

For more information, refer to the `numpy` module and examine the methods and attributes of an array.

###### Parameters

- (for the __new__ method; see Notes below)
- shape (tuple of ints): Shape of created array.
- dtype (data-type, optional): Any object that can be interpreted as a numpy data type.
- buffer (object exposing buffer interface, optional): Used to fill the array with data.
- offset (int, optional): Offset of array data in buffer.
- strides (tuple of ints, optional): Strides of data in memory.
- order ({'C', 'F'}, optional): Row-major (C-style) or column-major (Fortran-style) order.

###### Attributes

- T (ndarray): Transpose of the array.
- data (buffer): The array's elements, in memory.
- dtype (dtype object): Describes the format of the elements in the array.
- flags (dict): Dictionary containing information related to memory use, e.g., 'C_CONTIGUOUS', 'OWNDATA', 'WRITEABLE', etc.
- flat (numpy.flatiter object): Flattened version of the array as an iterator. The iterator allows assignments, e.g., `x.flat = 3` (See `ndarray.flat` for assignment examples; TODO).
- imag (ndarray): Imaginary part of the array.
- real (ndarray): Real part of the array.
- size (int): Number of elements in the array.
- itemsize (int): The memory use of each array element in bytes.
- nbytes (int): The total number of bytes required to store the array data, i.e., `itemsize * size`.
- ndim (int): The array's number of dimensions.
- shape (tuple of ints): Shape of the array.
- strides (tuple of ints): The step-size required to move from one element to the next in memory. For example, a contiguous `(3, 4)` array of type `int16` in C-order has strides `(8, 2)`. This implies that to move from element to element in memory requires jumps of 2 bytes. To move from row-to-row, one needs to jump 8 bytes at a time (`2 * 4`).
- ctypes (ctypes object): Class containing properties of the array needed for interaction with ctypes.
- base (ndarray): If the array is a view into another array, that array is its `base` (unless that array is also a view). The `base` array is where the array data is actually stored.

###### See Also

`array`: Construct an array.
`zeros`: Create an array, each element of which is zero.
`empty`: Create an array, but leave its allocated memory unchanged (i.e., it contains "garbage").
`dtype`: Create a data-type.
`numpy.typing.NDArray`: An ndarray alias :term:`generic <generic type>` w.r.t. its `dtype.type <numpy.dtype.type>`.

###### Notes

There are two modes of creating an array using `__new__`:

1. If `buffer` is None, then only `shape`, `dtype`, and `order` are used.
2. If `buffer` is an object exposing the buffer interface, then all keywords are interpreted.

No `__init__` method is needed because the array is fully initialized after the `__new__` method.

###### Examples

These examples illustrate the low-level `ndarray` constructor. Refer to the `See Also` section above for easier ways of constructing an ndarray.

First mode, `buffer` is None:

    >>> import numpy as np
    >>> np.ndarray(shape=(2,2), dtype=float, order='F')
    array([[0.0e+000, 0.0e+000], # random
           [     nan, 2.5e-323]])

Second mode:

    >>> np.ndarray((2,), buffer=np.array([1,2,3]),
    ...            offset=np.int_().itemsize,
    ...            dtype=int) # offset = 1*itemsize, i.e. skip first element
    array([2, 3])

g5H View Source

    354    @property
    355    def g5H(self):
    356        """Gamma_5 hermitean conjugate
    357
    358        Uses the fact that the propagator is gamma5 hermitean, so just the
    359        in and out momenta of the propagator are exchanged.
    360        """
    361        return Npr_matrix(self,
    362                          mom_in=self.mom_out,
    363                          mom_out=self.mom_in)

Gamma_5 hermitean conjugate

Uses the fact that the propagator is gamma5 hermitean, so just the in and out momenta of the propagator are exchanged.

def read_ExternalLeg_hd5(path, filestem, ens_id, idl=None): View Source

    386def read_ExternalLeg_hd5(path, filestem, ens_id, idl=None):
    387    """Read hadrons ExternalLeg hdf5 file and output an array of CObs
    388
    389    Parameters
    390    ----------
    391    path : str
    392        path to the files to read
    393    filestem : str
    394        namestem of the files to read
    395    ens_id : str
    396        name of the ensemble, required for internal bookkeeping
    397    idl : range
    398        If specified only configurations in the given range are read in.
    399
    400    Returns
    401    -------
    402    result : Npr_matrix
    403        read Cobs-matrix
    404    """
    405
    406    files, idx = _get_files(path, filestem, idl)
    407
    408    mom = None
    409
    410    corr_data = []
    411    for hd5_file in files:
    412        file = h5py.File(path + '/' + hd5_file, "r")
    413        raw_data = file['ExternalLeg/corr'][0][0].view('complex')
    414        corr_data.append(raw_data)
    415        if mom is None:
    416            mom = np.array(str(file['ExternalLeg/info'].attrs['pIn'])[3:-2].strip().split(), dtype=float)
    417        file.close()
    418    corr_data = np.array(corr_data)
    419
    420    rolled_array = np.rollaxis(corr_data, 0, 5)
    421
    422    matrix = np.empty((rolled_array.shape[:-1]), dtype=object)
    423    for si, sj, ci, cj in np.ndindex(rolled_array.shape[:-1]):
    424        real = Obs([rolled_array[si, sj, ci, cj].real], [ens_id], idl=[idx])
    425        imag = Obs([rolled_array[si, sj, ci, cj].imag], [ens_id], idl=[idx])
    426        matrix[si, sj, ci, cj] = CObs(real, imag)
    427
    428    return Npr_matrix(matrix, mom_in=mom)

Read hadrons ExternalLeg hdf5 file and output an array of CObs

###### Parameters

- path (str): path to the files to read
- filestem (str): namestem of the files to read
- ens_id (str): name of the ensemble, required for internal bookkeeping
- idl (range): If specified only configurations in the given range are read in.

###### Returns

- result (Npr_matrix): read Cobs-matrix

def read_Bilinear_hd5(path, filestem, ens_id, idl=None): View Source

    431def read_Bilinear_hd5(path, filestem, ens_id, idl=None):
    432    """Read hadrons Bilinear hdf5 file and output an array of CObs
    433
    434    Parameters
    435    ----------
    436    path : str
    437        path to the files to read
    438    filestem : str
    439        namestem of the files to read
    440    ens_id : str
    441        name of the ensemble, required for internal bookkeeping
    442    idl : range
    443        If specified only configurations in the given range are read in.
    444
    445    Returns
    446    -------
    447    result_dict: dict[Npr_matrix]
    448        extracted Bilinears
    449    """
    450
    451    files, idx = _get_files(path, filestem, idl)
    452
    453    mom_in = None
    454    mom_out = None
    455
    456    corr_data = {}
    457    for hd5_file in files:
    458        file = h5py.File(path + '/' + hd5_file, "r")
    459        for i in range(16):
    460            name = file['Bilinear/Bilinear_' + str(i) + '/info'].attrs['gamma'][0].decode('UTF-8')
    461            if name not in corr_data:
    462                corr_data[name] = []
    463            raw_data = file['Bilinear/Bilinear_' + str(i) + '/corr'][0][0].view('complex')
    464            corr_data[name].append(raw_data)
    465            if mom_in is None:
    466                mom_in = np.array(str(file['Bilinear/Bilinear_' + str(i) + '/info'].attrs['pIn'])[3:-2].strip().split(), dtype=float)
    467            if mom_out is None:
    468                mom_out = np.array(str(file['Bilinear/Bilinear_' + str(i) + '/info'].attrs['pOut'])[3:-2].strip().split(), dtype=float)
    469
    470        file.close()
    471
    472    result_dict = {}
    473
    474    for key, data in corr_data.items():
    475        local_data = np.array(data)
    476
    477        rolled_array = np.rollaxis(local_data, 0, 5)
    478
    479        matrix = np.empty((rolled_array.shape[:-1]), dtype=object)
    480        for si, sj, ci, cj in np.ndindex(rolled_array.shape[:-1]):
    481            real = Obs([rolled_array[si, sj, ci, cj].real], [ens_id], idl=[idx])
    482            imag = Obs([rolled_array[si, sj, ci, cj].imag], [ens_id], idl=[idx])
    483            matrix[si, sj, ci, cj] = CObs(real, imag)
    484
    485        result_dict[key] = Npr_matrix(matrix, mom_in=mom_in, mom_out=mom_out)
    486
    487    return result_dict

Read hadrons Bilinear hdf5 file and output an array of CObs

###### Parameters

- path (str): path to the files to read
- filestem (str): namestem of the files to read
- ens_id (str): name of the ensemble, required for internal bookkeeping
- idl (range): If specified only configurations in the given range are read in.

###### Returns

- result_dict (dict[Npr_matrix]): extracted Bilinears

def read_Fourquark_hd5(path, filestem, ens_id, idl=None, vertices=['VA', 'AV']): View Source

    490def read_Fourquark_hd5(path, filestem, ens_id, idl=None, vertices=["VA", "AV"]):
    491    """Read hadrons FourquarkFullyConnected hdf5 file and output an array of CObs
    492
    493    Parameters
    494    ----------
    495    path : str
    496        path to the files to read
    497    filestem : str
    498        namestem of the files to read
    499    ens_id : str
    500        name of the ensemble, required for internal bookkeeping
    501    idl : range
    502        If specified only configurations in the given range are read in.
    503    vertices : list
    504        Vertex functions to be extracted.
    505
    506    Returns
    507    -------
    508    result_dict : dict
    509        extracted fourquark matrizes
    510    """
    511
    512    files, idx = _get_files(path, filestem, idl)
    513
    514    mom_in = None
    515    mom_out = None
    516
    517    vertex_names = []
    518    for vertex in vertices:
    519        vertex_names += _get_lorentz_names(vertex)
    520
    521    corr_data = {}
    522
    523    tree = 'FourQuarkFullyConnected/FourQuarkFullyConnected_'
    524
    525    for hd5_file in files:
    526        file = h5py.File(path + '/' + hd5_file, "r")
    527
    528        for i in range(32):
    529            name = (file[tree + str(i) + '/info'].attrs['gammaA'][0].decode('UTF-8'), file[tree + str(i) + '/info'].attrs['gammaB'][0].decode('UTF-8'))
    530            if name in vertex_names:
    531                if name not in corr_data:
    532                    corr_data[name] = []
    533                raw_data = file[tree + str(i) + '/corr'][0][0].view('complex')
    534                corr_data[name].append(raw_data)
    535                if mom_in is None:
    536                    mom_in = np.array(str(file[tree + str(i) + '/info'].attrs['pIn'])[3:-2].strip().split(), dtype=float)
    537                if mom_out is None:
    538                    mom_out = np.array(str(file[tree + str(i) + '/info'].attrs['pOut'])[3:-2].strip().split(), dtype=float)
    539
    540        file.close()
    541
    542    intermediate_dict = {}
    543
    544    for vertex in vertices:
    545        lorentz_names = _get_lorentz_names(vertex)
    546        for v_name in lorentz_names:
    547            if v_name in [('SigmaXY', 'SigmaZT'),
    548                          ('SigmaXT', 'SigmaYZ'),
    549                          ('SigmaYZ', 'SigmaXT'),
    550                          ('SigmaZT', 'SigmaXY')]:
    551                sign = -1
    552            else:
    553                sign = 1
    554            if vertex not in intermediate_dict:
    555                intermediate_dict[vertex] = sign * np.array(corr_data[v_name])
    556            else:
    557                intermediate_dict[vertex] += sign * np.array(corr_data[v_name])
    558
    559    result_dict = {}
    560
    561    for key, data in intermediate_dict.items():
    562
    563        rolled_array = np.moveaxis(data, 0, 8)
    564
    565        matrix = np.empty((rolled_array.shape[:-1]), dtype=object)
    566        for index in np.ndindex(rolled_array.shape[:-1]):
    567            real = Obs([rolled_array[index].real], [ens_id], idl=[idx])
    568            imag = Obs([rolled_array[index].imag], [ens_id], idl=[idx])
    569            matrix[index] = CObs(real, imag)
    570
    571        result_dict[key] = Npr_matrix(matrix, mom_in=mom_in, mom_out=mom_out)
    572
    573    return result_dict

Read hadrons FourquarkFullyConnected hdf5 file and output an array of CObs

###### Parameters

- path (str): path to the files to read
- filestem (str): namestem of the files to read
- ens_id (str): name of the ensemble, required for internal bookkeeping
- idl (range): If specified only configurations in the given range are read in.
- vertices (list): Vertex functions to be extracted.

###### Returns

- result_dict (dict): extracted fourquark matrizes