322 Read trigger configuration keys (SMK, L1PSK, HLTPSK) and DB info from OKS via WEBDAQ REST API.
324 This reads the keys from the partition's TriggerConfiguration object and its
325 related L1TriggerConfiguration and TriggerDBConnection objects.
328 - Partition -> TriggerConfiguration -> L1TriggerConfiguration (Lvl1PrescaleKey)
329 - Partition -> TriggerConfiguration -> TriggerDBConnection (SuperMasterKey)
330 - Partition -> TriggerConfiguration -> HLTImplementationDB (hltPrescaleKey)
333 partition: The partition name (default: from TDAQ_PARTITION env var)
334 webdaq_base: Base URL for webis_server (default: from TDAQ_WEBDAQ_BASE env var)
335 strict: If True, raise an exception if OKS read fails (for --online-environment)
338 dict with keys: SMK, L1PSK, HLTPSK, db_alias (values may be None if not found)
341 RuntimeError: If strict=True and OKS read fails
346 if webdaq_base
is None:
347 webdaq_base = os.environ.get(
'TDAQ_WEBDAQ_BASE')
350 msg =
"TDAQ_WEBDAQ_BASE not set, cannot read from OKS"
352 raise RuntimeError(msg +
" (required for --online-environment)")
354 return {
'SMK':
None,
'L1PSK':
None,
'HLTPSK':
None,
'db_alias':
None}
357 if partition
is None:
358 partition = os.environ.get(
'TDAQ_PARTITION',
'ATLAS')
360 log.info(
"Reading trigger configuration keys from OKS via WEBDAQ: %s (partition=%s)",
361 webdaq_base, partition)
363 result = {
'SMK':
None,
'L1PSK':
None,
'HLTPSK':
None,
'db_alias':
None}
365 def extract_oks_data(response_json):
367 Extract data from OKS compact format: [name, type, attributes, relationships]
368 Returns tuple (attributes_dict, relationships_dict)
370 if isinstance(response_json, list)
and len(response_json) >= 4:
371 return response_json[2], response_json[3]
372 elif isinstance(response_json, list)
and len(response_json) >= 3:
373 return response_json[2], {}
374 return response_json, {}
377 """Extract object ID from a relationship reference."""
378 if isinstance(ref, list)
and len(ref) >= 2:
380 elif isinstance(ref, dict)
and 'id' in ref:
382 elif isinstance(ref, str):
391 url = f
"{webdaq_base}/info/current/{partition}/oks/Partition/{partition}?format=compact"
392 log.debug(
"Fetching Partition from OKS: %s", url)
394 response = requests.get(url, timeout=10)
395 if response.status_code == 200:
396 part_attrs, part_rels = extract_oks_data(response.json())
397 log.debug(
"Partition attributes: %s", part_attrs)
398 log.debug(
"Partition relationships: %s", part_rels)
402 if 'TriggerConfiguration' in part_rels:
403 trig_conf_id = get_ref_id(part_rels[
'TriggerConfiguration'])
406 log.debug(
"TriggerConfiguration ID: %s", trig_conf_id)
409 url = f
"{webdaq_base}/info/current/{partition}/oks/TriggerConfiguration/{trig_conf_id}?format=compact"
410 response = requests.get(url, timeout=10)
411 if response.status_code == 200:
412 trig_attrs, trig_rels = extract_oks_data(response.json())
413 log.debug(
"TriggerConfiguration attributes: %s", trig_attrs)
414 log.debug(
"TriggerConfiguration relationships: %s", trig_rels)
417 if 'l1' in trig_rels:
418 l1_id = get_ref_id(trig_rels[
'l1'])
420 url = f
"{webdaq_base}/info/current/{partition}/oks/L1TriggerConfiguration/{l1_id}?format=compact"
421 resp = requests.get(url, timeout=10)
422 if resp.status_code == 200:
423 l1_attrs, _ = extract_oks_data(resp.json())
424 log.debug(
"L1TriggerConfiguration attributes: %s", l1_attrs)
425 if 'Lvl1PrescaleKey' in l1_attrs:
426 result[
'L1PSK'] = int(l1_attrs[
'Lvl1PrescaleKey'])
427 log.info(
"Got L1PSK=%d from OKS", result[
'L1PSK'])
430 if 'TriggerDBConnection' in trig_rels:
431 db_id = get_ref_id(trig_rels[
'TriggerDBConnection'])
433 url = f
"{webdaq_base}/info/current/{partition}/oks/TriggerDBConnection/{db_id}?format=compact"
434 resp = requests.get(url, timeout=10)
435 if resp.status_code == 200:
436 db_attrs, _ = extract_oks_data(resp.json())
437 log.debug(
"TriggerDBConnection attributes: %s", db_attrs)
438 if 'SuperMasterKey' in db_attrs:
439 result[
'SMK'] = int(db_attrs[
'SuperMasterKey'])
440 log.info(
"Got SMK=%d from OKS", result[
'SMK'])
441 if 'Alias' in db_attrs:
442 result[
'db_alias'] = db_attrs[
'Alias']
443 log.info(
"Got db_alias=%s from OKS", result[
'db_alias'])
446 if 'hlt' in trig_rels:
447 hlt_id = get_ref_id(trig_rels[
'hlt'])
449 url = f
"{webdaq_base}/info/current/{partition}/oks/HLTImplementationDB/{hlt_id}?format=compact"
450 resp = requests.get(url, timeout=10)
451 if resp.status_code == 200:
452 hlt_attrs, _ = extract_oks_data(resp.json())
453 log.debug(
"HLTImplementationDB attributes: %s", hlt_attrs)
454 if 'hltPrescaleKey' in hlt_attrs:
455 result[
'HLTPSK'] = int(hlt_attrs[
'hltPrescaleKey'])
456 log.info(
"Got HLTPSK=%d from OKS", result[
'HLTPSK'])
458 msg = f
"Failed to fetch Partition from OKS: HTTP {response.status_code}"
460 raise RuntimeError(msg +
" (required for --online-environment)")
463 except requests.exceptions.RequestException
as e:
464 msg = f
"Error fetching trigger keys from OKS: {e}"
466 raise RuntimeError(msg +
" (required for --online-environment)")
468 except (ValueError, KeyError, TypeError)
as e:
469 msg = f
"Error parsing trigger keys from OKS: {e}"
471 raise RuntimeError(msg +
" (required for --online-environment)")
476 missing = [k
for k
in [
'SMK',
'L1PSK',
'HLTPSK']
if result.get(k)
is None]
478 raise RuntimeError(f
"Failed to get {', '.join(missing)} from OKS (required for --online-environment)")
483def get_run_params(args=None, from_is=False, partition=None, webdaq_base=None, strict=False,
484 solenoid_current_override=None, toroids_current_override=None):
486 Get run parameters from the appropriate source.
488 This is the main entry point for obtaining run parameters. It provides
489 a single place to modify when adding new sources (like WEBDAQ).
492 args: argparse Namespace with command-line arguments (optional)
493 from_is: If True, try to read from WEBDAQ first
494 partition: Partition name for IS access (defaults to TDAQ_PARTITION env var)
495 webdaq_base: WEBDAQ base URL (defaults to TDAQ_WEBDAQ_BASE env var)
496 strict: If True, raise an exception if IS read fails (for --online-environment)
497 solenoid_current_override: Command-line override for solenoid current
498 toroids_current_override: Command-line override for toroids current
504 RuntimeError: If strict=True and IS read fails
507 return RunParams.from_is(partition=partition, webdaq_base=webdaq_base, strict=strict,
508 solenoid_current_override=solenoid_current_override,
509 toroids_current_override=toroids_current_override)
510 elif args
is not None:
511 return RunParams.from_args(args)
864 """Update run parameters from IS, file, or conditions DB"""
867 if getattr(args,
'online_environment',
False):
868 log.info(
"Reading run parameters from Information Service via WEBDAQ")
872 solenoid_override = getattr(args,
'solenoid_current',
None)
873 toroids_override = getattr(args,
'toroids_current',
None)
876 partition=getattr(args,
'partition',
None),
877 webdaq_base=getattr(args,
'webdaq_base',
None),
879 solenoid_current_override=solenoid_override,
880 toroids_current_override=toroids_override)
882 if args.run_number
is None and run_params.run_number
is not None:
883 args.run_number = run_params.run_number
884 log.info(
"Using run_number=%d from IS", args.run_number)
885 if args.lb_number
is None and run_params.lb_number
is not None:
886 args.lb_number = run_params.lb_number
887 log.info(
"Using lb_number=%d from IS", args.lb_number)
888 if args.sor_time
is None and run_params.sor_time
is not None:
889 args.sor_time = run_params.sor_time
890 log.info(
"Using sor_time=%s from IS", args.sor_time)
891 if args.detector_mask
is None and run_params.detector_mask
is not None:
892 args.detector_mask = run_params.detector_mask
893 log.info(
"Using detector_mask=%s from IS", args.detector_mask)
895 args.solenoid_current = run_params.solenoid_current
896 args.toroids_current = run_params.toroids_current
897 args.beam_type = run_params.beam_type
898 args.beam_energy = run_params.beam_energy
900 if (args.run_number
is not None and args.lb_number
is None)
or (args.run_number
is None and args.lb_number
is not None):
901 log.error(
"Both or neither of the options -R (--run-number) and -L (--lb-number) have to be specified")
905 from eformat
import EventStorage
906 dr = EventStorage.pickDataReader(args.file[0])
907 if args.run_number
is None:
908 args.run_number = dr.runNumber()
909 args.lb_number = dr.lumiblockNumber()
910 args.T0_project_tag = dr.projectTag()
911 args.beam_type = dr.beamType()
912 args.beam_energy = dr.beamEnergy()
913 args.trigger_type = dr.triggerType()
914 args.stream = dr.stream()
915 args.lumiblock = dr.lumiblockNumber()
916 args.file_detector_mask =
"{:032x}".format(dr.detectorMask())
918 args.T0_project_tag = getattr(args,
'T0_project_tag',
'')
919 args.beam_type = getattr(args,
'beam_type', 0)
920 args.beam_energy = getattr(args,
'beam_energy', 0)
921 args.trigger_type = getattr(args,
'trigger_type', 0)
922 args.stream = getattr(args,
'stream',
'')
923 args.lumiblock = getattr(args,
'lumiblock', 0)
924 args.file_detector_mask = getattr(args,
'file_detector_mask',
'00000000000000000000000000000000')
927 if (args.sor_time
is None or args.detector_mask
is None)
and args.run_number
is not None:
928 sor_params = AthHLT.get_sor_params(args.run_number)
929 log.debug(
'SOR parameters: %s', sor_params)
930 if sor_params
is None:
931 log.error(
"Run %d does not exist. If you want to use this run-number specify "
932 "remaining run parameters, e.g.: --sor-time=now --detector-mask=all", args.run_number)
935 if args.sor_time
is None and sor_params
is not None:
936 args.sor_time =
arg_sor_time(str(sor_params[
'SORTime']))
938 if args.detector_mask
is None and sor_params
is not None:
939 dmask = sor_params[
'DetectorMask']
940 if args.run_number < AthHLT.CondDB._run2:
944 if args.dump_config_exit
and not args.run_number:
949 if getattr(args,
'solenoid_current',
None)
is None:
950 args.solenoid_current = RunParams.DEFAULT_SOLENOID_CURRENT
951 log.debug(
"Using default solenoid_current=%.1f", args.solenoid_current)
952 if getattr(args,
'toroids_current',
None)
is None:
953 args.toroids_current = RunParams.DEFAULT_TOROIDS_CURRENT
954 log.debug(
"Using default toroids_current=%.1f", args.toroids_current)
958 """Update trigger configuration keys from OKS, COOL, or CREST.
961 1. Command-line arguments (always take precedence)
962 2. OKS via WEBDAQ (if --online-environment is set)
963 3. CREST (if --use-crest is set)
967 if args.smk
is None or args.l1psk
is None or args.hltpsk
is None:
971 if getattr(args,
'online_environment',
False):
972 log.info(
"Reading trigger configuration keys from OKS (online environment)")
975 partition=getattr(args,
'partition',
None),
976 webdaq_base=getattr(args,
'webdaq_base',
None),
979 log.info(
"Retrieved trigger keys from OKS: %s", oks_keys)
983 'SMK': oks_keys.get(
'SMK'),
984 'LVL1PSK': oks_keys.get(
'L1PSK'),
985 'HLTPSK': oks_keys.get(
'HLTPSK')
988 if oks_keys.get(
'db_alias')
and args.db_server ==
'TRIGGERDB_RUN3':
989 args.db_server = oks_keys[
'db_alias']
990 log.info(
"Using db_server=%s from OKS", args.db_server)
995 log.info(
"Reading trigger configuration keys from CREST for run %s", args.run_number)
996 trigconf = AthHLT.get_trigconf_keys_crest(args.run_number, args.lb_number, args.crest_server)
997 log.info(
"Retrieved trigger keys from CREST: %s", trigconf)
999 log.info(
"Reading trigger configuration keys from COOL for run %s", args.run_number)
1000 trigconf = AthHLT.get_trigconf_keys(args.run_number, args.lb_number)
1001 log.info(
"Retrieved trigger keys from COOL: %s", trigconf)
1004 if args.smk
is None:
1005 args.smk = trigconf[
'SMK']
1006 log.debug(
"Using SMK=%d from conditions DB/OKS", args.smk)
1008 log.debug(
"Using SMK=%d from command line (ignoring DB/OKS value %s)", args.smk, trigconf.get(
'SMK'))
1009 if args.l1psk
is None:
1010 args.l1psk = trigconf[
'LVL1PSK']
1011 log.debug(
"Using L1PSK=%d from conditions DB/OKS", args.l1psk)
1013 log.debug(
"Using L1PSK=%d from command line (ignoring DB/OKS value %s)", args.l1psk, trigconf.get(
'LVL1PSK'))
1014 if args.hltpsk
is None:
1015 args.hltpsk = trigconf[
'HLTPSK']
1016 log.debug(
"Using HLTPSK=%d from conditions DB/OKS", args.hltpsk)
1018 log.debug(
"Using HLTPSK=%d from command line (ignoring DB/OKS value %s)", args.hltpsk, trigconf.get(
'HLTPSK'))
1020 log.error(
"Cannot read trigger configuration keys from the conditions database for run %d", args.run_number)
1023 log.info(
"Using trigger configuration keys from command line: SMK=%d, L1PSK=%d, HLTPSK=%d",
1024 args.smk, args.l1psk, args.hltpsk)
1048 """Start a private TDAQ infrastructure (offline test of OH publication)."""
1049 import shutil, socket, signal, subprocess, time
1051 infra_script = shutil.which(
'athenaEF_tdaq_infra.py')
1052 if infra_script
is None:
1053 log.error(
"athenaEF_tdaq_infra.py not found on PATH (required for -M)")
1056 partition = args.partition
or 'athenaEF'
1061 port = s.getsockname()[1]
1063 oh_server =
'Histogramming'
1064 run_number = args.run_number
if args.run_number
is not None else 0
1067 os.environ[
'TDAQ_PARTITION'] = partition
1068 os.environ[
'TDAQ_WEBDAQ_BASE'] = f
'http://{host}:{port}'
1069 os.environ[
'TDAQ_OH_SERVER'] = oh_server
1071 log.info(
"Starting private OH infrastructure: partition=%s, webdaq=%s, oh_server=%s",
1072 partition, os.environ[
'TDAQ_WEBDAQ_BASE'], oh_server)
1074 logfile = open(
'athenaEF_oh_infra.log',
'w')
1078 from ctypes
import cdll
1079 PR_SET_PDEATHSIG = 1
1081 cdll[
'libc.so.6'].prctl(PR_SET_PDEATHSIG, signal.SIGTERM)
1084 log.info(
"IS schema files: %s",
', '.join(schemas)
or '(none)')
1086 proc = subprocess.Popen(
1088 '--partition', partition,
1089 '--webdaq-port', str(port),
1090 '--oh-server', oh_server,
1091 '--run-number', str(run_number),
1092 *(arg
for f
in schemas
for arg
in (
'--schema', f))],
1093 stdout=logfile, stderr=subprocess.STDOUT,
1094 preexec_fn=_pdeathsig, close_fds=
True)
1098 deadline = time.time() + timeout
1099 while time.time() < deadline:
1100 if proc.poll()
is not None:
1101 log.error(
"OH infrastructure exited early (code %s); see %s", proc.returncode, logfile.name)
1103 with open(logfile.name)
as f:
1104 if 'ATHENAEF_INFRA_READY' in f.read():
1105 log.info(
"OH infrastructure is ready")
1109 log.error(
"OH infrastructure did not become ready within %d s; see %s", timeout, logfile.name)
1143 """Configure the job from a CA module and re-execute athenaEF from the resulting JSON.
1145 This function never returns: athenaEF either exits (--dump-config-exit) or replaces
1146 itself with a new athenaEF running from the JSON file it just created.
1148 from AthenaCommon
import Constants
1149 from AthenaConfiguration.AllConfigFlags
import initConfigFlags
1150 from AthenaConfiguration.ComponentAccumulator
import ComponentAccumulator
1151 from AthenaConfiguration.ComponentFactory
import CompFactory
1152 from AthenaConfiguration.MainServicesConfig
import addMainSequences
1153 from TrigServices.TrigServicesConfig
import commonServicesCfg, setDefaultOnlineFlags
1156 flags = initConfigFlags()
1157 setDefaultOnlineFlags(flags)
1160 flags.Exec.OutputLevel = getattr(Constants, args.log_level)
1163 if args.oh_monitoring:
1164 flags.Trigger.Online.useOnlineWebdaqHistSvc =
True
1165 log.info(
"Enabled WebdaqHistSvc for online histogram publishing")
1168 AthHLT.unparsedArguments = unparsed_args
1169 AthHLT.fillFromUnparsedArgs(flags)
1177 if args.conditions_run
is not None:
1178 log.info(
"Using conditions from reference run %d (overriding run %s for IOV lookup)",
1179 args.conditions_run, args.run_number)
1180 flags.Input.ConditionsRunNumber = args.conditions_run
1183 if args.number_of_events
is not None and args.number_of_events > 0:
1184 flags.Exec.MaxEvents = args.number_of_events
1187 if args.skip_events
is not None and args.skip_events > 0:
1188 flags.Exec.SkipEvents = args.skip_events
1194 flags.PerfMon.doFastMonMT = args.perfmon
1198 log.info(
"Executing precommand(s)")
1199 for cmd
in args.precommand:
1200 log.info(
" %s", cmd)
1201 exec(cmd, globals(), {
'flags': flags})
1207 log.info(
"Loading CA configuration from: %s", args.jobOptions)
1210 locked_flags = flags.clone()
1214 cfg = ComponentAccumulator(CompFactory.AthSequencer(
"AthMasterSeq", Sequential=
True))
1215 cfg.setAppProperty(
'ExtSvcCreates',
False)
1216 cfg.setAppProperty(
"MessageSvcType",
"TrigMessageSvc")
1217 cfg.setAppProperty(
"JobOptionsSvcType",
"TrigConf::JobOptionsSvc")
1220 addMainSequences(locked_flags, cfg)
1221 cfg.merge(commonServicesCfg(locked_flags))
1224 cfg_func = AthHLT.getCACfg(args.jobOptions)
1225 cfg.merge(cfg_func(flags))
1228 if args.postcommand:
1229 log.info(
"Executing postcommand(s)")
1230 for cmd
in args.postcommand:
1231 log.info(
" %s", cmd)
1232 exec(cmd, globals(), {
'flags': flags,
'cfg': cfg})
1235 fname =
"HLTJobOptions"
1236 log.info(
"Dumping configuration to %s.pkl and %s.json", fname, fname)
1237 with open(f
"{fname}.pkl",
"wb")
as f:
1240 from TrigConfIO.JsonUtils
import create_joboptions_json
1241 create_joboptions_json(f
"{fname}.pkl", f
"{fname}.json")
1244 if args.dump_config_exit:
1245 log.info(
"Configuration dumped to %s.json. Exiting...", fname)
1249 log.info(
"Configuration dumped to %s.json. Re-exec...", fname)
1250 AthHLT.reload_from_json(f
"{fname}.json", suppress_args=unparsed_args + [
'--dump-config'], jobOptions=args.jobOptions)
1254 parser = argparse.ArgumentParser(prog=
'athenaEF.py', formatter_class=
1255 lambda prog : argparse.ArgumentDefaultsHelpFormatter(prog, max_help_position=32, width=100),
1256 usage =
'%(prog)s [OPTION]... -f FILE jobOptions',
1258 parser.expert_groups = []
1261 g = parser.add_argument_group(
'Options')
1262 g.add_argument(
'jobOptions', nargs=
'?', help=
'job options: CA module (package.module:function) or JSON file (.json)')
1263 g.add_argument(
'--threads', metavar=
'N', type=int, default=1, help=
'number of threads')
1264 g.add_argument(
'--concurrent-events', metavar=
'N', type=int, help=
'number of concurrent events if different from --threads')
1265 g.add_argument(
'--log-level',
'-l', metavar=
'LVL', default=
'INFO', help=
'OutputLevel of athena')
1266 g.add_argument(
'--precommand',
'-c', metavar=
'CMD', action=
'append', default=[],
1267 help=
'Python commands executed before job options')
1268 g.add_argument(
'--postcommand',
'-C', metavar=
'CMD', action=
'append', default=[],
1269 help=
'Python commands executed after job options')
1270 g.add_argument(
'--interactive',
'-i', action=
'store_true', help=
'interactive mode')
1271 g.add_argument(
'--help',
'-h', nargs=
'?', choices=[
'all'], action=MyHelp, help=
'show help')
1273 g = parser.add_argument_group(
'Input/Output')
1274 g.add_argument(
'--file',
'--filesInput',
'-f', action=
'append', help=
'input RAW file')
1275 g.add_argument(
'--save-output',
'-o', metavar=
'FILE', help=
'output file name')
1276 g.add_argument(
'--number-of-events',
'--evtMax',
'-n', metavar=
'N', type=int, default=
None,
1277 help=
'processes N events (default: from DB/config, -1 means all)')
1278 g.add_argument(
'--skip-events',
'--skipEvents',
'-k', metavar=
'N', type=int, default=
None,
1279 help=
'skip N first events')
1280 g.add_argument(
'--loop-files', action=argparse.BooleanOptionalAction, default=
None,
1281 help=
'loop over input files if no more events')
1282 g.add_argument(
'--efdf-interface-library', metavar=
'LIB', default=
None,
1283 help=
'name of the EFDF interface shared library to load (default: TrigDFEmulator)')
1286 g = parser.add_argument_group(
'Performance and debugging')
1287 g.add_argument(
'--perfmon', action=
'store_true', help=
'enable PerfMon')
1288 g.add_argument(
'--tcmalloc', action=
'store_true', default=
True, help=
'use tcmalloc')
1289 g.add_argument(
'--stdcmalloc', action=
'store_true', help=
'use stdcmalloc')
1290 g.add_argument(
'--stdcmath', action=
'store_true', help=
'use stdcmath library')
1291 g.add_argument(
'--imf', action=
'store_true', default=
True, help=
'use Intel math library')
1292 g.add_argument(
'--timeout', metavar=
'MSEC', type=int, default=
None,
1293 help=
'event processing timeout (HardTimeout) in milliseconds. '
1294 f
'NB: only the soft timeout ({SOFT_TIMEOUT_FRACTION*100:.0f}%% of it) is enforced')
1297 g = parser.add_argument_group(
'Conditions')
1298 g.add_argument(
'--run-number',
'-R', metavar=
'RUN', type=int,
1299 help=
'run number (if None, read from first event)')
1300 g.add_argument(
'--lb-number',
'-L', metavar=
'LBN', type=int,
1301 help=
'lumiblock number (if None, read from first event)')
1302 g.add_argument(
'--conditions-run', metavar=
'RUN', type=int, default=
None,
1303 help=
'reference run number for conditions lookup (use when IS run number has no COOL data)')
1304 g.add_argument(
'--sor-time', type=arg_sor_time,
1305 help=
'The Start Of Run time. Three formats are accepted: '
1306 '1) the string "now", for current time; '
1307 '2) the number of nanoseconds since epoch (e.g. 1386355338658000000 or int(time.time() * 1e9)); '
1308 '3) human-readable "20/11/18 17:40:42.3043". If not specified the sor-time is read from the conditions DB')
1309 g.add_argument(
'--detector-mask', metavar=
'MASK', type=arg_detector_mask,
1310 help=
'detector mask (if None, read from the conditions DB), use string "all" to enable all detectors')
1313 g = parser.add_argument_group(
'Database')
1314 g.add_argument(
'--use-database',
'-b', action=
'store_true',
1315 help=
'configure from trigger database using SMK')
1316 g.add_argument(
'--db-server', metavar=
'DB', default=
'TRIGGERDB_RUN3', help=
'DB server name (alias)')
1317 g.add_argument(
'--smk', type=int, default=
None, help=
'Super Master Key')
1318 g.add_argument(
'--l1psk', type=int, default=
None, help=
'L1 prescale key')
1319 g.add_argument(
'--hltpsk', type=int, default=
None, help=
'HLT prescale key')
1320 g.add_argument(
'--use-crest', action=
'store_true', default=
False,
1321 help=
'Use CREST for trigger configuration')
1322 g.add_argument(
'--crest-server', metavar=
'URL', default=
None,
1323 help=
'CREST server URL (default: $CREST_SERVER or crest.cern.ch)')
1324 g.add_argument(
'--dump-config', action=
'store_true', help=
'Dump joboptions JSON file')
1325 g.add_argument(
'--dump-config-exit', action=
'store_true', help=
'Dump joboptions JSON file and exit')
1328 g = parser.add_argument_group(
'Magnets')
1329 g.add_argument(
'--solenoid-current', type=float, default=
None,
1330 help=
'Solenoid current in Amperes (default: nominal current for offline running, required from IS online)')
1331 g.add_argument(
'--toroids-current', type=float, default=
None,
1332 help=
'Toroids current in Amperes (default: nominal current for offline running, required from IS online)')
1335 g = parser.add_argument_group(
'Online')
1336 g.add_argument(
'--online-environment', action=
'store_true',
1337 help=
'Enable online environment: read run parameters from IS and trigger '
1338 'configuration keys (SMK, L1PSK, HLTPSK) from OKS via WEBDAQ REST API')
1339 g.add_argument(
'--partition', metavar=
'NAME', default=
None,
1340 help=
'TDAQ partition name (defaults to TDAQ_PARTITION environment variable)')
1341 g.add_argument(
'--webdaq-base', metavar=
'URL', default=
None,
1342 help=
'WEBDAQ base URL (defaults to TDAQ_WEBDAQ_BASE environment variable)')
1345 g = parser.add_argument_group(
'Online Histogramming')
1346 g.add_argument(
'--oh-monitoring',
'-M', action=
'store_true', default=
False,
1347 help=
'enable online histogram publishing via WebdaqHistSvc')
1350 g = parser.add_argument_group(
'Expert')
1351 parser.expert_groups.append(g)
1352 (args, unparsed_args) = parser.parse_known_args()
1356 from PyUtils.Helpers
import ROOTSetup
1357 ROOTSetup(batch=
True)
1361 ROOT.ROOT.EnableThreadSafety()
1364 import AthenaCommon.Logging
1365 AthenaCommon.Logging.log.setLevel(getattr(logging, args.log_level))
1366 AthenaCommon.Logging.log.setFormat(
"%(asctime)s Py:%(name)-31s %(levelname)7s %(message)s")
1369 if not args.concurrent_events:
1370 args.concurrent_events = args.threads
1373 is_database = args.use_database
1374 is_json = bool(args.jobOptions)
and not is_database
and args.jobOptions.endswith(
'.json')
1375 is_ca =
not (is_database
or is_json)
1378 log.info(
"Using CREST for trigger configuration: %s", args.use_crest)
1379 if args.use_crest
and args.crest_server
is None:
1380 from IOVDbSvc.IOVDbAutoCfgFlags
import getCrestConnection
1381 args.crest_server = getCrestConnection()
1382 log.info(
"Using default CREST server: %s", args.crest_server)
1390 force_psk = args.use_database
and ((args.hltpsk
is not None)
or args.online_environment)
1392 if args.use_database:
1404 config_source =
"the trigger database" if is_database
else "a JSON file"
1407 log.warning(
"Ignoring flag(s) given on the command line, the configuration is read from %s: %s",
1408 config_source,
' '.join(unparsed_args))
1415 overrides.set(
'AvalancheSchedulerSvc.ThreadPoolSize', args.threads)
1416 overrides.set(
'EventDataSvc.NSlots', args.concurrent_events)
1418 ef_files = args.file
if args.file
else []
1420 overrides.set(
'EFInterfaceSvc.Files', ef_files)
1421 overrides.set(
'EFInterfaceSvc.T0ProjectTag', args.T0_project_tag)
1422 overrides.set(
'EFInterfaceSvc.BeamType', args.beam_type)
1423 overrides.set(
'EFInterfaceSvc.BeamEnergy', args.beam_energy)
1424 overrides.set(
'EFInterfaceSvc.TriggerType', args.trigger_type)
1425 overrides.set(
'EFInterfaceSvc.Stream', args.stream)
1426 overrides.set(
'EFInterfaceSvc.Lumiblock', args.lumiblock)
1427 overrides.set(
'EFInterfaceSvc.DetMask', args.file_detector_mask)
1428 if args.run_number
is not None:
1429 overrides.set(
'EFInterfaceSvc.RunNumber', args.run_number)
1430 if args.save_output
is not None:
1431 overrides.set(
'EFInterfaceSvc.OutputFileName', args.save_output)
1432 if args.loop_files
is not None:
1433 overrides.set(
'EFInterfaceSvc.LoopOverFiles', args.loop_files)
1434 if args.number_of_events
is not None:
1435 overrides.set(
'EFInterfaceSvc.NumEvents', args.number_of_events)
1436 if args.skip_events
is not None:
1437 overrides.set(
'EFInterfaceSvc.SkipEvents', args.skip_events)
1438 if args.efdf_interface_library
is not None:
1439 overrides.set(
'EFInterfaceSvc.EFDFInterfaceLibraryName', args.efdf_interface_library)
1441 if args.timeout
is not None:
1442 overrides.set(
'HltEventLoopMgr.HardTimeout', float(args.timeout))
1443 overrides.set(
'HltEventLoopMgr.SoftTimeoutFraction', SOFT_TIMEOUT_FRACTION)
1444 if args.conditions_run
is not None:
1446 overrides.set(
'HltEventLoopMgr.forceRunNumber', args.conditions_run)
1449 overrides.set(
'HLTPrescaleCondAlg.Source',
'DB')
1454 if not args.online_environment:
1455 if args.oh_monitoring:
1456 overrides.declare_type(
'THistSvc',
'WebdaqHistSvc')
1457 overrides.create_service(
'WebdaqInfoSvc')
1459 overrides.declare_type(
'THistSvc',
'THistSvc')
1460 overrides.drop_service(
'WebdaqInfoSvc')
1463 for cmd
in args.postcommand:
1464 overrides.add_command(cmd)
1468 log.info(
"Executing precommand(s)")
1469 for cmd
in args.precommand:
1470 log.info(
" %s", cmd)
1471 exec(cmd, globals(), {})
1477 from TrigConfStorage.TriggerCrestUtil
import TriggerCrestUtil
1478 crestconn = TriggerCrestUtil.getCrestConnection(args.db_server)
1479 db_alias = f
"{args.crest_server}/{crestconn}"
1480 log.info(
"Loading configuration via CREST from %s with SMK %d", db_alias, args.smk)
1482 db_alias = args.db_server
1483 log.info(
"Loading configuration from database %s with SMK %d", db_alias, args.smk)
1487 acc =
load_from_database(db_alias, args.smk, args.l1psk, args.hltpsk, run_params, overrides=overrides)
1488 log.info(
"Configuration loaded from database")
1492 log.info(
"Loading configuration from JSON file: %s", args.jobOptions)
1495 acc =
load_from_json(args.jobOptions, run_params, overrides=overrides)
1496 log.info(
"Configuration loaded from JSON")
1499 if args.dump_config
or args.dump_config_exit:
1500 fname =
"HLTJobOptions"
1504 from TrigConfIO.HLTTriggerConfigAccess
import HLTJobOptionsAccess
1505 log.info(
"Fetching configuration from database for dump...")
1506 jo_access = HLTJobOptionsAccess(dbalias=acc.db_server, smkey=acc.smk)
1507 props = jo_access.algorithms()
1509 log.info(
"Dumping configuration to %s.json", fname)
1510 hlt_json = {
'filetype':
'joboptions',
'properties': props}
1511 with open(f
"{fname}.json",
"w")
as f:
1512 json.dump(hlt_json, f, indent=4, sort_keys=
True, ensure_ascii=
True)
1516 props = acc.properties
1518 log.info(
"Dumping configuration to %s.json", fname)
1519 hlt_json = {
'filetype':
'joboptions',
'properties': props}
1520 with open(f
"{fname}.json",
"w")
as f:
1521 json.dump(hlt_json, f, indent=4, sort_keys=
True, ensure_ascii=
True)
1523 log.warning(
"No properties available to dump")
1525 if args.dump_config_exit:
1526 log.info(
"Configuration dumped. Exiting...")
1530 log.info(
"Starting Athena execution...")
1535 worker_dir = os.path.join(os.getcwd(),
"athenaHLT_workers",
"athenaHLT-01")
1536 if not os.path.exists(worker_dir):
1537 log.info(
"Creating worker directory: %s", worker_dir)
1538 os.makedirs(worker_dir, exist_ok=
True)
1543 if args.interactive:
1544 log.info(
"Interactive mode - call acc.run() to execute")
1546 code.interact(local={
'acc': acc})
1549 from AthenaCommon
import ExitCodes
1553 sc = acc.run(args.number_of_events)
1555 exitcode = ExitCodes.EXE_ALG_FAILURE
1556 except SystemExit
as e:
1557 exitcode = ExitCodes.EXE_ALG_FAILURE
if e.code == 1
else e.code
1559 traceback.print_exc()
1560 exitcode = ExitCodes.UNKNOWN_EXCEPTION
1564 log.info(
'Leaving with code %d: "%s"', exitcode, ExitCodes.what(exitcode))
__init__(self, run_number=None, lb_number=None, detector_mask=None, sor_time=None, solenoid_current=None, toroids_current=None, beam_type=None, beam_energy=None, run_type=None, trigger_type=None, recording_enabled=None, T0_project_tag='', stream='', lumiblock=0)