ATLAS Offline Software
TrigMultiTrkComboHypoTool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /**************************************************************************
6  **
7  ** File: Trigger/TrigHypothesis/TrigBPhysHypo/TrigMultiTrkHypoTool.cxx
8  **
9  ** Description: multi-track hypothesis tool for bphys triggers
10  **
11  ** Author: Heather Russell
12  **
13  **************************************************************************/
14 
16 
17 #include <numeric>
18 #include <vector>
19 #include <iterator>
20 #include <algorithm>
21 #include "Math/GenVector/VectorUtil.h"
22 
25 
26 
27 TrigMultiTrkComboHypoTool::TrigMultiTrkComboHypoTool(const std::string& type, const std::string& name, const IInterface* parent)
29 
30 
32  ATH_MSG_DEBUG( "configuration for '" << this->name() << "'" << endmsg <<
33  " AcceptAll = " << (m_acceptAll ? "True" : "False") << endmsg <<
34  " isCombinedChain = " << (m_isCombinedChain ? "True" : "False") << endmsg <<
35  " isMergedElectronChain = " << (m_isMergedElectronChain ? "True" : "False") << endmsg <<
36  " mass range: ( " << m_massRange.value().first << ", " << m_massRange.value().second << " )" << endmsg <<
37  " chi2 cut: " << m_chi2 << endmsg <<
38  " " << (m_totalCharge < 0 ? "total charge cut is disabled" : "total charge cut: only right charge combinations") << endmsg <<
39  " LxyCut: > " << m_LxyCut.value() << endmsg <<
40  " sigmaLxyCut: > " << m_sigmaLxyCut.value() );
41 
42  ATH_CHECK( m_nTrk >= 2 );
44 
45  ATH_CHECK( !m_legMultiplicities.empty() );
46  if ( m_legMultiplicities.size() > 1 ) { // chain with asymmetric legs, as HLT_mu6_2mu4_bDimu_L1MU6_3MU4
47  // here we consider each decision as an individual object, i.e. for HLT_mu6_2mu4_bDimu_L1MU6_3MU4 we use
48  // m_legDecisionIDs = {createLegName("HLT_mu6_2mu4_bDimu_L1MU6_3MU4", 0),
49  // createLegName("HLT_mu6_2mu4_bDimu_L1MU6_3MU4", 1),
50  // createLegName("HLT_mu6_2mu4_bDimu_L1MU6_3MU4", 1)};
51  for (size_t legIndex = 0; legIndex < m_legMultiplicities.size(); ++legIndex) {
52  // can not use legDecisionId(legIndex) at initialize() step, use TrigCompositeUtils::createLegName() instead
53  auto legId = TrigCompositeUtils::createLegName(decisionId(), legIndex);
54  m_legDecisionIDs.insert(m_legDecisionIDs.end(), m_legMultiplicities[legIndex], legId.numeric());
55  }
56  }
57  else { // chain with symmetric legs, as HLT_2mu4_bDimu_L12MU4
58  m_legDecisionIDs.insert(m_legDecisionIDs.end(), m_legMultiplicities[0], decisionId().numeric());
59  }
61  ATH_CHECK( m_trkPt.size() == 2 || !m_isMuonTrkPEB );
62 
63  if (!m_monTool.empty()) {
64  ATH_CHECK( m_monTool.retrieve() );
65  ATH_MSG_DEBUG( "GenericMonitoringTool name:" << m_monTool );
66  }
67  else {
68  ATH_MSG_DEBUG( "No GenericMonitoringTool configured: no monitoring histograms will be available" );
69  }
70 
71  return StatusCode::SUCCESS;
72 }
73 
74 
75 bool TrigMultiTrkComboHypoTool::passed(const xAOD::TrigBphys* trigBphys) const {
76  ATH_MSG_DEBUG( "TrigMultiTrkComboHypoTool::passed()" );
77 
78  auto mon_totalCharge = Monitored::Scalar<int>("totalCharge", -100);
79  auto mon_chi2 = Monitored::Scalar<float>("chi2", -1.);
80  auto mon_mass = Monitored::Scalar<float>("mass", -1.);
81  auto mon_pT_trk1 = Monitored::Scalar<float>("pT_trk1", -1.);
82  auto mon_pT_trk2 = Monitored::Scalar<float>("pT_trk2", -1.);
83  auto mon_D0_trk1 = Monitored::Scalar<float>("d0_trk1", -1.);
84  auto mon_D0_trk2 = Monitored::Scalar<float>("d0_trk2", -1.);
85  auto mon_Lxy = Monitored::Scalar<float>("Lxy", -1.);
86  auto mon_Eta1 = Monitored::Scalar<float>("eta_trk1", -100.);
87  auto mon_Eta2 = Monitored::Scalar<float>("eta_trk2", -100.);
88 
89  auto mon = Monitored::Group( m_monTool, mon_totalCharge, mon_chi2, mon_mass, mon_pT_trk1, mon_pT_trk2, mon_Lxy, mon_D0_trk1, mon_D0_trk2, mon_Eta1, mon_Eta2);
90 
91  if (m_acceptAll || (trigBphys->nTrackParticles() == m_nTrk &&
92  isInMassRange(trigBphys->mass()) &&
93  passedChi2Cut(trigBphys->fitchi2()) &&
94  passedChargeCut(totalCharge(trigBphys)) &&
95  (m_LxyCut < 0. || trigBphys->lxy() > m_LxyCut) &&
96  (m_sigmaLxyCut < 0. || (trigBphys->lxyError() != 0. && trigBphys->lxy() / trigBphys->lxyError() > m_sigmaLxyCut)) &&
97  passedDeltaRcut(trigBphys) &&
98  passedPtCut(trigBphys))) {
99  mon_Lxy = trigBphys->lxy();
100  mon_totalCharge = totalCharge(trigBphys);
101  mon_chi2 = trigBphys->fitchi2();
102  mon_mass = 0.001 * trigBphys->mass();
103  mon_pT_trk1 = 0.001 * trigBphys->trackParticle(0)->pt();
104  mon_pT_trk2 = 0.001 * trigBphys->trackParticle(1)->pt();
105  mon_D0_trk1 = trigBphys->trackParticle(0)->d0();
106  mon_D0_trk2 = trigBphys->trackParticle(1)->d0();
107  mon_Eta1 = trigBphys->trackParticle(0)->eta();
108  mon_Eta2 = trigBphys->trackParticle(1)->eta();
109  ATH_MSG_DEBUG( "accepting event" );
110  return true;
111  }
112 
113  ATH_MSG_DEBUG( "reject event" );
114  return false;
115 }
116 
117 
118 StatusCode TrigMultiTrkComboHypoTool::decideOnSingleObject(Decision* decision, const std::vector<const DecisionIDContainer*>& previousDecisionIDs) const {
119  ATH_MSG_DEBUG( "decideOnSingleObject trigger tool: " << decisionId() );
120  ATH_CHECK( decision->hasObjectLink(TrigCompositeUtils::featureString()) );
121 
122  auto trigBphysEL = decision->objectLink<xAOD::TrigBphysContainer>(TrigCompositeUtils::featureString());
123  ATH_CHECK( trigBphysEL.isValid() );
124 
125  if (previousDecisionIDs.size() != (m_isMergedElectronChain || m_isMuonTrkPEB ? 1 : m_nTrk.value())) {
126  return StatusCode::SUCCESS;
127  }
128 
129  if (!checkPreviousDecisionIDs(previousDecisionIDs)) {
130  return StatusCode::SUCCESS;
131  }
132 
133  if (m_acceptAll || passed(*trigBphysEL)) {
135  if (m_isCombinedChain) {
136  for (size_t i = 0; i < m_nTrk; ++i) {
138  }
139  }
140  }
141 
142  return StatusCode::SUCCESS;
143 }
144 
145 
146 bool TrigMultiTrkComboHypoTool::checkPreviousDecisionIDs(const std::vector<const DecisionIDContainer*>& previousDecisionIDs) const {
147 
148  // the default ComboHypoTool is used at the previous step (muEFCB) to check the number of muons is sufficient to fire the BLS trigger
149  // now we should only check the muons fitted to the common vertex are marked as passed the corresponding trigger
150  // trigger with asymmetric legs (like HLT_mu6_2mu4_bDimu_L1MU6_3MU4) is treated in a specific way:
151  // all 6 possible combinations should be checked: {leg0, leg1}, {leg0, leg2}, {leg1, leg0}, {leg1, leg2}, {leg2, leg0}, {leg2, leg1}
152 
154  if (!TrigCompositeUtils::passed(m_legDecisionIDs.at(0), *previousDecisionIDs[0])) {
155  ATH_MSG_DEBUG( "Trigger for " << (m_isMergedElectronChain ? "close-by electrons" : "muon+track") << " didn't pass previous decision" );
156  return false;
157  }
158  return true;
159  }
160  else if (decisionId() == legDecisionId(0)) { // trigger with symmetric legs like HLT_3mu6_bDimu_L13MU6
161  for (size_t i = 0; i < m_nTrk; ++i) {
162  if (!TrigCompositeUtils::passed(decisionId().numeric(), *previousDecisionIDs[i])) {
163  ATH_MSG_DEBUG( "Trigger with symmetric legs didn't pass previous decision" );
164  return false;
165  }
166  }
167  ATH_MSG_DEBUG( "Trigger with symmetric legs passed previous decision" );
168  return true;
169  }
170  else { // trigger with asymmetric legs like HLT_mu6_2mu4_bDimu_L1MU6_3MU4
171 
172  std::vector<size_t> a(m_legDecisionIDs.size());
173  std::iota(a.begin(), a.end(), 0); // {0, 1, 2, .., m_legDecisionIDs().size() - 1}
174  int i = 1;
175  bool result = true;
176  do {
177  result = true;
178  for (size_t k = 0; k < m_nTrk; ++k) {
179  result = result && TrigCompositeUtils::passed(m_legDecisionIDs.at(a[k]), *previousDecisionIDs[k]);
180  }
181  if (msgLvl(MSG::DEBUG)) {
182  msg() << "combination #" << i++ << ": { ";
183  std::copy(a.begin(), a.begin() + m_nTrk, std::ostream_iterator<int>(msg().stream(), " "));
184  msg() << "} " << (result ? " passed" : "didn't pass") << endmsg;
185  }
186  if (result) break;
187  } while (std::next_permutation(a.begin(), a.end()));
188  ATH_MSG_DEBUG( "Trigger with asymmetric legs " << (result ? "passed" : "didn't pass") << " previous decision" );
189  return result;
190  }
191  return true;
192 }
193 
194 
196 
197  const auto& range = m_massRange.value();
198  if ( range.first > 0. && mass < range.first ) return false;
199  if ( range.second > 0. && mass > range.second ) return false;
200  return true;
201 }
202 
204  if (m_deltaRMax == std::numeric_limits<float>::max() && m_deltaRMin == std::numeric_limits<float>::lowest()) { // Cut disabled
205  return true;
206  }
207  size_t N = trigBphys->nTrackParticles();
208  for (size_t i = 0 ; i < N; i++) {
209  auto p1 = trigBphys->trackParticle(i)->genvecP4();
210  for (size_t j = i + 1; j < N; j++) {
211  auto p2 = trigBphys->trackParticle(j)->genvecP4();
212  double deltaR = ROOT::Math::VectorUtil::DeltaR(p1, p2);
213  if (deltaR > m_deltaRMax || deltaR < m_deltaRMin) return false;
214  }
215  }
216  return true;
217 }
218 
220  if (!m_isMuonTrkPEB) return true;
221 
222  size_t N = trigBphys->nTrackParticles();
223  for (size_t i = 0 ; i < N; ++i) {
224  if (m_trkPt[i] > 0. && trigBphys->trackParticle(i)->pt() < m_trkPt[i]) return false;
225  }
226  return true;
227 }
228 
230 
231  int charge = 0;
232  for (size_t i = 0; i < trigBphys->nTrackParticles(); ++i) {
233  charge += static_cast<int>(trigBphys->trackParticle(i)->charge());
234  }
235  return charge;
236 }
237 
238 
239 bool TrigMultiTrkComboHypoTool::executeAlg(const std::vector<Combo::LegDecision>&) const {
240  ATH_MSG_ERROR( "executeAlg() is not supported by TrigMultiTrkComboHypoTool" );
241  return true;
242 }
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
TrigMultiTrkComboHypoTool::m_acceptAll
Gaudi::Property< bool > m_acceptAll
Definition: TrigMultiTrkComboHypoTool.h:64
TrigMultiTrkComboHypoTool::passedDeltaRcut
bool passedDeltaRcut(const xAOD::TrigBphys *) const
Definition: TrigMultiTrkComboHypoTool.cxx:203
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
TrigMultiTrkComboHypoTool::m_deltaRMax
Gaudi::Property< float > m_deltaRMax
Definition: TrigMultiTrkComboHypoTool.h:67
get_generator_info.result
result
Definition: get_generator_info.py:21
max
#define max(a, b)
Definition: cfImp.cxx:41
TrigMultiTrkComboHypoTool::passed
bool passed(const xAOD::TrigBphys *) const
Definition: TrigMultiTrkComboHypoTool.cxx:75
TrigCompositeUtils::passed
bool passed(DecisionID id, const DecisionIDContainer &idSet)
checks if required decision ID is in the set of IDs in the container
Definition: TrigCompositeUtilsRoot.cxx:117
TrigMultiTrkComboHypoTool::m_sigmaLxyCut
Gaudi::Property< float > m_sigmaLxyCut
Definition: TrigMultiTrkComboHypoTool.h:66
xAOD::TrackParticle_v1::charge
float charge() const
Returns the charge.
Definition: TrackParticle_v1.cxx:150
ComboHypoToolBase::legDecisionId
HLT::Identifier legDecisionId(size_t i) const
Retrieves this ComboHypoTool's chain's decision ID for a given leg.
Definition: ComboHypoToolBase.h:60
TrigMultiTrkComboHypoTool::m_trkPt
Gaudi::Property< std::vector< double > > m_trkPt
Definition: TrigMultiTrkComboHypoTool.h:60
xAOD::TrackParticle_v1::eta
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
Definition: TrackParticle_v1.cxx:77
met::DeltaR
@ DeltaR
Definition: METRecoCommon.h:11
TrigCompositeUtils::addDecisionID
void addDecisionID(DecisionID id, Decision *d)
Appends the decision (given as ID) to the decision object.
Definition: TrigCompositeUtilsRoot.cxx:61
TrigMultiTrkComboHypoTool::TrigMultiTrkComboHypoTool
TrigMultiTrkComboHypoTool(const std::string &type, const std::string &name, const IInterface *parent)
Definition: TrigMultiTrkComboHypoTool.cxx:27
TrigMultiTrkComboHypoTool::passedChargeCut
bool passedChargeCut(int charge) const
Definition: TrigMultiTrkComboHypoTool.h:57
TrigMultiTrkComboHypoTool::m_isMuonTrkPEB
Gaudi::Property< bool > m_isMuonTrkPEB
Definition: TrigMultiTrkComboHypoTool.h:73
xAOD::TrigBphys_v1::mass
float mass() const
accessor method: mass
JetTiledMap::N
@ N
Definition: TiledEtaPhiMap.h:44
ComboHypoToolBase
Base class for tools which cut on properties of multi-object or multi-leg chains. User should derive ...
Definition: ComboHypoToolBase.h:26
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
dqt_zlumi_pandas.mass
mass
Definition: dqt_zlumi_pandas.py:170
xAOD::TrackParticle_v1::d0
float d0() const
Returns the parameter.
ComboHypoToolBase::decisionId
virtual HLT::Identifier decisionId() const
retrieves this ComboHypoTool's chain's decision ID
Definition: ComboHypoToolBase.h:41
TrigMultiTrkComboHypoTool::m_massRange
Gaudi::Property< std::pair< double, double > > m_massRange
Definition: TrigMultiTrkComboHypoTool.h:62
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
TrigMultiTrkComboHypoTool::initialize
virtual StatusCode initialize() override
Definition: TrigMultiTrkComboHypoTool.cxx:31
TrigMultiTrkComboHypoTool::isInMassRange
bool isInMassRange(double mass) const
Definition: TrigMultiTrkComboHypoTool.cxx:195
lumiFormat.i
int i
Definition: lumiFormat.py:92
TrigMultiTrkComboHypoTool::passedPtCut
bool passedPtCut(const xAOD::TrigBphys *) const
Definition: TrigMultiTrkComboHypoTool.cxx:219
TrigMultiTrkComboHypoTool::m_isCombinedChain
Gaudi::Property< bool > m_isCombinedChain
Definition: TrigMultiTrkComboHypoTool.h:71
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
xAOD::TrigBphys_v1::lxyError
float lxyError() const
accessor method: lxy uncertainty
Definition: TrigBphys_v1.cxx:390
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
TrigMultiTrkComboHypoTool::m_deltaRMin
Gaudi::Property< float > m_deltaRMin
Definition: TrigMultiTrkComboHypoTool.h:69
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
test_pyathena.parent
parent
Definition: test_pyathena.py:15
TrigMultiTrkComboHypoTool::m_nTrk
Gaudi::Property< unsigned int > m_nTrk
Definition: TrigMultiTrkComboHypoTool.h:59
TrigMultiTrkComboHypoTool::m_isMergedElectronChain
Gaudi::Property< bool > m_isMergedElectronChain
Definition: TrigMultiTrkComboHypoTool.h:72
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::TrigBphys_v1::fitchi2
float fitchi2() const
accessor method: chi2 from vertex fit
xAOD::TrackParticle_v1::genvecP4
GenVecFourMom_t genvecP4() const
The full 4-momentum of the particle : GenVector form.
Definition: TrackParticle_v1.cxx:116
xAOD::TrigBphys_v1::trackParticle
const xAOD::TrackParticle * trackParticle(size_t i) const
Get the Nth track's pointer.
Definition: TrigBphys_v1.cxx:217
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
TrigMultiTrkComboHypoTool::m_legDecisionIDs
std::vector< TrigCompositeUtils::DecisionID > m_legDecisionIDs
Definition: TrigMultiTrkComboHypoTool.h:77
TrigCompositeUtils::featureString
const std::string & featureString()
Definition: TrigCompositeUtilsRoot.cxx:886
TrigMultiTrkComboHypoTool::passedChi2Cut
bool passedChi2Cut(int chi2) const
Definition: TrigMultiTrkComboHypoTool.h:56
TrigMultiTrkComboHypoTool::decideOnSingleObject
virtual StatusCode decideOnSingleObject(TrigCompositeUtils::Decision *, const std::vector< const TrigCompositeUtils::DecisionIDContainer * > &) const override
Alternate method called by BPhysics ComboHypoAlgs instead of the base method decide(....
Definition: TrigMultiTrkComboHypoTool.cxx:118
TrigMultiTrkComboHypoTool::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: TrigMultiTrkComboHypoTool.h:75
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:192
TrigCompositeUtils::Decision
xAOD::TrigComposite Decision
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:20
charge
double charge(const T &p)
Definition: AtlasPID.h:494
TrigMultiTrkComboHypoTool::m_legMultiplicities
Gaudi::Property< std::vector< unsigned int > > m_legMultiplicities
Definition: TrigMultiTrkComboHypoTool.h:74
TrigCompositeUtils::createLegName
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.
Definition: TrigCompositeUtilsRoot.cxx:166
TrigMultiTrkComboHypoTool::m_totalCharge
Gaudi::Property< int > m_totalCharge
Definition: TrigMultiTrkComboHypoTool.h:61
a
TList * a
Definition: liststreamerinfos.cxx:10
TrigCompositeUtils::DecisionIDContainer
std::set< DecisionID > DecisionIDContainer
Definition: TrigComposite_v1.h:28
TrigMultiTrkComboHypoTool::executeAlg
virtual bool executeAlg(const std::vector< Combo::LegDecision > &) const override
Only a dummy implementation exists in ComboHypoToolBase.
Definition: TrigMultiTrkComboHypoTool.cxx:239
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
TrigMultiTrkComboHypoTool::checkPreviousDecisionIDs
bool checkPreviousDecisionIDs(const std::vector< const TrigCompositeUtils::DecisionIDContainer * > &) const
Definition: TrigMultiTrkComboHypoTool.cxx:146
DEBUG
#define DEBUG
Definition: page_access.h:11
plotBeamSpotMon.mon
mon
Definition: plotBeamSpotMon.py:67
TrigMultiTrkComboHypoTool::totalCharge
int totalCharge(const xAOD::TrigBphys *) const
Definition: TrigMultiTrkComboHypoTool.cxx:229
TrigMultiTrkComboHypoTool.h
calibdata.copy
bool copy
Definition: calibdata.py:27
TrigMultiTrkComboHypoTool::m_chi2
Gaudi::Property< float > m_chi2
Definition: TrigMultiTrkComboHypoTool.h:63
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
xAOD::TrigBphys_v1::lxy
float lxy() const
accessor method: lxy
Definition: TrigBphys_v1.cxx:387
TrigMultiTrkComboHypoTool::m_LxyCut
Gaudi::Property< float > m_LxyCut
Definition: TrigMultiTrkComboHypoTool.h:65
makeComparison.deltaR
float deltaR
Definition: makeComparison.py:36
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
xAOD::TrigBphys_v1
Class describing a Bphysics online composite object.
Definition: TrigBphys_v1.h:44
fitman.k
k
Definition: fitman.py:528
xAOD::TrigBphys_v1::nTrackParticles
size_t nTrackParticles() const
Number of tracks used to make particle.