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