8 from AnaAlgorithm.AlgSequence
import AlgSequence
9 from AnaAlgorithm.AnaAlgorithmMeta
import AnaAlgorithmMeta
10 from AnaAlgorithm.DualUseConfig
import createAlgorithm, isAthena
13 return f
"{comp.getType()}/{comp.getName()}"
16 """Analysis algorithm sequence
18 This is a thin layer above a generic algorithm sequence, which helps
19 with setting up the analysis algorithms for the job.
21 Note that this class is specifically meant for setting up the algorithms
22 provided centrally for analysis. The private analysis algorithms of the
23 users do not need to use this sequence type.
30 "_gaudiConfig2Algorithms",
31 "_gaudiConfig2PublicTools",
35 def __init__( self, name = "AnalysisSequence" ):
36 """Analysis algorithm sequence constructor
38 Nothing special, it just initialises the base class, and taking the
39 name of the input container of the sequence.
42 name -- The name of the analysis algorithm sequence
46 super( AnaAlgSequence, self ).
__init__( name )
48 print(
"WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING")
49 print(
"WARNING!!!!! Usage of AnaAlgSequence is deprecated, please use ConfigBlocks instead")
50 print(
"WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING")
90 assert inputPropName
or outputPropName,
"Either input or output name should be provided for decor-aware tools"
94 hiddenLayerPrefix = "" ):
95 """Perform a post-configuration on the analysis algorithm sequence
97 This function needs to be called once the sequence is configured to
98 hold the right algorithms, in the right order, with the right settings.
99 It sets the I/O properties of the algorithms to make sure that they
100 receive the input object(s) specified, and produce the output object(s)
103 The arguments can either be simple string names, or dictionaries in the
104 form of { "type" : "key", ... }. The latter is used to describe multiple
105 inputs/outputs to/from a sequence. See the descriptions of the various
106 analysis algorithm sequence setup functions on how their created
107 sequences should be configured by this function.
110 inputName -- The name(s) of the input object(s)/container(s) to
112 outputName -- The name(s) of the output object(s)/container(s) to
114 hiddenLayerPrefix -- Possible unique string prefix for
115 object(s)/container(s) in "hidden layers" of the
116 algorithm sequence. To avoid name clashes when
117 scheduling multiple instances of the sequence.
127 for alg
in self: listOfAlgs.append(alg)
131 nAlgs = len(listOfAlgs)
133 raise RuntimeError(
'Analysis algorithm sequence is in an ' \
134 'inconsistent state' )
139 metaConfig[name] = value[:]
142 for var, func
in meta.dynConfig.items() :
146 obj = getattr (alg, var[:var.find(
'.')])
147 var = var[var.find(
'.')+1:]
150 setattr (obj, var, func (metaConfig))
152 for name, value
in meta.metaConfig.items() :
153 if name
not in metaConfig :
154 raise RuntimeError (
"metaConfig value " + name +
" for algorithm " + alg.name() +
" not registered, did you forget to call addMetaConfigDefault?")
155 metaConfig[name] += value[:]
161 if isinstance( inputName, dict ):
162 inputNameDict = inputName
164 inputNameDict = {
"default" : inputName }
166 if isinstance( outputName, dict ):
167 outputNameDict = outputName
169 outputNameDict = {
"default" : outputName }
173 currentInputs = copy.deepcopy( inputNameDict )
179 if not meta.inputPropName:
183 for inputLabel, inputPropName
in meta.inputPropName.items():
184 if inputLabel
not in currentInputs:
186 setattr( alg, inputPropName, currentInputs[ inputLabel ] )
191 setattr( tool, inputPropName, currentInputs[ inputLabel ].
replace(
'%SYS%',
'NOSYS') )
195 if meta.outputPropName:
198 for outputLabel, outputPropName
in meta.outputPropName.items():
199 if outputLabel
not in tmpIndex:
200 tmpIndex[ outputLabel ] = 1
202 if outputLabel
in outputNameDict:
203 currentInputs[ outputLabel ] = \
204 '%s_tmp%i' % ( outputNameDict[ outputLabel ],
205 tmpIndex[ outputLabel ] )
207 currentInputs[ outputLabel ] = \
208 '%s%s_tmp%i' % ( hiddenLayerPrefix, outputLabel,
209 tmpIndex[ outputLabel ] )
212 tmpIndex[ outputLabel ] += 1
213 setattr( alg, outputPropName, currentInputs[ outputLabel ] )
218 setattr( tool, outputPropName, currentInputs[ outputLabel ].
replace(
'%SYS%',
'NOSYS') )
227 currentOutputs = copy.deepcopy( outputNameDict )
231 if len( currentOutputs ) == 0:
236 if meta.outputPropName:
237 for outputLabel, outputKey
in meta.outputPropName.items():
238 if outputLabel
in currentOutputs:
239 setattr( alg, outputKey, currentOutputs[ outputLabel ] )
244 setattr( tool, outputPropName, currentInputs[ outputLabel ].
replace(
'%SYS%',
'NOSYS') )
246 del currentOutputs[ outputLabel ]
253 if meta.inputPropName :
254 for inputLabel, inputKey
in meta.inputPropName.items():
255 if inputLabel
in currentOutputs:
256 setattr( alg, inputKey, currentOutputs[ inputLabel ] )
261 setattr( tool, inputPropName, currentInputs[ inputLabel ].
replace(
'%SYS%',
'NOSYS') )
267 def append( self, alg, inputPropName, outputPropName = None,
268 stageName = 'undefined',
271 """Add one analysis algorithm to the sequence
273 This function is specifically meant for adding one of the centrally
274 provided analysis algorithms to the sequence.
277 alg -- The algorithm to add (an Athena configurable, or an
278 EL::AnaAlgorithmConfig instance)
279 inputPropName -- The name of the property setting the input
280 object/container name for the algorithm
281 outputPropName -- The name of the property setting the output
282 object/container name for the algorithm [optional]
283 stageName -- name of the current processing stage [optional]
286 meta = AnaAlgorithmMeta( stageName=stageName, inputPropName=inputPropName, outputPropName=outputPropName, metaConfig=metaConfig, dynConfig=dynConfig )
288 if 'GaudiConfig2' in str(
type(alg)):
295 def insert( self, index, alg, inputPropName, outputPropName = None,
296 stageName = 'undefined',
299 """Insert one analysis algorithm into the sequence
301 This function is specifically meant for adding one of the centrally
302 provided analysis algorithms to the sequence, in a user defined
306 index -- The index to insert the algorithm at
307 alg -- The algorithm to add (an Athena configurable, or an
308 EL::AnaAlgorithmConfig instance)
309 inputPropName -- The name of the property setting the input
310 object/container name for the algorithm
311 outputPropName -- The name of the property setting the output
312 object/container name for the algorithm [optional]
313 stageName -- name of the current processing stage [optional]
316 meta = AnaAlgorithmMeta( stageName=stageName, inputPropName=inputPropName, outputPropName=outputPropName, metaConfig=metaConfig, dynConfig=dynConfig )
317 super( AnaAlgSequence, self ).
insert( index, alg )
322 """Add a public tool to the job
324 This function is here to provide a uniform interface with which
325 analysis algorithm sequences can declare the public tools that they
326 need. In Athena mode the function doesn't do anything. But in EventLoop
327 mode it remembers the EL::AnaAlgorithmConfig object that it receives,
328 which describes the public tool.
331 tool -- The tool object to add to the sequence/job
336 self.
append( tool, inputPropName =
None, stageName = stageName )
338 if 'GaudiConfig2' in str(
type(tool)):
343 """Remove one algorithm/sequence from this sequence, by name
345 This is to allow removing algorithms (or even sequences) from this
346 sequence in case that would be needed.
349 name -- The name of the algorithm/sequence to delete from the
357 if alg.name() == name:
365 raise AttributeError(
'Algorithm/sequence with name "%s" was not ' \
376 """Remove all algorithms for the given stage
379 stageName -- name of the processing stage to remove
383 raise ValueError (
'unknown stage name ' + stageName +
' allowed stage names are ' +
', '.
join(self.
allowedStageNames()))
387 if stageName !=
"undefined" :
389 if meta.stageName ==
"undefined" :
390 raise ValueError (
"can not remove stages from an algorithm sequence if some algorithms belong to an undefined stage")
396 names.append (alg.name())
399 while iter < len( self ):
401 super( AnaAlgSequence, self ).
__delattr__( names[iter] )
414 """add a default value for the given meta-configuration entry
416 This will both register name as a valid meta-configuration
417 value and set its default value, or add to its default value,
418 if that name is already known."""
431 """get the value for the given meta-configuration entry"""
434 raise RuntimeError (
"metaConfig value " + name +
" not registered, did you forget to call addMetaConfigDefault?")
437 if name
in meta.metaConfig :
438 result += meta.metaConfig[name]
447 return AnaAlgorithmMeta.allowedStageNames ()
462 self.
seq.
append( alg, inputPropName =
'electrons',
463 outputPropName =
'electronsOut',
464 stageName =
'calibration' )
466 self.
seq.
append( alg, inputPropName =
'egammas',
467 outputPropName =
'egammasOut',
468 stageName =
'efficiency' )
470 self.
seq.insert( 1, alg, inputPropName =
'particles',
471 outputPropName =
'particlesOut',
472 stageName =
'selection' )
474 self.
seq.
append( alg, inputPropName =
None )
477 outputName =
'AnalysisElectrons_%SYS%' )
482 self.assertEqual( len( self.
seq ), 3 )
487 self.assertEqual( self.
seq.Calibration.electrons,
'Electrons' )
488 self.assertEqual( self.
seq.Efficiency.egammasOut,
489 'AnalysisElectrons_%SYS%' )
502 self.
seq.
append( alg, inputPropName = {
'electrons' :
'particles' },
503 outputPropName = {
'electrons' :
'particlesOut' } )
505 self.
seq.
append( alg, inputPropName = {
'muons' :
'particles' },
506 outputPropName = {
'muons' :
'particlesOut' } )
508 self.
seq.
append( alg, inputPropName = {
'electrons' :
'particles' },
509 outputPropName = {
'electronZs' :
'zCandidates' } )
511 self.
seq.
append( alg, inputPropName = {
'muons' :
'particles' },
512 outputPropName = {
'muonZs' :
'zCandidates' } )
514 self.
seq.
append( alg, inputPropName = {
'electronZs' :
'container1',
515 'muonZs' :
'container2' },
516 outputPropName = {
'Zs' :
'output' } )
518 self.
seq.
append( alg, inputPropName = {
'Zs' :
'input' },
519 outputPropName =
'output' )
520 self.
seq.
configure( inputName = {
'electrons' :
'AnalysisElectrons_%SYS%',
521 'muons' :
'AnalysisMuons_%SYS%' },
522 outputName =
'ZCandidates_%SYS%' )
527 self.assertEqual( self.
seq.ElectronSelection.particles,
528 'AnalysisElectrons_%SYS%' )
529 self.assertEqual( self.
seq.MuonSelection.particles,
530 'AnalysisMuons_%SYS%' )
531 self.assertEqual( self.
seq.ZCalibrator.output,
532 'ZCandidates_%SYS%' )
543 self.
seq.
append( alg, inputPropName =
'particles',
544 outputPropName =
'particlesOut' )
546 self.
seq.
append( alg, inputPropName =
'particles',
547 outputPropName = {
'goodObjects' :
'goodParticles',
548 'badObjects' :
'badParticles' } )
550 self.
seq.
append( alg, inputPropName = {
'goodObjects' :
'particles' },
551 outputPropName = {
'goodObjects' :
'particlesOut' } )
553 self.
seq.
append( alg, inputPropName = {
'badObjects' :
'particles' },
554 outputPropName = {
'badObjects' :
'particlesOut' } )
556 outputName = {
'goodObjects' :
'GoodElectrons_%SYS%',
557 'badObjects' :
'BadElectrons_%SYS%' } )
562 self.assertEqual( self.
seq.Calibration.particles,
'Electrons' )
563 self.assertEqual( self.
seq.GoodParticleTrimmer.particlesOut,
564 'GoodElectrons_%SYS%' )
565 self.assertEqual( self.
seq.BadParticleTrimmer.particlesOut,
566 'BadElectrons_%SYS%' )
577 self.
seq.
append( alg, inputPropName = {
'electrons' :
'particles' },
578 outputPropName = {
'electrons' :
'particlesOut' } )
580 self.
seq.
append( alg, inputPropName = {
'muons' :
'particles' },
581 outputPropName = {
'muons' :
'particlesOut' } )
583 self.
seq.
append( alg, inputPropName = {
'electrons' :
'electrons',
585 outputPropName = {
'electrons' :
'electronsOut',
586 'muons' :
'muonsOut' } )
587 self.
seq.
configure( inputName = {
'electrons' :
'AnalysisElectrons_%SYS%',
588 'muons' :
'AnalysisMuons_%SYS%' },
589 outputName = {
'electrons' :
'FinalElectrons_%SYS%',
590 'muons' :
'FinalMuons_%SYS%' } )
595 self.assertEqual( self.
seq.ElectronSelection.particles,
596 'AnalysisElectrons_%SYS%' )
597 self.assertEqual( self.
seq.MuonSelection.particles,
598 'AnalysisMuons_%SYS%' )
599 self.assertEqual( self.
seq.OverlapRemoval.electronsOut,
600 'FinalElectrons_%SYS%' )
601 self.assertEqual( self.
seq.OverlapRemoval.muonsOut,