ATLAS Offline Software
PrescalingTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 #include "PrescalingTool.h"
5 
8 
9 #include "GaudiKernel/IToolSvc.h"
10 #include "CLHEP/Random/RandomEngine.h"
11 #include "CLHEP/Random/Ranlux64Engine.h"
12 
13 
14 const std::function< CLHEP::HepRandomEngine*(void) > PSTRanluxFactory = []()->CLHEP::HepRandomEngine*{
15  return new CLHEP::Ranlux64Engine();
16 };
17 
18 
20  const std::string& name,
21  const IInterface* parent ) :
22  base_class(type, name, parent),
23  m_RNGEngines( PSTRanluxFactory, SG::getNSlots() ) {}
24 
25 
30 
31  if ( !m_monTool.empty() ) {
32  ATH_CHECK(m_monTool.retrieve());
33  }
34 
35  if (m_keepUnknownChains.value()) {
36  ATH_MSG_WARNING(m_keepUnknownChains.name() << " is set to True. "
37  << "This is OK for testing but do not use this in production");
38  }
39  m_prescaleForUnknownChain = { m_keepUnknownChains.value(), (m_keepUnknownChains.value() ? 1.0 : -1.0) };
40  m_costChainID = HLT::Identifier("HLT_noalg_CostMonDS_L1All");
41  return StatusCode::SUCCESS;
42 }
43 
44 
46 
47  // Cleanup in case there was a stop/start transition
48  m_CPSGroups.clear();
49  m_nonCPSChains.clear();
50 
52  ATH_CHECK( hltMenuHandle.isValid() );
53 
54  std::map<std::string, std::set<std::string>> l1SeedsCheckForCPS;
55  for ( const TrigConf::Chain& chain: *hltMenuHandle ) {
56  HLT::Identifier chainID{ chain.name() };
57  int isCPS = 0;
58  for ( const auto& group: chain.groups() ) {
59  if ( group.find("CPS") != std::string::npos) {
60  m_CPSGroups[group].push_back( chainID );
61  l1SeedsCheckForCPS[group].insert(chain.l1item());
62  isCPS++;
63  }
64  }
65  if ( isCPS ==0 ) {
66  m_nonCPSChains.insert( chainID );
67  }
68  if ( isCPS > 1 ) {
69  ATH_MSG_ERROR("Chain " << chainID << " belongs to more than one CPS groups");
70  return StatusCode::FAILURE;
71  }
72  }
73 
74  for ( auto [group, chains]: m_CPSGroups ) {
75  if ( chains.size() == 1 ) {
76  ATH_MSG_ERROR("Only one chain " << chains.front() << " in CPS group " << group << " that makes no sense");
77  return StatusCode::FAILURE;
78  }
79  }
80 
81  for ( auto [group, l1SeedsSet]: l1SeedsCheckForCPS) {
82  if ( l1SeedsSet.size() != 1 ) {
83  ATH_MSG_ERROR("Chains in CPS group " << group << " have several different L1 seeds "
84  << std::vector<std::string>(l1SeedsSet.begin(), l1SeedsSet.end()));
85  return StatusCode::FAILURE;
86  }
87  }
88 
89  return StatusCode::SUCCESS;
90 }
91 
92 
93 StatusCode PrescalingTool::prescaleChains( const EventContext& ctx,
94  const HLT::IDVec& initiallyActive,
95  HLT::IDVec& remainActive,
96  bool forExpressStream) const {
97  if ( initiallyActive.empty() ) {
98  return StatusCode::SUCCESS;
99  }
100 
101  // clear the output just in case
102  remainActive.clear();
103 
104  if ( m_hltPrescaleSetInputKey.key().empty() ) {
105  // if no prescaling key is configured, treat all prescales according to the property KeepUnknownChains
106  if( m_keepUnknownChains ) {
107  remainActive.reserve( initiallyActive.size() );
108  for( const auto & ch : initiallyActive ) {
109  remainActive.push_back(ch);
110  }
111  }
112  return StatusCode::SUCCESS;
113  }
114 
116  ATH_CHECK(hltPrescaleSet.isValid());
117 
118  // access to psk
119  ATH_MSG_DEBUG("Using HLT PSK " << hltPrescaleSet->psk());
120  auto mon_lb = Monitored::Scalar<int>("LB", [&](){ return ctx.eventID().lumi_block(); });
121  auto mon_psk = Monitored::Scalar<std::string>("HLTPSK", [&](){ return std::to_string(hltPrescaleSet->psk()); });
122  auto mon = Monitored::Group(m_monTool, mon_lb, mon_psk);
123 
124  // prepare the result
125  remainActive.reserve( initiallyActive.size() );
126 
127  // create the seed from the event time
134  auto eventInfoHandle = SG::makeHandle( m_eventInfoKey, ctx );
135  CHECK( eventInfoHandle.isValid() );
136  size_t seed = eventInfoHandle->timeStamp() ^ eventInfoHandle->timeStampNSOffset();
137 
138  CLHEP::HepRandomEngine* engine = m_RNGEngines.getEngine( ctx );
139  engine->setSeed( seed, 0 );
140 
141  auto getPrescale = [&](const HLT::Identifier& ch) -> const TrigConf::HLTPrescalesSet::HLTPrescale& {
142  try {
143  if (forExpressStream) {
144  return hltPrescaleSet->prescale_express( ch.numeric() );
145  } else {
146  return hltPrescaleSet->prescale( ch.numeric() );
147  }
148  } catch(const std::out_of_range & ex) {
149  // if chain with that name is not found in the prescale set
150  if (m_keepUnknownChains.value()) {
151  ATH_MSG_DEBUG("No prescale value for chain " << ch << ", keeping it because "
152  << m_keepUnknownChains.name() << "=" << m_keepUnknownChains.value());
153  } else {
154  ATH_MSG_ERROR("No prescale value for chain " << ch);
155  }
156  }
158  };
159 
160  auto decisionPerChain = [&](const HLT::Identifier& ch, double prescaleValue ) -> bool {
161  auto flat = engine->flat();
162  if(ch == m_costChainID) { // this is to explicitly monitor the cost chain
163  auto mon_rndm = Monitored::Scalar<double>("Random", flat);
164  Monitored::Group(m_monTool, mon_rndm);
165  }
166  return flat < 1./ prescaleValue;
167  };
168 
169  struct ChainAndPrescale {
172  double relativePrescale{};
173  };
174 
175  for ( auto [groupName, chainIDs]: m_CPSGroups) {
176  // check if this group is seeded
177  // only need to find one CPS chain if initiallyActive is L1seeded HLT id's
178  if ( forExpressStream || std::find(initiallyActive.begin(), initiallyActive.end(), chainIDs.front()) != initiallyActive.end() ) {
179  std::vector<ChainAndPrescale> psValueSorted;
180  for ( const HLT::Identifier& ch: chainIDs ) {
181  // in express stream initiallyActive are HLT accept id's, but chainIDs contain all chains in the group
182  // regardless of HLT accept; skip the HLT reject id's to ensure remainActive is a subset of initiallyActive
183  if ( forExpressStream && std::find(initiallyActive.begin(), initiallyActive.end(), ch) == initiallyActive.end() ) {
184  continue;
185  }
186  auto ps = getPrescale(ch);
187  if ( ps.enabled ) // exclude prescaled out chains
188  psValueSorted.emplace_back( ChainAndPrescale({ch, ps}) );
189  }
190  if ( psValueSorted.empty() ) { // sometimes all chains may be presscaled out/disabled
191  continue;
192  }
193  std::sort(psValueSorted.begin(), psValueSorted.end(), [](const ChainAndPrescale& a, const ChainAndPrescale& b){
194  return a.ps.prescale < b.ps.prescale;
195  });
196  // setup relative prescales
197  // the first chain (with the lowest PS is relative w.r.t the all events)
198  psValueSorted.front().relativePrescale = psValueSorted.front().ps.prescale;
199  if ( psValueSorted.size() > 1 ) {
200  for ( auto i = psValueSorted.begin()+1; i < psValueSorted.end(); ++i ) {
201  i->relativePrescale = i->ps.prescale / (i-1)->ps.prescale ;
202  }
203  }
204  if (msgLvl(MSG::DEBUG)) {
205  ATH_MSG_DEBUG("Chains in CPS group '"<< groupName <<"' sorted by PS : ");
206  for ( const ChainAndPrescale& ch: psValueSorted ) {
207  ATH_MSG_DEBUG(" " << ch.id << " " << (ch.ps.enabled ?
208  "prescale relative to the above " + std::to_string(ch.relativePrescale) :
209  "disabled"));
210  }
211  }
212  // do actual prescaling
213  for ( const ChainAndPrescale& ch: psValueSorted ) {
214  const bool decision = decisionPerChain(ch.id, ch.relativePrescale);
215  if ( not decision ) {break;}
216  remainActive.push_back( ch.id );
217  }
218  }
219  }
220 
221  // go through all active chains that are not in CPS groups
222  for ( const HLT::Identifier& ch: m_nonCPSChains ) {
223  if ( std::find( initiallyActive.begin(), initiallyActive.end(), ch ) != initiallyActive.end() ) {
224  auto prescale = getPrescale(ch);
225  if ( prescale.enabled ) {
226  const bool decision = decisionPerChain(ch, prescale.prescale);
227  if ( decision ) {
228  remainActive.push_back( ch );
229  }
230  ATH_MSG_DEBUG("Prescaling decision for chain " << ch << " " << decision);
231  } else {
232  ATH_MSG_DEBUG("Chain " << ch << " is disabled, won't keep" );
233  }
234  }
235  }
236 
237  return StatusCode::SUCCESS;
238 }
TrigConf::HLTPrescalesSet::HLTPrescale::prescale
double prescale
Definition: HLTPrescalesSet.h:24
TrigConf::HLTPrescalesSet::HLTPrescale
Definition: HLTPrescalesSet.h:22
PrescalingTool::initialize
virtual StatusCode initialize() override
Definition: PrescalingTool.cxx:26
sendEI_SPB.ch
ch
Definition: sendEI_SPB.py:35
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
runLayerRecalibration.chain
chain
Definition: runLayerRecalibration.py:175
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
RunTileMonitoring.groupName
groupName
Definition: RunTileMonitoring.py:158
PrescalingTool::prescaleChains
virtual StatusCode prescaleChains(const EventContext &ctx, const HLT::IDVec &initiallyActive, HLT::IDVec &remainActive, bool forExpressStream=false) const override
The method to prescale chains.
Definition: PrescalingTool.cxx:93
PrescalingTool::m_RNGEngines
ATHRNG::RNGWrapper m_RNGEngines
Random engine for calculating prescales.
Definition: PrescalingTool.h:77
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
PrescalingTool::m_costChainID
HLT::Identifier m_costChainID
Definition: PrescalingTool.h:84
PrescalingTool.h
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
HLT::IDVec
std::vector< HLT::Identifier > IDVec
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:62
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
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
PrescalingTool::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: PrescalingTool.h:73
PrescalingTool::m_prescaleForUnknownChain
TrigConf::HLTPrescalesSet::HLTPrescale m_prescaleForUnknownChain
Definition: PrescalingTool.h:83
PSTRanluxFactory
const std::function< CLHEP::HepRandomEngine *(void) > PSTRanluxFactory
Definition: PrescalingTool.cxx:14
test_pyathena.parent
parent
Definition: test_pyathena.py:15
PrescalingTool::m_eventInfoKey
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
Definition: PrescalingTool.h:67
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
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
PrescalingTool::m_hltPrescaleSetInputKey
SG::ReadCondHandleKey< TrigConf::HLTPrescalesSet > m_hltPrescaleSetInputKey
Definition: PrescalingTool.h:61
HLT::Identifier
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:20
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
PrescalingTool::PrescalingTool
PrescalingTool()=delete
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:227
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
ATHRNG::RNGWrapper::getEngine
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition: RNGWrapper.h:134
EventInfo.h
python.copyTCTOutput.chains
chains
Definition: copyTCTOutput.py:81
a
TList * a
Definition: liststreamerinfos.cxx:10
CaloLCW_tf.group
group
Definition: CaloLCW_tf.py:28
PrescalingTool::m_keepUnknownChains
Gaudi::Property< bool > m_keepUnknownChains
Definition: PrescalingTool.h:70
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
SG::getNSlots
size_t getNSlots()
Return the number of event slots.
Definition: SlotSpecificObj.cxx:64
PrescalingTool::m_nonCPSChains
ChainSet m_nonCPSChains
Definition: PrescalingTool.h:80
DEBUG
#define DEBUG
Definition: page_access.h:11
plotBeamSpotMon.mon
mon
Definition: plotBeamSpotMon.py:67
SlotSpecificObj.h
Maintain a set of objects, one per slot.
PrescalingTool::start
virtual StatusCode start() override
Definition: PrescalingTool.cxx:45
PrescalingTool::m_HLTMenuKey
SG::ReadHandleKey< TrigConf::HLTMenu > m_HLTMenuKey
Definition: PrescalingTool.h:64
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
PrescalingTool::m_CPSGroups
std::map< std::string, HLT::IDVec > m_CPSGroups
Definition: PrescalingTool.h:81
TrigConf::Chain
HLT chain configuration.
Definition: TrigConfData/TrigConfData/HLTChain.h:18