21 #include "AthLinks/ElementLink.h"
34 constexpr
double kMass = 493.677;
56 return StatusCode::FAILURE;
67 return StatusCode::SUCCESS;
75 m_trkThresholdPt(0.0),
80 m_jpsiCollectionKey(
"JpsiCandidates"),
83 m_TrkParticleCollection(
"TrackParticleCandidate"),
84 m_MuonsUsedInJpsi(
""),
85 m_excludeJpsiMuonsOnly(true),
86 m_excludeCrossJpsiTracks(false),
87 m_iVertexFitter(
"Trk::TrkVKalVrtFitter"),
88 m_trkSelector(
"InDet::TrackSelectorTool"),
92 m_trkTrippletMassUpper(-1.0),
93 m_trkTrippletMassLower(-1.0),
94 m_trkTrippletPt(-1.0),
96 m_TrkParticleGSFCollection(
""),
97 m_electronCollectionKey(
""),
98 m_candidateLimit(std::numeric_limits<size_t>::
max())
100 declareInterface<JpsiPlus1Track>(
this);
148 if(!jpsiCollectionhandle.
isValid()){
150 return StatusCode::FAILURE;
152 importedJpsiCollection = jpsiCollectionhandle.
cptr();
160 if(!TrkParticleHandle.
isValid()){
162 return StatusCode::FAILURE;
164 importedTrackCollection = TrkParticleHandle.
cptr();
167 ATH_MSG_DEBUG(
"Track container size "<< importedTrackCollection->size());
173 importedGSFTrackCollection =
h.cptr();
183 return StatusCode::FAILURE;
185 importedMuonCollection =
h.cptr();
197 return StatusCode::FAILURE;
199 importedElectronCollection =
h.cptr();
207 typedef std::vector<const xAOD::TrackParticle*>
TrackBag;
208 typedef std::vector<const xAOD::Electron*> ElectronBag;
213 for (
auto trkPBItr=importedTrackCollection->cbegin(); trkPBItr!=importedTrackCollection->cend(); ++trkPBItr) {
225 ATH_MSG_DEBUG(
"importedTrackCollection contains GSF tracks " << importedGSFTrackCollection->
size());
226 for (
auto trkPBItr=importedGSFTrackCollection->
cbegin(); trkPBItr!=importedGSFTrackCollection->
cend(); ++trkPBItr) {
236 if (theIDTracksAfterSelection.empty())
return StatusCode::SUCCESS;
237 ATH_MSG_DEBUG(
"Number of tracks after ID trkSelector: " << theIDTracksAfterSelection.size());
240 std::vector<const xAOD::Vertex*> selectedJpsiCandidates;
241 std::vector<const xAOD::TrackParticle*> jpsiTracks;
242 for(
auto vxcItr=importedJpsiCollection->
cbegin(); vxcItr!=importedJpsiCollection->
cend(); ++vxcItr) {
250 selectedJpsiCandidates.push_back(*vxcItr);
257 jpsiTracks.push_back(jpsiTP1);
258 jpsiTracks.push_back(jpsiTP2);
263 std::vector<double> massHypotheses;
267 massHypotheses.push_back(
kMass); massHypotheses.push_back(
piMass);
273 std::vector<double> massCuts;
277 for(
auto muon : *importedMuonCollection){
278 if(!
muon->inDetTrackParticleLink().isValid())
continue;
279 auto track =
muon->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
280 if(
track==
nullptr)
continue;
282 muonTracks.push_back(
track);
287 ElectronBag theElectronsAfterSelection;
288 if (importedElectronCollection && !importedElectronCollection->
empty()) {
289 for(
auto electron : *importedElectronCollection) {
290 if (!
electron->trackParticleLink().isValid())
continue;
292 elTrk =
electron->trackParticleLink().cachedElement();
293 if (!elTrk)
continue;
294 theElectronsAfterSelection.push_back(
electron);
295 electronTracks.push_back(elTrk);
297 if (
m_skipNoElectron && theElectronsAfterSelection.size() == 0)
return StatusCode::SUCCESS;
298 ATH_MSG_DEBUG(
"Number of electrons after selection: " << theElectronsAfterSelection.size());
301 std::vector<const xAOD::TrackParticle*> tracks(3,
nullptr);
303 for(
auto jpsiItr=selectedJpsiCandidates.cbegin(); jpsiItr!=selectedJpsiCandidates.cend(); ++jpsiItr) {
312 jpsiTracks.resize(2);
313 jpsiTracks[0] = jpsiTP1;
314 jpsiTracks[1] = jpsiTP2;
318 for (
auto trkItr=theIDTracksAfterSelection.cbegin(); trkItr!=theIDTracksAfterSelection.cend(); ++trkItr) {
321 return StatusCode::SUCCESS;
324 int linkedMuonTrk = 0;
327 if (linkedMuonTrk)
ATH_MSG_DEBUG(
"This id track is a muon track!");
329 if (linkedMuonTrk)
ATH_MSG_DEBUG(
"ID track removed: id track is slected to build Jpsi!");
335 int linkedElectronTrk = 0;
337 if (linkedElectronTrk)
ATH_MSG_DEBUG(
"This id track is an electron track!");
339 if (linkedElectronTrk)
ATH_MSG_DEBUG(
"ID track removed: id track is selected to build Jpsi!");
353 fabs(theThirdTP->
z0() + theThirdTP->
vz() - (*jpsiItr)->z()) >
m_trkDeltaZ )
361 bool passRoughMassCuts(
true);
369 if (!passRoughMassCuts)
continue;
373 std::unique_ptr<xAOD::Vertex> bVertex(
fit(tracks, importedTrackCollection, importedGSFTrackCollection));
381 if(!chi2CutPassed) {
ATH_MSG_DEBUG(
"Chi Cut failed!");
continue; }
388 bool masspTpassed =
true;
390 masspTpassed =
false;
391 for (
double masshypo3rd : massHypotheses) {
392 tripletMasses.push_back(masshypo3rd);
393 TLorentzVector bMomentum = bHelper.
totalP(tripletMasses);
394 tripletMasses.pop_back();
395 double bpt = bMomentum.Pt();
397 double bMass = bMomentum.M();
398 ATH_MSG_DEBUG(
"candidate pt/mass under track mass hypothesis of " << masshypo3rd <<
" is " << bpt <<
" / " << bMass);
400 if(masscut && PtPassed) { masspTpassed =
true;
break; }
405 std::vector<const xAOD::Vertex*> theJpsiPreceding;
406 theJpsiPreceding.push_back(*jpsiItr);
418 return StatusCode::SUCCESS;
436 constexpr
double jpsiTableMass = 3096.916;
440 std::array<int,2>
indices = {1, 2};
455 std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
460 newLinkVector.push_back( mylink );
474 double mass2,
double mass3)
476 const auto trk1V = trk[0]->p4();
477 double px1 = trk1V.Px();
478 double py1 = trk1V.Py();
479 double pz1 = trk1V.Pz();
480 double e1 = sqrt(px1*px1+py1*py1+pz1*pz1+mass1*mass1);
482 const auto trk2V = trk[1]->p4();
483 double px2 = trk2V.Px();
484 double py2 = trk2V.Py();
485 double pz2 = trk2V.Pz();
486 double e2 = sqrt(px2*px2+py2*py2+pz2*pz2+mass2*mass2);
488 const auto trk3V = trk[2]->p4();
489 double px3 = trk3V.Px();
490 double py3 = trk3V.Py();
491 double pz3 = trk3V.Pz();
492 double e3 = sqrt(px3*px3+py3*py3+pz3*pz3+mass3*mass3);
495 double pxSum=px1+px2+px3;
496 double pySum=py1+py2+py3;
497 double pzSum=pz1+pz2+pz3;
500 double M=sqrt((eSum*eSum)-(pxSum*pxSum)-(pySum*pySum)-(pzSum*pzSum));