pyerrors.input.hadrons

  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.stem
 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'):
 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.stem
 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):
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):
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):
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):
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:

>>> 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

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.

Inherited Members
numpy.ndarray
dumps
dump
all
any
argmax
argmin
argpartition
argsort
astype
byteswap
choose
clip
compress
conj
conjugate
copy
cumprod
cumsum
diagonal
dot
fill
flatten
getfield
item
itemset
max
mean
min
newbyteorder
nonzero
partition
prod
ptp
put
ravel
repeat
reshape
resize
round
searchsorted
setfield
setflags
sort
squeeze
std
sum
swapaxes
take
tobytes
tofile
tolist
tostring
trace
transpose
var
view
ndim
flags
shape
strides
data
itemsize
size
nbytes
base
dtype
real
imag
flat
ctypes
T
def read_ExternalLeg_hd5(path, filestem, ens_id, idl=None):
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):
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']):
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