ATLAS Offline Software
ConfigText_unitTest.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
4 #
5 # @author Joseph Lambert
6 
7 def compareConfigSeq(seq1, seq2, *, checkOrder=False):
8  """Compares two ConfigSequences"""
9  blocks1 = seq1._blocks
10  blocks2 = seq2._blocks
11  print("Block order for each config sequence")
12  print("\033[4m{0:<30} {1:<30}\033[0m".format("Sequence1", "Sequence2"))
13  for i in range(max(len(blocks1), len(blocks2))):
14  name1, name2 = '', ''
15  if i < len(blocks1):
16  name1 = blocks1[i].__class__.__name__
17  if i < len(blocks2):
18  name2 = blocks2[i].__class__.__name__
19  print(f"{name1:<30} {name2}")
20  if not checkOrder:
21  print("Sorting blocks by name (will not sort blocks with same name)")
22  blocks1.sort(key=lambda x: x.__class__.__name__)
23  blocks2.sort(key=lambda x: x.__class__.__name__)
24  if len(blocks1) != len(blocks2):
25  raise Exception("Number of blocks are different")
26  for i in range(len(blocks1)):
27  block1 = blocks1[i]
28  block2 = blocks2[i]
29  name1 = block1.__class__.__name__
30  name2 = block2.__class__.__name__
31  if name1 != name2:
32  raise Exception(f"In position {i} "
33  f"the first sequence results in {name1} "
34  f"and the second sequence results in {name2}")
35  for name in block1.getOptions():
36  if name == 'groupName':
37  continue
38  value1 = block1.getOptionValue(name)
39  value2 = block2.getOptionValue(name)
40  if value1 != value2:
41  raise Exception(f"For block {name1}, the block "
42  f"option {name} the first sequence results in {value1} "
43  f"and the second sequence results in {value2}")
44 
45 
46 def compareTextBuilder(yamlPath='', *, checkOrder=False) :
47  """
48  Create a configSequence using provided YAML file and a
49  configSequence using ConfigText python commands and compare.
50 
51  Will raise an exception if configSequences differ
52  """
53  # create text config object to build text configurations
54  from AnalysisAlgorithmsConfig.ConfigText import TextConfig
55  config = TextConfig()
56 
57  # CommonServices
58  config.addBlock('CommonServices')
59  config.setOptions(systematicsHistogram='systematicsList')
60  config.setOptions(filterSystematics="^(?:(?!PseudoData).)*$")
61 
62  # PileupReweighting
63  config.addBlock('PileupReweighting')
64 
65  # EventCleaning
66  config.addBlock('EventCleaning')
67  config.setOptions (runEventCleaning=True)
68 
69  # Jets
70  config.addBlock('Jets')
71  config.setOptions (containerName='AnaJets')
72  config.setOptions (jetCollection='AntiKt4EMPFlowJets')
73  config.setOptions (runJvtUpdate=False)
74  config.setOptions (runNNJvtUpdate=True)
75  # Jets.FlavourTagging
76  config.addBlock( 'Jets.FlavourTagging')
77  config.setOptions (containerName='AnaJets')
78  config.setOptions (selectionName='ftag')
79  config.setOptions (noEffSF=True)
80  config.setOptions (btagger='DL1dv01')
81  config.setOptions (btagWP='FixedCutBEff_60')
82  # Jets.JVT
83  config.addBlock('Jets.JVT', containerName='AnaJets')
84  # Jets.PtEtaSelection
85  config.addBlock ('Jets.PtEtaSelection')
86  config.setOptions (containerName='AnaJets')
87  config.setOptions (selectionDecoration='selectPtEta')
88 
89  # Electrons
90  config.addBlock ('Electrons')
91  config.setOptions (containerName='AnaElectrons')
92  config.setOptions (forceFullSimConfig=True)
93  # Electrons.WorkingPoint
94  config.addBlock ('Electrons.WorkingPoint')
95  config.setOptions (containerName='AnaElectrons')
96  config.setOptions (selectionName='loose')
97  config.setOptions (forceFullSimConfig=True)
98  config.setOptions (noEffSF=True)
99  config.setOptions (likelihoodWP='LooseBLayerLH')
100  config.setOptions (isolationWP='Loose_VarRad')
101  config.setOptions (recomputeLikelihood=False)
102  config.setOptions (writeTrackD0Z0=True)
103  # Electrons.PtEtaSelection
104  config.addBlock ('Electrons.PtEtaSelection')
105  config.setOptions (containerName='AnaElectrons')
106  config.setOptions (selectionDecoration='selectPtEta')
107  config.setOptions (minPt=10000.0)
108 
109  # Photons
110  config.addBlock ('Photons', containerName='AnaPhotons')
111  config.setOptions (forceFullSimConfig=True)
112  config.setOptions (recomputeIsEM=False)
113  # Photons.WorkingPoint
114  config.addBlock ('Photons.WorkingPoint')
115  config.setOptions (containerName='AnaPhotons')
116  config.setOptions (selectionName='tight')
117  config.setOptions (forceFullSimConfig=True)
118  config.setOptions (noEffSF=True)
119  config.setOptions (qualityWP='Tight')
120  config.setOptions (isolationWP='FixedCutTight')
121  config.setOptions (recomputeIsEM=False)
122  # Photons.PtEtaSelection
123  config.addBlock ('Photons.PtEtaSelection')
124  config.setOptions (containerName='AnaPhotons')
125  config.setOptions (selectionDecoration='selectPtEta')
126  config.setOptions (minPt=10000.0)
127 
128  # Muons
129  config.addBlock ('Muons', containerName='AnaMuons')
130  # Muons.WorkingPoint
131  config.addBlock ('Muons.WorkingPoint')
132  config.setOptions (containerName='AnaMuons')
133  config.setOptions (selectionName='medium')
134  config.setOptions (quality='Medium')
135  config.setOptions (isolation='Loose_VarRad')
136  config.setOptions (onlyRecoEffSF=True)
137  config.setOptions (writeTrackD0Z0=True)
138  # Muons.PtEtaSelection
139  config.addBlock ('Muons.PtEtaSelection')
140  config.setOptions (containerName='AnaMuons')
141  config.setOptions (selectionDecoration='selectPtEta')
142 
143  # TauJets
144  config.addBlock ('TauJets', containerName='AnaTauJets')
145  # TauJets.WorkingPoint
146  config.addBlock ('TauJets.WorkingPoint')
147  config.setOptions (containerName='AnaTauJets')
148  config.setOptions (selectionName='tight')
149  config.setOptions (quality='Tight')
150  # TauJets.PtEtaSelection
151  config.addBlock ('TauJets.PtEtaSelection')
152  config.setOptions (containerName='AnaTauJets')
153  config.setOptions (selectionDecoration='selectPtEta')
154 
155  config.addBlock ('SystObjectLink')
156  config.setOptions (containerName='AnaJets')
157  config.addBlock ('SystObjectLink')
158  config.setOptions (containerName='AnaElectrons')
159  config.addBlock ('SystObjectLink')
160  config.setOptions (containerName='AnaPhotons')
161  config.addBlock ('SystObjectLink')
162  config.setOptions (containerName='AnaMuons')
163  config.addBlock ('SystObjectLink')
164  config.setOptions (containerName='AnaTauJets')
165 
166  config.addBlock ('ObjectCutFlow')
167  config.setOptions (containerName='AnaJets')
168  config.setOptions (selectionName='jvt')
169  config.addBlock ('ObjectCutFlow')
170  config.setOptions (containerName='AnaElectrons')
171  config.setOptions (selectionName='loose')
172  config.addBlock ('ObjectCutFlow')
173  config.setOptions (containerName='AnaPhotons')
174  config.setOptions (selectionName='tight')
175  config.addBlock ('ObjectCutFlow')
176  config.setOptions (containerName='AnaMuons')
177  config.setOptions (selectionName='medium')
178  config.addBlock ('ObjectCutFlow')
179  config.setOptions (containerName='AnaTauJets')
180  config.setOptions (selectionName='tight')
181 
182  # GeneratorLevelAnalysis
183  config.addBlock( 'GeneratorLevelAnalysis')
184  config.setOptions (saveCutBookkeepers=True)
185  config.setOptions (runNumber=284500)
186  config.setOptions (cutBookkeepersSystematics=True)
187 
188  # MissingET
189  config.addBlock ('MissingET')
190  config.setOptions (containerName='AnaMET')
191  config.setOptions (jets='AnaJets')
192  config.setOptions (taus='AnaTauJets.tight')
193  config.setOptions (electrons='AnaElectrons.loose')
194  config.setOptions (photons='AnaPhotons.tight')
195  config.setOptions (muons='AnaMuons.medium')
196 
197  # OverlapRemoval
198  config.addBlock( 'OverlapRemoval' )
199  config.setOptions (inputLabel='preselectOR')
200  config.setOptions (outputLabel='passesOR' )
201  config.setOptions (jets='AnaJets')
202  config.setOptions (taus='AnaTauJets.tight')
203  config.setOptions (electrons='AnaElectrons.loose')
204  config.setOptions (photons='AnaPhotons.tight')
205  config.setOptions (muons='AnaMuons.medium')
206 
207  # Thinning
208  config.addBlock ('Thinning')
209  config.setOptions (containerName='AnaElectrons')
210  config.setOptions (selectionName='loose')
211  config.setOptions (outputName='OutElectrons')
212  config.addBlock ('Thinning')
213  config.setOptions (containerName='AnaPhotons')
214  config.setOptions (selectionName='tight')
215  config.setOptions (outputName='OutPhotons')
216  config.addBlock ('Thinning')
217  config.setOptions (containerName='AnaMuons')
218  config.setOptions (selectionName='medium')
219  config.setOptions (outputName='OutMuons')
220  config.addBlock ('Thinning')
221  config.setOptions (containerName='AnaTauJets')
222  config.setOptions (selectionName='tight')
223  config.setOptions (outputName='OutTauJets')
224  config.addBlock ('Thinning')
225  config.setOptions (containerName='AnaJets')
226  config.setOptions (outputName='OutJets')
227 
228  config.addBlock ('Output')
229  config.setOptions (treeName='analysis')
230  config.setOptions (vars=[])
231  config.setOptions (metVars=[])
232  outputContainers = {
233  'mu_': 'OutMuons',
234  'el_': 'OutElectrons',
235  'ph_' : 'OutPhotons',
236  'tau_': 'OutTauJets',
237  'jet_': 'OutJets',
238  'met_': 'AnaMET',
239  '': 'EventInfo'}
240  config.setOptions (containers=outputContainers)
241  disable_commands = [
242  'disable jet_select_baselineJvt.*',
243  'disable mu_select_medium.*',
244  'disable ph_select_tight.*',
245  'disable tau_select_tight.*',
246  'disable el_select_loose.*',
247  ]
248  config.setOptions (commands=disable_commands)
249 
250  # configure ConfigSequence
251  configSeq = config.configure()
252 
253  # create text config object to build text configurations
254  textConfig = TextConfig(yamlPath)
255  textConfigSeq = textConfig.configure()
256 
257  # compare - will raise error if False
258  compareConfigSeq(configSeq, textConfigSeq, checkOrder=checkOrder)
259 
260 
261 def compareBlockConfig(yamlPath='', *, checkOrder=False) :
262  """
263  Create a configSequence using provided YAML file and a
264  configSequence using the block configuration and compare.
265 
266  Will raise an exception if configSequences differ
267  """
268  # create configSeq for block configuration
269  from AnalysisAlgorithmsConfig.FullCPAlgorithmsTest import makeSequenceBlocks
270  configSeq = makeSequenceBlocks(dataType='fullsim', algSeq=None,
271  forCompare=True, isPhyslite=False, forceEGammaFullSimConfig=True,
272  returnConfigSeq=True)
273 
274  # create text config object to build text configurations
275  from AnalysisAlgorithmsConfig.ConfigText import TextConfig
276  textConfig = TextConfig(yamlPath)
277  textConfigSeq = textConfig.configure()
278 
279  # compare - will raise error if False
280  compareConfigSeq(configSeq, textConfigSeq, checkOrder=checkOrder)
281 
282 
283 if __name__ == '__main__':
284  import os
285  import optparse
286  parser = optparse.OptionParser()
287  parser.add_option('--text-config', dest='text_config',
288  default='', action='store',
289  help='YAML file used in unit test')
290  parser.add_option('--compare-block', dest='compare_block',
291  default=False, action='store_true',
292  help='Compare config sequence from YAML and block configuration')
293  parser.add_option('--compare-builder', dest='compare_builder',
294  default=False, action='store_true',
295  help='Compare config sequence from YAML and python configuration')
296  parser.add_option('--check-order', dest='check_order',
297  default=False, action='store_true',
298  help='Require blocks to be in the same order')
299  (options, args) = parser.parse_args()
300  textConfig = options.text_config
301  compareBlock = options.compare_block
302  compareBuilder = options.compare_builder
303  checkOrder = options.check_order
304 
305  if not os.path.isfile(textConfig):
306  raise FileNotFoundError(f"{textConfig} is not a file")
307 
308  # compare YAML and builder
309  if compareBuilder:
310  print("Comparing config sequences from the block and text"
311  "configuration methods")
312  compareTextBuilder(textConfig, checkOrder=checkOrder)
313  # compare YAML and block config
314  if compareBlock:
315  print("Comparing config sequences from the block and block"
316  "configuration methods")
317  compareBlockConfig(textConfig, checkOrder=checkOrder)
python.ConfigText_unitTest.compareConfigSeq
def compareConfigSeq(seq1, seq2, *checkOrder=False)
Definition: ConfigText_unitTest.py:7
python.FullCPAlgorithmsTest.makeSequenceBlocks
def makeSequenceBlocks(dataType, algSeq, forCompare, isPhyslite, geometry=None, autoconfigFromFlags=None, noSystematics=None, onlyNominalOR=False, forceEGammaFullSimConfig=False, returnConfigSeq=False)
Definition: FullCPAlgorithmsTest.py:658
max
#define max(a, b)
Definition: cfImp.cxx:41
python.ConfigText_unitTest.compareTextBuilder
def compareTextBuilder(yamlPath='', *checkOrder=False)
Definition: ConfigText_unitTest.py:46
vtune_athena.format
format
Definition: vtune_athena.py:14
python.ConfigText_unitTest.compareBlockConfig
def compareBlockConfig(yamlPath='', *checkOrder=False)
Definition: ConfigText_unitTest.py:261
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
Muon::print
std::string print(const MuPatSegment &)
Definition: MuonTrackSteering.cxx:28