5 from fnmatch
import fnmatchcase
6 from AthenaCommon.Logging
import logging
7 from AthenaConfiguration.AthConfigFlags
import isGaudiEnv
8 from PyUtils.PoolFile
import isRNTuple
9 from ROOT
import gSystem
10 from AthenaConfiguration.Enums
import Project
13 msg = logging.getLogger(
'MetaReader')
16 regexEventStreamInfo = re.compile(
r'^EventStreamInfo(_p\d+)?$')
17 regexIOVMetaDataContainer = re.compile(
r'^IOVMetaDataContainer(_p\d+)?$')
18 regexByteStreamMetadataContainer = re.compile(
r'^ByteStreamMetadataContainer(_p\d+)?$')
19 regexXAODCutBookkeeperContainer = re.compile(
r'^xAOD::CutBookkeeperContainer(_v\d+)?$')
20 regexXAODCutBookkeeperContainerAux = re.compile(
r'^xAOD::CutBookkeeperAuxContainer(_v\d+)?$')
21 regexXAODEventFormat = re.compile(
r'^xAOD::EventFormat(_v\d+)?$')
22 regexXAODFileMetaData = re.compile(
r'^xAOD::FileMetaData(_v\d+)?$')
23 regexXAODFileMetaDataAux = re.compile(
r'^xAOD::FileMetaDataAuxInfo(_v\d+)?$')
24 regexXAODFileMetaDataAuxDyn = re.compile(
r'^(xAOD::)?FileMetaData.*AuxDyn(\.[a-zA-Z0-9]+)?$')
25 regexXAODTriggerMenu = re.compile(
r'^DataVector<xAOD::TriggerMenu(_v\d+)?>$')
26 regexXAODTriggerMenuAux = re.compile(
r'^xAOD::TriggerMenuAuxContainer(_v\d+)?$')
27 regexXAODTriggerMenuJson = re.compile(
r'^DataVector<xAOD::TriggerMenuJson(_v\d+)?>$')
28 regexXAODTriggerMenuJsonAux = re.compile(
r'^xAOD::TriggerMenuJsonAuxContainer(_v\d+)?$')
29 regexXAODTruthMetaData = re.compile(
r'^DataVector<xAOD::TruthMetaData(_v\d+)?>$')
30 regexXAODTruthMetaDataAux = re.compile(
r'^xAOD::TruthMetaDataAuxContainer(_v\d+)?$')
31 regex_cppname = re.compile(
r'^([\w:]+)(<.*>)?$')
33 regex_persistent_class = re.compile(
r'^([a-zA-Z]+(_[pv]\d+)?::)*[a-zA-Z]+_[pv]\d+$')
34 regex_BS_files = re.compile(
r'^(\w+):.*((\.D?RAW\..*)|(\.data$))')
35 regex_URI_scheme = re.compile(
r'^([A-Za-z0-9\+\.\-]+)\:')
37 lite_primary_keys_to_keep = [
38 'lumiBlockNumbers',
'runNumbers',
'mc_event_number',
'mc_channel_number',
39 'eventTypes',
'processingTags',
'itemList']
40 lite_TagInfo_keys_to_keep = [
41 'beam_energy',
'beam_type',
'GeoAtlas',
'IOVDbGlobalTag',
42 'AODFixVersion',
'project_name',
'mc_campaign',
'keywords']
46 'TriggerMenu',
'TriggerMenuJson_BG',
'TriggerMenuJson_HLT',
'TriggerMenuJson_HLTMonitoring',
'TriggerMenuJson_HLTPS',
'TriggerMenuJson_L1',
'TriggerMenuJson_L1PS',
47 '/TRIGGER/HLT/Groups',
'/TRIGGER/HLT/HltConfigKeys',
'/TRIGGER/HLT/Menu',
'/TRIGGER/HLT/PrescaleKey',
'/TRIGGER/HLT/Prescales',
48 '/TRIGGER/LVL1/ItemDef',
'/TRIGGER/LVL1/Lvl1ConfigKey',
'/TRIGGER/LVL1/Menu',
'/TRIGGER/LVL1/Prescales',
'/TRIGGER/LVL1/Thresholds',
49 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenu',
'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_BG',
'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLT',
50 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTMonitoring',
'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTPS',
51 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1',
'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1PS',
54 trigger_menu_json_map = {
55 "xAOD__TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_L1PSAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1PS",
56 "xAOD__TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_BGAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_BG",
57 "xAOD__TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLT",
58 "xAOD__TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTMonitoringAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTMonitoring",
59 "xAOD__TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTPSAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTPS",
60 "xAOD__TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_L1Aux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1",
61 "TriggerMenuJson_L1PSAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1PS",
62 "TriggerMenuJson_BGAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_BG",
63 "TriggerMenuJson_HLTAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLT",
64 "TriggerMenuJson_HLTMonitoringAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTMonitoring",
65 "TriggerMenuJson_HLTPSAux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTPS",
66 "TriggerMenuJson_L1Aux:":
"DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1",
70 def read_metadata(filenames, file_type = None, mode = 'lite', promote = None, meta_key_filter = None,
71 unique_tag_info_values = True, ignoreNonExistingLocalFiles=False):
73 This tool is independent of Athena framework and returns the metadata from a given file.
74 :param filenames: the input file from which metadata needs to be extracted.
75 :param file_type: the type of file. POOL or BS (bytestream: RAW, DRAW) files.
76 :param mode: if true, will return all metadata associated with the filename. By default, is false and this will
77 return a "tiny" version which have only the following keys: 'file_guid', 'file_size', 'file_type', 'nentries'.
78 :return: a dictionary of metadata for the given input file.
85 from RootUtils
import PyROOTFixes
88 if isinstance(filenames, str):
89 filenames = [filenames]
92 if file_type
is not None:
93 if file_type
not in (
'POOL',
'BS'):
94 raise NameError(
'Allowed values for \'file_type\' parameter are: "POOL" or "BS": you provided "' + file_type +
'"')
96 msg.info(
'Forced file_type: {0}'.
format(file_type))
99 if mode
not in (
'tiny',
'lite',
'full',
'peeker',
'iov'):
100 raise NameError(
'Allowed values for "mode" parameter are: "tiny", "lite", "peeker", "iov" or "full"')
102 if meta_key_filter
is None:
107 if mode
in (
'full',
'iov'):
108 raise NameError(
'The following modes are not available in AnalysisBase: "iov" and "full"')
110 msg.info(
'Current mode used: {0}'.
format(mode))
111 msg.info(
'Current filenames: {0}'.
format(filenames))
113 if mode !=
'full' and mode !=
'iov' and len(meta_key_filter) > 0:
114 raise NameError(
'It is possible to use the meta_key_filter option only for full mode')
116 msg.info(
'Filter used: {0}'.
format(meta_key_filter))
122 for filename
in filenames:
123 meta_dict[filename] = {}
124 current_file_type =
None
127 if os.path.isfile(filename):
129 if ignoreNonExistingLocalFiles
and not regex_URI_scheme.match(filename)
and gSystem.AccessPathName(filename):
130 msg.warn(
'Ignoring not accessible file: {}'.
format(filename))
133 with open(filename,
'rb')
as binary_file:
134 magic_file = binary_file.read(4)
136 if magic_file ==
'root' or magic_file == b
'root':
137 current_file_type =
'POOL'
138 meta_dict[filename][
'file_type'] =
'POOL'
140 elif Project.determine()
in (
141 Project.AnalysisBase, Project.AthAnalysis):
143 f
"{filename} is not a ROOT file, assumed bytestream"
144 ", this is not supported in Analysis releases")
146 current_file_type =
'BS'
147 meta_dict[filename][
'file_type'] =
'BS'
150 meta_dict[filename][
'file_size'] = os.path.getsize(filename)
154 if regex_BS_files.match(filename):
155 current_file_type =
'BS'
156 meta_dict[filename][
'file_type'] =
'BS'
158 current_file_type =
'POOL'
159 meta_dict[filename][
'file_type'] =
'POOL'
162 meta_dict[filename][
'file_size'] =
None
165 current_file_type = file_type
168 if current_file_type ==
'POOL':
170 if ignoreNonExistingLocalFiles
and not regex_URI_scheme.match(filename)
and gSystem.AccessPathName(filename):
171 msg.warn(
'Ignoring not accessible file: {}'.
format(filename))
176 current_file = ROOT.TFile.Open(
_get_pfn(filename) )
179 from PyUtils.PoolFile
import PoolOpts
180 collectionTree = current_file.Get(PoolOpts.TTreeNames.EventData)
181 if isinstance(collectionTree, ROOT.TTree):
182 meta_dict[filename][
'auto_flush'] = collectionTree.GetAutoFlush()
185 meta_dict[filename][
'file_guid'] =
_read_guid(filename)
188 meta_dict[filename][
'file_comp_alg'] = current_file.GetCompressionAlgorithm()
189 meta_dict[filename][
'file_comp_level'] = current_file.GetCompressionLevel()
192 isRNTuple(md:=current_file.Get(PoolOpts.RNTupleNames.MetaData))
196 "Reading in-file metadata from RNTuple is currently of limited support"
198 meta_dict[filename][
"metadata_items"] = {}
201 from ROOT
import RNTupleReader
203 from ROOT.Experimental
import RNTupleReader
205 reader = RNTupleReader.Open(md)
206 entry = reader.CreateEntry()
207 reader.LoadEntry(0, entry)
210 "xAOD::FileMetaData_v1",
211 "xAOD::FileMetaDataAuxInfo_v1",
212 "xAOD::TriggerMenuJsonAuxContainer_v1",
213 "DataVector<xAOD::TriggerMenuJson_v1>",
214 "xAOD::TruthMetaDataAuxContainer_v1",
215 "DataVector<xAOD::TruthMetaData_v1>",
216 "xAOD::CutBookkeeperContainer_v1",
217 "xAOD::CutBookkeeperAuxContainer_v1",
218 "xAOD::LumiBlockRangeAuxContainer_v1",
219 "DataVector<xAOD::LumiBlockRange_v1>",
222 dynamic_fmd_items = {}
226 for field
in reader.GetDescriptor().GetTopLevelFields():
227 normalizedName = field.GetFieldName()
228 if "index_ref" in normalizedName:
230 if regexIOVMetaDataContainer.match(field.GetTypeName()):
235 .
replace(
"IOVMetaDataContainer_p1_",
"")
238 meta_dict[filename][
"metadata_items"][normalizedName] = (
239 "IOVMetaDataContainer"
241 elif regexByteStreamMetadataContainer.match(field.GetTypeName()):
242 meta_dict[filename][
"metadata_items"][field.GetFieldName()] = (
243 "ByteStreamMetadataContainer"
245 elif regexEventStreamInfo.match(field.GetTypeName()):
246 meta_dict[filename][
"metadata_items"][field.GetFieldName()] = (
249 elif regexXAODFileMetaData.match(field.GetTypeName()):
250 meta_dict[filename][
"metadata_items"][
251 field.GetFieldName().
replace(
"xAOD__",
"xAOD::")
252 ] = field.GetTypeName()
253 elif regexXAODFileMetaDataAuxDyn.match(
254 normalizedName := field.GetFieldName()
260 if entry[field.GetFieldName()] ==
"\x00"
261 else entry[field.GetFieldName()]
263 dynamic_fmd_items[normalizedName.split(
".")[1]] = result
264 meta_dict[filename][
"metadata_items"][normalizedName] = (
268 elif regexXAODFileMetaDataAux.match(field.GetTypeName()):
269 meta_dict[filename][
"metadata_items"][
273 ] = field.GetTypeName()
274 elif regexXAODTruthMetaData.match(field.GetTypeName()):
275 meta_dict[filename][
"metadata_items"][
278 .
replace(
"DataVector_",
"DataVector<")
281 elif regexXAODTruthMetaDataAux.match(field.GetTypeName()):
282 meta_dict[filename][
"metadata_items"][
286 ] = field.GetTypeName()
287 elif regexXAODEventFormat.match(field.GetTypeName()):
288 meta_dict[filename][
"metadata_items"][
289 field.GetFieldName().
replace(
"xAOD__",
"xAOD::")
290 ] = field.GetTypeName()
291 elif regexXAODTriggerMenuJson.match(field.GetTypeName()):
292 meta_dict[filename][
"metadata_items"][
295 .
replace(
"DataVector_",
"DataVector<")
296 .
replace(
"__Trigger",
">_Trigger")
297 ] = field.GetTypeName()
298 elif regexXAODTriggerMenuJsonAux.match(field.GetTypeName()):
299 meta_dict[filename][
"metadata_items"][
303 ] = field.GetTypeName()
304 elif regexXAODCutBookkeeperContainer.match(field.GetTypeName()):
305 meta_dict[filename][
"metadata_items"][
308 .
replace(
"DataVector_",
"DataVector<")
309 .
replace(
"__CutBookkeeper",
">_CutBookkeeper")
310 ] = field.GetTypeName()
311 elif regexXAODCutBookkeeperContainerAux.match(field.GetTypeName()):
312 meta_dict[filename][
"metadata_items"][
316 ] = field.GetTypeName()
318 meta_dict[filename][
"metadata_items"][
319 field.GetFieldName().
replace(
"Aux:",
"Aux.")
320 ] = field.GetTypeName()
322 if field.GetTypeName()
in classes_with_aux:
324 auxes[field.GetFieldName()] = field.GetTypeName()
328 normalizedName, field.GetTypeName(), meta_filter
334 entry[field.GetFieldName()]
337 msg.warning(f
"missing type {field.GetTypeName()}")
340 meta_dict[filename][
"metadata_items"]
343 def _get_aux_base(aux_key: str) -> str:
346 key = key.replace(
"xAOD__TriggerMenuJsonAuxContainer_v1_",
"")
347 key = key.replace(
"xAOD__FileMetaDataAuxInfo_v1_",
"")
348 key = key.replace(
"xAOD__TruthMetaDataAuxContainer_v1_",
"")
350 if key.endswith(
"Aux:"):
352 elif key.endswith(
"Aux"):
355 key = key.strip(
"_:")
358 def _get_main_base(main_key: str) -> str:
361 if main_key.startswith(
"DataVector_xAOD__TriggerMenuJson_v1__"):
362 main_base = main_key.replace(
363 "DataVector_xAOD__TriggerMenuJson_v1__",
""
366 elif main_key.startswith(
"xAOD__FileMetaData_v1_"):
367 main_base = main_key.replace(
"xAOD__FileMetaData_v1_",
"")
369 elif main_key.startswith(
"DataVector_xAOD__TruthMetaData_v1__"):
370 main_base = main_key.replace(
371 "DataVector_xAOD__TruthMetaData_v1__",
""
375 def _find_associated_pairs(auxes: dict) -> list[tuple[str, str]]:
380 aux_map[_get_aux_base(k)] = k
384 base = _get_main_base(k)
390 for base, aux_key
in aux_map.items():
392 pairs.append((aux_key, main_map[base]))
395 for pair
in _find_associated_pairs(auxes):
403 for k, v
in trigger_menu_json_map.items()
407 .
replace(
"DataVector_",
"DataVector<")
408 .
replace(
"__Trigger",
">_Trigger")
415 key.replace(
"xAOD__",
"xAOD::")
416 if key.count(
"_") <= 1
417 else key.replace(
"xAOD__",
"xAOD::").rsplit(
"_", 2)[0]
425 .
replace(
"DataVector_",
"DataVector<")
426 .
replace(
"__Trigger",
">_Trigger")
433 if "TriggerMenuJson" in pair[0]:
434 if "RAWTriggerMenuJson" in return_obj:
437 if pair[0].startswith(
"Trigger")
438 else trigger_menu_json_map[pair[0]]
440 meta_dict[filename][key] = return_obj[
"RAWTriggerMenuJson"]
441 del return_obj[
"RAWTriggerMenuJson"]
442 if "TriggerConfigInfo" not in meta_dict[filename]:
443 meta_dict[filename][
"TriggerConfigInfo"] = {}
444 if "dbkey" in return_obj:
445 meta_dict[filename][
"TriggerConfigInfo"][
447 ] = {
"key": return_obj[
"dbkey"],
"name": return_obj[
"name"]}
448 del return_obj[
"dbkey"]
449 del return_obj[
"name"]
450 if "TriggerMenu" not in meta_dict[filename]:
451 meta_dict[filename][
"TriggerMenu"] = {}
452 meta_dict[filename][
"TriggerMenu"].update(return_obj)
453 elif "FileMetaData" in pair[0]:
454 if "FileMetaData" not in meta_dict[filename]:
455 meta_dict[filename][
"FileMetaData"] = dynamic_fmd_items
456 meta_dict[filename][
"FileMetaData"].update(return_obj)
457 elif "TruthMetaData" in pair[0]:
458 if pair == (
"TruthMetaDataAux:",
"TruthMetaData"):
459 if "TruthMetaData" not in meta_dict[filename]:
460 meta_dict[filename][
"TruthMetaData"] = {}
461 meta_dict[filename][
"TruthMetaData"].update(return_obj)
467 .
replace(
"DataVector_",
"DataVector<")
475 elif pair == (
"CutBookkeepersAux:",
"CutBookkeepers"):
476 meta_dict[filename][
"CutBookkeepers"] = return_obj
478 msg.debug(f
"Read metadata from RNTuple: {meta_dict[filename]}")
484 metadata_tree = current_file.Get(
'MetaData')
486 metadata_branches = metadata_tree.GetListOfBranches()
487 nr_of_branches = metadata_branches.GetEntriesFast()
490 meta_dict[filename][
'metadata_items'] = {}
495 persistent_instances = {}
496 dynamic_fmd_items = {}
500 metadata_tree.SetBranchStatus(
"*",
False)
502 for i
in range(0, nr_of_branches):
503 branch = metadata_branches.At(i)
504 name = branch.GetName()
505 if name ==
'index_ref':
509 class_name = branch.GetClassName()
511 if regexIOVMetaDataContainer.match(class_name):
512 name = name.replace(
'IOVMetaDataContainer_p1_',
'').
replace(
'_',
'/')
514 if regexIOVMetaDataContainer.match(class_name):
515 meta_dict[filename][
'metadata_items'][name] =
'IOVMetaDataContainer'
516 elif regexByteStreamMetadataContainer.match(class_name):
517 meta_dict[filename][
'metadata_items'][name] =
'ByteStreamMetadataContainer'
518 elif regexEventStreamInfo.match(class_name):
519 meta_dict[filename][
'metadata_items'][name] =
'EventStreamInfo'
520 elif regexXAODFileMetaData.match(class_name):
521 meta_dict[filename][
'metadata_items'][name] =
'FileMetaData'
522 elif regexXAODTruthMetaData.match(class_name):
523 meta_dict[filename][
'metadata_items'][name] =
'TruthMetaData'
525 type_name = class_name
528 type_name = branch.GetListOfLeaves()[0].GetTypeName()
531 meta_dict[filename][
'metadata_items'][name] = type_name
533 if len(meta_filter) > 0:
535 for filter_key, filter_class
in meta_filter.items():
536 if (filter_key.replace(
'/',
'_')
in name.replace(
'/',
'_')
or filter_key ==
'*')
and fnmatchcase(class_name, filter_class):
537 if 'CutBookkeepers' in filter_key:
538 keep = filter_key == name
549 if 'CutBookkeepers' in name
and name
not in [
'CutBookkeepers',
'CutBookkeepersAux.']:
553 metadata_tree.SetBranchStatus(f
"{name}*",
True)
556 if regexEventStreamInfo.match(class_name):
557 if class_name.endswith(
'_p1'):
558 persistent_instances[name] = ROOT.EventStreamInfo_p1()
559 elif class_name.endswith(
'_p2'):
560 persistent_instances[name] = ROOT.EventStreamInfo_p2()
562 persistent_instances[name] = ROOT.EventStreamInfo_p3()
563 elif regexIOVMetaDataContainer.match(class_name):
564 persistent_instances[name] = ROOT.IOVMetaDataContainer_p1()
565 elif regexXAODEventFormat.match(class_name):
566 persistent_instances[name] = ROOT.xAOD.EventFormat_v1()
567 elif regexXAODTriggerMenu.match(class_name)
and _check_project()
not in [
'AthGeneration']:
568 persistent_instances[name] = ROOT.xAOD.TriggerMenuContainer_v1()
569 elif regexXAODTriggerMenuAux.match(class_name)
and _check_project()
not in [
'AthGeneration']:
570 persistent_instances[name] = ROOT.xAOD.TriggerMenuAuxContainer_v1()
571 elif regexXAODTriggerMenuJson.match(class_name)
and _check_project()
not in [
'AthGeneration']:
572 persistent_instances[name] = ROOT.xAOD.TriggerMenuJsonContainer_v1()
573 elif regexXAODTriggerMenuJsonAux.match(class_name)
and _check_project()
not in [
'AthGeneration']:
574 persistent_instances[name] = ROOT.xAOD.TriggerMenuJsonAuxContainer_v1()
575 elif regexXAODCutBookkeeperContainer.match(class_name):
576 persistent_instances[name] = ROOT.xAOD.CutBookkeeperContainer_v1()
577 elif regexXAODCutBookkeeperContainerAux.match(class_name):
578 persistent_instances[name] = ROOT.xAOD.CutBookkeeperAuxContainer_v1()
579 elif regexXAODFileMetaData.match(class_name):
580 persistent_instances[name] = ROOT.xAOD.FileMetaData_v1()
581 elif regexXAODFileMetaDataAux.match(class_name):
582 persistent_instances[name] = ROOT.xAOD.FileMetaDataAuxInfo_v1()
583 elif regexXAODTruthMetaData.match(class_name):
584 persistent_instances[name] = ROOT.xAOD.TruthMetaDataContainer_v1()
585 elif regexXAODTruthMetaDataAux.match(class_name):
586 persistent_instances[name] = ROOT.xAOD.TruthMetaDataAuxContainer_v1()
588 if name
in persistent_instances:
589 branch.SetAddress(ROOT.AddressOf(persistent_instances[name]))
592 dynamicFMD = regexXAODFileMetaDataAuxDyn.match(name)
594 dynamicName = dynamicFMD.group().
split(
'.')[-1]
595 dynamicType = regex_cppname.match(class_name)
598 dynamic_fmd_items[dynamicName] = ROOT.std.string()
599 branch.SetAddress(ROOT.AddressOf(dynamic_fmd_items[dynamicName]))
601 dynamic_fmd_items[dynamicName] =
None
604 metadata_tree.GetEntry(0)
607 for key
in dynamic_fmd_items:
608 if dynamic_fmd_items[key]
is None:
610 if key.startswith(
"is"):
612 dynamic_fmd_items[key] = getattr(metadata_tree, key) !=
'\x00'
615 dynamic_fmd_items[key] = getattr(metadata_tree, key)
616 except AttributeError:
621 dynamic_fmd_items[key] =
str(dynamic_fmd_items[key])
625 meta_dict[filename] = {}
628 for name, content
in persistent_instances.items():
630 if hasattr(content,
'm_folderName'):
631 key = content.m_folderName
634 has_r3_trig_meta = (
'TriggerMenuJson_HLT' in persistent_instances
or 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLT' in persistent_instances)
636 if key.startswith(
'TriggerMenuJson_')
and not key.endswith(
'Aux.'):
637 aux = persistent_instances[key+
'Aux.']
638 elif key.startswith(
'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_')
and not key.endswith(
'Aux.'):
639 menuPart = key.split(
'_')[-1]
640 aux = persistent_instances[
'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_'+menuPart+
'Aux.']
641 elif key ==
'TriggerMenu' and 'TriggerMenuAux.' in persistent_instances
and not has_r3_trig_meta:
642 aux = persistent_instances[
'TriggerMenuAux.']
643 elif key ==
'DataVector<xAOD::TriggerMenu_v1>_TriggerMenu' and 'xAOD::TriggerMenuAuxContainer_v1_TriggerMenuAux.' in persistent_instances
and not has_r3_trig_meta:
644 aux = persistent_instances[
'xAOD::TriggerMenuAuxContainer_v1_TriggerMenuAux.']
645 elif (key ==
'CutBookkeepers'
646 and 'CutBookkeepersAux.' in persistent_instances):
647 aux = persistent_instances[
'CutBookkeepersAux.']
648 elif key ==
'CutBookkeepersAux.':
650 elif (key ==
'FileMetaData'
651 and 'FileMetaDataAux.' in persistent_instances):
652 aux = persistent_instances[
'FileMetaDataAux.']
653 elif (key ==
'xAOD::FileMetaData_v1_FileMetaData'
654 and 'xAOD::FileMetaDataAuxInfo_v1_FileMetaDataAux.' in persistent_instances):
655 aux = persistent_instances[
'xAOD::FileMetaDataAuxInfo_v1_FileMetaDataAux.']
656 elif (key ==
'TruthMetaData'
657 and 'TruthMetaDataAux.' in persistent_instances):
658 aux = persistent_instances[
'TruthMetaDataAux.']
659 elif key ==
'TruthMetaDataAux.':
661 elif 'Menu' in key
and key.endswith(
'Aux.'):
666 if 'TriggerMenuJson' in key
or (
'TriggerMenu' in key
and not has_r3_trig_meta):
667 if 'RAWTriggerMenuJson' in return_obj:
668 meta_dict[filename][key] = return_obj[
'RAWTriggerMenuJson']
669 del return_obj[
'RAWTriggerMenuJson']
670 if 'TriggerConfigInfo' not in meta_dict[filename]:
671 meta_dict[filename][
'TriggerConfigInfo'] = {}
672 if 'dbkey' in return_obj:
673 meta_dict[filename][
'TriggerConfigInfo'][key.split(
'_')[-1]] = {
674 'key' : return_obj[
'dbkey'],
675 'name': return_obj[
'name']
677 del return_obj[
'dbkey']
678 del return_obj[
'name']
679 if 'TriggerMenu' not in meta_dict[filename]:
680 meta_dict[filename][
'TriggerMenu'] = {}
681 meta_dict[filename][
'TriggerMenu'].update(return_obj)
682 elif "FileMetaData" in key:
683 if "FileMetaData" not in meta_dict[filename]:
684 meta_dict[filename][
"FileMetaData"] = dynamic_fmd_items
685 meta_dict[filename][
"FileMetaData"].update(return_obj)
687 meta_dict[filename][key] = return_obj
691 esi_dict =
next(key
for key, value
in meta_dict[filename].
items()
692 if isinstance(value, dict)
and "numberOfEvents" in value
and
693 meta_dict[filename][
"metadata_items"][key] ==
"EventStreamInfo")
694 msg.debug(f
"{esi_dict=}")
695 meta_dict[filename][
"nentries"] = meta_dict[filename][esi_dict][
"numberOfEvents"]
696 except StopIteration
as err:
697 msg.debug(f
"Caught {err=}, {type(err)=}, falling back on opening the DataHeader"
698 " Container to read the number of entries")
700 msg.debug(f
"{meta_dict[filename]['nentries']=}")
702 if unique_tag_info_values
and mode==
'iov':
703 unique_tag_info_values =
False
704 msg.info(
'disabling "unique_tag_info_values" option for "iov" mode')
711 if unique_tag_info_values:
712 msg.info(
'MetaReader is called with the parameter "unique_tag_info_values" set to True. '
713 'This is a workaround to remove all duplicate values from "/TagInfo" key')
714 if '/TagInfo' in meta_dict[filename]:
715 for key, value
in meta_dict[filename][
'/TagInfo'].
items():
716 if isinstance(value, list)
and value:
717 if len(unique_values :=
set(value)) > 1:
719 f
"Found multiple values for {key}: {value}. "
720 "Looking for possible duplicates."
725 unique_amitags =
set()
726 for amitags
in unique_values:
728 "_".
join({tag
for tag
in amitags.split(
"_")
if tag})
730 if len(unique_amitags) == 1:
732 elif key ==
"beam_energy":
734 unique_energies =
set()
735 for energy
in unique_values:
740 energy =
float(energy)
743 unique_energies.add(energy)
744 if len(unique_energies) == 1:
746 elif key
in [
"AtlasRelease",
"IOVDbGlobalTag",
"AODFixVersion"]:
750 f
"Multiple values for {key} may mean the same, or "
751 "the input file was produced in multi-step job. "
752 f
"Ignoring all but the first entry: {key} = {value[0]}"
756 f
"{key} from /TagInfo contains more than 1 unique value: {value}"
759 meta_dict[filename][
'/TagInfo'][key] = value[0]
762 promote = mode ==
'lite' or mode ==
'peeker'
776 if isinstance(collectionTree, ROOT.TTree):
777 meta_dict[filename][
'itemList'] = [ (b.GetClassName(), b.GetName())
for b
in collectionTree.GetListOfBranches() ]
780 elif current_file_type ==
'BS':
782 if ignoreNonExistingLocalFiles
and not regex_URI_scheme.match(filename)
and not os.path.isfile(filename):
783 msg.warn(
'Ignoring not accessible file: {}'.
format(filename))
789 bs = eformat.istream(filename)
790 meta_dict[filename][
'nentries'] = bs.total_events
793 data_reader = eformat.EventStorage.pickDataReader(filename)
794 assert data_reader,
'problem picking a data reader for file [%s]' % filename
797 meta_dict[filename][
'auto_flush'] = 1
799 if hasattr(data_reader,
'GUID'):
800 meta_dict[filename][
'file_guid'] = data_reader.GUID()
803 meta_dict[filename][
'file_comp_alg'] = 1
804 meta_dict[filename][
'file_comp_level'] = 1
812 for md
in data_reader.freeMetaDataStrings():
813 if md.startswith(
'Event type:'):
817 v.append(
'IS_SIMULATION')
824 v.append(
'IS_TESTBEAM')
826 if 'is physics' in md:
827 v.append(
'IS_PHYSICS')
829 v.append(
'IS_CALIBRATION')
831 bs_metadata[k] = tuple(v)
833 elif md.startswith(
'GeoAtlas:'):
835 v = md.split(
'GeoAtlas:')[1].strip()
838 elif md.startswith(
'IOVDbGlobalTag:'):
840 v = md.split(
'IOVDbGlobalTag:')[1].strip()
847 bs_metadata[
'detectorMask'] = data_reader.detectorMask()
848 bs_metadata[
'runNumbers'] = data_reader.runNumber()
849 bs_metadata[
'lumiBlockNumbers'] = data_reader.lumiblockNumber()
850 bs_metadata[
'projectTag'] = data_reader.projectTag()
851 bs_metadata[
'stream'] = data_reader.stream()
853 beamTypeNbr= data_reader.beamType()
858 if (beamTypeNbr==0): bs_metadata[
'beamType'] =
'cosmics'
859 elif (beamTypeNbr==1
or beamTypeNbr==2): bs_metadata[
'beamType'] =
'collisions'
860 else: bs_metadata[
'beamType'] =
'unknown'
862 bs_metadata[
'beamEnergy'] = data_reader.beamEnergy()
864 meta_dict[filename][
'eventTypes'] = bs_metadata.get(
'eventTypes', [])
865 meta_dict[filename][
'GeoAtlas'] = bs_metadata.get(
'geometry',
None)
866 meta_dict[filename][
'conditions_tag'] = bs_metadata.get(
'conditions_tag',
None)
867 meta_dict[filename][
'project_name'] = bs_metadata.get(
'projectTag',
None)
870 meta_dict[filename][
'detectorMask'] = [bs_metadata.get(
'detectorMask',
None)]
871 meta_dict[filename][
'runNumbers'] = [bs_metadata.get(
'runNumbers',
None)]
872 meta_dict[filename][
'lumiBlockNumbers'] = [bs_metadata.get(
'lumiBlockNumbers',
None)]
873 meta_dict[filename][
'beam_type'] = bs_metadata.get(
'beamType',
None)
874 meta_dict[filename][
'beam_energy'] = bs_metadata.get(
'beamEnergy',
None)
875 meta_dict[filename][
'stream'] = bs_metadata.get(
'stream',
None)
877 if not data_reader.good():
879 meta_dict[filename][
'runNumbers'].
append(bs_metadata.get(
'run_number', 0))
880 meta_dict[filename][
'lumiBlockNumbers'].
append(bs_metadata.get(
'LumiBlock', 0))
882 msg.debug(f
"{meta_dict[filename]=}")
883 msg.debug(f
"{len(bs)=}")
888 meta_dict[filename][
'processingTags'] = [tag.name
for tag
in evt.stream_tag()]
889 meta_dict[filename][
'evt_number'] = [evt.global_id()]
890 meta_dict[filename][
'run_type'] = [eformat.helper.run_type2string(evt.run_type())]
893 if meta_dict[filename][
'lumiBlockNumbers'] == [0]:
894 msg.debug(
'Taking the luminosity block info from the first event (%i)', evt.lumi_block())
895 meta_dict[filename][
'lumiBlockNumbers'] = [evt.lumi_block()]
898 if meta_dict[filename][
'runNumbers'] == [0]:
899 msg.debug(
'Taking the run number info from the first event (%i)', evt.run_no())
900 meta_dict[filename][
'runNumbers'] = [evt.run_no()]
901 except RuntimeError
as err:
902 msg.error(
"Issue while reading the first event of BS file %r: %r", filename, err)
904 msg.debug(f
"{meta_dict[filename]=}")
906 msg.warn(f
"Event-less BS {filename=}, will not read metadata information from the first event")
909 if len(bs_metadata.get(
'eventTypes',
'')) == 0:
910 evt_type = [
'IS_DATA',
'IS_ATLAS']
911 if bs_metadata.get(
'stream',
'').startswith(
'physics_'):
912 evt_type.append(
'IS_PHYSICS')
913 elif bs_metadata.get(
'stream',
'').startswith(
'calibration_'):
914 evt_type.append(
'IS_CALIBRATION')
915 elif bs_metadata.get(
'projectTag',
'').endswith(
'_calib'):
916 evt_type.append(
'IS_CALIBRATION')
918 evt_type.append(
'Unknown')
920 meta_dict[filename][
'eventTypes'] = evt_type
923 meta_dict[filename][
'bs_metadata'] = bs_metadata
927 msg.error(
'Unknown filetype for {0} - there is no metadata interface for type {1}'.
format(filename, current_file_type))
935 if 'AthSimulation_DIR' in os.environ:
936 return 'AthSimulation'
937 if 'AthGeneration_DIR' in os.environ:
938 return 'AthGeneration'
944 Extract the actual filename if LFN or PFN notation is used
950 import subprocess, os
951 os.environ[
'POOL_OUTMSG_LEVEL'] =
'Error'
952 output = subprocess.check_output([
'FClistPFN',
'-l',filename[4:]],text=
True).
split(
'\n')
955 msg.error(
'FClistPFN({0}) returned unexpected number of lines:'.
format(filename) )
956 msg.error(
'\n'.
join(output) )
962 Extracts the "guid" (Globally Unique Identifier) in POOL files and Grid catalogs) value from a POOL file.
963 :param filename: the input file
964 :return: the guid value, None if unavailable
967 root_file = ROOT.TFile.Open(
_get_pfn(filename) )
968 params = root_file.Get(
'##Params')
970 from ROOT
import RNTuple
as rnt
972 from ROOT.Experimental
import RNTuple
as rnt
975 if not isinstance(params, ROOT.TTree)
and not isinstance(params, rnt)
and not isinstance(params, ROOT.TDirectory):
976 raise NotImplementedError(f
"Cannot extract GUID from object {params!r} of type {type(params)!r}")
978 regex = re.compile(
r'\[NAME=(\w+)\]\[VALUE=(.*)\]', re.ASCII)
981 if isinstance(params, ROOT.TTree):
983 param = entry.GetLeaf(
'db_string').GetValueString()
984 result = regex.match(param)
985 if result
and result.group(1) ==
'FID' :
987 fid = result.group(2)
988 elif isinstance(params, rnt):
990 from ROOT
import RNTupleReader
992 from ROOT.Experimental
import RNTupleReader
993 reader = RNTupleReader.Open(params)
995 entry = reader.CreateEntry()
996 except AttributeError:
997 entry = reader.GetModel().CreateEntry()
998 for idx
in range(reader.GetNEntries()):
999 reader.LoadEntry(idx, entry)
1001 result = regex.match(
str(entry[
'db_string']))
1002 except (AttributeError, TypeError)
as err:
1005 msg.error(f
"Cannot read FID from ##Params in RNTuple w/ ROOT error: {err}")
1007 if result
and result.group(1) ==
'FID' :
1009 fid = result.group(2)
1010 elif isinstance(params, ROOT.TDirectory):
1011 for key
in params.GetListOfKeys():
1012 param = params.Get(key.GetName())
1013 result = regex.match(
str(param))
1014 if result
and result.group(1) ==
'FID' :
1016 fid = result.group(2)
1024 for meth
in dir(obj):
1025 if not meth.startswith(
'_'):
1026 if meth.startswith(
'm_'):
1028 field_name =
str(meth)[2:]
1029 field_value = getattr(obj, meth)
1038 if hasattr(cl,
'__cpp_name__'):
1039 result = regex_cppname.match(cl.__cpp_name__)
1041 cpp_type = result.group(1)
1042 if cpp_type ==
'vector' or cpp_type ==
'std::vector':
1044 elif cpp_type ==
'set' or cpp_type ==
'std::set':
1046 elif cpp_type ==
'pair' or cpp_type ==
'std::pair':
1052 elif cpp_type ==
'string' or cpp_type ==
'std::string':
1055 elif cl.__cpp_name__ ==
"_Bit_reference":
1059 elif cl.__cpp_name__ ==
'IOVMetaDataContainer_p1':
1062 elif cl.__cpp_name__ ==
'IOVPayloadContainer_p1':
1063 if _gbl_mode ==
'iov':
1068 elif cl.__cpp_name__ ==
'xAOD::EventFormat_v1':
1070 elif cl.__cpp_name__ ==
'xAOD::CutBookkeeperContainer_v1':
1072 elif cl.__cpp_name__ ==
'xAOD::FileMetaData_v1':
1074 elif cl.__cpp_name__ ==
'DataVector<xAOD::TruthMetaData_v1>':
1077 elif cl.__cpp_name__ ==
'DataVector<xAOD::TriggerMenu_v1>' :
1080 elif cl.__cpp_name__ ==
'DataVector<xAOD::TriggerMenuJson_v1>' :
1083 elif (cl.__cpp_name__ ==
'EventStreamInfo_p1' or
1084 cl.__cpp_name__ ==
'EventStreamInfo_p2' or
1085 cl.__cpp_name__ ==
'EventStreamInfo_p3'):
1088 elif (cl.__cpp_name__ ==
'EventType_p1' or
1089 cl.__cpp_name__ ==
'EventType_p3'):
1095 elif regex_persistent_class.match(cl.__cpp_name__):
1102 type_idx = attr_idx.typeIndex()
1103 obj_idx = attr_idx.objIndex()
1108 attr_value =
bool(iov_container.m_bool[obj_idx])
1110 attr_value =
int(iov_container.m_char[obj_idx])
1112 attr_value =
int(iov_container.m_unsignedChar[obj_idx])
1114 attr_value =
int(iov_container.m_short[obj_idx])
1116 attr_value =
int(iov_container.m_unsignedShort[obj_idx])
1118 attr_value =
int(iov_container.m_int[obj_idx])
1120 attr_value =
int(iov_container.m_unsignedInt[obj_idx])
1122 attr_value =
int(iov_container.m_long[obj_idx])
1124 attr_value =
int(iov_container.m_unsignedLong[obj_idx])
1126 attr_value =
int(iov_container.m_longLong[obj_idx])
1127 elif type_idx == 10:
1128 attr_value =
int(iov_container.m_unsignedLongLong[obj_idx])
1129 elif type_idx == 11:
1130 attr_value =
float(iov_container.m_float[obj_idx])
1131 elif type_idx == 12:
1132 attr_value =
float(iov_container.m_double[obj_idx])
1133 elif type_idx == 13:
1136 elif type_idx == 14:
1137 attr_value =
str(iov_container.m_string[obj_idx])
1139 if attr_value.startswith(
'IOVMetaDataContainer_p1_'):
1140 attr_value = attr_value.replace(
'IOVMetaDataContainer_p1_',
'')
1141 if attr_value.startswith(
'_'):
1142 attr_value = attr_value.replace(
'_',
'/')
1144 elif type_idx == 15:
1145 attr_value =
int(iov_container.m_date[obj_idx])
1146 elif type_idx == 16:
1147 attr_value =
int(iov_container.m_timeStamp[obj_idx])
1149 raise ValueError(
'Unknown type id {0} for attribute {1}'.
format(type_idx, attr_name))
1157 for idx
in idx_range:
1158 attr_idx = iov_container.m_attrIndexes[idx]
1159 name_idx = attr_idx.nameIndex()
1160 attr_name = iov_container.m_attrName[name_idx]
1163 if attr_name
not in result:
1164 result[attr_name] = [attr_value]
1166 result[attr_name].
append(attr_value)
1168 max_element_count = 0
1169 for content
in result.values():
1170 if len(content) > max_element_count:
1171 max_element_count = len(content)
1173 if max_element_count <= 1:
1174 for name, content
in result.items():
1175 if len(content) > 0:
1176 result[name] = content[0]
1186 return "({h}:{l})".
format(h=t>>32, l=t&(2^32-1))
1188 def extract_list_collection(iov_container, listCollection ):
1191 for list
in listCollection.m_attrLists:
1193 lname =
'List {ln}: iov=[{s} ,{e}]; Channel#={ch}'.
format(
1194 ln=ln, s=iovtostr(list.m_range.m_start),
1195 e=iovtostr(list.m_range.m_stop),
1196 ch=list.m_channelNumber )
1202 for listCollection
in iov_container.m_payloadVec:
1204 pname =
'IOV range {n}: [{s}, {e}]'.
format(n=pn, s=iovtostr(listCollection.m_start),
1205 e=iovtostr(listCollection.m_stop))
1206 result[ pname ] = extract_list_collection(iov_container, listCollection )
1217 result[
'eventTypes'] = []
1218 for eventType
in value.m_eventTypes:
1221 result[
'numberOfEvents'] = value.m_numberOfEvents
1222 result[
'runNumbers'] =
list(value.m_runNumbers)
1223 result[
'lumiBlockNumbers'] =
list(value.m_lumiBlockNumbers)
1224 result[
'processingTags'] = [
str(v)
for v
in value.m_processingTags]
1225 result[
'itemList'] = []
1228 from CLIDComps.clidGenerator
import clidGenerator
1229 cgen = clidGenerator(
"")
1230 for clid, sgkey
in value.m_itemList:
1231 if isinstance(sgkey, bytes):
1232 sgkey = sgkey.decode()
1233 result[
'itemList'].
append((cgen.getNameFromClid(clid), sgkey))
1241 for ef_element
in value:
1242 result[ef_element.first] = ef_element.second.className()
1248 """Extract CutBookkeeper content into dictionary
1250 This function takes the CutBookkeeperContainer_v1 and CutBookkeeperAuxContainer_v1 objects.
1251 It makes sure the the interface object uses the auxiliary object as store.
1253 interface (CutBookkeeperContainer_v1): the interface class
1254 aux (CutBookkeeperAuxContainer_v1): auxiliary container object
1256 dict: with the cycle number and last stream
1258 if not interface
or not aux:
1260 interface.setStore(aux)
1265 for cbk
in interface:
1266 current_cycle =
int(cbk.cycle())
1267 if current_cycle > max_cycle:
1268 max_cycle = current_cycle
1269 input_stream =
str(cbk.inputStream())
1272 'currentCutCycle': max_cycle,
1273 'currentCutInputStream': input_stream,
1279 """Turn static FileMetaData content into dictionary
1281 This function takes the FileMetaData_v1 and FileMetaDataAuxInfo_v1 objects.
1282 It makes sure the the interface object uses the auxiliary object as store.
1283 Next the two static variables of FileMetaDataAuxInfo_v1 are retrieved and
1284 added to the dictionary that is returned.
1286 interface (FileMetaData_v1): the interface class
1287 aux (FileMetaDataAuxInfo_v1): auxiliary container object
1289 dict: with the production release and dataType
1292 if not interface
or not aux:
1294 interface.setStore(aux)
1296 "productionRelease": ROOT.std.string(),
1297 "dataType": ROOT.std.string(),
1298 "runNumbers": ROOT.std.vector(
'unsigned int')(),
1299 "lumiBlocks": ROOT.std.vector(
'unsigned int')(),
1302 for k, v
in metaContent.items():
1304 interface.value(getattr(interface, k), v)
1305 except AttributeError:
1306 interface.value(k, v)
1308 result = {k:
str(v)
for k, v
in metaContent.items()
if type(v)
is ROOT.std.string}
1309 result.update({k:
list(v)
for k, v
in metaContent.items()
if type(v)
is ROOT.std.vector(
'unsigned int')})
1315 BadAuxVarException = ROOT.SG.ExcBadAuxVar
1316 """Extract TruthMetaData content into dictionary
1318 This function takes the TruthMetaDataContainer_v1 and TruthMetaDataAuxContainer_v1 objects.
1319 It makes sure the the interface object uses the auxiliary object as store.
1321 interface (TruthMetaDataContainer_v1): the interface class
1322 aux (TruthMetaDataAuxContainer_v1): auxiliary container object
1326 if not interface
or not aux:
1328 interface.setStore(aux)
1332 for tmd
in interface:
1333 result[
'mcChannelNumber'] = tmd.mcChannelNumber()
1336 result[
'weightNames'] =
list(tmd.weightNames())
1337 except BadAuxVarException:
1338 result[
'weightNames'] = []
1341 result[
'lhefGenerator'] =
str(tmd.lhefGenerator())
1342 except BadAuxVarException:
1343 result[
'lhefGenerator'] =
''
1346 result[
'generators'] =
str(tmd.generators())
1347 except BadAuxVarException:
1348 result[
'generators'] =
''
1351 result[
'evgenProcess'] =
str(tmd.evgenProcess())
1352 except BadAuxVarException:
1353 result[
'evgenProcess'] =
''
1356 result[
'evgenTune'] =
str(tmd.evgenTune())
1357 except BadAuxVarException:
1358 result[
'evgenTune'] =
''
1361 result[
'hardPDF'] =
str(tmd.hardPDF())
1362 except BadAuxVarException:
1363 result[
'hardPDF'] =
''
1366 result[
'softPDF'] =
str(tmd.softPDF())
1367 except BadAuxVarException:
1368 result[
'softPDF'] =
''
1373 """ Note: Deprecated. Legacy support for Run 2 AODs produced in release 21 or in release 22 prior to April 2021
1383 interface.setStore( aux )
1384 if interface.size() > 0:
1387 firstMenu = interface.at(0)
1388 L1Items = [
_convert_value(item)
for item
in firstMenu.itemNames() ]
1389 HLTChains = [
_convert_value(chain)
for chain
in firstMenu.chainNames() ]
1390 except Exception
as err:
1391 msg.warn(
'Problem reading xAOD::TriggerMenu:')
1394 result[
'L1Items'] = L1Items
1395 result[
'HLTChains'] = HLTChains
1403 interface.setStore( aux )
1404 if interface.size() > 0:
1407 firstMenu = interface.at(0)
1409 decoded = json.loads(firstMenu.payload())
1410 result[
'RAWTriggerMenuJson'] = firstMenu.payload()
1411 result[
'name'] = firstMenu.name()
1412 result[
'dbkey'] = firstMenu.key()
1413 if decoded[
'filetype'] ==
'hltmenu':
1414 result[
'HLTChains'] = [
_convert_value(chain)
for chain
in decoded[
'chains'] ]
1415 elif decoded[
'filetype'] ==
'l1menu':
1416 result[
'L1Items'] = [
_convert_value(item)
for item
in decoded[
'items'] ]
1417 elif decoded[
'filetype']
in [
'bunchgroupset',
'hltprescale',
'l1prescale',
'hltmonitoringsummary']:
1421 msg.warn(
'Got an xAOD::TriggerMenuJson called {0} but only expecting hltmenu or l1menu'.
format(decoded[
'filetype']))
1424 except Exception
as err:
1425 msg.warn(
'Problem reading xAOD::TriggerMenuJson')
1430 if 'user_type' in value:
1431 items = value[
'user_type'].
split(
'#')[3:]
1432 for i
in range(0, len(items), 2):
1440 if key ==
'bit_mask':
1443 bitmask_length = len(val)
1445 is_simulation =
False
1447 is_calibration =
False
1449 if bitmask_length > 0:
1450 is_simulation = val[0]
1452 if bitmask_length > 1:
1453 is_testbeam = val[1]
1455 if bitmask_length > 2:
1456 is_calibration = val[2]
1459 'IS_SIMULATION' if is_simulation
else 'IS_DATA',
1460 'IS_TESTBEAM' if is_testbeam
else 'IS_ATLAS',
1461 'IS_CALIBRATION' if is_calibration
else 'IS_PHYSICS'
1464 value[
'type'] = types
1469 for filename, file_content
in meta_dict.items():
1470 for key
in file_content:
1471 if key
in meta_dict[filename][
'metadata_items']
and regexEventStreamInfo.match(meta_dict[filename][
'metadata_items'][key]):
1472 for item
in list(meta_dict[filename][key]):
1473 if item
not in lite_primary_keys_to_keep:
1474 meta_dict[filename][key].pop(item)
1476 if '/TagInfo' in file_content:
1479 for item
in list(meta_dict[filename][
'/TagInfo']):
1480 if item
not in lite_TagInfo_keys_to_keep:
1481 meta_dict[filename][
'/TagInfo'].pop(item)
1486 for filename, file_content
in meta_dict.items():
1487 for key
in file_content:
1488 if key
in meta_dict[filename][
'metadata_items']
and regexEventStreamInfo.match(meta_dict[filename][
'metadata_items'][key]):
1493 'mc_channel_number',
1498 for item
in list(meta_dict[filename][key]):
1499 if item
not in keys_to_keep:
1500 meta_dict[filename][key].pop(item)
1502 if '/TagInfo' in file_content:
1511 'triggerStreamOfFile',
1513 'specialConfiguration',
1520 for item
in list(meta_dict[filename][
'/TagInfo']):
1521 if item
not in keys_to_keep:
1522 meta_dict[filename][
'/TagInfo'].pop(item)
1524 if '/Simulation/Parameters' in file_content:
1529 'RegenerationIncrement',
1531 'SimulationFlavour',
1534 'SimulatedDetectors',
1537 for item
in list(meta_dict[filename][
'/Simulation/Parameters']):
1538 if item
not in keys_to_keep:
1539 meta_dict[filename][
'/Simulation/Parameters'].pop(item)
1541 if '/Digitization/Parameters' in file_content:
1543 'numberOfCollisions',
1544 'intraTrainBunchSpacing',
1545 'BeamIntensityPattern'
1549 'DigitizedDetectors',
1551 for item
in list(meta_dict[filename][
'/Digitization/Parameters']):
1552 if item
not in keys_to_keep:
1553 meta_dict[filename][
'/Digitization/Parameters'].pop(item)
1555 if 'CutBookkeepers' in file_content:
1558 'currentCutInputStream',
1560 for item
in list(meta_dict[filename][
'CutBookkeepers']):
1561 if item
not in keys_to_keep:
1562 meta_dict[filename][
'CutBookkeepers'].pop(item)
1564 if 'TruthMetaData' in file_content:
1569 for item
in list(meta_dict[filename][
'TruthMetaData']):
1570 if item
not in keys_to_keep:
1571 meta_dict[filename][
'TruthMetaData'].pop(item)
1577 for filename, file_content
in meta_dict.items():
1578 md = meta_dict[filename]
1579 for key
in file_content:
1580 if key
in md[
'metadata_items']
and regexEventStreamInfo.match(md[
'metadata_items'][key]):
1583 if 'eventTypes' in md
and len(md[
'eventTypes']):
1584 et = md[
'eventTypes'][0]
1585 md[
'mc_event_number'] = et.get(
'mc_event_number', md[
'runNumbers'][0])
1586 if 'mc_channel_number' in et:
1587 md[
'mc_channel_number'] = et.get(
'mc_channel_number',
None)
1588 md[
'eventTypes'] = et[
'type']
1591 if 'GeoAtlas' in et:
1592 md[
'GeoAtlas'] = et.get(
'GeoAtlas',
None)
1593 if 'IOVDbGlobalTag' in et:
1594 md[
'IOVDbGlobalTag'] = et.get(
'IOVDbGlobalTag',
None)
1596 if 'lumiBlockNumbers' in md[key]:
1597 md[
'lumiBlockNumbers'] = md[key][
'lumiBlockNumbers']
1599 if 'processingTags' in md[key]:
1600 md[
'processingTags'] = md[key][
'processingTags']
1602 meta_dict[filename].pop(key)
1605 if not isGaudiEnv()
and key
in md[
'metadata_items']
and 'FileMetaData' in key:
1606 if 'beamType' in md[key]:
1607 md[
'beam_type'] = md[key][
'beamType']
1609 if 'runNumbers' in md[key]:
1610 md[
'runNumbers'] = md[key][
'runNumbers']
1612 if 'mcProcID' in md[key]:
1613 md[
'mc_channel_number'] =
int(md[key][
'mcProcID'])
1615 if 'mcCampaign' in md[key]:
1616 md[
'mc_campaign'] = md[key][
'mcCampaign']
1618 if 'dataYear' in md[key]:
1619 md[
'data_year'] =
int(md[key][
'dataYear'])
1621 if 'lumiBlocks' in md[key]:
1622 md[
'lumiBlockNumbers'] = md[key][
'lumiBlocks']
1624 if mode ==
'peeker' and 'amiTag' in md[key]:
1625 md[
'AMITag'] = md[key][
'amiTag']
1627 if 'beamEnergy' in md[key]:
1628 md[
'beam_energy'] =
int(md[key][
'beamEnergy'])
1630 if 'geometryVersion' in md[key]:
1631 md[
'GeoAtlas'] = md[key][
'geometryVersion']
1634 md[
'eventTypes'] = []
1635 if mode ==
'peeker' and 'simFlavour' in md[key]:
1636 md[
'SimulationFlavour'] = md[key][
'simFlavour']
1638 if mode ==
'peeker' and 'isDataOverlay' in md[key]:
1639 md[
'IsDataOverlay'] = md[key][
'isDataOverlay']
1641 if 'dataType' in md[key]:
1642 md[
'processingTags'] = [md[key][
'dataType']]
1645 (
'simFlavour' in md[key]
and (
'FullG4' in md[key][
'simFlavour']
or 'ATLFAST' in md[key][
'simFlavour']))
1646 or 'DAOD_TRUTH' in md[key][
'dataType']
1648 md[
'eventTypes'].
append(
'IS_SIMULATION')
1650 md[
'eventTypes'].
append(
'IS_DATA')
1653 'GeoAtlas' in md
and 'ATLAS' in md[
'GeoAtlas']
1654 or 'DAOD_TRUTH' in md[key][
'dataType']
1656 md[
'eventTypes'].
append(
'IS_ATLAS')
1658 md[
'eventTypes'].
append(
'IS_PHYSICS')
1660 md[
'eventTypes'].
append(
'IS_TESTBEAM')
1662 if mode ==
'peeker':
1663 if 'productionRelease' in md[key]:
1664 md[
'AtlasRelease'] = md[key][
'productionRelease']
1666 if 'generatorsInfo' in md[key]:
1667 md[
'generators'] = md[key][
'generatorsInfo']
1670 meta_dict[filename].pop(key)
1673 if '/TagInfo' in file_content:
1674 md.update(md[
'/TagInfo'])
1677 if '/Generation/Parameters' in file_content:
1678 md.update(md[
'/Generation/Parameters'])
1679 md.pop(
'/Generation/Parameters')
1681 if '/Simulation/Parameters' in file_content:
1682 md.update(md[
'/Simulation/Parameters'])
1683 md.pop(
'/Simulation/Parameters')
1685 if '/Digitization/Parameters' in file_content:
1686 md.update(md[
'/Digitization/Parameters'])
1687 md.pop(
'/Digitization/Parameters')
1689 if 'CutBookkeepers' in file_content:
1690 md.update(md[
'CutBookkeepers'])
1691 md.pop(
'CutBookkeepers')
1698 This function will rearrange the itemList values to match the format of 'eventdata_items', 'eventdata_itemsList'
1699 or 'eventdata_itemsDic' generated with the legacy file peeker tool
1700 :param metadata: a dictionary obtained using read_metadata method.
1701 The mode for read_metadata must be 'peeker of 'full'
1702 :param layout: the mode in which the data will be converted:
1703 * for 'eventdata_items' use: layout= None
1704 * for 'eventdata_itemsList' use: layout= '#join'
1705 * for 'eventdata_itemsDic' use: layout= 'dict'
1711 if 'itemList' in metadata:
1712 item_list = metadata[
'itemList']
1717 for key
in metadata:
1718 if 'metadata_items' in metadata
and key
in metadata[
'metadata_items']
and metadata[
'metadata_items'][key] ==
'EventStreamInfo_p3':
1721 if current_key
is not None:
1722 item_list = metadata[current_key][
'itemList']
1724 if item_list
is not None:
1729 elif layout ==
'#join':
1730 return [k +
'#' + v
for k, v
in item_list
if k]
1733 elif layout ==
'dict':
1734 from collections
import defaultdict
1735 dic = defaultdict(list)
1737 for k, v
in item_list:
1744 """Extract number of entries from DataHeader.
1746 infile ROOT TFile object or filename string
1747 return Number of entries as returned by DataHeader object in infile,
1748 None in absence of DataHeader object
1751 from PyUtils.PoolFile
import PoolOpts
1752 if not isinstance(infile, ROOT.TFile):
1753 infile = ROOT.TFile.Open(infile)
1755 for name
in {PoolOpts.TTreeNames.DataHeader, PoolOpts.RNTupleNames.DataHeader}:
1756 obj = infile.Get(name)
1757 msg.debug(f
"dataheader_nentries: {name=}, {obj=}, {type(obj)=}")
1760 if isinstance(obj, ROOT.TTree):
1761 return obj.GetEntriesFast()
1764 if ROOT.gROOT.GetVersionInt() < 63100:
1765 raise RuntimeError(
"ROOT ver. 6.31/01 or greater needed to read RNTuple files")
1768 return ROOT.Experimental.RNTupleReader.Open(obj).GetNEntries()
1769 except AttributeError:
1770 return ROOT.RNTupleReader.Open(obj).GetNEntries()
1772 raise NotImplementedError(f
"Keys of type {type(obj)!r} not supported")
1775 """Return a dictionary of metadata filters based on the mode and
1776 optional meta_key_filter.
1779 if meta_key_filter
is None:
1780 meta_key_filter = []
1789 '/TagInfo':
'IOVMetaDataContainer_p1',
1790 'IOVMetaDataContainer_p1__TagInfo':
'IOVMetaDataContainer_p1',
1791 '*':
'EventStreamInfo_p*'
1795 'FileMetaData':
'*',
1796 'FileMetaDataAux.':
'xAOD::FileMetaDataAuxInfo_v1',
1800 if mode ==
'peeker':
1801 meta_filter.update({
1802 'TriggerMenu':
'DataVector<xAOD::TriggerMenu_v1>',
1803 'TriggerMenuAux.':
'xAOD::TriggerMenuAuxContainer_v1',
1804 'DataVector<xAOD::TriggerMenu_v1>_TriggerMenu':
'DataVector<xAOD::TriggerMenu_v1>',
1805 'xAOD::TriggerMenuAuxContainer_v1_TriggerMenuAux.':
'xAOD::TriggerMenuAuxContainer_v1',
1806 'TriggerMenuJson_HLT':
'DataVector<xAOD::TriggerMenuJson_v1>',
1807 'TriggerMenuJson_HLTAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1808 'TriggerMenuJson_HLTMonitoring':
'DataVector<xAOD::TriggerMenuJson_v1>',
1809 'TriggerMenuJson_HLTMonitoringAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1810 'TriggerMenuJson_HLTPS':
'DataVector<xAOD::TriggerMenuJson_v1>',
1811 'TriggerMenuJson_HLTPSAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1812 'TriggerMenuJson_L1':
'DataVector<xAOD::TriggerMenuJson_v1>',
1813 'TriggerMenuJson_L1Aux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1814 'TriggerMenuJson_L1PS':
'DataVector<xAOD::TriggerMenuJson_v1>',
1815 'TriggerMenuJson_L1PSAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1816 'CutBookkeepers':
'xAOD::CutBookkeeperContainer_v1',
1817 'CutBookkeepersAux.':
'xAOD::CutBookkeeperAuxContainer_v1',
1818 'FileMetaData':
'*',
1819 'FileMetaDataAux.':
'xAOD::FileMetaDataAuxInfo_v1',
1820 'TruthMetaData':
'*',
1821 'TruthMetaDataAux.':
'xAOD::TruthMetaDataAuxContainer_v1',
1822 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLT':
'DataVector<xAOD::TriggerMenuJson_v1>',
1823 'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1824 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTMonitoring':
'DataVector<xAOD::TriggerMenuJson_v1>',
1825 'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTMonitoringAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1826 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_HLTPS':
'DataVector<xAOD::TriggerMenuJson_v1>',
1827 'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_HLTPSAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1828 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1':
'DataVector<xAOD::TriggerMenuJson_v1>',
1829 'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_L1Aux.':
'xAOD::TriggerMenuJsonAuxContainer_v1',
1830 'DataVector<xAOD::TriggerMenuJson_v1>_TriggerMenuJson_L1PS':
'DataVector<xAOD::TriggerMenuJson_v1>',
1831 'xAOD::TriggerMenuJsonAuxContainer_v1_TriggerMenuJson_L1PSAux.':
'xAOD::TriggerMenuJsonAuxContainer_v1'
1835 meta_filter.update({
1836 '/TagInfo':
'IOVMetaDataContainer_p1',
1837 'IOVMetaDataContainer_p1__TagInfo':
'IOVMetaDataContainer_p1',
1838 '/Simulation/Parameters':
'IOVMetaDataContainer_p1',
1839 '/Digitization/Parameters':
'IOVMetaDataContainer_p1',
1840 '/EXT/DCS/MAGNETS/SENSORDATA':
'IOVMetaDataContainer_p1',
1841 '*':
'EventStreamInfo_p*'
1844 if (mode ==
'full' or mode ==
'iov')
and meta_key_filter:
1845 meta_filter = {f:
'*' for f
in meta_key_filter}
1851 Convert canonical/C++ STL types in the metadata_items dictionary back to their
1852 ROOT equivalents for backward compatibility.
1853 - 'float' => 'Float_t'
1854 - 'char' => 'Char_t'
1855 - 'std::string' => 'string'
1856 - 'xAOD::FileMetaData_v1' => 'FileMetaData'
1857 - 'xAOD::FileMetaDataAuxInfo_v1' => 'FileMetaDataAux'
1858 (add more as needed)
1863 "std::string":
"string",
1864 "std::uint32_t":
"UInt_t",
1865 "xAOD::FileMetaData_v1":
"FileMetaData",
1868 for k, v
in metadata_dict.items():
1870 for old, new
in type_map.items():
1873 elif new_v.endswith(
"." + old):
1874 new_v = new_v.rsplit(
".", 1)[0] +
"." + new
1875 denormalized[k] = new_v
1881 Helper function to determine if metadata should be kept based on meta_filter.
1883 if len(meta_filter) == 0:
1886 for filter_key, filter_class
in meta_filter.items():
1888 filter_key.replace(
"/",
"_")
in normalizedName.replace(
"/",
"_")
1889 or filter_key ==
"*"
1890 )
and fnmatchcase(typeName, filter_class):
1891 if "CutBookkeepers" in filter_key:
1892 keep = filter_key == normalizedName