ATLAS Offline Software
Loading...
Searching...
No Matches
GetCrossSectionAMITool.py
Go to the documentation of this file.
1# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
2
3from AthenaCommon.Logging import logging
4import re
5
6
10 def __init__(self):
11 self.log = logging.getLogger('GetCrossSectionAMI')
12
13 try:
14 import pyAMI.client
15 import pyAMI.atlas.api as api
16 except ImportError:
17 self.log.fatal('Unable to import the pyAMI client. Did you run "lsetup pyami; voms-proxy-init -voms atlas"?')
18 exit()
19
20 self.ami_api = api
21 self.ami_client = pyAMI.client.Client('atlas')
22 self.ami_api.init()
23
24 @property
25 def crossSection(self):
26 return self.xsec
27
28 @property
30 return self.filtereff
31
32 def getDatasetNameFromPath(self, path):
33 import re
34 datasetRegex = r'mc.._.*TeV\..*|valid.\..*' # mc??_????TeV.??? or valid?.???
35 parts = path.split('/')
36 for part in parts: # Do any of these parts look like a dataset name?
37 if re.match(datasetRegex, part):
38 return part
39
40 self.log.error('Unable to figure out the MC dataset name from the path, you must supply it yourself as MCDatasetName')
41
42 def cleanupDatasetName(self, dataset):
43 dataset = re.sub('_tid[0-9]{8}_[0-9]{2}', '', dataset)
44 dataset = re.sub('_sub[0-9]{10}', '', dataset)
45 dataset = re.sub('/$', '', dataset)
46 return dataset
47
48 def convertDatasetNameToEVNT(self, dataset):
49 dsid = dataset.split('.')[1]
50 try:
51 res_d = self.ami_api.get_dataset_prov(self.ami_client, dataset)
52 except Exception as reason:
53 self.log.fatal('Unable to query AMI. Do you have a grid certificate? "voms-proxy-init -voms atlas"')
54 self.log.fatal('You can also supply the MCCrossSection and MCFilterEfficiency by hand for this sample')
55 self.log.fatal(f'The reason for failure was: {reason}')
56 exit()
57
58 previous_nodes = [
59 n for n in res_d['node']
60 if 'logicalDatasetName' in n.keys() and n['logicalDatasetName'].split('.')[1] == dsid and 'EVNT' in n['logicalDatasetName']
61 ]
62
63 sorted_nodes = sorted(previous_nodes, key=lambda n: n['distance'])
64 # We pick the latest one, just in case the cross section was modified (shouldn't have)
65 evnt_dataset = sorted_nodes[0]['logicalDatasetName']
66
67 if 'EVNT' in evnt_dataset:
68 self.log.info('Found the original EVNT dataset using AMI provenance.')
69 self.log.info(f'Went from: {dataset}')
70 self.log.info(f' to: {evnt_dataset}')
71 return evnt_dataset
72 else:
73 self.log.fatal('Unable to get the original EVNT dataset from AMI provenance, you must supply it yourself as MCDatasetName')
74 self.log.fatal('You can also supply the MCCrossSection and MCFilterEfficiency by hand for this sample')
75 exit()
76
77 def queryAmi(self, dataset):
78 if 'EVNT' not in dataset:
79 dataset = self.convertDatasetNameToEVNT(self.cleanupDatasetName(dataset))
80 self.dataset = dataset
81 self.log.info(f'Looking up details of {self.dataset} on AMI')
82
83 # search for EVNT file
84 fields = 'cross_section,generator_filter_efficiency'
85 try:
86 res_l = self.ami_api.list_datasets(self.ami_client, patterns=self.dataset, fields=fields)
87 except Exception as reason:
88 self.log.fatal('Unable to query AMI. Do you have a grid certificate? "voms-proxy-init -voms atlas"')
89 self.log.fatal('You can also supply the MCCrossSection and MCFilterEfficiency by hand for this sample')
90 self.log.fatal(f'The reason for failure was: {reason}')
91 exit()
92
93 if len(res_l) == 0:
94 self.log.fatal(f'The dataset "{dataset}" was not found in AMI')
95 self.log.fatal('You can also supply the MCCrossSection and MCFilterEfficiency by hand for this sample')
96 exit()
97 elif len(res_l) > 1:
98 self.log.fatal(f'More than one dataset "{dataset}" was found in AMI.')
99 exit()
100
101 xsec = res_l[0]['cross_section']
102 gfe = res_l[0]['generator_filter_efficiency']
103
104 if xsec == 'NULL' or gfe == 'NULL':
105 self.log.fatal(f'NULL cross section/filter efficiency values set on AMI for the dataset "{dataset}"')
106 self.log.fatal('You can supply the MCCrossSection and MCFilterEfficiency by hand for this sample')
107 exit()
108
109 try:
110 self.xsec = float(xsec)
111 self.filtereff = float(gfe)
112 except ValueError:
113 self.log.fatal('Coudn\'t convert cross section/filter efficiency values to floats')
114 self.log.fatal(f' Cross Section: {xsec}')
115 self.log.fatal(f'Filter Efficiency: {gfe}')
116 self.log.fatal('You can supply the MCCrossSection and MCFilterEfficiency by hand for this sample')
117 exit()
118
119 if self.xsec and self.filtereff:
120 self.log.info('################## ################## AMI Query Complete ################## ################## ')
121 self.log.info(f' Cross section: {self.xsec} nb')
122 self.log.info(f'Filter efficiency: {self.filtereff}')
123 self.log.info('You may want to supply these numbers directly in future as MCCrossSection and MCFilterEfficiency for speed')
124 self.log.info('################## ################## ################## ################## ################### ')
125 else:
126 self.log.fatal(f'The cross section and/or filter efficiency values for the dataset "{dataset}" are set to 0 on AMI')
127 self.log.fatal('You can supply the MCCrossSection and MCFilterEfficiency by hand for this sample')
128 exit()
Basic wrapper around pyAMI for getting MC dataset cross sections & maniuplating dataset name strings.
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177