5 from AthenaConfiguration.ComponentFactory
import CompFactory, isComponentAccumulatorCfg
7 AlgSequence = CompFactory.AthSequencer
9 from AthenaCommon.AlgSequence
import AthSequencer
as AlgSequence
16 from AnaAlgorithm.AnaAlgorithmConfig
import AnaAlgorithmConfig, indentBy
17 from AnaAlgorithm.PythonConfig
import PythonConfig
20 """Standalone algorithm sequence
22 This is a light-weight emulation of Athena's AthSequencer class,
23 implementing a simple algorithm sequence for EventLoop jobs.
27 """Algorithm sequence constructor
30 name -- The name of the algorithm sequence (for debugging)
40 """Return the name of this sequence
42 Mainly for debugging purposes, and for when we are embedding
43 one sequence into another one.
49 """Insert one algorithm/sequence into this sequence
51 This allows us to extend existing sequences with a greater
55 index -- The index to insert the algorithm/sequence under
56 algOrSeq -- The object to insert
59 return self.
__iadd__( algOrSeq, index = index )
62 """add a copy of this config to the EventLoop job object
65 job -- The job object to add ourself to
68 alg.addSelfToJob (job)
73 """Return one algorithm/sequence from the sequence by index
75 This is to allow getting the n'th element of an algorithm sequence
76 (which itself may either be an algorithm or a sequence),
77 including the n'th element from the back of it if needed.
80 index -- The index of the algorithm/sequence to get from the
87 """Access one algorithm/sequence in this sequence, by name
89 This is to allow modifying the properties of algorithms in a
90 sequence that was set up centrally.
93 name -- The name of the algorithm/sequence to look up in the
99 if algOrSeq.name() == name:
104 raise AttributeError(
'Algorithm/sequence with name "%s" was not ' \
108 """Remove one algorithm/sequence from this sequence, by name
110 This is to allow removing algorithms (or even sequences) from this
111 sequence in case that would be needed.
114 name -- The name of the algorithm/sequence to delete from the
120 if algOrSeq.name() == name:
128 raise AttributeError(
'Algorithm/sequence with name "%s" was not ' \
132 """Create an iterator over all the algorithms of this sequence
134 This is to allow for a Python-like iteration over all algorithms
135 that are part of the sequence. This includes iterating over the
136 algorithms that may be in sub-sequences of this sequence.
143 """Add one algorithm/sequence to the sequence
145 This function is used to add one algorithm (or algorithm sequence)
146 to the sequence object, using the '+=' operator.
149 algOrSeq -- The algorithm/sequence to add to the sequence
153 if not isinstance( algOrSeq, AnaAlgorithmConfig )
and \
154 not isinstance( algOrSeq, PythonConfig )
and \
155 not isinstance( algOrSeq, AlgSequence ):
156 raise TypeError(
'The received object is not of type ' \
157 'AnaAlgorithmConfig or PythonConfig or AlgSequence' )
163 raise RuntimeError(
'Algorithm/sequence %s is already in ' \
164 'this sequence' % algOrSeq.name() )
178 """Check for equality with another object
180 The implementation of this is very simple. We only check that
181 the name of the sequences would match.
184 other -- The object to compare this one against
188 if not isinstance( other, AlgSequence ):
193 return ( self.
name() == other.name() )
196 """Check for an inequality with another object
198 This is just defined to make the '!=' operator of Python behave
199 consistently with the '==' operator for such objects.
202 other -- The object to compare this one against
204 return not self.
__eq__( other )
207 """Print the algorithm sequence in a user-friendly way
209 This function takes care of printing the full configuration of every
210 algorithm in the sequence.
213 result = AnaAlgorithmConfig._printHeader(
'AlgSequence/%s' %
217 result +=
'| %s\n' %
indentBy(
str( algOrSeq ),
'| ' )
219 result += AnaAlgorithmConfig._printFooter(
'AlgSequence/%s' %
224 """Return the size/length of the algorithm sequence
226 Just returning the number of algorithms and sequences that are in
227 this sequence. So this is not a recursive count.
235 """Iterator over a standalone algorithm sequence
237 This custom class is needed to implement a "recursive iteration", which
238 would loop over all algorithms in a sequence that itself may have
239 sub-sequences inside of it.
243 """Constructor for the algorithm sequence iterator
246 sequence -- The sequence to iterate over (recursively)
257 """Function making this iterator iterable itself
262 """Function implementing the recursive iteration over an AlgSequence
264 This is where most of the logic is. The iterator loops over the
265 elements of the AlgSequence that was given to it, one by one. When
266 it finds an element in the AlgSequence that itself is also an
267 AlgSequence, then it creates a helper iterator object that would
268 process that sub-sequence, and continue the iteration using that
271 The end result is that the iteration should loop over every
272 algorithm in the sequence and its sub-sequences.
277 raise StopIteration()
284 except StopIteration:
299 if isinstance( element, AlgSequence ):
320 self.
seq += AnaAlgorithmConfig(
'AlgType1/Algorithm1' )
321 self.
seq += AnaAlgorithmConfig(
'AlgType2/Algorithm2' )
326 self.assertEqual( self.
seq.
name(),
'TestSequence' )
327 self.assertEqual( len( self.
seq ), 2 )
332 self.assertEqual( self.
seq[ 0 ].
name(),
'Algorithm1' )
333 self.assertEqual( self.
seq[ 1 ].
name(),
'Algorithm2' )
334 with self.assertRaises( IndexError ):
341 self.assertEqual( self.
seq.Algorithm1.type(),
'AlgType1' )
342 self.assertEqual( self.
seq.Algorithm2.type(),
'AlgType2' )
343 with self.assertRaises( AttributeError ):
344 self.
seq.Algorithm3.type()
350 algNames = [ alg.name()
for alg
in self.
seq ]
351 self.assertEqual( algNames, [
'Algorithm1',
'Algorithm2' ] )
356 self.
seq.insert( 1, AnaAlgorithmConfig(
'AlgType3/Algorithm3' ) )
357 self.assertEqual( len( self.
seq ), 3 )
358 self.assertEqual( self.
seq[ 0 ].
name(),
'Algorithm1' )
359 self.assertEqual( self.
seq[ 1 ].
name(),
'Algorithm3' )
360 self.assertEqual( self.
seq[ 2 ].
name(),
'Algorithm2' )
365 del self.
seq.Algorithm1
366 self.assertEqual( len( self.
seq ), 1 )
367 self.assertEqual( self.
seq[ 0 ].
name(),
'Algorithm2' )
378 self.
seq += AnaAlgorithmConfig(
'PreSelectionAlg/PreSelection' )
380 self.
seq.MuonSequence += \
381 AnaAlgorithmConfig(
'MuonAnalysisAlg/MuonAnalysis' )
382 self.
seq.MuonSequence += \
383 AnaAlgorithmConfig(
'MuonHistoAlg/MuonHistogramming' )
386 self.
seq.JetSequence.JetPreSequence += \
387 AnaAlgorithmConfig(
'JetPreSelectorAlg/JetPreSelector' )
388 self.
seq.JetSequence.JetPreSequence += \
389 AnaAlgorithmConfig(
'JetDecoratorAlg/JetDecorator' )
390 self.
seq.JetSequence += \
391 AnaAlgorithmConfig(
'JetAnalysisAlg/JetAnalysis' )
392 self.
seq.JetSequence += \
393 AnaAlgorithmConfig(
'JetHistoAlg/JetHistogramming' )
394 self.
seq += AnaAlgorithmConfig(
'PostProcessingAlg/PostProcessing' )
399 self.assertEqual( len( self.
seq ), 4 )
404 self.assertEqual( self.
seq[ 0 ].
name(),
'PreSelection' )
405 self.assertEqual( self.
seq[ 2 ].
name(),
'JetSequence' )
406 with self.assertRaises( IndexError ):
413 self.assertEqual( self.
seq.MuonSequence.MuonAnalysis.type(),
415 self.assertEqual( self.
seq.JetSequence.JetHistogramming.type(),
417 self.assertEqual( self.
seq.JetSequence.JetPreSequence.JetDecorator.type(),
419 with self.assertRaises( AttributeError ):
420 self.
seq.MuonSequence.InvalidAlg.type()
426 algNames = [ alg.name()
for alg
in self.
seq ]
427 self.assertEqual( algNames, [
'PreSelection',
'MuonAnalysis',
428 'MuonHistogramming',
'JetPreSelector',
429 'JetDecorator',
'JetAnalysis',