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)
852 """Update run parameters from IS, file, or conditions DB"""
855 if getattr(args,
'online_environment',
False):
856 log.info(
"Reading run parameters from Information Service via WEBDAQ")
860 solenoid_override = getattr(args,
'solenoid_current',
None)
861 toroids_override = getattr(args,
'toroids_current',
None)
864 partition=getattr(args,
'partition',
None),
865 webdaq_base=getattr(args,
'webdaq_base',
None),
867 solenoid_current_override=solenoid_override,
868 toroids_current_override=toroids_override)
870 if args.run_number
is None and run_params.run_number
is not None:
871 args.run_number = run_params.run_number
872 log.info(
"Using run_number=%d from IS", args.run_number)
873 if args.lb_number
is None and run_params.lb_number
is not None:
874 args.lb_number = run_params.lb_number
875 log.info(
"Using lb_number=%d from IS", args.lb_number)
876 if args.sor_time
is None and run_params.sor_time
is not None:
877 args.sor_time = run_params.sor_time
878 log.info(
"Using sor_time=%s from IS", args.sor_time)
879 if args.detector_mask
is None and run_params.detector_mask
is not None:
880 args.detector_mask = run_params.detector_mask
881 log.info(
"Using detector_mask=%s from IS", args.detector_mask)
883 args.solenoid_current = run_params.solenoid_current
884 args.toroids_current = run_params.toroids_current
885 args.beam_type = run_params.beam_type
886 args.beam_energy = run_params.beam_energy
888 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):
889 log.error(
"Both or neither of the options -R (--run-number) and -L (--lb-number) have to be specified")
893 from eformat
import EventStorage
894 dr = EventStorage.pickDataReader(args.file[0])
895 if args.run_number
is None:
896 args.run_number = dr.runNumber()
897 args.lb_number = dr.lumiblockNumber()
898 args.T0_project_tag = dr.projectTag()
899 args.beam_type = dr.beamType()
900 args.beam_energy = dr.beamEnergy()
901 args.trigger_type = dr.triggerType()
902 args.stream = dr.stream()
903 args.lumiblock = dr.lumiblockNumber()
904 args.file_detector_mask =
"{:032x}".format(dr.detectorMask())
906 args.T0_project_tag = getattr(args,
'T0_project_tag',
'')
907 args.beam_type = getattr(args,
'beam_type', 0)
908 args.beam_energy = getattr(args,
'beam_energy', 0)
909 args.trigger_type = getattr(args,
'trigger_type', 0)
910 args.stream = getattr(args,
'stream',
'')
911 args.lumiblock = getattr(args,
'lumiblock', 0)
912 args.file_detector_mask = getattr(args,
'file_detector_mask',
'00000000000000000000000000000000')
915 if (args.sor_time
is None or args.detector_mask
is None)
and args.run_number
is not None:
916 sor_params = AthHLT.get_sor_params(args.run_number)
917 log.debug(
'SOR parameters: %s', sor_params)
918 if sor_params
is None:
919 log.error(
"Run %d does not exist. If you want to use this run-number specify "
920 "remaining run parameters, e.g.: --sor-time=now --detector-mask=all", args.run_number)
923 if args.sor_time
is None and sor_params
is not None:
924 args.sor_time =
arg_sor_time(str(sor_params[
'SORTime']))
926 if args.detector_mask
is None and sor_params
is not None:
927 dmask = sor_params[
'DetectorMask']
928 if args.run_number < AthHLT.CondDB._run2:
932 if args.dump_config_exit
and not args.run_number:
937 if getattr(args,
'solenoid_current',
None)
is None:
938 args.solenoid_current = RunParams.DEFAULT_SOLENOID_CURRENT
939 log.debug(
"Using default solenoid_current=%.1f", args.solenoid_current)
940 if getattr(args,
'toroids_current',
None)
is None:
941 args.toroids_current = RunParams.DEFAULT_TOROIDS_CURRENT
942 log.debug(
"Using default toroids_current=%.1f", args.toroids_current)
946 """Update trigger configuration keys from OKS, COOL, or CREST.
949 1. Command-line arguments (always take precedence)
950 2. OKS via WEBDAQ (if --online-environment is set)
951 3. CREST (if --use-crest is set)
955 if args.smk
is None or args.l1psk
is None or args.hltpsk
is None:
959 if getattr(args,
'online_environment',
False):
960 log.info(
"Reading trigger configuration keys from OKS (online environment)")
963 partition=getattr(args,
'partition',
None),
964 webdaq_base=getattr(args,
'webdaq_base',
None),
967 log.info(
"Retrieved trigger keys from OKS: %s", oks_keys)
971 'SMK': oks_keys.get(
'SMK'),
972 'LVL1PSK': oks_keys.get(
'L1PSK'),
973 'HLTPSK': oks_keys.get(
'HLTPSK')
976 if oks_keys.get(
'db_alias')
and args.db_server ==
'TRIGGERDB_RUN3':
977 args.db_server = oks_keys[
'db_alias']
978 log.info(
"Using db_server=%s from OKS", args.db_server)
983 log.info(
"Reading trigger configuration keys from CREST for run %s", args.run_number)
984 trigconf = AthHLT.get_trigconf_keys_crest(args.run_number, args.lb_number, args.crest_server)
985 log.info(
"Retrieved trigger keys from CREST: %s", trigconf)
987 log.info(
"Reading trigger configuration keys from COOL for run %s", args.run_number)
988 trigconf = AthHLT.get_trigconf_keys(args.run_number, args.lb_number)
989 log.info(
"Retrieved trigger keys from COOL: %s", trigconf)
993 args.smk = trigconf[
'SMK']
994 log.debug(
"Using SMK=%d from conditions DB/OKS", args.smk)
996 log.debug(
"Using SMK=%d from command line (ignoring DB/OKS value %s)", args.smk, trigconf.get(
'SMK'))
997 if args.l1psk
is None:
998 args.l1psk = trigconf[
'LVL1PSK']
999 log.debug(
"Using L1PSK=%d from conditions DB/OKS", args.l1psk)
1001 log.debug(
"Using L1PSK=%d from command line (ignoring DB/OKS value %s)", args.l1psk, trigconf.get(
'LVL1PSK'))
1002 if args.hltpsk
is None:
1003 args.hltpsk = trigconf[
'HLTPSK']
1004 log.debug(
"Using HLTPSK=%d from conditions DB/OKS", args.hltpsk)
1006 log.debug(
"Using HLTPSK=%d from command line (ignoring DB/OKS value %s)", args.hltpsk, trigconf.get(
'HLTPSK'))
1008 log.error(
"Cannot read trigger configuration keys from the conditions database for run %d", args.run_number)
1011 log.info(
"Using trigger configuration keys from command line: SMK=%d, L1PSK=%d, HLTPSK=%d",
1012 args.smk, args.l1psk, args.hltpsk)
1036 """Start a private TDAQ infrastructure (offline test of OH publication)."""
1037 import shutil, socket, signal, subprocess, time
1039 infra_script = shutil.which(
'athenaEF_tdaq_infra.py')
1040 if infra_script
is None:
1041 log.error(
"athenaEF_tdaq_infra.py not found on PATH (required for -M)")
1044 partition = args.partition
or 'athenaEF'
1049 port = s.getsockname()[1]
1051 oh_server =
'Histogramming'
1052 run_number = args.run_number
if args.run_number
is not None else 0
1055 os.environ[
'TDAQ_PARTITION'] = partition
1056 os.environ[
'TDAQ_WEBDAQ_BASE'] = f
'http://{host}:{port}'
1057 os.environ[
'TDAQ_OH_SERVER'] = oh_server
1059 log.info(
"Starting private OH infrastructure: partition=%s, webdaq=%s, oh_server=%s",
1060 partition, os.environ[
'TDAQ_WEBDAQ_BASE'], oh_server)
1062 logfile = open(
'athenaEF_oh_infra.log',
'w')
1066 from ctypes
import cdll
1067 PR_SET_PDEATHSIG = 1
1069 cdll[
'libc.so.6'].prctl(PR_SET_PDEATHSIG, signal.SIGTERM)
1072 log.info(
"IS schema files: %s",
', '.join(schemas)
or '(none)')
1074 proc = subprocess.Popen(
1076 '--partition', partition,
1077 '--webdaq-port', str(port),
1078 '--oh-server', oh_server,
1079 '--run-number', str(run_number),
1080 *(arg
for f
in schemas
for arg
in (
'--schema', f))],
1081 stdout=logfile, stderr=subprocess.STDOUT,
1082 preexec_fn=_pdeathsig, close_fds=
True)
1086 deadline = time.time() + timeout
1087 while time.time() < deadline:
1088 if proc.poll()
is not None:
1089 log.error(
"OH infrastructure exited early (code %s); see %s", proc.returncode, logfile.name)
1091 with open(logfile.name)
as f:
1092 if 'ATHENAEF_INFRA_READY' in f.read():
1093 log.info(
"OH infrastructure is ready")
1097 log.error(
"OH infrastructure did not become ready within %d s; see %s", timeout, logfile.name)
1131 """Configure the job from a CA module and re-execute athenaEF from the resulting JSON.
1133 This function never returns: athenaEF either exits (--dump-config-exit) or replaces
1134 itself with a new athenaEF running from the JSON file it just created.
1136 from AthenaCommon
import Constants
1137 from AthenaConfiguration.AllConfigFlags
import initConfigFlags
1138 from AthenaConfiguration.ComponentAccumulator
import ComponentAccumulator
1139 from AthenaConfiguration.ComponentFactory
import CompFactory
1140 from AthenaConfiguration.MainServicesConfig
import addMainSequences
1141 from TrigServices.TrigServicesConfig
import commonServicesCfg, setDefaultOnlineFlags
1144 flags = initConfigFlags()
1145 setDefaultOnlineFlags(flags)
1148 flags.Exec.OutputLevel = getattr(Constants, args.log_level)
1151 if args.oh_monitoring:
1152 flags.Trigger.Online.useOnlineWebdaqHistSvc =
True
1153 log.info(
"Enabled WebdaqHistSvc for online histogram publishing")
1156 AthHLT.unparsedArguments = unparsed_args
1157 AthHLT.fillFromUnparsedArgs(flags)
1165 if args.conditions_run
is not None:
1166 log.info(
"Using conditions from reference run %d (overriding run %s for IOV lookup)",
1167 args.conditions_run, args.run_number)
1168 flags.Input.ConditionsRunNumber = args.conditions_run
1171 if args.number_of_events
is not None and args.number_of_events > 0:
1172 flags.Exec.MaxEvents = args.number_of_events
1175 if args.skip_events
is not None and args.skip_events > 0:
1176 flags.Exec.SkipEvents = args.skip_events
1182 flags.PerfMon.doFastMonMT = args.perfmon
1186 log.info(
"Executing precommand(s)")
1187 for cmd
in args.precommand:
1188 log.info(
" %s", cmd)
1189 exec(cmd, globals(), {
'flags': flags})
1195 log.info(
"Loading CA configuration from: %s", args.jobOptions)
1198 locked_flags = flags.clone()
1202 cfg = ComponentAccumulator(CompFactory.AthSequencer(
"AthMasterSeq", Sequential=
True))
1203 cfg.setAppProperty(
'ExtSvcCreates',
False)
1204 cfg.setAppProperty(
"MessageSvcType",
"TrigMessageSvc")
1205 cfg.setAppProperty(
"JobOptionsSvcType",
"TrigConf::JobOptionsSvc")
1208 addMainSequences(locked_flags, cfg)
1209 cfg.merge(commonServicesCfg(locked_flags))
1212 cfg_func = AthHLT.getCACfg(args.jobOptions)
1213 cfg.merge(cfg_func(flags))
1216 if args.postcommand:
1217 log.info(
"Executing postcommand(s)")
1218 for cmd
in args.postcommand:
1219 log.info(
" %s", cmd)
1220 exec(cmd, globals(), {
'flags': flags,
'cfg': cfg})
1223 fname =
"HLTJobOptions"
1224 log.info(
"Dumping configuration to %s.pkl and %s.json", fname, fname)
1225 with open(f
"{fname}.pkl",
"wb")
as f:
1228 from TrigConfIO.JsonUtils
import create_joboptions_json
1229 create_joboptions_json(f
"{fname}.pkl", f
"{fname}.json")
1232 if args.dump_config_exit:
1233 log.info(
"Configuration dumped to %s.json. Exiting...", fname)
1237 log.info(
"Configuration dumped to %s.json. Re-exec...", fname)
1238 AthHLT.reload_from_json(f
"{fname}.json", suppress_args=unparsed_args + [
'--dump-config'], jobOptions=args.jobOptions)
1242 parser = argparse.ArgumentParser(prog=
'athenaEF.py', formatter_class=
1243 lambda prog : argparse.ArgumentDefaultsHelpFormatter(prog, max_help_position=32, width=100),
1244 usage =
'%(prog)s [OPTION]... -f FILE jobOptions',
1246 parser.expert_groups = []
1249 g = parser.add_argument_group(
'Options')
1250 g.add_argument(
'jobOptions', nargs=
'?', help=
'job options: CA module (package.module:function) or JSON file (.json)')
1251 g.add_argument(
'--threads', metavar=
'N', type=int, default=1, help=
'number of threads')
1252 g.add_argument(
'--concurrent-events', metavar=
'N', type=int, help=
'number of concurrent events if different from --threads')
1253 g.add_argument(
'--log-level',
'-l', metavar=
'LVL', default=
'INFO', help=
'OutputLevel of athena')
1254 g.add_argument(
'--precommand',
'-c', metavar=
'CMD', action=
'append', default=[],
1255 help=
'Python commands executed before job options')
1256 g.add_argument(
'--postcommand',
'-C', metavar=
'CMD', action=
'append', default=[],
1257 help=
'Python commands executed after job options')
1258 g.add_argument(
'--interactive',
'-i', action=
'store_true', help=
'interactive mode')
1259 g.add_argument(
'--help',
'-h', nargs=
'?', choices=[
'all'], action=MyHelp, help=
'show help')
1261 g = parser.add_argument_group(
'Input/Output')
1262 g.add_argument(
'--file',
'--filesInput',
'-f', action=
'append', help=
'input RAW file')
1263 g.add_argument(
'--save-output',
'-o', metavar=
'FILE', help=
'output file name')
1264 g.add_argument(
'--number-of-events',
'--evtMax',
'-n', metavar=
'N', type=int, default=
None,
1265 help=
'processes N events (default: from DB/config, -1 means all)')
1266 g.add_argument(
'--skip-events',
'--skipEvents',
'-k', metavar=
'N', type=int, default=
None,
1267 help=
'skip N first events')
1268 g.add_argument(
'--loop-files', action=argparse.BooleanOptionalAction, default=
None,
1269 help=
'loop over input files if no more events')
1270 g.add_argument(
'--efdf-interface-library', metavar=
'LIB', default=
None,
1271 help=
'name of the EFDF interface shared library to load (default: TrigDFEmulator)')
1274 g = parser.add_argument_group(
'Performance and debugging')
1275 g.add_argument(
'--perfmon', action=
'store_true', help=
'enable PerfMon')
1276 g.add_argument(
'--tcmalloc', action=
'store_true', default=
True, help=
'use tcmalloc')
1277 g.add_argument(
'--stdcmalloc', action=
'store_true', help=
'use stdcmalloc')
1278 g.add_argument(
'--stdcmath', action=
'store_true', help=
'use stdcmath library')
1279 g.add_argument(
'--imf', action=
'store_true', default=
True, help=
'use Intel math library')
1280 g.add_argument(
'--timeout', metavar=
'MSEC', type=int, default=
None,
1281 help=
'event processing timeout (HardTimeout) in milliseconds. '
1282 f
'NB: only the soft timeout ({SOFT_TIMEOUT_FRACTION*100:.0f}%% of it) is enforced')
1285 g = parser.add_argument_group(
'Conditions')
1286 g.add_argument(
'--run-number',
'-R', metavar=
'RUN', type=int,
1287 help=
'run number (if None, read from first event)')
1288 g.add_argument(
'--lb-number',
'-L', metavar=
'LBN', type=int,
1289 help=
'lumiblock number (if None, read from first event)')
1290 g.add_argument(
'--conditions-run', metavar=
'RUN', type=int, default=
None,
1291 help=
'reference run number for conditions lookup (use when IS run number has no COOL data)')
1292 g.add_argument(
'--sor-time', type=arg_sor_time,
1293 help=
'The Start Of Run time. Three formats are accepted: '
1294 '1) the string "now", for current time; '
1295 '2) the number of nanoseconds since epoch (e.g. 1386355338658000000 or int(time.time() * 1e9)); '
1296 '3) human-readable "20/11/18 17:40:42.3043". If not specified the sor-time is read from the conditions DB')
1297 g.add_argument(
'--detector-mask', metavar=
'MASK', type=arg_detector_mask,
1298 help=
'detector mask (if None, read from the conditions DB), use string "all" to enable all detectors')
1301 g = parser.add_argument_group(
'Database')
1302 g.add_argument(
'--use-database',
'-b', action=
'store_true',
1303 help=
'configure from trigger database using SMK')
1304 g.add_argument(
'--db-server', metavar=
'DB', default=
'TRIGGERDB_RUN3', help=
'DB server name (alias)')
1305 g.add_argument(
'--smk', type=int, default=
None, help=
'Super Master Key')
1306 g.add_argument(
'--l1psk', type=int, default=
None, help=
'L1 prescale key')
1307 g.add_argument(
'--hltpsk', type=int, default=
None, help=
'HLT prescale key')
1308 g.add_argument(
'--use-crest', action=
'store_true', default=
False,
1309 help=
'Use CREST for trigger configuration')
1310 g.add_argument(
'--crest-server', metavar=
'URL', default=
None,
1311 help=
'CREST server URL (default: $CREST_SERVER or crest.cern.ch)')
1312 g.add_argument(
'--dump-config', action=
'store_true', help=
'Dump joboptions JSON file')
1313 g.add_argument(
'--dump-config-exit', action=
'store_true', help=
'Dump joboptions JSON file and exit')
1316 g = parser.add_argument_group(
'Magnets')
1317 g.add_argument(
'--solenoid-current', type=float, default=
None,
1318 help=
'Solenoid current in Amperes (default: nominal current for offline running, required from IS online)')
1319 g.add_argument(
'--toroids-current', type=float, default=
None,
1320 help=
'Toroids current in Amperes (default: nominal current for offline running, required from IS online)')
1323 g = parser.add_argument_group(
'Online')
1324 g.add_argument(
'--online-environment', action=
'store_true',
1325 help=
'Enable online environment: read run parameters from IS and trigger '
1326 'configuration keys (SMK, L1PSK, HLTPSK) from OKS via WEBDAQ REST API')
1327 g.add_argument(
'--partition', metavar=
'NAME', default=
None,
1328 help=
'TDAQ partition name (defaults to TDAQ_PARTITION environment variable)')
1329 g.add_argument(
'--webdaq-base', metavar=
'URL', default=
None,
1330 help=
'WEBDAQ base URL (defaults to TDAQ_WEBDAQ_BASE environment variable)')
1333 g = parser.add_argument_group(
'Online Histogramming')
1334 g.add_argument(
'--oh-monitoring',
'-M', action=
'store_true', default=
False,
1335 help=
'enable online histogram publishing via WebdaqHistSvc')
1338 g = parser.add_argument_group(
'Expert')
1339 parser.expert_groups.append(g)
1340 (args, unparsed_args) = parser.parse_known_args()
1344 from PyUtils.Helpers
import ROOTSetup
1345 ROOTSetup(batch=
True)
1349 ROOT.ROOT.EnableThreadSafety()
1352 import AthenaCommon.Logging
1353 AthenaCommon.Logging.log.setLevel(getattr(logging, args.log_level))
1354 AthenaCommon.Logging.log.setFormat(
"%(asctime)s Py:%(name)-31s %(levelname)7s %(message)s")
1357 if not args.concurrent_events:
1358 args.concurrent_events = args.threads
1361 is_database = args.use_database
1362 is_json = bool(args.jobOptions)
and not is_database
and args.jobOptions.endswith(
'.json')
1363 is_ca =
not (is_database
or is_json)
1366 log.info(
"Using CREST for trigger configuration: %s", args.use_crest)
1367 if args.use_crest
and args.crest_server
is None:
1368 from IOVDbSvc.IOVDbAutoCfgFlags
import getCrestConnection
1369 args.crest_server = getCrestConnection()
1370 log.info(
"Using default CREST server: %s", args.crest_server)
1378 force_psk = args.use_database
and ((args.hltpsk
is not None)
or args.online_environment)
1380 if args.use_database:
1392 config_source =
"the trigger database" if is_database
else "a JSON file"
1395 log.warning(
"Ignoring flag(s) given on the command line, the configuration is read from %s: %s",
1396 config_source,
' '.join(unparsed_args))
1403 overrides.set(
'AvalancheSchedulerSvc.ThreadPoolSize', args.threads)
1404 overrides.set(
'EventDataSvc.NSlots', args.concurrent_events)
1406 ef_files = args.file
if args.file
else []
1408 overrides.set(
'EFInterfaceSvc.Files', ef_files)
1409 overrides.set(
'EFInterfaceSvc.T0ProjectTag', args.T0_project_tag)
1410 overrides.set(
'EFInterfaceSvc.BeamType', args.beam_type)
1411 overrides.set(
'EFInterfaceSvc.BeamEnergy', args.beam_energy)
1412 overrides.set(
'EFInterfaceSvc.TriggerType', args.trigger_type)
1413 overrides.set(
'EFInterfaceSvc.Stream', args.stream)
1414 overrides.set(
'EFInterfaceSvc.Lumiblock', args.lumiblock)
1415 overrides.set(
'EFInterfaceSvc.DetMask', args.file_detector_mask)
1416 if args.run_number
is not None:
1417 overrides.set(
'EFInterfaceSvc.RunNumber', args.run_number)
1418 if args.save_output
is not None:
1419 overrides.set(
'EFInterfaceSvc.OutputFileName', args.save_output)
1420 if args.loop_files
is not None:
1421 overrides.set(
'EFInterfaceSvc.LoopOverFiles', args.loop_files)
1422 if args.number_of_events
is not None:
1423 overrides.set(
'EFInterfaceSvc.NumEvents', args.number_of_events)
1424 if args.skip_events
is not None:
1425 overrides.set(
'EFInterfaceSvc.SkipEvents', args.skip_events)
1426 if args.efdf_interface_library
is not None:
1427 overrides.set(
'EFInterfaceSvc.EFDFInterfaceLibraryName', args.efdf_interface_library)
1429 if args.timeout
is not None:
1430 overrides.set(
'HltEventLoopMgr.HardTimeout', float(args.timeout))
1431 overrides.set(
'HltEventLoopMgr.SoftTimeoutFraction', SOFT_TIMEOUT_FRACTION)
1432 if args.conditions_run
is not None:
1434 overrides.set(
'HltEventLoopMgr.forceRunNumber', args.conditions_run)
1437 overrides.set(
'HLTPrescaleCondAlg.Source',
'DB')
1442 if not args.online_environment:
1443 if args.oh_monitoring:
1444 overrides.declare_type(
'THistSvc',
'WebdaqHistSvc')
1445 overrides.create_service(
'WebdaqInfoSvc')
1447 overrides.declare_type(
'THistSvc',
'THistSvc')
1448 overrides.drop_service(
'WebdaqInfoSvc')
1452 log.info(
"Executing precommand(s)")
1453 for cmd
in args.precommand:
1454 log.info(
" %s", cmd)
1455 exec(cmd, globals(), {})
1461 from TrigConfStorage.TriggerCrestUtil
import TriggerCrestUtil
1462 crestconn = TriggerCrestUtil.getCrestConnection(args.db_server)
1463 db_alias = f
"{args.crest_server}/{crestconn}"
1464 log.info(
"Loading configuration via CREST from %s with SMK %d", db_alias, args.smk)
1466 db_alias = args.db_server
1467 log.info(
"Loading configuration from database %s with SMK %d", db_alias, args.smk)
1471 acc =
load_from_database(db_alias, args.smk, args.l1psk, args.hltpsk, run_params, overrides=overrides)
1472 log.info(
"Configuration loaded from database")
1476 log.info(
"Loading configuration from JSON file: %s", args.jobOptions)
1479 acc =
load_from_json(args.jobOptions, run_params, overrides=overrides)
1480 log.info(
"Configuration loaded from JSON")
1483 if args.postcommand:
1484 log.info(
"Executing postcommand(s)")
1485 for cmd
in args.postcommand:
1486 log.info(
" %s", cmd)
1487 exec(cmd, globals(), {
'acc': acc})
1490 if args.dump_config
or args.dump_config_exit:
1491 fname =
"HLTJobOptions"
1495 from TrigConfIO.HLTTriggerConfigAccess
import HLTJobOptionsAccess
1496 log.info(
"Fetching configuration from database for dump...")
1497 jo_access = HLTJobOptionsAccess(dbalias=acc.db_server, smkey=acc.smk)
1498 props = jo_access.algorithms()
1500 log.info(
"Dumping configuration to %s.json", fname)
1501 hlt_json = {
'filetype':
'joboptions',
'properties': props}
1502 with open(f
"{fname}.json",
"w")
as f:
1503 json.dump(hlt_json, f, indent=4, sort_keys=
True, ensure_ascii=
True)
1507 props = acc.properties
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)
1514 log.warning(
"No properties available to dump")
1516 if args.dump_config_exit:
1517 log.info(
"Configuration dumped. Exiting...")
1521 log.info(
"Starting Athena execution...")
1526 worker_dir = os.path.join(os.getcwd(),
"athenaHLT_workers",
"athenaHLT-01")
1527 if not os.path.exists(worker_dir):
1528 log.info(
"Creating worker directory: %s", worker_dir)
1529 os.makedirs(worker_dir, exist_ok=
True)
1534 if args.interactive:
1535 log.info(
"Interactive mode - call acc.run() to execute")
1537 code.interact(local={
'acc': acc})
1540 from AthenaCommon
import ExitCodes
1544 sc = acc.run(args.number_of_events)
1546 exitcode = ExitCodes.EXE_ALG_FAILURE
1547 except SystemExit
as e:
1548 exitcode = ExitCodes.EXE_ALG_FAILURE
if e.code == 1
else e.code
1550 traceback.print_exc()
1551 exitcode = ExitCodes.UNKNOWN_EXCEPTION
1555 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)