ATLAS Offline Software
Functions
InnerDetector/InDetMonitoring/InDetGlobalMonitoring/macros/EnhancedPrimaryVertexMonitoring/TrigD3PD/ChainGroup.cxx File Reference
#include <algorithm>
#include <cmath>
#include <TRegexp.h>
#include <TString.h>
#include "ChainGroup.h"
#include "IDataAccess.h"
#include "TrigConfigSvcD3PD.h"
Include dependency graph for InnerDetector/InDetMonitoring/InDetGlobalMonitoring/macros/EnhancedPrimaryVertexMonitoring/TrigD3PD/ChainGroup.cxx:

Go to the source code of this file.

Functions

 ClassImp (D3PD::ChainGroup) namespace D3PD
 

Function Documentation

◆ ClassImp()

ClassImp ( D3PD::ChainGroup  )

Protected constructor, to be only used by the code itself.

Parameters
triggerNamesPatterns given by the user
parentInterface to enable access to the trigger data
svcThe trigger configuration service

This function implements an "OR" of the triggers that match the selection. The function returns kTRUE if any of the matching triggers pass the selection.

If you want to mix LVL1 and HLT triggers, you can only use TrigDefs::Physics as the decision type. The function will issue warnings if you reuest special LVL1 or HLT decision types for a trigger that doesn't belong to the correct group.

Parameters
typeThe trigger decision type you're interested in
Returns
kTRUE if any of the selected triggers passed the selection, kFALSE otherwise

This function is implemented in the same way as the offline version of ChainGroup::getPrescale(...). If the chain group only holds one chain/item, then the function returns the cumulative prescale of this chain/item. (e.g. EF prescale * LVL2 prescale * LVL1 prescale)

In case there are multiple triggers defined, there are two cases. If one of the defined triggers is unprescaled (prescale = 1.0) then the chain group by definition has a prescale of 1.0. But if all of the chains/items are prescaled, we can't provide a single prescale for them. In this case the function returns 0.0.

Returns
The cumulative prescale of the triggers

This function returns the list of triggers that match a given selection. For instance to get the list of all LVL2 chains, one has to request a chain group with the pattern "L2.*".

Returns
The list of triggers matching the selection

This function makes sure that the object is aware of the configuration that was used in the current event, and is confugured appropriately.

Returns
kTRUE if the operation was successful, kFALSE otherwise

This function is used to create properly formatted names from a comma separated list of names. The list can even contain spaces.

Parameters
namesComma separated trigger names list
Returns
The trigger names split into a vector

Definition at line 20 of file InnerDetector/InDetMonitoring/InDetGlobalMonitoring/macros/EnhancedPrimaryVertexMonitoring/TrigD3PD/ChainGroup.cxx.

22  {
23 
31  ChainGroup::ChainGroup( const std::vector< std::string >& triggerNames,
33  TrigConfigSvcD3PD& svc )
34  : TNamed( "ChainGroup", "A particular chain group" ),
35  m_parent( parent ), m_configSvc( svc ), m_triggerNames( triggerNames ) {
36 
37  }
38 
52  Bool_t ChainGroup::IsPassed( TrigDefs::DecisionTypes type ) {
53 
54  //
55  // Make sure the object is up to date:
56  //
57  if( ! Update() ) {
58  Error( "IsPassed", "Trigger(s) can't be evaluated" );
59  return kFALSE;
60  }
61 
62  //
63  // Loop over the matching triggers:
64  //
65  for( size_t i = 0; i < m_existingTriggers.size(); ++i ) {
66 
67  // If this is a LVL1 item:
68  if( m_existingTriggers[ i ].find( "L1_" ) != std::string::npos ) {
69 
70  // Variables helping in looking up the correct bit in the result:
71  const Int_t word = m_existingIDs[ i ] / 32;
72  const Int_t bit = m_existingIDs[ i ] % 32;
73 
74  switch( type ) {
75 
76  case TrigDefs::Physics:
77  if( m_parent.GetDetailLevel() >= 0 ) {
78  // Return right away if the trigger fired
79  if( ( ( * m_parent.GetL1Result( Trig::IDataAccess::TAV ) )[ word ] >> bit ) & 0x1 ) {
80  return kTRUE;
81  }
82  } else {
83  Warning( "IsPassed",
84  "The requested information is not available in the input" );
85  return kFALSE;
86  }
87  break;
88  case TrigDefs::L1_TBP:
89  if( m_parent.GetDetailLevel() >= 1 ) {
90  // Return right away if the trigger fired
91  if( ( ( * m_parent.GetL1Result( Trig::IDataAccess::TBP ) )[ word ] >> bit ) & 0x1 ) {
92  return kTRUE;
93  }
94  } else {
95  Warning( "IsPassed",
96  "The requested information is not available in the input" );
97  return kFALSE;
98  }
99  break;
100  case TrigDefs::L1_TAP:
101  if( m_parent.GetDetailLevel() >= 1 ) {
102  // Return right away if the trigger fired
103  if( ( ( * m_parent.GetL1Result( Trig::IDataAccess::TAP ) )[ word ] >> bit ) & 0x1 ) {
104  return kTRUE;
105  }
106  } else {
107  Warning( "IsPassed",
108  "The requested information is not available in the input" );
109  return kFALSE;
110  }
111  break;
112  default:
113  Warning( "IsPassed", "Decision type not recognised for LVL1 items!" );
114  break;
115  }
116 
117  }
118  // If this is a LVL2 chain:
119  else if( m_existingTriggers[ i ].find( "L2_" ) != std::string::npos ) {
120 
121  std::vector< short >::const_iterator begin, end;
122  switch( type ) {
123 
124  case TrigDefs::Physics:
125  if( m_parent.GetDetailLevel() >= 0 ) {
126  begin = m_parent.GetL2Result( Trig::IDataAccess::Physics )->begin();
127  end = m_parent.GetL2Result( Trig::IDataAccess::Physics )->end();
128  } else {
129  Warning( "IsPassed",
130  "The requested information is not available in the input" );
131  return kFALSE;
132  }
133  break;
134  case TrigDefs::requireDecision:
135  if( m_parent.GetDetailLevel() >= 1 ) {
136  begin = m_parent.GetL2Result( Trig::IDataAccess::Raw )->begin();
137  end = m_parent.GetL2Result( Trig::IDataAccess::Raw )->end();
138  } else {
139  Warning( "IsPassed",
140  "The requested information is not available in the input" );
141  return kFALSE;
142  }
143  break;
145  if( m_parent.GetDetailLevel() >= 2 ) {
146  begin = m_parent.GetL2Result( Trig::IDataAccess::Resurrected )->begin();
147  end = m_parent.GetL2Result( Trig::IDataAccess::Resurrected )->end();
148  } else {
149  Warning( "IsPassed",
150  "The requested information is not available in the input" );
151  return kFALSE;
152  }
153  break;
154  case TrigDefs::passedThrough:
155  if( m_parent.GetDetailLevel() >= 2 ) {
156  begin = m_parent.GetL2Result( Trig::IDataAccess::PassedThrough )->begin();
157  end = m_parent.GetL2Result( Trig::IDataAccess::PassedThrough )->end();
158  } else {
159  Warning( "IsPassed",
160  "The requested information is not available in the input" );
161  return kFALSE;
162  }
163  break;
164  default:
165  Warning( "IsPassed", "Decision type not recognised for HLT chains!" );
166  break;
167  }
168 
169  if( std::find( begin, end, m_existingIDs[ i ] ) != end ) {
170  return kTRUE; // Return right away if the trigger fired
171  }
172 
173  }
174  // If this is an EF chain:
175  else if( m_existingTriggers[ i ].find( "EF_" ) != std::string::npos ) {
176 
177  std::vector< short >::const_iterator begin, end;
178  switch( type ) {
179 
180  case TrigDefs::Physics:
181  if( m_parent.GetDetailLevel() >= 0 ) {
182  begin = m_parent.GetEFResult( Trig::IDataAccess::Physics )->begin();
183  end = m_parent.GetEFResult( Trig::IDataAccess::Physics )->end();
184  } else {
185  Warning( "IsPassed",
186  "The requested information is not available in the input" );
187  return kFALSE;
188  }
189  break;
190  case TrigDefs::requireDecision:
191  if( m_parent.GetDetailLevel() >= 1 ) {
192  begin = m_parent.GetEFResult( Trig::IDataAccess::Raw )->begin();
193  end = m_parent.GetEFResult( Trig::IDataAccess::Raw )->end();
194  } else {
195  Warning( "IsPassed",
196  "The requested information is not available in the input" );
197  return kFALSE;
198  }
199  break;
201  if( m_parent.GetDetailLevel() >= 2 ) {
202  begin = m_parent.GetEFResult( Trig::IDataAccess::Resurrected )->begin();
203  end = m_parent.GetEFResult( Trig::IDataAccess::Resurrected )->end();
204  } else {
205  Warning( "IsPassed",
206  "The requested information is not available in the input" );
207  return kFALSE;
208  }
209  break;
210  case TrigDefs::passedThrough:
211  if( m_parent.GetDetailLevel() >= 2 ) {
212  begin = m_parent.GetEFResult( Trig::IDataAccess::PassedThrough )->begin();
213  end = m_parent.GetEFResult( Trig::IDataAccess::PassedThrough )->end();
214  } else {
215  Warning( "IsPassed",
216  "The requested information is not available in the input" );
217  return kFALSE;
218  }
219  break;
220  default:
221  Warning( "IsPassed", "Decision type not recognised for HLT chains!" );
222  break;
223  }
224 
225  if( std::find( begin, end, m_existingIDs[ i ] ) != end ) {
226  return kTRUE; // Return right away if the trigger fired
227  }
228 
229  } else {
230  Fatal( "IsPassed", "Something seems to be wrong with this function!" );
231  return kFALSE;
232  }
233 
234  }
235 
236  return kFALSE; // If none of the matching triggers fired in the event
237  }
238 
253  Float_t ChainGroup::GetPrescale() {
254 
255  //
256  // Make sure the object is up to date:
257  //
258  if( ! Update() ) {
259  Error( "IsPassed", "Trigger(s) can't be evaluated" );
260  return 0.0;
261  }
262 
263  // We handle the case when there's only one trigger in the chain group
264  // in a distinct way:
265  const Bool_t singleTrigger = ( m_existingTriggers.size() == 1 );
266 
267  //
268  // Loop over all the matching triggers:
269  //
270  std::vector< std::string >::const_iterator name_itr = m_existingTriggers.begin();
271  std::vector< std::string >::const_iterator name_end = m_existingTriggers.end();
272  for( ; name_itr != name_end; ++name_itr ) {
273 
274  //
275  // Calculate the overall prescale of the chain, or just request the
276  // prescale of LVL1 items:
277  //
278  Float_t chainPrescale = 1.0;
279  if( name_itr->find( "EF_" ) != name_itr->npos ) {
280 
281  chainPrescale = m_configSvc.GetPrescale( *name_itr );
282  const std::string& l2name = m_configSvc.GetLowerChainName( *name_itr );
283  chainPrescale *= m_configSvc.GetPrescale( l2name );
284  const std::string& l1name = m_configSvc.GetLowerChainName( l2name );
285  chainPrescale *= m_configSvc.GetPrescale( l1name );
286 
287  } else if( name_itr->find( "L2_" ) != name_itr->npos ) {
288 
289  chainPrescale = m_configSvc.GetPrescale( *name_itr );
290  const std::string& l1name = m_configSvc.GetLowerChainName( *name_itr );
291  chainPrescale *= m_configSvc.GetPrescale( l1name );
292 
293  } else if( name_itr->find( "L1_" ) != name_itr->npos ) {
294 
295  chainPrescale = m_configSvc.GetPrescale( *name_itr );
296 
297  } else {
298  Fatal( "GetPrescale", "Something seems to be wrong with this function!" );
299  return 0.0;
300  }
301 
302  // If we just have this one trigger in the group, just return now:
303  if( singleTrigger ) return chainPrescale;
304 
305  // If we have multiple triggers, but one of them is unprescaled, then the
306  // whole group is labelled as unprescaled as well:
307  const Bool_t unprescaled = ( std::abs( chainPrescale - 1.0 ) < 1e-5 );
308  if( unprescaled ) return 1.0;
309 
310  }
311 
312  // If we have multiple triggers, and all are prescaled:
313  return 0.0;
314  }
315 
323  const std::vector< std::string >& ChainGroup::GetListOfTriggers() {
324 
325  //
326  // Make sure the object is up to date:
327  //
328  if( ! Update() ) {
329  Error( "IsPassed", "Trigger(s) can't be evaluated" );
330  m_existingTriggers.clear();
331  }
332 
333  return m_existingTriggers;
334  }
335 
343  Bool_t ChainGroup::Update() {
344 
345  // Return right away if we're already configured correctly:
346  if( m_smk == m_parent.GetSMK() ) return kTRUE;
347 
348  // Load the configuration, and remember that the object is initialized with this
349  // configuration:
350  m_configSvc.Load( m_parent.GetSMK(), m_parent.GetL1PSK(), m_parent.GetHLTPSK() );
351  m_smk = m_parent.GetSMK();
352 
353  // Clear the cache variables:
354  m_existingTriggers.clear();
355  m_existingIDs.clear();
356 
357  // Loop over the provided trigger names, and expand them in case they contain lists
358  // or wildcards:
359  std::vector< std::string >::const_iterator name_itr = m_triggerNames.begin();
360  std::vector< std::string >::const_iterator name_end = m_triggerNames.end();
361  for( ; name_itr != name_end; ++name_itr ) {
362 
363  // It's also possible to specify triggers like "L1_MU6,L1_EM5". In this case
364  // the code has to split up these strings into separate trigger names.
365  std::vector< std::string > split_names = ToVector( *name_itr );
366  std::vector< std::string >::const_iterator splitname_itr = split_names.begin();
367  std::vector< std::string >::const_iterator splitname_end = split_names.end();
368  for( ; splitname_itr != splitname_end; ++splitname_itr ) {
369 
370  // Use a TRegexp object only if it's needed:
371  TRegexp re( *splitname_itr );
372  Ssiz_t len = 0;
373  const Bool_t isWildcarded = ( ( splitname_itr->find( '^' ) != splitname_itr->npos ) ||
374  ( splitname_itr->find( '$' ) != splitname_itr->npos ) ||
375  ( splitname_itr->find( '.' ) != splitname_itr->npos ) ||
376  ( splitname_itr->find( '[' ) != splitname_itr->npos ) ||
377  ( splitname_itr->find( ']' ) != splitname_itr->npos ) ||
378  ( splitname_itr->find( '*' ) != splitname_itr->npos ) ||
379  ( splitname_itr->find( '+' ) != splitname_itr->npos ) ||
380  ( splitname_itr->find( '?' ) != splitname_itr->npos ) );
381 
382  // Find out which LVL1 items match the selection:
383  std::vector< std::string >::const_iterator trigger_itr =
384  m_configSvc.GetLVL1Items().begin();
385  std::vector< std::string >::const_iterator trigger_end =
386  m_configSvc.GetLVL1Items().end();
387  for( ; trigger_itr != trigger_end; ++trigger_itr ) {
388  if( isWildcarded ) {
389  if( re.Index( *trigger_itr, &len ) != kNPOS ) {
390  m_existingTriggers.push_back( *trigger_itr );
391  m_existingIDs.push_back( m_configSvc.GetCTPId( *trigger_itr ) );
392  }
393  } else {
394  if( *splitname_itr == *trigger_itr ) {
395  m_existingTriggers.push_back( *trigger_itr );
396  m_existingIDs.push_back( m_configSvc.GetCTPId( *trigger_itr ) );
397  }
398  }
399  }
400 
401  // Find out which HLT chains match the selection:
402  trigger_itr = m_configSvc.GetHLTChains().begin();
403  trigger_end = m_configSvc.GetHLTChains().end();
404  for( ; trigger_itr != trigger_end; ++trigger_itr ) {
405  if( isWildcarded ) {
406  if( re.Index( *trigger_itr, &len ) != kNPOS ) {
407  m_existingTriggers.push_back( *trigger_itr );
408  m_existingIDs.push_back( m_configSvc.GetChainId( *trigger_itr ) );
409  }
410  } else {
411  if( *splitname_itr == *trigger_itr ) {
412  m_existingTriggers.push_back( *trigger_itr );
413  m_existingIDs.push_back( m_configSvc.GetChainId( *trigger_itr ) );
414  }
415  }
416  }
417  }
418  }
419 
420  // Do a final sanity check:
421  if( m_existingTriggers.size() != m_existingIDs.size() ) {
422  Fatal( "Update", "There is a serious problem in the code!" );
423  return kFALSE;
424  }
425 
426  return kTRUE; // The update was successful
427  }
428 
436  std::vector< std::string > ChainGroup::ToVector( const std::string& names ) {
437 
438  // First let's erase all whitespaces:
439  std::string local_names( names );
440  std::string::size_type pos;
441  while( ( pos = local_names.find_first_of( ' ' ) ) != local_names.npos ) {
442  local_names.erase( pos, 1 );
443  }
444 
445  // Now let's split it up:
446  std::vector< std::string > result;
447  std::string::size_type old_pos = 0;
448  while( ( pos = local_names.find( ',', old_pos ) ) != local_names.npos ) {
449  result.push_back( local_names.substr( old_pos, pos - old_pos ) );
450  old_pos = pos + 1;
451  }
452  if( old_pos < local_names.size() ) {
453  result.push_back( local_names.substr( old_pos, local_names.size() - old_pos ) );
454  }
455 
456  return result;
457  }
458 
459 } // namespace D3PD
runTriggerAPIExample.unprescaled
unprescaled
Definition: runTriggerAPIExample.py:15
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
get_generator_info.result
result
Definition: get_generator_info.py:21
D3PD::TrigDefs::L1_TAP
@ L1_TAP
LVL1 Trigger After Prescale decision.
Definition: InnerDetector/InDetMonitoring/InDetGlobalMonitoring/macros/EnhancedPrimaryVertexMonitoring/TrigD3PD/Conditions.h:93
ToVector
std::vector< T > ToVector(const TrigConf::DataStructure &ds, const std::string &child)
Helper function ptree key->[] to std::vector<T>
Definition: JsonFileWriterHLT.cxx:23
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
D3PD::TrigDefs::DecisionTypes
DecisionTypes
Trigger decision types available from the D3PDs.
Definition: InnerDetector/InDetMonitoring/InDetGlobalMonitoring/macros/EnhancedPrimaryVertexMonitoring/TrigD3PD/Conditions.h:39
PlotCalibFromCool.begin
begin
Definition: PlotCalibFromCool.py:94
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
lumiFormat.i
int i
Definition: lumiFormat.py:92
python.subdetectors.mmg.names
names
Definition: mmg.py:8
test_pyathena.parent
parent
Definition: test_pyathena.py:15
Handler::svc
AthROOTErrorHandlerSvc * svc
Definition: AthROOTErrorHandlerSvc.cxx:10
D3PD::TrigDefs::allowResurrected
@ allowResurrected
The decision while allowing the chain to be resurrected.
Definition: InnerDetector/InDetMonitoring/InDetGlobalMonitoring/macros/EnhancedPrimaryVertexMonitoring/TrigD3PD/Conditions.h:67
ROOT::Shadow::D3PD::Trig::IDataAccess
::D3PD::Trig::IDataAccess IDataAccess
Definition: TriggerD3PDHelpers_Dict.cxx:43
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
re
const boost::regex re(r_e)
ZDCMsg::Fatal
@ Fatal
Definition: ZDCMsg.h:23
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
D3PD::TrigDefs::L1_TBP
@ L1_TBP
LVL1 Trigger Before Prescale decision.
Definition: InnerDetector/InDetMonitoring/InDetGlobalMonitoring/macros/EnhancedPrimaryVertexMonitoring/TrigD3PD/Conditions.h:84