ATLAS Offline Software
Loading...
Searching...
No Matches
TrigBmuxComboHypo.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <algorithm>
6#include <numeric>
7#include <iterator>
8
9#include "TrigBmuxComboHypo.h"
10
11#include "xAODMuon/Muon.h"
13#include "xAODTracking/Vertex.h"
20
24
25#include "AthViews/View.h"
26#include "AthViews/ViewHelper.h"
28
29#include "Math/GenVector/VectorUtil.h"
30#include "Math/Vector2D.h"
32
33
38using ROOT::Math::XYVector;
39
40
41const std::vector<std::vector<std::vector<double>>> TrigBmuxComboHypo::s_trkMass{
42 {{PDG::mKaon, PDG::mPion}, {PDG::mMuon}}, // {D0.K-, D0.pi+}, {mu-}
43 {{PDG::mKaon, PDG::mPion}, {PDG::mMuon, PDG::mPion}}, // {D*+.D0.K-, D*+.D0.pi+}, {mu-, D*+.pi+}
44 {{PDG::mKaon, PDG::mKaon, PDG::mPion}, {PDG::mMuon}}, // {D_s+.K+, D_s+.K-, D_s+.pi+}, {mu-}
45 {{PDG::mKaon, PDG::mPion, PDG::mPion}, {PDG::mMuon}}, // {D+.K-, D+.pi+, D+.pi+}, {mu-}
46 {{PDG::mProton, PDG::mKaon, PDG::mPion}, {PDG::mMuon}} // {Lambda_c+.p, Lambda_c+.K-, Lambda_c+.pi+}, {mu-}
47};
48
49
50TrigBmuxComboHypo::TrigBmuxComboHypo(const std::string& name, ISvcLocator* pSvcLocator)
51 : ::ComboHypo(name, pSvcLocator) {}
52
53
55 ATH_MSG_DEBUG( "TrigBmuxComboHypo::initialize()" );
56
58
59 ATH_CHECK( m_muonContainerKey.initialize() );
63 ATH_CHECK( m_trigBphysContainerKey.initialize() );
64 ATH_CHECK( m_beamSpotKey.initialize() );
65
66 ATH_CHECK( m_vertexFitter.retrieve() );
68 ATH_CHECK( m_trackToVertexTool.retrieve() );
69
70 // allowed IDs to filter out incoming decisions at L2 level
71 for (const auto& item : triggerMultiplicityMap()) {
72 const HLT::Identifier id = HLT::Identifier(item.first);
73 m_allowedIDs.insert(id.numeric());
74 if (item.second.size() > 1) {
75 for (size_t i = 0; i < item.second.size(); i++) {
76 m_allowedIDs.insert(TrigCompositeUtils::createLegName(id, i).numeric());
77 }
78 }
79 }
80 if (msgLvl(MSG::DEBUG)) {
81 ATH_MSG_DEBUG( "Allowed decisions:" );
82 for (const DecisionID& id : m_allowedIDs) {
83 ATH_MSG_DEBUG( " +++ " << HLT::Identifier(id) );
84 }
85 }
86
87 if (!m_monTool.empty()) {
88 ATH_CHECK( m_monTool.retrieve() );
89 ATH_MSG_DEBUG( "GenericMonitoringTool name:" << m_monTool );
90 }
91 else {
92 ATH_MSG_DEBUG( "No GenericMonitoringTool configured: no monitoring histograms will be available" );
93 }
94
95 return StatusCode::SUCCESS;
96}
97
98
99StatusCode TrigBmuxComboHypo::execute(const EventContext& context) const {
100
101 ATH_MSG_DEBUG( "TrigBmuxComboHypo::execute() starts" );
102
103 ATH_MSG_DEBUG( "decision input key: " << decisionsInput().at(0).key() );
104 auto previousDecisionsHandle = SG::makeHandle(decisionsInput().at(0), context);
105 ATH_CHECK( previousDecisionsHandle.isValid() );
106 ATH_MSG_DEBUG( "Running with " << previousDecisionsHandle->size() << " previous decisions" );
107
109
110 auto trigBphysHandle = SG::makeHandle(m_trigBphysContainerKey, context);
111 ATH_CHECK( trigBphysHandle.record(std::make_unique<xAOD::TrigBphysContainer>(),
112 std::make_unique<xAOD::TrigBphysAuxContainer>()) );
113
115 ATH_CHECK( beamSpotHandle.isValid() );
116
117 auto state = std::make_unique<TrigBmuxState>(context, *previousDecisionsHandle, *outputDecisionsHandle, trigBphysHandle.ptr(), *beamSpotHandle);
118
119 ATH_CHECK( findBmuxCandidates(*state) );
121
122 ATH_MSG_DEBUG( "TrigBmuxComboHypo::execute() terminates with StatusCode::SUCCESS" );
123 return StatusCode::SUCCESS;
124}
125
126
128
129 auto& muons = state.muons;
130 muons.clear();
131
132 // monitored variables
133 std::vector<int> nTrk;
134 auto mon_nMuon = Monitored::Scalar<int>("nMuon", 0);
135 auto mon_nTrk = Monitored::Collection("nTrk", nTrk);
136 auto mon_nBPhysObject = Monitored::Scalar<int>("nBPhysObject", 0);
137
138 auto group = Monitored::Group(m_monTool,
139 mon_nMuon, mon_nTrk, mon_nBPhysObject);
140
141 for (const Decision* decision : state.previousDecisions()) {
142 if (!TrigCompositeUtils::isAnyIDPassing(decision, m_allowedIDs)) continue;
143
144 auto decisionEL = TrigCompositeUtils::decisionToElementLink(decision, state.context());
146 auto muonEL = decision->objectLink<xAOD::MuonContainer>(TrigCompositeUtils::featureString());
147 const auto muon = *muonEL;
148 if (!muon->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) continue;
149 if (!muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)) continue;
150 const auto muonInDetTrack = muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
151 auto p_mu = muonInDetTrack->genvecP4();
152 p_mu.SetM(PDG::mMuon);
153 double z0_mu = (m_trkZ0 > 0. ? getTrkImpactParameterZ0(state.context(), *muonInDetTrack, state.beamSpotPosition()) : -1.);
154 mon_nMuon++;
155
156 // add muon from decision to state.leptons
159 size_t muonIndex = muons.size();
160 muons.push_back({muonEL, decisionEL, decisionIDs});
161
162 ATH_MSG_DEBUG( "Found muon (CombinedTrackParticle) pt/eta/phi/q: " << muon->pt() << " / " << muon->eta() << " / " << muon->phi() << " / " << muon->charge() );
163
165 ATH_CHECK( viewLinkInfo.isValid() );
166 auto view = *viewLinkInfo.link;
167
169 ATH_CHECK( roiLinkInfo.isValid() );
170 const auto roi = *roiLinkInfo.link;
171
172 auto tracksHandle = ViewHelper::makeHandle(view, m_trackParticleContainerKey, state.context());
173 ATH_CHECK( tracksHandle.isValid() );
174 ATH_MSG_DEBUG( "Tracks container " << m_trackParticleContainerKey << " size: " << tracksHandle->size() );
175
176 std::vector<ElementLink<xAOD::TrackParticleContainer>> tracks;
177 tracks.reserve(tracksHandle->size());
178 for (size_t idx = 0; idx < tracksHandle->size(); ++idx) {
179 const auto track = tracksHandle->get(idx);
180 if (track->definingParametersCovMatrixVec().empty() || (m_trkZ0 > 0. && std::abs(getTrkImpactParameterZ0(state.context(), *track, state.beamSpotPosition()) - z0_mu) > m_trkZ0)) continue;
181 if (roi->composite() && !isInSameRoI(muon, track)) continue;
182 tracks.emplace_back(ViewHelper::makeLink<xAOD::TrackParticleContainer>(view, tracksHandle, idx));
183 }
184 // find the best match to the original muon and remove it
185 if (tracks.size() < 2) continue;
186 std::sort(tracks.begin(), tracks.end(), [p_mu](const auto& lhs, const auto& rhs){ return ROOT::Math::VectorUtil::DeltaR(p_mu, (*lhs)->genvecP4()) > ROOT::Math::VectorUtil::DeltaR(p_mu, (*rhs)->genvecP4()); });
187 if (isIdenticalTracks(muonInDetTrack, *tracks.back())) tracks.pop_back();
188 nTrk.push_back(tracks.size());
189
190 std::sort(tracks.begin(), tracks.end(), [](const auto& lhs, const auto& rhs){ return ((*lhs)->pt() > (*rhs)->pt()); });
191
192 if (msgLvl(MSG::DEBUG)) {
193 ATH_MSG_DEBUG( "Dump found tracks before vertex fit: " << tracks.size() << " candidates" );
194 for (const auto& trackEL : tracks) {
195 const xAOD::TrackParticle* track = *trackEL;
196 ATH_MSG_DEBUG( " -- track pt/eta/phi/q: " << track->pt() << " / " << track->eta() << " / " << track->phi() << " / " << track->charge() );
197 }
198 }
199
200 size_t iterations = 0;
201 bool isOverWarningThreshold = false;
202 for (size_t itrk1 = 0; itrk1 < tracks.size(); ++itrk1) {
203 const xAOD::TrackParticle* trk1 = *tracks[itrk1];
204 auto p_trk1 = trk1->genvecP4();
205 auto charge1 = trk1->charge();
206
207 for (size_t itrk2 = 0; itrk2 < tracks.size(); ++itrk2) {
208 if (itrk2 == itrk1) continue;
209 const xAOD::TrackParticle* trk2 = *tracks[itrk2];
210 auto p_trk2 = trk2->genvecP4();
211 auto charge2 = trk2->charge();
212
213 // D0(-> K- pi+)
215 std::unique_ptr<xAOD::Vertex> vtx_D0;
217 if (m_BToD0 &&
218 charge1 * charge2 < 0. &&
219 p_trk1.Pt() > m_BToD0_minD0KaonPt &&
220 p_trk2.Pt() > m_BToD0_minD0PionPt &&
221 (p_trk1 + p_trk2).Pt() > m_BToD0_minD0Pt &&
222 isInMassRange((p_trk1.SetM(PDG::mKaon) + p_trk2.SetM(PDG::mPion)).M(), m_BToD0_D0MassRange) &&
223 isInMassRange((p_mu + p_trk1.SetM(PDG::mKaon) + p_trk2.SetM(PDG::mPion)).M(), m_BToD0_massRange)) {
224 vtx_D0 = fit(state.context(), {linkTrack(muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)), tracks[itrk1], tracks[itrk2]}, kD0);
225 ++iterations;
226
227 if (vtx_D0 && vtx_D0->chiSquared() < m_BToD0_chi2) {
228 ATH_MSG_DEBUG( "Partially reconstructed B+ -> mu+ nu_mu anti-D0(-> K+ pi-) candidate has been created from { " << itrk1 << ", " << itrk2 << " }" );
229 if (m_makeCascadeFit) {
230 auto result = fitCascade(state.context(), {linkTrack(muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)),
231 tracks[itrk1], tracks[itrk2]}, kD0);
232 // all fitted (muon + D0) candidates should be taken into account to avoid bias in (muon + D*-) sample
233 if (result &&
234 result->fitChi2() < m_cascadeChi2 && result->nDoF() == 2) {
235 std::vector<xAOD::TrigBphys*> triggerObjects = state.addTriggerObjects(2, muonIndex);
236 ATH_CHECK( fillTriggerObjects(triggerObjects, xAOD::TrigBphys::DZKPI, *result, state.beamSpotPosition()) );
237 p_D0 = ROOT::Math::PtEtaPhiMVector(triggerObjects[0]->pt(), triggerObjects[0]->eta(), triggerObjects[0]->phi(), triggerObjects[0]->fitmass());
239 ATH_CHECK( D0.isValid() );
240
241 // only candidates with proper Lxy values should fire B2D0MUX trigger
242 if (triggerObjects[1]->lxy() > m_BToD0_LxyB && triggerObjects[0]->lxy() > m_BToD0_LxyD0) {
243 triggerObjects[1]->setParticleType(xAOD::TrigBphys::B2D0MUX);
244 mon_nBPhysObject++;
245 }
246 }
247 }
248 else {
249 xAOD::TrigBphys* triggerObject = state.addTriggerObject(muonIndex);
250 ATH_CHECK( fillTriggerObject(*triggerObject, xAOD::TrigBphys::B2D0MUX, *vtx_D0, s_trkMass[kD0][0]) );
251 p_D0 = ROOT::Math::PtEtaPhiMVector(triggerObject->pt(), triggerObject->eta(), triggerObject->phi(), triggerObject->fitmass());
252 triggerObject->setMass((p_mu + p_D0).M());
254 ATH_CHECK( D0.isValid() );
255 mon_nBPhysObject++;
256 }
257 }
258 } // end of D0
259
260 for (size_t itrk3 = 0; itrk3 < tracks.size(); ++itrk3) {
261 if (itrk3 == itrk1 || itrk3 == itrk2) continue;
262 const xAOD::TrackParticle* trk3 = *tracks[itrk3];
263 auto p_trk3 = trk3->genvecP4();
264 auto charge3 = trk3->charge();
265
266 std::vector<ElementLink<xAOD::TrackParticleContainer>> trackParticleLinks = {linkTrack(muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)),
267 tracks[itrk1], tracks[itrk2], tracks[itrk3]};
268
269 // D*-(-> anti-D0(-> K+ pi-) pi-)
270 if (m_BToD0_makeDstar && D0.isValid() &&
271 p_trk3.Pt() > m_BToD0_minDstarPionPt &&
272 (p_trk1 + p_trk2 + p_trk3).Pt() > m_BToD0_minDstarPt &&
273 isInMassRange((p_D0 + p_trk3.SetM(PDG::mPion)).M() - p_D0.M() + PDG::mD0, m_BToD0_DstarMassRange)) {
274
275 bool makeDstar = true;
276 if (m_BToD0_maxDstarPionZ0 > 0.) {
277 std::unique_ptr<const Trk::Perigee> perigee(m_trackToVertexTool->perigeeAtVertex(state.context(), *trk3, vtx_D0->position()));
278 if (!perigee || std::abs(perigee->parameters()[Trk::z0]) > m_BToD0_maxDstarPionZ0) makeDstar = false;
279 }
280
281 if (makeDstar) {
282 if (m_makeCascadeFit) {
283 auto result = fitCascade(state.context(), trackParticleLinks, kDstar);
284 if (result &&
285 result->fitChi2() < m_cascadeChi2 && result->nDoF() == 4 &&
286 Lxy(state.beamSpotPosition(), result->vertices()[1]->position(), result->getParticleMoms()[1]) > m_BToD0_LxyBd &&
287 Lxy(result->vertices()[1]->position(), result->vertices()[0]->position(), result->getParticleMoms()[0]) > m_BToD0_LxyD0) {
288
289 std::vector<xAOD::TrigBphys*> triggerObjects = state.addTriggerObjects(2, muonIndex);
290 ATH_CHECK( fillTriggerObjects(triggerObjects, xAOD::TrigBphys::BD2DSTMUX, *result, state.beamSpotPosition()) );
291 triggerObjects[1]->setSecondaryDecayLink(D0);
292 mon_nBPhysObject++;
293 }
294 }
295 else {
296 xAOD::TrackParticle::GenVecFourMom_t p_Dstar = p_D0 + p_trk3.SetM(PDG::mPion);
297 xAOD::TrigBphys* Dstar = state.addTriggerObject(muonIndex);
298 Dstar->initialise(0, p_Dstar.Eta(), p_Dstar.Phi(), p_Dstar.Pt(), xAOD::TrigBphys::BD2DSTMUX, (p_mu + p_Dstar).M(), xAOD::TrigBphys::EF);
299 Dstar->setFitmass((p_D0 + p_trk3).M() - p_D0.M() + PDG::mD0);
300 Dstar->setTrackParticleLinks(trackParticleLinks);
301 Dstar->setLowerChainLink(D0);
302
304 "TrigBphys object:\n\t " <<
305 "roiId: " << Dstar->roiId() << "\n\t " <<
306 "particleType: " << Dstar->particleType() << "\n\t " <<
307 "level: " << Dstar->level() << "\n\t " <<
308 "eta: " << Dstar->eta() << "\n\t " <<
309 "phi: " << Dstar->phi() << "\n\t " <<
310 "mass: " << Dstar->mass() << "\n\t " <<
311 "fitmass: " << Dstar->fitmass() << "\n\t " <<
312 "chi2/NDF: " << Dstar->fitchi2() << " / " << Dstar->fitndof() << "\n\t " <<
313 "vertex: (" << Dstar->fitx() << ", " << Dstar->fity() << ", " << Dstar->fitz() << ")" );
314
315 mon_nBPhysObject++;
316 }
317 }
318 } // end of D*-
319
320 // B0 -> mu+ nu_mu D-(-> K+ pi- pi-)
321 if (m_BdToD &&
322 itrk3 > itrk2 &&
323 charge1 * charge2 < 0. && charge2 * charge3 > 0. &&
324 p_trk1.Pt() > m_BdToD_minKaonPt &&
325 p_trk2.Pt() > m_BdToD_minPionPt &&
326 p_trk3.Pt() > m_BdToD_minPionPt &&
327 (p_trk1 + p_trk2 + p_trk3).Pt() > m_BdToD_minDPt &&
328 isInMassRange((p_trk1.SetM(PDG::mKaon) + p_trk2.SetM(PDG::mPion) + p_trk3.SetM(PDG::mPion)).M(), m_BdToD_DMassRange) &&
329 isInMassRange((p_mu + p_trk1.SetM(PDG::mKaon) + p_trk2.SetM(PDG::mPion) + p_trk3.SetM(PDG::mPion)).M(), m_BdToD_massRange)) {
330 auto vtx_D = fit(state.context(), trackParticleLinks, kDplus);
331 ++iterations;
332
333 if (vtx_D && vtx_D->chiSquared() < m_BdToD_chi2) {
334 ATH_MSG_DEBUG( "Partially reconstructed B0 -> mu+ nu_mu D-(-> K+ pi- pi-) candidate has been created from { " << itrk1 << ", " << itrk2 << ", " << itrk3 << " }" );
335 if (m_makeCascadeFit) {
336 auto result = fitCascade(state.context(), trackParticleLinks, kDplus);
337 if (result &&
338 result->fitChi2() < m_cascadeChi2 && result->nDoF() == 4 &&
339 Lxy(state.beamSpotPosition(), result->vertices()[1]->position(), result->getParticleMoms()[1]) > m_BdToD_LxyBd &&
340 Lxy(result->vertices()[1]->position(), result->vertices()[0]->position(), result->getParticleMoms()[0]) > m_BdToD_LxyD) {
341
342 std::vector<xAOD::TrigBphys*> triggerObjects = state.addTriggerObjects(2, muonIndex);
343 ATH_CHECK( fillTriggerObjects(triggerObjects, xAOD::TrigBphys::BD2DMMUX, *result, state.beamSpotPosition()) );
344 mon_nBPhysObject++;
345 }
346 }
347 else {
348 xAOD::TrigBphys* triggerObject = state.addTriggerObject(muonIndex);
350 xAOD::TrackParticle::GenVecFourMom_t p_D(ROOT::Math::PtEtaPhiMVector(triggerObject->pt(), triggerObject->eta(), triggerObject->phi(), triggerObject->fitmass()));
351 triggerObject->setMass((p_mu + p_D).M());
352 mon_nBPhysObject++;
353 }
354 }
355 } // end of B0
356
357 // B_s0 -> mu+ nu_mu D_s-(->phi(-> K+ K-) pi-)
358 if (m_BsToDs &&
359 itrk2 > itrk1 &&
360 charge1 * charge2 < 0. &&
361 p_trk1.Pt() > m_BsToDs_minKaonPt &&
362 p_trk2.Pt() > m_BsToDs_minKaonPt &&
363 p_trk3.Pt() > m_BsToDs_minPionPt &&
364 (p_trk1 + p_trk2 + p_trk3).Pt() > m_BsToDs_minDsPt &&
365 isInMassRange((p_trk1.SetM(PDG::mKaon) + p_trk2.SetM(PDG::mKaon)).M(), m_BsToDs_phiMassRange) &&
366 isInMassRange((p_trk1.SetM(PDG::mKaon) + p_trk2.SetM(PDG::mKaon) + p_trk3.SetM(PDG::mPion)).M(), m_BsToDs_DsMassRange) &&
367 isInMassRange((p_mu + p_trk1.SetM(PDG::mKaon) + p_trk2.SetM(PDG::mKaon) + p_trk3.SetM(PDG::mPion)).M(), m_BsToDs_massRange)) {
368 auto vtx_Ds = fit(state.context(), trackParticleLinks, kDs);
369 ++iterations;
370
371 if (vtx_Ds && vtx_Ds->chiSquared() < m_BsToDs_chi2) {
372 ATH_MSG_DEBUG( "Partially reconstructed B_s0 -> mu+ nu_mu D_s-(->phi(-> K+ K-) pi-) candidate has been created from { " << itrk1 << ", " << itrk2 << ", " << itrk3 << " }" );
373 if (m_makeCascadeFit) {
374 auto result = fitCascade(state.context(), trackParticleLinks, kDs);
375 if (result &&
376 result->fitChi2() < m_cascadeChi2 && result->nDoF() == 4 &&
377 Lxy(state.beamSpotPosition(), result->vertices()[1]->position(), result->getParticleMoms()[1]) > m_BsToDs_LxyBs &&
378 Lxy(result->vertices()[1]->position(), result->vertices()[0]->position(), result->getParticleMoms()[0]) > m_BsToDs_LxyDs) {
379
380 std::vector<xAOD::TrigBphys*> triggerObjects = state.addTriggerObjects(2, muonIndex);
381 ATH_CHECK( fillTriggerObjects(triggerObjects, xAOD::TrigBphys::BS2DSMUX, *result, state.beamSpotPosition()) );
382 mon_nBPhysObject++;
383 }
384 }
385 else {
386 xAOD::TrigBphys* triggerObject = state.addTriggerObject(muonIndex);
387 ATH_CHECK( fillTriggerObject(*triggerObject, xAOD::TrigBphys::BS2DSMUX, *vtx_Ds, s_trkMass[kDs][0]) );
388 xAOD::TrackParticle::GenVecFourMom_t p_Ds(ROOT::Math::PtEtaPhiMVector(triggerObject->pt(), triggerObject->eta(), triggerObject->phi(), triggerObject->fitmass()));
389 triggerObject->setMass((p_mu + p_Ds).M());
390 mon_nBPhysObject++;
391 }
392 }
393 } // end of B_s0
394
395 // Lambda_b0 -> mu+ nu_mu anti-Lambda_c-(-> anti-p K+ pi-)
396 if (m_LambdaBToLambdaC &&
397 charge1 * charge3 > 0. && charge1 * charge2 < 0. &&
398 p_trk1.Pt() > m_LambdaBToLambdaC_minProtonPt &&
399 p_trk2.Pt() > m_LambdaBToLambdaC_minKaonPt &&
400 p_trk3.Pt() > m_LambdaBToLambdaC_minPionPt &&
401 (p_trk1 + p_trk2 + p_trk3).Pt() > m_LambdaBToLambdaC_minLambdaCPt &&
402 isInMassRange((p_trk1.SetM(PDG::mProton) + p_trk2.SetM(PDG::mKaon) + p_trk3.SetM(PDG::mPion)).M(), m_LambdaBToLambdaC_LambdaCMassRange) &&
403 isInMassRange((p_mu + p_trk1.SetM(PDG::mProton) + p_trk2.SetM(PDG::mKaon) + p_trk3.SetM(PDG::mPion)).M(), m_LambdaBToLambdaC_massRange)) {
404 auto vtx_LambdaC = fit(state.context(), trackParticleLinks, kLambdaC);
405 ++iterations;
406
407 if (vtx_LambdaC && vtx_LambdaC->chiSquared() < m_LambdaBToLambdaC_chi2) {
408 ATH_MSG_DEBUG( "Partially reconstructed Lambda_b0 -> mu+ nu_mu anti-Lambda_c-(-> anti-p K+ pi-) candidate has been created from { " << itrk1 << ", " << itrk2 << ", " << itrk3 << " }" );
409 if (m_makeCascadeFit) {
410 auto result = fitCascade(state.context(), trackParticleLinks, kLambdaC);
411 if (result &&
412 result->fitChi2() < m_cascadeChi2 && result->nDoF() == 4 &&
413 Lxy(state.beamSpotPosition(), result->vertices()[1]->position(), result->getParticleMoms()[1]) > m_LambdaBToLambdaC_LxyLb &&
414 Lxy(result->vertices()[1]->position(), result->vertices()[0]->position(), result->getParticleMoms()[0]) > m_LambdaBToLambdaC_LxyLc) {
415
416 std::vector<xAOD::TrigBphys*> triggerObjects = state.addTriggerObjects(2, muonIndex);
417 ATH_CHECK( fillTriggerObjects(triggerObjects, xAOD::TrigBphys::LB2LCMUX, *result, state.beamSpotPosition()) );
418 mon_nBPhysObject++;
419 }
420 }
421 else {
422 xAOD::TrigBphys* triggerObject = state.addTriggerObject(muonIndex);
423 ATH_CHECK( fillTriggerObject(*triggerObject, xAOD::TrigBphys::LB2LCMUX, *vtx_LambdaC, s_trkMass[kLambdaC][0]) );
424 xAOD::TrackParticle::GenVecFourMom_t p_LambdaC(ROOT::Math::PtEtaPhiMVector(triggerObject->pt(), triggerObject->eta(), triggerObject->phi(), triggerObject->fitmass()));
425 triggerObject->setMass((p_mu + p_LambdaC).M());
426 mon_nBPhysObject++;
427 }
428 }
429 } // end of Lambda_b0
430
431 }
432 vtx_D0.reset();
433
434 }
435
436 if (iterations > m_fitAttemptsWarningThreshold && !isOverWarningThreshold) {
437 ATH_MSG_WARNING( iterations << " combinations for vertex fitter have been processed; " << mon_nBPhysObject << " vertices have been created" );
438 isOverWarningThreshold = true;
439 }
440 if (iterations > m_fitAttemptsBreakThreshold) {
441 ATH_MSG_WARNING( "the number of fit attempts has exceeded the limit; breaking the loop at this point" );
442 break;
443 }
444 }
445 }
446 return StatusCode::SUCCESS;
447}
448
449
451
452 size_t idx = 0;
453 for (const xAOD::TrigBphys* triggerObject : state.trigBphysCollection()) {
454 if (triggerObject->particleType() == xAOD::TrigBphys::UNKNOWNPTYPE) continue;
455
456 ATH_MSG_DEBUG( "Found xAOD::TrigBphys object: mass = " << triggerObject->mass() );
457
458 auto triggerObjectEL = ElementLink<xAOD::TrigBphysContainer>(state.trigBphysCollection(), triggerObject->index());
459 ATH_CHECK( triggerObjectEL.isValid() );
460
461 const auto& muon = state.muons.at(state.trigBphysMuonIndices.at(idx));
462
463 // create a new output Decision object, backed by the 'decisions' container.
465
466 // add link to the previous decision
467 decision->addObjectCollectionLink(TrigCompositeUtils::seedString(), muon.decisionLink);
468
469 // set mandatory link to the trigger object
471
472 std::vector<const DecisionIDContainer*> previousDecisionIDs(1, &muon.decisionIDs);
473 for (const auto& tool : hypoTools()) {
474 ATH_MSG_DEBUG( "Go to " << tool );
475 ATH_CHECK( tool->decideOnSingleObject(decision, previousDecisionIDs) );
476 }
477 ++idx;
478 }
479
480 return StatusCode::SUCCESS;
481}
482
483
484std::unique_ptr<xAOD::Vertex> TrigBmuxComboHypo::fit(
485 const EventContext& context,
486 const std::vector<ElementLink<xAOD::TrackParticleContainer>>& trackParticleLinks,
487 Decay decay) const {
488
489 ATH_MSG_DEBUG( "Perform vertex fit" );
490
491 if (trackParticleLinks.size() < 3) {
492 ATH_MSG_WARNING( "At least muon and two tracks should be given to the vertex fitter" );
493 return std::unique_ptr<xAOD::Vertex>(nullptr);
494 }
495
496 std::vector<const xAOD::TrackParticle*> tracklist(trackParticleLinks.size() - 1, nullptr);
497 std::transform(trackParticleLinks.begin() + 1, trackParticleLinks.end(), tracklist.begin(),
498 [](const ElementLink<xAOD::TrackParticleContainer>& link){ return *link; });
499
500 Amg::Vector3D startingPoint = Amg::Vector3D::Zero(3);
501 int flag = 0;
502 int errorcode = 0;
503 const Trk::Perigee& perigee1 = tracklist[0]->perigeeParameters();
504 const Trk::Perigee& perigee2 = tracklist[1]->perigeeParameters();
505 startingPoint = m_vertexPointEstimator->getCirclesIntersectionPoint(&perigee1, &perigee2, flag, errorcode);
506 if (errorcode != 0) startingPoint = Amg::Vector3D::Zero(3);
507 ATH_MSG_DEBUG( "Starting point: (" << startingPoint(0) << ", " << startingPoint(1) << ", " << startingPoint(2) << ")" );
508
509 auto fitterState = m_vertexFitter->makeState(context);
510 m_vertexFitter->setMassInputParticles(s_trkMass[static_cast<size_t>(decay)][0], *fitterState);
511
512 std::unique_ptr<xAOD::Vertex> vertex(m_vertexFitter->fit(tracklist, startingPoint, *fitterState));
513 if (!vertex) {
514 ATH_MSG_DEBUG( "Vertex fit fails" );
515 return vertex;
516 }
517 if (vertex->chiSquared() > 50.) {
518 ATH_MSG_DEBUG( "Fit is successful, but vertex chi2 is too high, we are not going to save it (chi2 = " << vertex->chiSquared() << ")" );
519 vertex.reset();
520 return vertex;
521 }
522 ATH_MSG_DEBUG( "Fit is successful" );
523
524 // update trackParticleLinks()
525 vertex->clearTracks();
526 vertex->setTrackParticleLinks(trackParticleLinks);
527
528 return vertex;
529}
530
531
532std::unique_ptr<Trk::VxCascadeInfo> TrigBmuxComboHypo::fitCascade(
533 const EventContext& context,
534 const std::vector<ElementLink<xAOD::TrackParticleContainer>>& trackParticleLinks,
535 Decay decay) const {
536
537 if (trackParticleLinks.size() != (decay == kD0 ? 3 : 4)) {
538 ATH_MSG_WARNING( "fitCascade(): " << (decay == kD0 ? 3 : 4) << " tracks required for decay " << decay << ", but trackParticleLinks size = " << trackParticleLinks.size() );
539 return std::unique_ptr<Trk::VxCascadeInfo>(nullptr);
540 }
541
542 std::vector<std::vector<ElementLink<xAOD::TrackParticleContainer>>> vtx_trackParticleLinks;
543 switch (decay) {
544
545 case kD0: // B+ -> mu+ nu_mu anti-D0(-> K+ pi-)
546 vtx_trackParticleLinks = {{trackParticleLinks[1], trackParticleLinks[2]}, // B+.anti-D0.K+, B+.anti-D0.pi-
547 {trackParticleLinks[0]}}; // B+.mu+
548 break;
549
550 case kDstar: // B0 -> mu+ nu_mu D*-(-> anti-D0(-> K+ pi-) pi-)
551 vtx_trackParticleLinks = {{trackParticleLinks[1], trackParticleLinks[2]}, // B0.D*-.anti-D0.K+, B0.D*-.anti-D0.pi-
552 {trackParticleLinks[0], trackParticleLinks[3]}}; // B0.mu+, B0.D*-.pi-
553 break;
554
555 case kDs: // B_s0 -> mu+ nu_mu D_s-(->phi(-> K+ K-) pi-)
556 case kDplus: // B0 -> mu+ nu_mu D-(-> K+ pi- pi-)
557 case kLambdaC: // anti-Lambda_b0 -> mu+ nu_mu anti-Lambda_c-(-> anti-p K+ pi-)
558 vtx_trackParticleLinks = {{trackParticleLinks[1], trackParticleLinks[2], trackParticleLinks[3]}, // B_s0.D_s-.phi.K+, B_s0.D_s-.phi.K-, B_s0.D_s-.pi-
559 {trackParticleLinks[0]}}; // B_s0.mu+
560 break;
561
562 default:
563 ATH_MSG_WARNING( "fitCascade(): decay " << decay << " has not been defined in McTopologyTool" );
564 return std::unique_ptr<Trk::VxCascadeInfo>(nullptr);
565 break;
566 }
567
568 std::vector<std::vector<const xAOD::TrackParticle*>> vtx_tracks(vtx_trackParticleLinks.size());
569 for (size_t i = 0; i < vtx_trackParticleLinks.size(); ++i) {
570 for (size_t j = 0; j < vtx_trackParticleLinks[i].size(); ++j) {
571 vtx_tracks[i].push_back(*vtx_trackParticleLinks[i][j]);
572 }
573 }
574
575 auto state = m_vertexFitter->makeState(context);
576 m_vertexFitter->setRobustness(0, *state);
577
578 std::vector<Trk::VertexID> precedingVertices(1, m_vertexFitter->startVertex(vtx_tracks[0], s_trkMass[static_cast<size_t>(decay)][0], *state));
579 m_vertexFitter->nextVertex(vtx_tracks[1], s_trkMass[static_cast<size_t>(decay)][1], precedingVertices, *state);
580 std::unique_ptr<Trk::VxCascadeInfo> result(m_vertexFitter->fitCascade(*state));
581
582 if (result) {
583 ATH_MSG_DEBUG( "Cascade fit is successful: chi2 = " << result->fitChi2() << "; NDF = " << result->nDoF() );
584 result->setSVOwnership(true);
585
586 size_t i = 0;
587 for (xAOD::Vertex* vertex : result->vertices()) {
588 vertex->clearTracks();
589 vertex->setTrackParticleLinks(vtx_trackParticleLinks[i++]);
590 }
591 }
592
593 return result;
594}
595
596
598 xAOD::TrigBphys& triggerObject,
600 const xAOD::Vertex& vertex,
601 const std::vector<double>& trkMass) const {
602
603 // refitted track momentum as a 4-vector for mass hypothesis defined by the given decay value
605 std::vector<xAOD::TrackParticle::GenVecFourMom_t> momenta;
606 ATH_CHECK( vertex.vxTrackAtVertexAvailable() );
607 ATH_CHECK( vertex.vxTrackAtVertex().size() == trkMass.size() );
608 for (size_t i = 0; i < vertex.vxTrackAtVertex().size(); ++i) {
609 const Trk::TrackParameters* perigee = vertex.vxTrackAtVertex()[i].perigeeAtVertex();
610 ATH_CHECK( perigee != nullptr );
611 const Amg::Vector3D& p = perigee->momentum();
612 momenta.emplace_back(p.x(), p.y(), p.z(), trkMass[i]);
613 momentum += momenta.back();
614 }
615
616 triggerObject.initialise(0, momentum.Eta(), momentum.Phi(), momentum.Pt(), type, momentum.M(), xAOD::TrigBphys::EF);
617
618 triggerObject.setFitmass(momentum.M());
619 triggerObject.setFitx(vertex.x());
620 triggerObject.setFity(vertex.y());
621 triggerObject.setFitz(vertex.z());
622 triggerObject.setFitchi2(vertex.chiSquared());
623 triggerObject.setFitndof(vertex.numberDoF());
624
625 // set all the particles associated with the decay
626 triggerObject.setTrackParticleLinks(vertex.trackParticleLinks());
627
629 "TrigBphys object:\n\t " <<
630 "roiId: " << triggerObject.roiId() << "\n\t " <<
631 "particleType: " << triggerObject.particleType() << "\n\t " <<
632 "level: " << triggerObject.level() << "\n\t " <<
633 "eta: " << triggerObject.eta() << "\n\t " <<
634 "phi: " << triggerObject.phi() << "\n\t " <<
635 "mass: " << triggerObject.mass() << "\n\t " <<
636 "fitmass: " << triggerObject.fitmass() << "\n\t " <<
637 "chi2/NDF: " << triggerObject.fitchi2() << " / " << triggerObject.fitndof() << "\n\t " <<
638 "vertex: (" << triggerObject.fitx() << ", " << triggerObject.fity() << ", " << triggerObject.fitz() << ")" );
639
640 return StatusCode::SUCCESS;
641}
642
643
645 std::vector<xAOD::TrigBphys*>& triggerObjects,
647 const Trk::VxCascadeInfo& vxCascadeInfo,
648 const Amg::Vector3D& beamSpotPosition) const {
649
650 const std::vector<xAOD::Vertex*>& vertices = vxCascadeInfo.vertices();
651 const std::vector<std::vector<TLorentzVector>>& momenta = vxCascadeInfo.getParticleMoms();
652 ATH_CHECK( triggerObjects.size() == vertices.size() );
653
654 for (size_t i = 0; i < vertices.size(); ++i) {
655 const xAOD::Vertex* vertex = vertices[i];
656 TLorentzVector momentum = std::accumulate(momenta[i].begin(), momenta[i].end(), TLorentzVector());
657 xAOD::TrigBphys* triggerObject = triggerObjects[i];
658 triggerObject->initialise(0, momentum.Eta(), momentum.Phi(), momentum.Pt(), xAOD::TrigBphys::UNKNOWNPTYPE, momentum.M(), xAOD::TrigBphys::EF);
659 triggerObject->setFitmass(momentum.M());
660 triggerObject->setFitx(vertex->x());
661 triggerObject->setFity(vertex->y());
662 triggerObject->setFitz(vertex->z());
663 triggerObject->setTrackParticleLinks(vertex->trackParticleLinks());
664 }
665
666 // D0/D(*)-/D_s-/Lambda_c+
667 triggerObjects[0]->setLxy(Lxy(vertices[1]->position(), vertices[0]->position(), momenta[0]));
668 triggerObjects[0]->setSecondaryDecayLink(ElementLink<xAOD::TrigBphysContainer>(m_trigBphysContainerKey.key(), triggerObjects[1]->index()));
669 ATH_CHECK( triggerObjects[0]->secondaryDecayLink().isValid() );
670
671 // B+/B0/B_s0/Lambda_b0
672 triggerObjects[1]->setParticleType(type);
673 triggerObjects[1]->setFitchi2(vxCascadeInfo.fitChi2());
674 triggerObjects[1]->setFitndof(vxCascadeInfo.nDoF());
675 triggerObjects[1]->setLxy(Lxy(beamSpotPosition, vertices[1]->position(), momenta[1]));
676 triggerObjects[1]->setLowerChainLink(ElementLink<xAOD::TrigBphysContainer>(m_trigBphysContainerKey.key(), triggerObjects[0]->index()));
677 ATH_CHECK( triggerObjects[1]->lowerChainLink().isValid() );
678
679 if (msgLvl(MSG::DEBUG)) {
680 const xAOD::TrigBphys* vtx0 = triggerObjects[0];
681 const xAOD::TrigBphys* vtx1 = triggerObjects[1];
683 "TrigBphys object:\n\t " <<
684 "particleType: " << vtx1->particleType() << "\n\t " <<
685 "chi2/NDF: " << vtx1->fitchi2() << " / " << vtx1->fitndof() << "\n\t " <<
686 "vertex0: (" << vtx0->fitx() << ", " << vtx0->fity() << ", " << vtx0->fitz() << ")\n\t " <<
687 "vertex1: (" << vtx1->fitx() << ", " << vtx1->fity() << ", " << vtx1->fitz() << ")\n\t " <<
688 "Lxy(B): " << vtx1->lxy() << "\n\t " <<
689 "Lxy(D): " << vtx0->lxy() );
690 }
691
692 return StatusCode::SUCCESS;
693}
694
695
697
698 if (lhs->charge() * rhs->charge() < 0.) return false;
699 return (ROOT::Math::VectorUtil::DeltaR(lhs->genvecP4(), rhs->genvecP4()) < m_deltaR);
700}
701
702
703bool TrigBmuxComboHypo::isInSameRoI(const xAOD::Muon* muon, const xAOD::TrackParticle* track) const {
704
705 auto p_mu = muon->genvecP4();
706 auto p_trk = track->genvecP4();
707 return (ROOT::Math::VectorUtil::DeltaPhi(p_mu, p_trk) < m_roiPhiWidth && std::abs(p_mu.eta() - p_trk.eta()) < m_roiEtaWidth);
708}
709
710
711double TrigBmuxComboHypo::getTrkImpactParameterZ0(const EventContext& ctx, const xAOD::TrackParticle& track, const Amg::Vector3D& vertex) const {
712
713 std::unique_ptr<const Trk::Perigee> perigee(m_trackToVertexTool->perigeeAtVertex(ctx, track, vertex));
714 return (perigee ? perigee->parameters()[Trk::z0] : -1000.);
715}
716
717
718double TrigBmuxComboHypo::Lxy(const Amg::Vector3D& productionVertex, const Amg::Vector3D& decayVertex, const std::vector<TLorentzVector>& momenta) const {
719
720 XYVector R(decayVertex.x() - productionVertex.x(), decayVertex.y() - productionVertex.y());
721 XYVector pT;
722 for (const auto& p : momenta) {
723 pT += XYVector(p.Px(), p.Py());
724 }
725 return R.Dot(pT.unit());
726}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
int charge3(const T &p)
Definition AtlasPID.h:995
Base class for elements of a container that can have aux data.
ElementLink< xAOD::TrackParticleContainer > linkTrack(const xAOD::TrackParticle *trk)
void decisionIDs(const Decision *d, DecisionIDContainer &id)
Extracts DecisionIDs stored in the Decision object.
size_t size() const
Number of registered mappings.
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)
bool msgLvl(const MSG::Level lvl) const
ComboHypo(const std::string &name, ISvcLocator *pSvcLocator)
Definition ComboHypo.cxx:13
const SG::WriteHandleKeyArray< TrigCompositeUtils::DecisionContainer > & decisionsOutput() const
Definition ComboHypo.h:42
const Combo::MultiplicityReqMap & triggerMultiplicityMap() const
Definition ComboHypo.h:43
ToolHandleArray< ComboHypoToolBase > & hypoTools()
Definition ComboHypo.h:45
const SG::ReadHandleKeyArray< TrigCompositeUtils::DecisionContainer > & decisionsInput() const
Definition ComboHypo.h:41
virtual StatusCode initialize() override
Definition ComboHypo.cxx:22
size_type size() const noexcept
Returns the number of elements in the collection.
TrigCompositeUtils::DecisionContainer & decisions()
const TrigCompositeUtils::DecisionContainer & previousDecisions() const
xAOD::TrigBphysContainer & trigBphysCollection()
Amg::Vector3D beamSpotPosition() const
const EventContext & context() const
Group of local monitoring quantities and retain correlation when filling histograms
Declare a monitored scalar variable.
pointer_type ptr()
Dereference the pointer.
Gaudi::Property< float > m_BsToDs_chi2
double getTrkImpactParameterZ0(const EventContext &ctx, const xAOD::TrackParticle &track, const Amg::Vector3D &vertex) const
Returns the longitudinal impact parameter z0 of the track w.r.t.
Gaudi::Property< double > m_BdToD_minPionPt
Gaudi::Property< std::pair< double, double > > m_LambdaBToLambdaC_LambdaCMassRange
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_trackParticleContainerKey
Gaudi::Property< bool > m_BsToDs
Gaudi::Property< float > m_BsToDs_LxyBs
Gaudi::Property< std::pair< double, double > > m_BdToD_massRange
bool isInSameRoI(const xAOD::Muon *, const xAOD::TrackParticle *) const
Checks that the given track is close enough to the muon, i.e.
Gaudi::Property< float > m_BToD0_chi2
Gaudi::Property< bool > m_BdToD
Gaudi::Property< std::pair< double, double > > m_LambdaBToLambdaC_massRange
TrigCompositeUtils::DecisionIDContainer m_allowedIDs
Gaudi::Property< bool > m_BToD0_makeDstar
Gaudi::Property< size_t > m_fitAttemptsWarningThreshold
Gaudi::Property< float > m_BsToDs_LxyDs
SG::ReadHandleKey< xAOD::MuonContainer > m_muonContainerKey
ToolHandle< Trk::TrkVKalVrtFitter > m_vertexFitter
Gaudi::Property< float > m_BToD0_LxyB
Gaudi::Property< float > m_BdToD_LxyD
std::unique_ptr< xAOD::Vertex > fit(const EventContext &context, const std::vector< ElementLink< xAOD::TrackParticleContainer > > &trackParticleLinks, Decay decay) const
Perform a vertex fit on selected tracks.
StatusCode createDecisionObjects(TrigBmuxState &) const
Gaudi::Property< double > m_BToD0_minD0Pt
Gaudi::Property< double > m_LambdaBToLambdaC_minPionPt
double Lxy(const Amg::Vector3D &productionVertex, const Amg::Vector3D &decayVertex, const std::vector< TLorentzVector > &momenta) const
Returns the transverse decay length of a particle Lxy in [mm].
SG::WriteHandleKey< xAOD::TrigBphysContainer > m_trigBphysContainerKey
Gaudi::Property< double > m_trkZ0
Gaudi::Property< double > m_BsToDs_minPionPt
ToolHandle< GenericMonitoringTool > m_monTool
bool isInMassRange(double mass, const std::pair< double, double > &range) const
Checks that the given mass value falls into the specified range.
Gaudi::Property< double > m_BdToD_minKaonPt
Gaudi::Property< double > m_BToD0_minDstarPionPt
Gaudi::Property< float > m_BdToD_chi2
Gaudi::Property< std::pair< double, double > > m_BToD0_DstarMassRange
Gaudi::Property< double > m_roiEtaWidth
Gaudi::Property< double > m_BdToD_minDPt
Gaudi::Property< float > m_BdToD_LxyBd
static const std::vector< std::vector< std::vector< double > > > s_trkMass
Gaudi::Property< std::pair< double, double > > m_BsToDs_DsMassRange
ToolHandle< Reco::ITrackToVertex > m_trackToVertexTool
Gaudi::Property< float > m_LambdaBToLambdaC_LxyLc
Gaudi::Property< double > m_LambdaBToLambdaC_minProtonPt
Gaudi::Property< double > m_BsToDs_minDsPt
Gaudi::Property< float > m_BToD0_LxyD0
Gaudi::Property< size_t > m_fitAttemptsBreakThreshold
StatusCode findBmuxCandidates(TrigBmuxState &) const
Gaudi::Property< double > m_BsToDs_minKaonPt
Gaudi::Property< std::pair< double, double > > m_BsToDs_phiMassRange
Gaudi::Property< double > m_BToD0_minD0PionPt
Gaudi::Property< double > m_roiPhiWidth
Gaudi::Property< double > m_LambdaBToLambdaC_minLambdaCPt
Gaudi::Property< double > m_BToD0_minD0KaonPt
Gaudi::Property< bool > m_LambdaBToLambdaC
Gaudi::Property< float > m_LambdaBToLambdaC_LxyLb
std::unique_ptr< Trk::VxCascadeInfo > fitCascade(const EventContext &context, const std::vector< ElementLink< xAOD::TrackParticleContainer > > &trackParticleLinks, Decay decay) const
Perform a cascade vertex fit on selected tracks.
Gaudi::Property< double > m_deltaR
Gaudi::Property< float > m_BToD0_LxyBd
Gaudi::Property< bool > m_BToD0
StatusCode fillTriggerObjects(std::vector< xAOD::TrigBphys * > &triggerObjects, xAOD::TrigBphys::pType type, const Trk::VxCascadeInfo &vxCascadeInfo, const Amg::Vector3D &beamSpotPosition) const
Fill the trigger object that may be stored for debugging or matching for a cascade vertex.
Gaudi::Property< double > m_BToD0_minDstarPt
bool isIdenticalTracks(const xAOD::TrackParticle *lhs, const xAOD::TrackParticle *rhs) const
Returns false for the tracks with opposite charges.
Gaudi::Property< bool > m_makeCascadeFit
SG::ReadCondHandleKey< InDet::BeamSpotData > m_beamSpotKey
Gaudi::Property< double > m_LambdaBToLambdaC_minKaonPt
StatusCode fillTriggerObject(xAOD::TrigBphys &triggerObject, xAOD::TrigBphys::pType type, const xAOD::Vertex &vertex, const std::vector< double > &trkMass) const
Fill the trigger object that may be stored for debugging or matching.
Gaudi::Property< float > m_LambdaBToLambdaC_chi2
virtual StatusCode execute(const EventContext &context) const override
virtual StatusCode initialize() override
TrigBmuxComboHypo()=delete
Gaudi::Property< std::pair< double, double > > m_BToD0_D0MassRange
Gaudi::Property< double > m_BToD0_maxDstarPionZ0
Gaudi::Property< std::pair< double, double > > m_BdToD_DMassRange
Gaudi::Property< float > m_cascadeChi2
ToolHandle< InDet::VertexPointEstimator > m_vertexPointEstimator
Gaudi::Property< std::pair< double, double > > m_BsToDs_massRange
Gaudi::Property< std::pair< double, double > > m_BToD0_massRange
State class for TrigBmuxComboHypo algorithm.
std::vector< Muon > muons
xAOD::TrigBphys * addTriggerObject(size_t muonIndex)
std::vector< size_t > trigBphysMuonIndices
std::vector< xAOD::TrigBphys * > addTriggerObjects(size_t n, size_t muonIndex)
const Amg::Vector3D & momentum() const
Access method for the momentum.
double fitChi2() const
const std::vector< std::vector< TLorentzVector > > & getParticleMoms() const
const std::vector< xAOD::Vertex * > & vertices() const
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzM4D< double > > GenVecFourMom_t
Base 4 Momentum type for TrackParticle.
GenVecFourMom_t genvecP4() const
The full 4-momentum of the particle : GenVector form.
float charge() const
Returns the charge.
int fitndof() const
accessor method: ndof from vertex fit
void setFitchi2(float FitChi2)
set method: chi2 from vertex fit
float pt() const
accessor method: pt
void setFitx(float FitX)
set method: x position of vertex
uint32_t roiId() const
accessor method: ID of L1 RoI
void setFity(float FitY)
set method: y position of vertex
float eta() const
accessor method: eta
pType particleType() const
accessor method: particle Type
float phi() const
accessor method: phi
float fitchi2() const
accessor method: chi2 from vertex fit
void setFitndof(int FitNdof)
set method: ndof from vertex fit
void setFitz(float FitZ)
set method: z position of vertex
float lxy() const
accessor method: lxy
float fitx() const
accessor method: x position of vertex
void setFitmass(float FitMass)
set method: mass from vertex fit
float fitz() const
accessor method: z position of vertex
float fitmass() const
accessor method: mass from vertex fit
float mass() const
accessor method: mass
void setMass(float)
Set the mass of the object.
pType
enum for different particle types
float fity() const
accessor method: y position of vertex
levelType level() const
accessor method: level Type
void setTrackParticleLinks(const std::vector< ElementLink< TrackParticleContainer > > &links)
Set the track particle links on the object.
void setLowerChainLink(const ElementLink< xAOD::TrigBphysContainer_v1 > &link)
set method: link to lowerChain decay particle
bool addObjectCollectionLink(const std::string &collectionName, const ElementLink< CONTAINER > &link)
Add a link to a single object within a collection. Performs de-duplication.
bool setObjectLink(const std::string &name, const ElementLink< CONTAINER > &link)
Set the link to an object.
Eigen::Matrix< double, 3, 1 > Vector3D
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
HLT::Identifier createLegName(const HLT::Identifier &chainIdentifier, size_t counter)
Generate the HLT::Identifier which corresponds to a specific leg of a given chain.
unsigned int DecisionID
const std::string & viewString()
const std::string & roiString()
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.
const std::string & featureString()
const std::string & comboHypoAlgNodeName()
std::set< DecisionID > DecisionIDContainer
SG::WriteHandle< DecisionContainer > createAndStore(const SG::WriteHandleKey< DecisionContainer > &key, const EventContext &ctx)
Creates and right away records the DecisionContainer with the key.
LinkInfo< T > findLink(const Decision *start, const std::string &linkName, const bool suppressMultipleLinksWarning=false)
Perform a recursive search for ElementLinks of type T and name 'linkName', starting from Decision obj...
const std::string & seedString()
void decisionIDs(const Decision *d, DecisionIDContainer &destination)
Extracts DecisionIDs stored in the Decision object.
bool isAnyIDPassing(const Decision *d, const DecisionIDContainer &required)
Checks if any of the DecisionIDs passed in arg required is availble in Decision object.
ElementLink< DecisionContainer > decisionToElementLink(const Decision *d, const EventContext &ctx)
Takes a raw pointer to a Decision and returns an ElementLink to the Decision.
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ z0
Definition ParamDefs.h:64
ParametersBase< TrackParametersDim, Charged > TrackParameters
ElementLink< T > makeLink(const SG::View *view, const SG::ReadHandle< T > &handle, size_t index)
Create EL to a collection in view.
Definition ViewHelper.h:309
auto makeHandle(const SG::View *view, const KEY &key, const EventContext &ctx)
Create a view handle from a handle key.
Definition ViewHelper.h:273
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
TrigBphys_v1 TrigBphys
Definition TrigBphys.h:18
TrackParticle_v1 TrackParticle
Reference the current persistent version:
Vertex_v1 Vertex
Define the latest version of the vertex class.
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
TrigBphysContainer_v1 TrigBphysContainer