127 {
128
129 auto& muons = state.
muons;
130 muons.clear();
131
132
133 std::vector<int> nTrk;
134 auto mon_nMuon = Monitored::Scalar<int>("nMuon", 0);
136 auto mon_nBPhysObject = Monitored::Scalar<int>("nBPhysObject", 0);
137
139 mon_nMuon, mon_nTrk, mon_nBPhysObject);
140
143
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();
154 mon_nMuon++;
155
156
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
166 auto view = *viewLinkInfo.link;
167
170 const auto roi = *roiLinkInfo.link;
171
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);
181 if (roi->composite() && !
isInSameRoI(muon, track))
continue;
183 }
184
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()); });
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
193 ATH_MSG_DEBUG(
"Dump found tracks before vertex fit: " << tracks.size() <<
" candidates" );
194 for (const auto& trackEL : tracks) {
197 }
198 }
199
200 size_t iterations = 0;
201 bool isOverWarningThreshold = false;
202 for (size_t itrk1 = 0; itrk1 < tracks.size(); ++itrk1) {
205 auto charge1 = trk1->
charge();
206
207 for (size_t itrk2 = 0; itrk2 < tracks.size(); ++itrk2) {
208 if (itrk2 == itrk1) continue;
211 auto charge2 = trk2->
charge();
212
213
215 std::unique_ptr<xAOD::Vertex> vtx_D0;
218 charge1 * charge2 < 0. &&
224 vtx_D0 =
fit(state.
context(), {linkTrack(muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)), tracks[itrk1], tracks[itrk2]},
kD0);
225 ++iterations;
226
228 ATH_MSG_DEBUG(
"Partially reconstructed B+ -> mu+ nu_mu anti-D0(-> K+ pi-) candidate has been created from { " << itrk1 <<
", " << itrk2 <<
" }" );
230 auto result =
fitCascade(state.
context(), {linkTrack(muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)),
231 tracks[itrk1], tracks[itrk2]},
kD0);
232
233 if (result &&
235 std::vector<xAOD::TrigBphys*> triggerObjects = state.
addTriggerObjects(2, muonIndex);
237 p_D0 = ROOT::Math::PtEtaPhiMVector(triggerObjects[0]->
pt(), triggerObjects[0]->
eta(), triggerObjects[0]->
phi(), triggerObjects[0]->fitmass());
240
241
244 mon_nBPhysObject++;
245 }
246 }
247 }
248 else {
251 p_D0 = ROOT::Math::PtEtaPhiMVector(triggerObject->
pt(), triggerObject->
eta(), triggerObject->
phi(), triggerObject->
fitmass());
252 triggerObject->
setMass((p_mu + p_D0).M());
255 mon_nBPhysObject++;
256 }
257 }
258 }
259
260 for (size_t itrk3 = 0; itrk3 < tracks.size(); ++itrk3) {
261 if (itrk3 == itrk1 || itrk3 == itrk2) continue;
265
266 std::vector<ElementLink<xAOD::TrackParticleContainer>>
trackParticleLinks = {
linkTrack(
muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle)),
267 tracks[itrk1], tracks[itrk2], tracks[itrk3]};
268
269
274
275 bool makeDstar = true;
277 std::unique_ptr<const Trk::Perigee> perigee(
m_trackToVertexTool->perigeeAtVertex(state.
context(), *trk3, vtx_D0->position()));
279 }
280
281 if (makeDstar) {
284 if (result &&
288
289 std::vector<xAOD::TrigBphys*> triggerObjects = state.
addTriggerObjects(2, muonIndex);
291 triggerObjects[1]->setSecondaryDecayLink(
D0);
292 mon_nBPhysObject++;
293 }
294 }
295 else {
302
304 "TrigBphys object:\n\t " <<
305 "roiId: " << Dstar->
roiId() <<
"\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 }
319
320
322 itrk3 > itrk2 &&
323 charge1 * charge2 < 0. && charge2 * charge3 > 0. &&
331 ++iterations;
332
334 ATH_MSG_DEBUG(
"Partially reconstructed B0 -> mu+ nu_mu D-(-> K+ pi- pi-) candidate has been created from { " << itrk1 <<
", " << itrk2 <<
", " << itrk3 <<
" }" );
337 if (result &&
341
342 std::vector<xAOD::TrigBphys*> triggerObjects = state.
addTriggerObjects(2, muonIndex);
344 mon_nBPhysObject++;
345 }
346 }
347 else {
351 triggerObject->
setMass((p_mu + p_D).M());
352 mon_nBPhysObject++;
353 }
354 }
355 }
356
357
359 itrk2 > itrk1 &&
360 charge1 * charge2 < 0. &&
369 ++iterations;
370
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 <<
" }" );
375 if (result &&
379
380 std::vector<xAOD::TrigBphys*> triggerObjects = state.
addTriggerObjects(2, muonIndex);
382 mon_nBPhysObject++;
383 }
384 }
385 else {
389 triggerObject->
setMass((p_mu + p_Ds).M());
390 mon_nBPhysObject++;
391 }
392 }
393 }
394
395
397 charge1 *
charge3 > 0. && charge1 * charge2 < 0. &&
405 ++iterations;
406
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 <<
" }" );
411 if (result &&
415
416 std::vector<xAOD::TrigBphys*> triggerObjects = state.
addTriggerObjects(2, muonIndex);
418 mon_nBPhysObject++;
419 }
420 }
421 else {
425 triggerObject->
setMass((p_mu + p_LambdaC).M());
426 mon_nBPhysObject++;
427 }
428 }
429 }
430
431 }
432 vtx_D0.reset();
433
434 }
435
437 ATH_MSG_WARNING( iterations <<
" combinations for vertex fitter have been processed; " << mon_nBPhysObject <<
" vertices have been created" );
438 isOverWarningThreshold = true;
439 }
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}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
ElementLink< xAOD::TrackParticleContainer > linkTrack(const xAOD::TrackParticle *trk)
void decisionIDs(const Decision *d, DecisionIDContainer &id)
Extracts DecisionIDs stored in the Decision object.
size_type size() const noexcept
Returns the number of elements in the collection.
const TrigCompositeUtils::DecisionContainer & previousDecisions() const
Amg::Vector3D beamSpotPosition() const
const EventContext & context() const
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
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.
Gaudi::Property< double > m_BToD0_minD0Pt
Gaudi::Property< double > m_LambdaBToLambdaC_minPionPt
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_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
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_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< 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
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
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
Gaudi::Property< std::pair< double, double > > m_BsToDs_massRange
Gaudi::Property< std::pair< double, double > > m_BToD0_massRange
xAOD::TrigBphys * addTriggerObject(size_t muonIndex)
std::vector< xAOD::TrigBphys * > addTriggerObjects(size_t n, size_t muonIndex)
GenVecFourMom_t genvecP4() const
The full 4-momentum of the particle : GenVector form.
float charge() const
Returns the charge.
float pt() const
accessor method: pt
void setMass(float)
Set the mass of the object.
void setLowerChainLink(const ElementLink< xAOD::TrigBphysContainer_v1 > &link)
set method: link to lowerChain decay particle
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
const std::string & viewString()
const std::string & roiString()
bool isAnyIDPassing(const Decision *d, const DecisionIDContainer &required)
Checks if any of the DecisionIDs passed in arg required is availble in Decision object.
ElementLink< T > makeLink(const SG::View *view, const SG::ReadHandle< T > &handle, size_t index)
Create EL to a collection in view.
auto makeHandle(const SG::View *view, const KEY &key, const EventContext &ctx)
Create a view handle from a handle key.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::vector< ElementLink< xAOD::TrackParticleContainer > > trackParticleLinks(const xAOD::TauJet *tau, xAOD::TauJetParameters::TauTrackFlag flag=xAOD::TauJetParameters::TauTrackFlag::classifiedCharged)
TrackParticle_v1 TrackParticle
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".
static constexpr CLID ID()
static constexpr double mD0
static constexpr double mProton
static constexpr double mPion
static constexpr double mMuon
static constexpr double mKaon