From 722e6e44072ed2cd3df4c2a771feda143eec30ae Mon Sep 17 00:00:00 2001 From: NichtJens Date: Tue, 16 Apr 2024 13:14:02 +0200 Subject: [PATCH] added buffer config command line tool --- tools/buffer_config.py | 174 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 tools/buffer_config.py diff --git a/tools/buffer_config.py b/tools/buffer_config.py new file mode 100644 index 0000000..268e513 --- /dev/null +++ b/tools/buffer_config.py @@ -0,0 +1,174 @@ +import argparse +import os +from collections import defaultdict + +from sf_daq_broker.detector.detector_config import DetectorConfig, DETECTOR_DAQ +from sf_daq_broker.utils import json_load, json_save + + +BUFFER = "/gpfs/photonics/swissfel/buffer" + +#TODO: look up gain and pedestal files +EXTRA_PARAMS = { + "gain_file": "", + "pedestal_file": "", + "live_rate": 100, + "streamvis_rate": 100 +} + + + +def run(): + dbcfs = "detector buffer config files" + parser = argparse.ArgumentParser(description=f"create, update or update {dbcfs}") + + subparsers = parser.add_subparsers(title="commands", required=True) + + parser_detname = argparse.ArgumentParser(add_help=False) + parser_detname.add_argument("detector_name", help="Name of a JF detector") + + commands = ["create", "update", "compare"] + for cmd in commands: + func = globals()[f"cmd_{cmd}"] + parser_cmd = subparsers.add_parser(cmd, parents=[parser_detname], description=f"{cmd} {dbcfs}") + parser_cmd.set_defaults(func=func) + + clargs = parser.parse_args() + + try: + clargs.func(clargs.detector_name) + except Exception as e: + raise SystemExit(f"{e} -- skipping {clargs.detector_name}") from e + + +def cmd_create(detector_name): + params = get_detector_params(detector_name) + + # the buffer expects a few extra params that are not part of DetectorConfig + res = EXTRA_PARAMS.copy() + res.update(params) + + fn_cfg = f"{BUFFER}/config/{detector_name}.json" + json_save(res, fn_cfg) + + +def cmd_update(detector_name): + params_code = get_detector_params(detector_name) + + fn_cfg = f"{BUFFER}/config/{detector_name}.json" + params_file = load_config_file(fn_cfg) + + params_file.update(params_code) + + json_save(params_file, fn_cfg, mode="w") + + +def cmd_compare(detector_name): + params_code = get_detector_params(detector_name) + + fn_cfg = f"{BUFFER}/config/{detector_name}.json" + params_file = load_config_file(fn_cfg) + + diff = diff_dicts(params_code, params_file) + print_table(detector_name, diff) + + + +def get_detector_params(detector_name): + try: + cfg = DetectorConfig(detector_name) + except RuntimeError as e: + raise RuntimeError(f"cannot configure detector {detector_name} ({e})") from e + + params = { + "detector_name": cfg.get_detector_name(), + "n_modules": cfg.get_number_modules(), + "streamvis_stream": cfg.get_detector_daq_public_address(), + "live_stream": cfg.get_detector_daq_data_address(), + "start_udp_port": cfg.get_detector_port_first_module(), + "buffer_folder": f"{BUFFER}/{detector_name}" + } + return params + + +def load_config_file(fn_cfg): + if not os.path.exists(fn_cfg): + raise RuntimeError(f"buffer config file {fn_cfg} does not exist") + return json_load(fn_cfg) + + +def diff_dicts(d1, d2): + all_keys = d1.keys() | d2.keys() + + dd1 = defaultdict(Missing, d1) + dd2 = defaultdict(Missing, d2) + + diff = {} + for k in all_keys: + v1 = dd1[k] + v2 = dd2[k] + if v1 != v2: + diff[k] = (v1, v2) + + return diff + + +class Missing: + """ + Semaphore for missing entries + """ + + def __repr__(self): + return "" + + +def print_table(header, diff): + #TODO: this is a bit ugly + col1 = [] + col2 = [] + col3 = [] + for k, (v1, v2) in sorted(diff.items()): + col1.append(k + ":") + col2.append(repr(v1)) + col3.append(repr(v2)) + + col1 = ljust(col1) + col2 = rjust(col2) + col3 = rjust(col3) + + header = header + ":" + print(header) + print("-" * len(header)) + + #TODO + if not col1: + print("empty") + + for i1, i2, i3 in zip(col1, col2, col3): + print(i1, i2, i3, sep=2 * " ") + + print() + + +def ljust(seq): + length = maxstrlen(seq) + return (str(i).ljust(length) for i in seq) + +def rjust(seq): + length = maxstrlen(seq) + return (str(i).rjust(length) for i in seq) + +def maxstrlen(seq): + if not seq: + return 0 + return max(len(str(i)) for i in seq) + + + + + +if __name__ == "__main__": + run() + + +