Merge branch 'develop' into tests/find
All checks were successful
Mypy / mypy (push) Successful in 1m21s
Pytest / pytest (3.12) (push) Successful in 1m19s
Pytest / pytest (3.13) (push) Successful in 1m11s
Pytest / pytest (3.14) (push) Successful in 1m27s
Mypy / mypy (pull_request) Successful in 1m23s
Ruff / ruff (push) Successful in 1m1s
Pytest / pytest (3.12) (pull_request) Successful in 1m19s
Pytest / pytest (3.13) (pull_request) Successful in 1m23s
Pytest / pytest (3.14) (pull_request) Successful in 1m26s
Ruff / ruff (pull_request) Successful in 2m26s

This commit is contained in:
Justus Kuhlmann 2026-04-15 12:17:54 +02:00
commit 111e42adeb
8 changed files with 225 additions and 13 deletions

View file

@ -108,6 +108,8 @@ def find(
Find a record in the backlog at hand. Through specifying it's ensemble and the measured correlator. Find a record in the backlog at hand. Through specifying it's ensemble and the measured correlator.
""" """
results = find_record(path, ensemble, corr, code) results = find_record(path, ensemble, corr, code)
if results.empty:
return
if arg == 'all': if arg == 'all':
print(results) print(results)
else: else:

View file

@ -4,9 +4,12 @@ import os
import fnmatch import fnmatch
from typing import Any, Optional from typing import Any, Optional
from pathlib import Path from pathlib import Path
from ..pars.openQCD import ms1
from ..pars.openQCD import qcd2
def read_ms1_param(path: Path, project: str, file_in_project: str) -> dict[str, Any]:
def load_ms1_infile(path: Path, project: str, file_in_project: str) -> dict[str, Any]:
""" """
Read the parameters for ms1 measurements from a parameter file in the project. Read the parameters for ms1 measurements from a parameter file in the project.
@ -70,7 +73,7 @@ def read_ms1_param(path: Path, project: str, file_in_project: str) -> dict[str,
return param return param
def read_ms3_param(path: Path, project: str, file_in_project: str) -> dict[str, Any]: def load_ms3_infile(path: Path, project: str, file_in_project: str) -> dict[str, Any]:
""" """
Read the parameters for ms3 measurements from a parameter file in the project. Read the parameters for ms3 measurements from a parameter file in the project.
@ -304,3 +307,51 @@ def extract_t1(path: Path, project: str, dir_in_project: str, param: dict[str, A
t1_dict[param["type"]] = {} t1_dict[param["type"]] = {}
t1_dict[param["type"]][pars] = t0 t1_dict[param["type"]][pars] = t0
return t1_dict return t1_dict
def load_qcd2_pars(path: Path, project: str, file_in_project: str) -> dict[str, Any]:
"""
Thin wrapper around read_qcd2_par_file, getting the file before reading.
Parameters
----------
path: Path
Path of the corrlib repository.
project: str
UUID of the project of the parameter-file.
file_in_project: str
The loaction of the file in the project directory.
Returns
-------
par_dict: dict
The dict with the parameters read from the .par-file.
"""
fname = path / "projects" / project / file_in_project
ds = os.path.join(path, "projects", project)
dl.get(fname, dataset=ds)
return qcd2.read_qcd2_par_file(fname)
def load_ms1_parfile(path: Path, project: str, file_in_project: str) -> dict[str, Any]:
"""
Thin wrapper around read_qcd2_ms1_par_file, getting the file before reading.
Parameters
----------
path: Path
Path of the corrlib repository.
project: str
UUID of the project of the parameter-file.
file_in_project: str
The loaction of the file in the project directory.
Returns
-------
par_dict: dict
The dict with the parameters read from the .par-file.
"""
fname = path / "projects" / project / file_in_project
ds = os.path.join(path, "projects", project)
dl.get(fname, dataset=ds)
return ms1.read_qcd2_ms1_par_file(fname)

View file

@ -59,7 +59,7 @@ def write_measurement(path: Path, ensemble: str, measurement: dict[str, dict[str
if file not in files_to_save: if file not in files_to_save:
unlock(path, file_in_archive) unlock(path, file_in_archive)
files_to_save.append(file_in_archive) files_to_save.append(file_in_archive)
known_meas = pj.load_json_dict(file, verbose=False) known_meas = pj.load_json_dict(str(file), verbose=False)
if code == "sfcf": if code == "sfcf":
if parameter_file is not None: if parameter_file is not None:
parameters = sfcf.read_param(path, uuid, parameter_file) parameters = sfcf.read_param(path, uuid, parameter_file)
@ -74,9 +74,24 @@ def write_measurement(path: Path, ensemble: str, measurement: dict[str, dict[str
ms_type = list(measurement.keys())[0] ms_type = list(measurement.keys())[0]
if ms_type == 'ms1': if ms_type == 'ms1':
if parameter_file is not None: if parameter_file is not None:
parameters = openQCD.read_ms1_param(path, uuid, parameter_file) if parameter_file.endswith(".ms1.in"):
parameters = openQCD.load_ms1_infile(path, uuid, parameter_file)
elif parameter_file.endswith(".ms1.par"):
parameters = openQCD.load_ms1_parfile(path, uuid, parameter_file)
else: else:
raise Exception("Need parameter file for this code!") # Temporary solution
parameters = {}
parameters["rand"] = {}
parameters["rw_fcts"] = [{}]
for nrw in range(1):
if "nsrc" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["nsrc"] = 1
if "mu" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["mu"] = "None"
if "np" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["np"] = "None"
if "irp" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["irp"] = "None"
pars = {} pars = {}
subkeys = [] subkeys = []
for i in range(len(parameters["rw_fcts"])): for i in range(len(parameters["rw_fcts"])):
@ -88,7 +103,7 @@ def write_measurement(path: Path, ensemble: str, measurement: dict[str, dict[str
pars[subkey] = json.dumps(parameters["rw_fcts"][i]) pars[subkey] = json.dumps(parameters["rw_fcts"][i])
elif ms_type in ['t0', 't1']: elif ms_type in ['t0', 't1']:
if parameter_file is not None: if parameter_file is not None:
parameters = openQCD.read_ms3_param(path, uuid, parameter_file) parameters = openQCD.load_ms3_infile(path, uuid, parameter_file)
else: else:
parameters = {} parameters = {}
for rwp in ["integrator", "eps", "ntot", "dnms"]: for rwp in ["integrator", "eps", "ntot", "dnms"]:
@ -113,7 +128,7 @@ def write_measurement(path: Path, ensemble: str, measurement: dict[str, dict[str
c.execute("INSERT INTO backlogs (name, ensemble, code, path, project, parameters, parameter_file, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))", c.execute("INSERT INTO backlogs (name, ensemble, code, path, project, parameters, parameter_file, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'), datetime('now'))",
(corr, ensemble, code, meas_path, uuid, pars[subkey], parameter_file)) (corr, ensemble, code, meas_path, uuid, pars[subkey], parameter_file))
conn.commit() conn.commit()
pj.dump_dict_to_json(known_meas, file) pj.dump_dict_to_json(known_meas, str(file))
conn.close() conn.close()
save(path, message="Add measurements to database", files=files_to_save) save(path, message="Add measurements to database", files=files_to_save)
return return
@ -269,11 +284,11 @@ def drop_record(path: Path, meas_path: str) -> None:
raise ValueError("This measurement does not exist as an entry!") raise ValueError("This measurement does not exist as an entry!")
conn.commit() conn.commit()
known_meas = pj.load_json_dict(file) known_meas = pj.load_json_dict(str(file))
if sub_key in known_meas: if sub_key in known_meas:
del known_meas[sub_key] del known_meas[sub_key]
unlock(path, Path(file_in_archive)) unlock(path, Path(file_in_archive))
pj.dump_dict_to_json(known_meas, file) pj.dump_dict_to_json(known_meas, str(file))
save(path, message="Drop measurements to database", files=[db, file]) save(path, message="Drop measurements to database", files=[db, file])
return return
else: else:

View file

@ -0,0 +1,3 @@
from . import ms1 as ms1
from . import qcd2 as qcd2

View file

@ -0,0 +1,59 @@
"""
Reconstruct the outputs of flags.
"""
import struct
from typing import Any, BinaryIO
# lat_parms.c
def lat_parms_write_lat_parms(fp: BinaryIO) -> dict[str, Any]:
"""
NOTE: This is a duplcation from qcd2.
Unpack the lattice parameters written by write_lat_parms.
"""
lat_pars = {}
t = fp.read(16)
lat_pars["N"] = list(struct.unpack('iiii', t)) # lattice extends
t = fp.read(8)
nk, isw = struct.unpack('ii', t) # number of kappas and isw parameter
lat_pars["nk"] = nk
lat_pars["isw"] = isw
t = fp.read(8)
lat_pars["beta"] = struct.unpack('d', t)[0] # beta
t = fp.read(8)
lat_pars["c0"] = struct.unpack('d', t)[0]
t = fp.read(8)
lat_pars["c1"] = struct.unpack('d', t)[0]
t = fp.read(8)
lat_pars["csw"] = struct.unpack('d', t)[0] # csw factor
kappas = []
m0s = []
# read kappas
for ik in range(nk):
t = fp.read(8)
kappas.append(struct.unpack('d', t)[0])
t = fp.read(8)
m0s.append(struct.unpack('d', t)[0])
lat_pars["kappas"] = kappas
lat_pars["m0s"] = m0s
return lat_pars
def lat_parms_write_bc_parms(fp: BinaryIO) -> dict[str, Any]:
"""
NOTE: This is a duplcation from qcd2.
Unpack the boundary parameters written by write_bc_parms.
"""
bc_pars: dict[str, Any] = {}
t = fp.read(4)
bc_pars["type"] = struct.unpack('i', t)[0] # type of hte boundaries
t = fp.read(104)
bc_parms = struct.unpack('d'*13, t)
bc_pars["cG"] = list(bc_parms[:2]) # boundary gauge field improvement
bc_pars["cF"] = list(bc_parms[2:4]) # boundary fermion field improvement
phi: list[list[float]] = [[], []]
phi[0] = list(bc_parms[4:7])
phi[1] = list(bc_parms[7:10])
bc_pars["phi"] = phi
bc_pars["theta"] = list(bc_parms[10:])
return bc_pars

View file

@ -0,0 +1,30 @@
from . import flags
from typing import Any
from pathlib import Path
def read_qcd2_ms1_par_file(fname: Path) -> dict[str, dict[str, Any]]:
"""
The subroutines written here have names according to the openQCD programs and functions that write out the data.
Parameters
----------
fname: Path
Location of the parameter file.
Returns
-------
par_dict: dict
Dictionary holding the parameters specified in the given file.
"""
with open(fname, "rb") as fp:
lat_par_dict = flags.lat_parms_write_lat_parms(fp)
bc_par_dict = flags.lat_parms_write_bc_parms(fp)
fp.close()
par_dict = {}
par_dict["lat"] = lat_par_dict
par_dict["bc"] = bc_par_dict
return par_dict

View file

@ -0,0 +1,29 @@
from . import flags
from pathlib import Path
from typing import Any
def read_qcd2_par_file(fname: Path) -> dict[str, dict[str, Any]]:
"""
The subroutines written here have names according to the openQCD programs and functions that write out the data.
Parameters
----------
fname: Path
Location of the parameter file.
Returns
-------
par_dict: dict
Dictionary holding the parameters specified in the given file.
"""
with open(fname, "rb") as fp:
lat_par_dict = flags.lat_parms_write_lat_parms(fp)
bc_par_dict = flags.lat_parms_write_bc_parms(fp)
fp.close()
par_dict = {}
par_dict["lat"] = lat_par_dict
par_dict["bc"] = bc_par_dict
return par_dict

View file

@ -178,8 +178,10 @@ def import_toml(path: Path, file: str, copy_file: bool=True) -> None:
update_aliases(path, uuid, aliases) update_aliases(path, uuid, aliases)
else: else:
uuid = import_project(path, project['url'], aliases=aliases) uuid = import_project(path, project['url'], aliases=aliases)
imeas = 1
nmeas = len(measurements.keys())
for mname, md in measurements.items(): for mname, md in measurements.items():
print("Import measurement: " + mname) print(f"Import measurement {imeas}/{nmeas}: {mname}")
ensemble = md['ensemble'] ensemble = md['ensemble']
if project['code'] == 'sfcf': if project['code'] == 'sfcf':
param = sfcf.read_param(path, uuid, md['param_file']) param = sfcf.read_param(path, uuid, md['param_file'])
@ -192,12 +194,32 @@ def import_toml(path: Path, file: str, copy_file: bool=True) -> None:
elif project['code'] == 'openQCD': elif project['code'] == 'openQCD':
if md['measurement'] == 'ms1': if md['measurement'] == 'ms1':
param = openQCD.read_ms1_param(path, uuid, md['param_file']) if 'param_file' in md.keys():
parameter_file = md['param_file']
if parameter_file.endswith(".ms1.in"):
param = openQCD.load_ms1_infile(path, uuid, parameter_file)
elif parameter_file.endswith(".ms1.par"):
param = openQCD.load_ms1_parfile(path, uuid, parameter_file)
else:
# Temporary solution
parameters: dict[str, Any] = {}
parameters["rand"] = {}
parameters["rw_fcts"] = [{}]
for nrw in range(1):
if "nsrc" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["nsrc"] = 1
if "mu" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["mu"] = "None"
if "np" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["np"] = "None"
if "irp" not in parameters["rw_fcts"][nrw]:
parameters["rw_fcts"][nrw]["irp"] = "None"
param = parameters
param['type'] = 'ms1' param['type'] = 'ms1'
measurement = openQCD.read_rwms(path, uuid, md['path'], param, md["prefix"], version=md["version"], names=md['names'], files=md['files']) measurement = openQCD.read_rwms(path, uuid, md['path'], param, md["prefix"], version=md["version"], names=md['names'], files=md['files'])
elif md['measurement'] == 't0': elif md['measurement'] == 't0':
if 'param_file' in md: if 'param_file' in md:
param = openQCD.read_ms3_param(path, uuid, md['param_file']) param = openQCD.load_ms3_infile(path, uuid, md['param_file'])
else: else:
param = {} param = {}
for rwp in ["integrator", "eps", "ntot", "dnms"]: for rwp in ["integrator", "eps", "ntot", "dnms"]:
@ -207,11 +229,12 @@ def import_toml(path: Path, file: str, copy_file: bool=True) -> None:
fit_range=int(md.get('fit_range', 5)), postfix=str(md.get('postfix', '')), names=md.get('names', []), files=md.get('files', [])) fit_range=int(md.get('fit_range', 5)), postfix=str(md.get('postfix', '')), names=md.get('names', []), files=md.get('files', []))
elif md['measurement'] == 't1': elif md['measurement'] == 't1':
if 'param_file' in md: if 'param_file' in md:
param = openQCD.read_ms3_param(path, uuid, md['param_file']) param = openQCD.load_ms3_infile(path, uuid, md['param_file'])
param['type'] = 't1' param['type'] = 't1'
measurement = openQCD.extract_t1(path, uuid, md['path'], param, str(md["prefix"]), int(md["dtr_read"]), int(md["xmin"]), int(md["spatial_extent"]), measurement = openQCD.extract_t1(path, uuid, md['path'], param, str(md["prefix"]), int(md["dtr_read"]), int(md["xmin"]), int(md["spatial_extent"]),
fit_range=int(md.get('fit_range', 5)), postfix=str(md.get('postfix', '')), names=md.get('names', []), files=md.get('files', [])) fit_range=int(md.get('fit_range', 5)), postfix=str(md.get('postfix', '')), names=md.get('names', []), files=md.get('files', []))
write_measurement(path, ensemble, measurement, uuid, project['code'], (md['param_file'] if 'param_file' in md else None)) write_measurement(path, ensemble, measurement, uuid, project['code'], (md['param_file'] if 'param_file' in md else None))
imeas += 1
print(mname + " imported.") print(mname + " imported.")
if not os.path.exists(path / "toml_imports" / uuid): if not os.path.exists(path / "toml_imports" / uuid):