ATLAS Offline Software
RoRSeqFilter.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // DecisionHandling includes
6 #include "RoRSeqFilter.h"
7 #include "AthenaKernel/Timeout.h"
10 #include "Gaudi/Property.h"
11 
22 
23 RoRSeqFilter::RoRSeqFilter( const std::string& name,
24  ISvcLocator* pSvcLocator ) :
25  ::AthReentrantAlgorithm( name, pSvcLocator )
26 {}
27 
28 
30 {
31  CHECK( not m_inputKeys.empty() );
32  CHECK( not m_outputKeys.empty() );
33 
34  CHECK( m_inputKeys.initialize() );
35  CHECK( m_outputKeys.initialize() );
36 
38 
39  // default IO mappnig nth input -> nth output
40  if ( m_ioMappingProperty.empty()) {
41  CHECK( m_inputKeys.size() == m_outputKeys.size() );
42  for ( unsigned i = 0; i < m_inputKeys.size(); ++i ) {
43  m_ioMapping.push_back( {i} );
44  }
45  ATH_MSG_DEBUG( "Default I/O collections mapping nth input -> nth output" );
46  } else {
48  ATH_MSG_DEBUG( "Custom I/O mapping used by the filter" );
49  }
50 
51  for ( size_t i = 0; i < m_ioMapping.size(); ++i ) {
52  for ( unsigned inIndex: m_ioMapping[i] ) {
53  ATH_MSG_DEBUG("Input collection: " << m_inputKeys[inIndex] );
54  }
55  ATH_MSG_DEBUG(" Routed to output collection " << m_outputKeys[i] );
56  }
57 
58  // crosscheck mapping (also the default one)
59  CHECK( m_ioMapping.size() == m_outputKeys.size() ); // all outputs will be filled
60  std::set<int> inIndices;
61  for ( auto i: m_ioMapping ) {
62  CHECK( not i.empty() ); // all outputs are connected to at least one input
63  inIndices.insert( i.begin(), i.end() );
64  }
65  CHECK( inIndices.size() == m_inputKeys.size() ); // all inputs are routed
66  for ( size_t i = 0; i < m_ioMapping.size(); ++i ) {
67  auto iset = std::set( m_ioMapping[i].begin(), m_ioMapping[i].end() );
68  for ( size_t j = i+1; j < m_ioMapping.size(); ++j ) {
69  for ( auto el: m_ioMapping[j] ) {
70  if ( iset.count( el ) != 0 ) {
71  ATH_MSG_ERROR( "The input index " << el << " directed to two outputs " << m_ioMapping[i] << " " << m_ioMapping[j] );
72  return StatusCode::FAILURE;
73  }
74  }
75  }
76  }
77 
78  if (msgLvl(MSG::DEBUG)){
79  ATH_MSG_DEBUG("Will consume implicit ReadDH:" );
80  for (auto& input: m_inputKeys){
81  ATH_MSG_DEBUG(" - "<<input.key());
82  }
83  ATH_MSG_DEBUG("Will produce WriteDH: ");
84  for (auto& output: m_outputKeys){
85  ATH_MSG_DEBUG(" - "<<output.key());
86  }
87  }
88 
89  CHECK( not m_chainsProperty.empty() );
90 
91  for ( const std::string& el: m_chainsProperty )
92  m_chains.insert( HLT::Identifier( el ).numeric() );
93 
94 
96  for ( size_t i = 0; i < m_chainsPerInputProperty.size(); ++i ) {
97  for ( const std::string& el: m_chainsPerInputProperty[i] )
98  m_chainsPerInput[i].insert( HLT::Identifier( el ).numeric() );
99  }
100 
101  if (msgLvl(MSG::DEBUG)){
102  ATH_MSG_DEBUG( "Configured to require these chains: ");
103  for ( const HLT::Identifier& id: m_chains )
104  ATH_MSG_DEBUG( " - " << id );
105  }
106 
107  if ( not m_monTool.name().empty() ) {
108  ATH_CHECK( m_monTool.retrieve() );
109  }
110 
111  return StatusCode::SUCCESS;
112 }
113 
114 
115 StatusCode RoRSeqFilter::execute( const EventContext& ctx ) const {
116  ATH_MSG_DEBUG ( "Executing " << name() << "..." );
117  if (Athena::Timeout::instance(ctx).reached()) {
118  ATH_MSG_ERROR("Timeout reached before " << name());
120  }
121  auto inputHandles = m_inputKeys.makeHandles( ctx );
122  auto outputHandles = m_outputKeys.makeHandles( ctx );
123 
124  std::vector<std::string> inputNames( {"exec", "anyvalid"} );
125  std::vector<bool> inputStats({true, false}); // position 0 for number of execs, always true, bool at position 1 is set later
126  inputNames.reserve(inputHandles.size() + 2);
127  inputStats.reserve(inputHandles.size() + 2);
128  bool validInputs = false;
129  for ( auto& inputHandle: inputHandles ) {
130  inputNames.push_back( inputHandle.name() );
131  if( inputHandle.isValid() ) {// this is because input is implicit
132  validInputs = true;
133  inputStats.push_back( true );
134  } else {
135  inputStats.push_back( false );
136  }
137  }
138  inputStats[1] = validInputs; // position 1 for number of execes with any collection valid
139  auto inputName = Monitored::Collection<std::vector<std::string>>( "name", inputNames );
140  auto inputStat = Monitored::Collection<std::vector<bool>>( "stat", inputStats );
141  Monitored::Group( m_monTool, inputStat, inputName );
142 
143  if (!validInputs) {
144  setFilterPassed(false, ctx);
145  ATH_MSG_DEBUG ( "No valid inputs found, filter failed. Return...." );
146  return StatusCode::SUCCESS;
147  }
148 
149  ATH_MSG_DEBUG ( "Running on "<< inputHandles.size() <<" input keys" );
150 
151  size_t passCounter = 0;
152 
153  for ( size_t outputIndex = 0; outputIndex < m_ioMapping.size(); ++outputIndex ) {
154  bool anyPresent = false;
155  for ( unsigned inputIndex : m_ioMapping[outputIndex] ) {
156  if( not inputHandles[inputIndex].isValid() ) {
157  ATH_MSG_DEBUG( "InputHandle "<< inputHandles[inputIndex].key() <<" not present" );
158  } else if ( inputHandles[inputIndex]->empty() ) {
159  ATH_MSG_DEBUG( "InputHandle "<< inputHandles[inputIndex].key() <<" contains all rejected decisions, skipping" );
160  } else {
161  anyPresent = true;
162  }
163  }
164  if ( anyPresent ) {
165  createAndStore(outputHandles[outputIndex]);
166  DecisionContainer* output = outputHandles[outputIndex].ptr();
167  for ( auto inputIndex : m_ioMapping[outputIndex] ) {
168  if ( inputHandles[inputIndex].isValid() and not inputHandles[inputIndex]->empty() ) {
169  ATH_MSG_DEBUG( "Checking inputHandle: "<< inputHandles[inputIndex].key() <<" has " << inputHandles[inputIndex]->size() <<" elements");
170  if ( not m_chainsPerInput.empty() ) {
171  passCounter += copyPassing( *inputHandles[inputIndex], *output, m_chainsPerInput[inputIndex], ctx );
172  } else {
173  passCounter += copyPassing( *inputHandles[inputIndex], *output, m_chains, ctx );
174  }
175  ATH_MSG_DEBUG( "Recorded output key " << m_outputKeys[ outputIndex ].key() <<" of size "<<output->size() <<" at index "<< outputIndex);
176  }
177  }
178  }
179  }
180 
181  setFilterPassed( passCounter != 0, ctx );
182  ATH_MSG_DEBUG( "Filter " << ( filterPassed(ctx) ? "passed" : "rejected" ) );
183  if ( msgLvl( MSG::DEBUG ) ){
184  for ( auto& output: outputHandles ) {
185  if( output.isValid() ) ATH_MSG_DEBUG( " "<<output.key() );
186  }
187  }
188 
189 
190  return StatusCode::SUCCESS;
191 }
192 
194  DecisionContainer& output, const std::set<HLT::Identifier>& topass,
195  const EventContext& ctx ) const {
196  size_t passCounter = 0;
197  for (const Decision* inputDecision : input) {
198 
199  ATH_MSG_DEBUG("Number of positive decisions for this input is " << decisionIDs(inputDecision).size()
200  <<". Applying filter of size " << topass.size());
201 
202  const DecisionIDContainer& intersection = passedDecisionIDs(inputDecision, topass);
203 
204  if ( not intersection.empty() ) {
205  // This sets up the 'self' link & the 'seed' link (seeds from inputDecision)
206  Decision* decisionCopy = newDecisionIn( &output, inputDecision, filterNodeName(), ctx );
207 
208  // Copy accross only the DecisionIDs which have passed through this Filter for this Decision object.
209  // WARNING: Still need to 100% confirm if the correct set to propagate forward is objDecisions or intersection.
210  // Tim M changing this from inputDecisions (all IDs) -> intersection (only passed IDs) Feb 19
211  insertDecisionIDs(intersection, decisionCopy);
212  passCounter ++;
213  if (msgLvl(MSG::DEBUG)){
214  ATH_MSG_DEBUG("Input satisfied at least one filtering chain. Chain(s) passing:");
215  for ( DecisionID id : intersection ) {
216  ATH_MSG_DEBUG( " -- " << HLT::Identifier( id ) );
217  }
218  }
219 
220  } else {
221  ATH_MSG_DEBUG("No Input decisions requested by filtering chains");
222  }
223  }
224  return passCounter;
225 }
RoRSeqFilter::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: RoRSeqFilter.h:98
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
TrigCompositeUtils::DecisionID
unsigned int DecisionID
Definition: TrigComposite_v1.h:27
TrigCompositeUtils::DecisionContainer
xAOD::TrigCompositeContainer DecisionContainer
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigCompositeContainer.h:21
TrigCompositeUtils::newDecisionIn
Decision * newDecisionIn(DecisionContainer *dc, const std::string &name)
Helper method to create a Decision object, place it in the container and return a pointer to it.
Definition: TrigCompositeUtilsRoot.cxx:46
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
RoRSeqFilter::m_outputKeys
SG::WriteHandleKeyArray< TrigCompositeUtils::DecisionContainer > m_outputKeys
Definition: RoRSeqFilter.h:67
TrigCompositeUtils::insertDecisionIDs
void insertDecisionIDs(const Decision *src, Decision *dest)
Appends the decision IDs of src to the dest decision object.
Definition: TrigCompositeUtilsRoot.cxx:80
TrigCompositeUtils::passedDecisionIDs
DecisionIDContainer passedDecisionIDs(const Decision *d, const T &required)
return DecisionIDs in Decision object that match the required ones
AthCommonMsg< Gaudi::Algorithm >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
TrigCompositeUtils::createAndStore
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
Definition: TrigCompositeUtilsRoot.cxx:30
RoRSeqFilter::m_inputKeys
SG::ReadHandleKeyArray< TrigCompositeUtils::DecisionContainer > m_inputKeys
Definition: RoRSeqFilter.h:66
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::renounceArray
void renounceArray(SG::VarHandleKeyArray &handlesArray)
remove all handles from I/O resolution
Definition: AthCommonDataStore.h:364
isValid
bool isValid(const T &p)
Definition: AtlasPID.h:214
intersection
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Definition: compareFlatTrees.cxx:25
empty
bool empty(TH1 *h)
Definition: computils.cxx:294
AthReentrantAlgorithm::filterPassed
virtual bool filterPassed(const EventContext &ctx) const
Definition: AthReentrantAlgorithm.h:135
RoRSeqFilter.h
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::inputHandles
virtual std::vector< Gaudi::DataHandle * > inputHandles() const override
Return this algorithm's input handles.
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
RoRSeqFilter::m_chainsProperty
Gaudi::Property< std::vector< std::string > > m_chainsProperty
Definition: RoRSeqFilter.h:69
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
RoRSeqFilter::initialize
virtual StatusCode initialize() override final
Setup input and output handles.
Definition: RoRSeqFilter.cxx:29
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::outputHandles
virtual std::vector< Gaudi::DataHandle * > outputHandles() const override
Return this algorithm's output handles.
lumiFormat.i
int i
Definition: lumiFormat.py:92
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
RoRSeqFilter::copyPassing
size_t copyPassing(const TrigCompositeUtils::DecisionContainer &input, TrigCompositeUtils::DecisionContainer &output, const std::set< HLT::Identifier > &topass, const EventContext &ctx) const
Applies generic filter to input container, keeping only the decision objects with at least one affirm...
Definition: RoRSeqFilter.cxx:193
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
plotIsoValidation.el
el
Definition: plotIsoValidation.py:197
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
CHECK
#define CHECK(...)
Evaluate an expression and check for errors.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:422
RoRSeqFilter::execute
virtual StatusCode execute(const EventContext &ctx) const override final
Apply this filter in-between Steps of trigger execution.
Definition: RoRSeqFilter.cxx:115
Athena::Timeout::instance
static Timeout & instance()
Get reference to Timeout singleton.
Definition: Timeout.h:64
HLT::Identifier
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:20
Monitored.h
Header file to be included by clients of the Monitored infrastructure.
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:224
merge.output
output
Definition: merge.py:17
RoRSeqFilter::m_ioMappingProperty
Gaudi::Property< std::vector< std::vector< unsigned > > > m_ioMappingProperty
It can be used to define a custom routing from input to output collections Example: [[0,...
Definition: RoRSeqFilter.h:80
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
TrigCompositeUtils::Decision
xAOD::TrigComposite Decision
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:20
RoRSeqFilter::m_ioMapping
std::vector< std::vector< unsigned > > m_ioMapping
Definition: RoRSeqFilter.h:81
Athena::Status::TIMEOUT
@ TIMEOUT
Timeout during event processing.
TrigCompositeUtils::filterNodeName
const std::string & filterNodeName()
Definition: TrigCompositeUtilsRoot.cxx:898
Timeout.h
Timeout singleton.
TrigCompositeUtils::DecisionIDContainer
std::set< DecisionID > DecisionIDContainer
Definition: TrigComposite_v1.h:28
DEBUG
#define DEBUG
Definition: page_access.h:11
TrigCompositeUtils::decisionIDs
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
Definition: TrigCompositeUtilsRoot.cxx:67
RoRSeqFilter::m_chains
std::set< HLT::Identifier > m_chains
Definition: RoRSeqFilter.h:70
RoRSeqFilter::m_chainsPerInputProperty
Gaudi::Property< std::vector< std::vector< std::string > > > m_chainsPerInputProperty
Definition: RoRSeqFilter.h:72
RoRSeqFilter::m_chainsPerInput
std::vector< std::set< HLT::Identifier > > m_chainsPerInput
Definition: RoRSeqFilter.h:73
RoRSeqFilter::RoRSeqFilter
RoRSeqFilter(const std::string &name, ISvcLocator *pSvcLocator)
Definition: RoRSeqFilter.cxx:23
AthStatusCode.h
AthReentrantAlgorithm::setFilterPassed
virtual void setFilterPassed(bool state, const EventContext &ctx) const
Definition: AthReentrantAlgorithm.h:139
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37