ATLAS Offline Software
DecisionSummaryMakerAlg.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
7 #include "CxxUtils/phihelper.h"
8 
9 #include <algorithm>
10 #include <sstream>
11 #include <unordered_set>
12 
13 namespace {
14  const std::string s_expressStreamName{"express"};
15 }
16 
17 DecisionSummaryMakerAlg::DecisionSummaryMakerAlg(const std::string& name, ISvcLocator* pSvcLocator)
18  : AthReentrantAlgorithm(name, pSvcLocator) {}
19 
22  ATH_CHECK( m_finalDecisionKeys.initialize() );
23  ATH_CHECK( m_summaryKey.initialize() );
25  ATH_CHECK( m_hltSeedingSummaryKey.initialize() );
27 
28  for ( auto& [chain, collections]: m_lastStepForChain ) {
29  for ( auto& collection: collections ) {
30  m_collectionFilter[ collection ].insert( HLT::Identifier( chain ).numeric() );
31  ATH_MSG_DEBUG( "Final decision of the chain " << chain << " will be read from " << collection );
32  }
33  }
34 
35  ATH_CHECK( m_prescaler.retrieve() );
36  if (!m_monTool.empty()) {
37  ATH_CHECK(m_monTool.retrieve());
38  }
39 
40  return StatusCode::SUCCESS;
41 }
42 
45  ATH_CHECK(hltMenu.isValid());
46  m_chainToStreamsMap.clear();
47  // Fill the map of Chain ID -> stream names, omitting express which is treated separately due to express prescaling
48  for (const TrigConf::Chain& chain : *hltMenu) {
49  std::vector<std::string> streams = chain.streams();
50  streams.erase(std::remove(streams.begin(),streams.end(),s_expressStreamName), streams.end());
51  m_chainToStreamsMap.insert({HLT::Identifier(chain.name()).numeric(),std::move(streams)});
52  }
53 
54  return StatusCode::SUCCESS;
55 }
56 
58  return StatusCode::SUCCESS;
59 }
60 
61 StatusCode DecisionSummaryMakerAlg::execute(const EventContext& context) const {
62 
63  using namespace TrigCompositeUtils;
64 
66  auto container = outputHandle.ptr();
67 
68  Decision* passRawOutput = newDecisionIn( container, summaryPassNodeName() );
69  Decision* passExpressOutput = newDecisionIn( container, summaryPassExpressNodeName() );
70  Decision* prescaledOutput = newDecisionIn( container, summaryPrescaledNodeName() );
71 
72  DecisionIDContainer allPassingFinalIDs;
73 
74  // Collate final decisions into the passRawOutput object
75  for ( auto& key: m_finalDecisionKeys ) {
76  auto handle{ SG::makeHandle(key, context) };
77  if ( not handle.isValid() ) {
78  ATH_MSG_DEBUG("Input " << key.key() << " not present, did not run in this event.");
79  continue;
80  }
81  const auto thisCollFilter = m_collectionFilter.find( key.key() );
82  if ( thisCollFilter == m_collectionFilter.end() ) {
83  ATH_MSG_WARNING( "The collection " << key.key() << " is not configured to contain any final decision,"
84  << "remove it from the configuration of " << name() << " to save time" );
85  continue;
86  }
87 
88  for ( const Decision* decisionObject: *handle ) {
89  // Filter out chains for which this is NOT the final step of their processing
90  const DecisionIDContainer& passingFinalIDs = passedDecisionIDs(decisionObject, thisCollFilter->second);
91 
92  if (passingFinalIDs.empty()) {
93  continue;
94  }
95 
96  // Create a node to act as a filter between the final summary node and this HypoAlg.
97  // This ensures that we follow this edge (now two edges) in the graph only for the chains in
98  // passingFinalIDs rather than for other chains which are active in decisionObject which
99  // may accept the event via other objects
100 
101  // filter -> HypoAlg
102  Decision* filter = newDecisionIn( container, decisionObject, summaryFilterNodeName(), context );
103  decisionIDs(filter).insert( decisionIDs(filter).end(), passingFinalIDs.begin(), passingFinalIDs.end() );
104 
105  // HLTPassRaw -> filter
106  linkToPrevious(passRawOutput, filter, context);
107 
108  // Accumulate and de-duplicate passed IDs for which this hypo was the Chain's final step
109  allPassingFinalIDs.insert( passingFinalIDs.begin(), passingFinalIDs.end() );
110  }
111  }
112 
113  // Copy decisions set into passRawOutput's persistent vector
114  decisionIDs(passRawOutput).insert( decisionIDs(passRawOutput).end(),
115  allPassingFinalIDs.begin(), allPassingFinalIDs.end() );
116 
117  if (msgLvl(MSG::DEBUG)) {
118  ATH_MSG_DEBUG( "Number of positive decisions " << allPassingFinalIDs.size() << " passing chains");
119  for ( auto d: allPassingFinalIDs ) {
121  }
122  }
123 
124  // Monitor RoI updates between initial and final RoI
125  monitorRoIs(passRawOutput);
126 
127  // Get the data from the HLTSeeding, this is where prescales were applied
128  SG::ReadHandle<DecisionContainer> hltSeedingSummary( m_hltSeedingSummaryKey, context );
129  const Decision* l1SeededChains = nullptr; // Activated by L1
130  const Decision* activeChains = nullptr; // Activated and passed prescale check
131  const Decision* prescaledChains = nullptr; // Activated but failed prescale check
132  for (const Decision* d : *hltSeedingSummary) {
133  if (d->name() == "l1seeded") {
134  l1SeededChains = d;
135  } else if (d->name() == "unprescaled") {
136  activeChains = d;
137  } else if (d->name() == "prescaled") {
138  prescaledChains = d;
139  } else {
140  ATH_MSG_ERROR("DecisionSummaryMakerAlg encountered an unknown set of decisions from the HLTSeeding, name '" << d->name() << "'");
141  return StatusCode::FAILURE;
142  }
143  }
144 
145  if (l1SeededChains == nullptr || activeChains == nullptr || prescaledChains == nullptr) {
146  ATH_MSG_ERROR("Unable to read in the summary from the HLTSeeding. Cannot write to the HLT output summary the prescale status of HLT chains.");
147  return StatusCode::FAILURE;
148  }
149 
150  // l1SeededChains is not currently used here
151 
152  // activeChains is not currently used here
153 
154  // Get chains which were prescaled out. This is the set of chains which were seeded but which were NOT active (in the first pass)
155  DecisionIDContainer prescaledIDs;
156  decisionIDs( prescaledChains, prescaledIDs ); // Extract from prescaledChains (a Decision*) into prescaledIDs (a set<int>)
157  decisionIDs( prescaledOutput ).insert( decisionIDs( prescaledOutput ).end(),
158  prescaledIDs.begin(), prescaledIDs.end() ); // Save this to the output
159 
160  // Calculate and save express stream prescale decisions
161  // TODO: this involves pointless conversions set<uint> -> vector<HLT::Identifier> -> set<uint>, adapt IPrescalingTool to operate on set<uint>
162  HLT::IDVec allPassingFinalIDsVec{allPassingFinalIDs.begin(),allPassingFinalIDs.end()}; // Convert set to vector
163  HLT::IDVec expressIDsVec;
164  ATH_CHECK( m_prescaler->prescaleChains(context, allPassingFinalIDsVec, expressIDsVec, /*forExpressStream=*/ true) );
165  DecisionIDContainer expressIDs; // Convert vector to set
166  for (const HLT::Identifier& id : expressIDsVec) {
167  expressIDs.insert(id.numeric());
168  }
169  decisionIDs( passExpressOutput ).insert( decisionIDs( passExpressOutput ).end(),
170  expressIDs.begin(),
171  expressIDs.end() ); // Save this to the output
172 
173  // Fill and write out a set of passed streams
174  std::unordered_set<std::string> passStreamsSet;
175  for (const DecisionID chainID : allPassingFinalIDs) {
176  if (const auto it = m_chainToStreamsMap.find(chainID); it!=m_chainToStreamsMap.cend()) {
177  for (const std::string& streamName : it->second) {
178  passStreamsSet.insert(streamName);
179  }
180  } else {
181  ATH_MSG_ERROR("Passed chain " << HLT::Identifier(chainID).name() << " not in m_chainToStreamsMap");
182  }
183  }
184  // Add express
185  if (!expressIDs.empty()) {
186  passStreamsSet.insert(s_expressStreamName);
187  }
189  ATH_CHECK(passStreams.record(std::make_unique<std::vector<std::string>>(passStreamsSet.begin(),passStreamsSet.end())));
190 
191  if (msgLvl(MSG::DEBUG)) {
192  std::ostringstream streamNames;
193  bool first{true};
194  for (const std::string& s : passStreamsSet) {
195  if (first) {first=false;}
196  else {streamNames << ", ";}
197  streamNames << s;
198  }
199  ATH_MSG_DEBUG("This event is accepted to " << passStreamsSet.size() << " streams: " << streamNames.str());
200  }
201 
202  // Set the algorithm's filter status. This controlls the running of finalisation algs which we only want to execute
203  // in events which are accepted by one ore more chains.
204  bool filterStatus = true;
205  if (m_setFilterStatus) {
206  filterStatus = (not allPassingFinalIDs.empty());
207  }
208  setFilterPassed(filterStatus, context );
209 
210  return StatusCode::SUCCESS;
211 }
212 
214  using namespace TrigCompositeUtils;
215  using RoILinkVec = std::vector<LinkInfo<TrigRoiDescriptorCollection>>;
216 
217  auto printDecision = [this](const Decision* d){
218  ATH_MSG_INFO("The decision corresponds to chain(s):");
219  for (const DecisionID id : decisionIDs(d)) {
220  ATH_MSG_INFO("-- " << HLT::Identifier(id).name());
221  }
222  };
223  auto printDecisionAndRoI = [this,&printDecision](const Decision* d, const TrigRoiDescriptor& roi){
224  printDecision(d);
225  ATH_MSG_INFO("and final RoI: " << roi);
226  };
227 
228  // Loop over all final RoIs
229  const RoILinkVec allFinalRoIs = findLinks<TrigRoiDescriptorCollection>(terminusNode, roiString(), TrigDefs::lastFeatureOfType);
230  for (const auto& finalRoILink : allFinalRoIs) {
231  // Get the final TrigRoiDescriptor reference
232  if (!finalRoILink.isValid() || *(finalRoILink.link)==nullptr) {
233  ATH_MSG_WARNING("Encountered invalid final RoI link");
234  printDecision(finalRoILink.source);
235  continue;
236  }
237  const TrigRoiDescriptor& finalRoI = **(finalRoILink.link);
238 
239  // Skip full-scan and SuperRoI
240  if (finalRoI.isFullscan() || finalRoI.composite()) {continue;}
241 
242  // Get all initial RoIs associated with this final RoI (should be exactly one)
243  const RoILinkVec initialRoIs = findLinks<TrigRoiDescriptorCollection>(finalRoILink.source, initialRoIString(), TrigDefs::lastFeatureOfType);
244 
245  // Warn if the number of initial RoIs differs from one
246  if (initialRoIs.empty()) {
247  ATH_MSG_WARNING("Encountered decision node with no " << initialRoIString() << " link");
248  printDecisionAndRoI(finalRoILink.source, finalRoI);
249  continue;
250  }
251  if (initialRoIs.size()>1) {
252  ATH_MSG_WARNING("Encountered decision node with multiple (" << initialRoIs.size() << ") "
253  << initialRoIString() << " links");
254  printDecisionAndRoI(finalRoILink.source, finalRoI);
255  }
256 
257  // Get the initial TrigRoiDescriptor reference
258  const auto& initialRoILink = initialRoIs.front();
259  if (!initialRoILink.isValid() || *(initialRoILink.link)==nullptr) {
260  ATH_MSG_WARNING("Encountered invalid initial RoI link");
261  printDecisionAndRoI(finalRoILink.source, finalRoI);
262  continue;
263  }
264  const TrigRoiDescriptor& initialRoI = **(initialRoILink.link);
265 
266  // Skip full-scan
267  if (initialRoI.isFullscan()) {continue;}
268 
269  // Fill the monitoring histograms
270  Monitored::Scalar dEta{"RoIsDEta", finalRoI.eta() - initialRoI.eta()};
271  Monitored::Scalar dPhi{"RoIsDPhi", CxxUtils::deltaPhi(finalRoI.phi(), initialRoI.phi())};
272  Monitored::Scalar dZed{"RoIsDZed", finalRoI.zed() - initialRoI.zed()};
274 
275  // Print warnings on large updates
276  if (m_warnOnLargeRoIUpdates.value()) {
277  if (std::abs(dEta) > 1.0 || std::abs(dPhi) > 1.0 || std::abs(dZed) > 200) {
278  ATH_MSG_WARNING("Large RoI difference between initial and final RoI: "
279  << "dEta=" << dEta << ", dPhi=" << dPhi << ", dZed=" << dZed
280  << "initialRoI: " << initialRoI << ", finalRoI: " << finalRoI);
281  printDecision(finalRoILink.source);
282  }
283  }
284  }
285 }
TrigCompositeUtils::summaryPrescaledNodeName
const std::string & summaryPrescaledNodeName()
Definition: TrigCompositeUtilsRoot.cxx:924
TrigCompositeUtils::summaryFilterNodeName
const std::string & summaryFilterNodeName()
Definition: TrigCompositeUtilsRoot.cxx:912
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
DecisionSummaryMakerAlg::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: DecisionSummaryMakerAlg.h:55
RunTileMonitoring.streamNames
streamNames
Definition: RunTileMonitoring.py:158
runLayerRecalibration.chain
chain
Definition: runLayerRecalibration.py:175
TrigCompositeUtils::DecisionID
unsigned int DecisionID
Definition: TrigComposite_v1.h:27
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
TrigCompositeUtils::summaryPassExpressNodeName
const std::string & summaryPassExpressNodeName()
Definition: TrigCompositeUtilsRoot.cxx:920
HLT::Identifier::numeric
TrigCompositeUtils::DecisionID numeric() const
numeric ID
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:47
python.outputTest_v2.streams
streams
Definition: outputTest_v2.py:55
DecisionSummaryMakerAlg::m_streamsSummaryKey
SG::WriteHandleKey< std::vector< std::string > > m_streamsSummaryKey
Definition: DecisionSummaryMakerAlg.h:43
DecisionSummaryMakerAlg::start
virtual StatusCode start() override
Definition: DecisionSummaryMakerAlg.cxx:43
make_unique
std::unique_ptr< T > make_unique(Args &&... args)
Definition: SkimmingToolEXOT5.cxx:23
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
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
hist_file_dump.d
d
Definition: hist_file_dump.py:137
DecisionSummaryMakerAlg::m_warnOnLargeRoIUpdates
Gaudi::Property< bool > m_warnOnLargeRoIUpdates
Definition: DecisionSummaryMakerAlg.h:61
DecisionSummaryMakerAlg::m_summaryKey
SG::WriteHandleKey< TrigCompositeUtils::DecisionContainer > m_summaryKey
Definition: DecisionSummaryMakerAlg.h:37
skel.it
it
Definition: skel.GENtoEVGEN.py:396
RoiDescriptor::composite
virtual bool composite() const override final
SuperRoI compatability methods.
Definition: RoiDescriptor.h:137
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
TrigRoiDescriptor
nope - should be used for standalone also, perhaps need to protect the class def bits #ifndef XAOD_AN...
Definition: TrigRoiDescriptor.h:56
DecisionSummaryMakerAlg.h
AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::renounceArray
void renounceArray(SG::VarHandleKeyArray &handlesArray)
remove all handles from I/O resolution
Definition: AthCommonDataStore.h:364
DecisionSummaryMakerAlg::execute
virtual StatusCode execute(const EventContext &context) const override
Definition: DecisionSummaryMakerAlg.cxx:61
DecisionSummaryMakerAlg::m_setFilterStatus
Gaudi::Property< bool > m_setFilterStatus
Definition: DecisionSummaryMakerAlg.h:64
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
covarianceTool.filter
filter
Definition: covarianceTool.py:514
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:270
PixelModuleFeMask_create_db.remove
string remove
Definition: PixelModuleFeMask_create_db.py:83
DecisionSummaryMakerAlg::m_collectionFilter
std::map< std::string, TrigCompositeUtils::DecisionIDContainer > m_collectionFilter
Definition: DecisionSummaryMakerAlg.h:68
HLT::IDVec
std::vector< HLT::Identifier > IDVec
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:62
DecisionSummaryMakerAlg::m_prescaler
ToolHandle< IPrescalingTool > m_prescaler
Definition: DecisionSummaryMakerAlg.h:52
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
TrigCompositeUtils::initialRoIString
const std::string & initialRoIString()
Definition: TrigCompositeUtilsRoot.cxx:868
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
SG::WriteHandle::ptr
pointer_type ptr()
Dereference the pointer.
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TauGNNUtils::Variables::Track::dPhi
bool dPhi(const xAOD::TauJet &tau, const xAOD::TauTrack &track, double &out)
Definition: TauGNNUtils.cxx:538
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
DecisionSummaryMakerAlg::DecisionSummaryMakerAlg
DecisionSummaryMakerAlg(const std::string &name, ISvcLocator *pSvcLocator)
Definition: DecisionSummaryMakerAlg.cxx:17
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
xAOD::TrigComposite_v1
Class used to describe composite objects in the HLT.
Definition: TrigComposite_v1.h:52
DecisionSummaryMakerAlg::m_chainToStreamsMap
std::unordered_map< TrigCompositeUtils::DecisionID, std::vector< std::string > > m_chainToStreamsMap
Chain to streams map filled from the HLT Menu JSON.
Definition: DecisionSummaryMakerAlg.h:71
HLT::Identifier
Definition: TrigCompositeUtils/TrigCompositeUtils/HLTIdentifier.h:20
RoiDescriptor::zed
virtual double zed() const override final
Definition: RoiDescriptor.h:102
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
CxxUtils::deltaPhi
T deltaPhi(T phiA, T phiB)
Return difference phiA - phiB in range [-pi, pi].
Definition: phihelper.h:42
phihelper.h
Helper for azimuthal angle calculations.
DecisionSummaryMakerAlg::m_lastStepForChain
Gaudi::Property< std::map< std::string, std::vector< std::string > > > m_lastStepForChain
Definition: DecisionSummaryMakerAlg.h:58
TrigCompositeUtils::summaryPassNodeName
const std::string & summaryPassNodeName()
Definition: TrigCompositeUtilsRoot.cxx:916
DecisionSummaryMakerAlg::m_finalDecisionKeys
SG::ReadHandleKeyArray< TrigCompositeUtils::DecisionContainer > m_finalDecisionKeys
Definition: DecisionSummaryMakerAlg.h:40
DecisionSummaryMakerAlg::initialize
virtual StatusCode initialize() override
Definition: DecisionSummaryMakerAlg.cxx:20
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
TrigCompositeUtils::linkToPrevious
void linkToPrevious(Decision *d, const std::string &previousCollectionKey, size_t previousIndex)
Links to the previous object, location of previous 'seed' decision supplied by hand.
Definition: TrigCompositeUtilsRoot.cxx:139
AthenaPoolExample_Copy.streamName
string streamName
Definition: AthenaPoolExample_Copy.py:39
TrigCompositeUtils::DecisionIDContainer
std::set< DecisionID > DecisionIDContainer
Definition: TrigComposite_v1.h:28
DecisionSummaryMakerAlg::m_hltSeedingSummaryKey
SG::ReadHandleKey< xAOD::TrigCompositeContainer > m_hltSeedingSummaryKey
Definition: DecisionSummaryMakerAlg.h:46
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
RoiDescriptor::phi
virtual double phi() const override final
Methods to retrieve data members.
Definition: RoiDescriptor.h:100
DecisionSummaryMakerAlg::finalize
virtual StatusCode finalize() override
Definition: DecisionSummaryMakerAlg.cxx:57
DeMoScan.first
bool first
Definition: DeMoScan.py:536
DEBUG
#define DEBUG
Definition: page_access.h:11
HLTIdentifier.h
TrigCompositeUtils::decisionIDs
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
Definition: TrigCompositeUtilsRoot.cxx:67
RoiDescriptor::isFullscan
virtual bool isFullscan() const override final
is this a full scan RoI?
Definition: RoiDescriptor.h:132
RoiDescriptor::eta
virtual double eta() const override final
Definition: RoiDescriptor.h:101
TrigCompositeUtils
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:19
TrigCompositeUtils::roiString
const std::string & roiString()
Definition: TrigCompositeUtilsRoot.cxx:876
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
TrigConf::Chain
HLT chain configuration.
Definition: TrigConfData/TrigConfData/HLTChain.h:18
TauGNNUtils::Variables::Track::dEta
bool dEta(const xAOD::TauJet &tau, const xAOD::TauTrack &track, double &out)
Definition: TauGNNUtils.cxx:527
DecisionSummaryMakerAlg::monitorRoIs
void monitorRoIs(const TrigCompositeUtils::Decision *terminusNode) const
Monitor RoI updates between initial and final RoI.
Definition: DecisionSummaryMakerAlg.cxx:213
DecisionSummaryMakerAlg::m_hltMenuKey
SG::ReadHandleKey< TrigConf::HLTMenu > m_hltMenuKey
Definition: DecisionSummaryMakerAlg.h:49
TrigRoiDescriptorCollection.h
AthReentrantAlgorithm::setFilterPassed
virtual void setFilterPassed(bool state, const EventContext &ctx) const
Definition: AthReentrantAlgorithm.h:139
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37