diff --git a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/AsgAnalysisAlgorithms/AsgLeptonTrackSelectionAlg.h b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/AsgAnalysisAlgorithms/AsgLeptonTrackSelectionAlg.h index 7bdf763e711ccaf9f2644d4695f88370f44af9e0..e2730b1957b0d74a209c21f0f011adcc8d7cdc29 100644 --- a/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/AsgAnalysisAlgorithms/AsgLeptonTrackSelectionAlg.h +++ b/PhysicsAnalysis/Algorithms/AsgAnalysisAlgorithms/AsgAnalysisAlgorithms/AsgLeptonTrackSelectionAlg.h @@ -56,15 +56,7 @@ namespace CP std::string m_primaryVertices {"PrimaryVertices"}; /// \} - - /// \brief the smearing tool cast to an ISystematicsTool - /// - /// Normally selection tools don't have systematics, but I believe - /// I have seen one or two with systematics, so I added that - /// possibility in. - private: - ISystematicsTool *m_systematicsTool {nullptr}; /// \brief the systematics list we run private: diff --git a/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py b/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py index 329b2273b5bb6d3ec8a607ef2d050fbc5c541972..231fa9c5aaa9e53910b3fbf20e78e491254f3279 100644 --- a/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py +++ b/PhysicsAnalysis/D3PDTools/AnaAlgorithm/python/AnaAlgSequence.py @@ -37,9 +37,32 @@ class AnaAlgSequence( AlgSequence ): self._inputPropNames = [] self._outputPropNames = [] self._affectingSystematics = [] + self._outputAffectingSystematics = None return + def affectingSystematics( self, label = "default" ): + """Get the systematic variations for (one of) the output container(s) + + In order to more easily chain together analysis algorithm sequences, + where one sequence's output would be used as the input for another one, + this function can be used to get the systematic variation regular + expression that should be fed to the sequence takig the output of this + one as input. + + Keyword arguments: + label -- The output container label, for sequences with multiple + outputs + """ + + # A security check: + if not self._outputAffectingSystematics: + raise RuntimeError( 'You have to call configure(...) before calling ' + 'affectingSystematics(...)' ) + + # Return the requested value: + return self._outputAffectingSystematics[ label ] + def configure( self, inputName, outputName, affectingSystematics = None, hiddenLayerPrefix = "" ): """Perform a post-configuration on the analysis algorithm sequence @@ -242,6 +265,9 @@ class AnaAlgSequence( AlgSequence ): pass + # Store the affecting systematics for further queries: + self._outputAffectingSystematics = affectingSystematics + return def append( self, alg, inputPropName, outputPropName = None, @@ -385,12 +411,14 @@ class AnaAlgSequence( AlgSequence ): sequence """ - # Look up the algorithm by index: + # Figure out the algorithm's index: algIndex = -1 - for index in xrange( len( self ) ): - if self[ index ].name() == name: + index = 0 + for alg in self: + if alg.name() == name: algIndex = index break + index += 1 pass # Check if we were successful: @@ -458,6 +486,20 @@ class TestAnaAlgSeqSingleContainer( unittest.TestCase ): self.assertEqual( self.seq.Efficiency.systematicsRegex, '(^EG_.*)' ) return + ## Test that the correct value is returned for the users for the affecting + ## systematics. + def test_affectingSystematics( self ): + self.assertEqual( self.seq.affectingSystematics(), + '(^$)|(^EL_.*)|(^EG_.*)' ) + with self.assertRaises( KeyError ): + self.seq.affectingSystematics( 'invalidLabel' ) + pass + emptySeq = AnaAlgSequence( 'EmptySequence' ) + with self.assertRaises( RuntimeError ): + emptySeq.affectingSystematics() + pass + return + pass ## Test case for a sequence receiving multiple containers, and producing just @@ -521,6 +563,13 @@ class TestAnaAlgSeqMultiInputContainer( unittest.TestCase ): '(^$)|(^MU_.*)|(^EL_.*)|(^EG_.*)' ) return + ## Test that the correct value is returned for the users for the affecting + ## systematics. + def test_affectingSystematics( self ): + self.assertEqual( self.seq.affectingSystematics(), + '(^$)|(^MU_.*)|(^EL_.*)|(^EG_.*)' ) + return + ## Test case for a sequence starting from a single container, producing ## multiple ones. class TestAnaAlgSeqMultiOutputContainer( unittest.TestCase ): @@ -570,6 +619,15 @@ class TestAnaAlgSeqMultiOutputContainer( unittest.TestCase ): '(^$)|(^EL_.*)|(^BAR_.*)' ) return + ## Test that the correct value is returned for the users for the affecting + ## systematics. + def test_affectingSystematics( self ): + self.assertEqual( self.seq.affectingSystematics( 'goodObjects' ), + '(^$)|(^EL_.*)|(^FOO_.*)' ) + self.assertEqual( self.seq.affectingSystematics( 'badObjects' ), + '(^$)|(^EL_.*)|(^BAR_.*)' ) + return + ## Test case for a sequence starting from multiple containers, and producing ## multiple new ones. class TestAnaAlgSeqMultiInputOutputContainer( unittest.TestCase ): @@ -617,3 +675,12 @@ class TestAnaAlgSeqMultiInputOutputContainer( unittest.TestCase ): '(^$)|(^EL_.*)' ) self.assertEqual( self.seq.OverlapRemoval.muonsRegex, '(^$)|(^MU_.*)' ) return + + ## Test that the correct value is returned for the users for the affecting + ## systematics. + def test_affectingSystematics( self ): + self.assertEqual( self.seq.affectingSystematics( 'electrons' ), + '(^$)|(^EL_.*)|(^MU_.*)' ) + self.assertEqual( self.seq.affectingSystematics( 'muons' ), + '(^$)|(^MU_.*)|(^EL_.*)' ) + return