21 #include "GaudiKernel/IPartPropSvc.h"
22 #include "HepPDT/ParticleDataTable.hh"
23 #include "AthLinks/ElementLink.h"
52 IPartPropSvc* partPropSvc = 0;
53 StatusCode sc = service(
"PartPropSvc", partPropSvc,
true);
55 ATH_MSG_ERROR(
"Could not initialize Particle Properties Service");
56 return StatusCode::SUCCESS;
58 auto particleDataTable = partPropSvc->PDT();
59 const HepPDT::ParticleData* pd_mu = particleDataTable->particle(
MC::MUON);
63 if (
m_doTagAndProbe)
ATH_MSG_WARNING(
"You have requested tag and probe mode. Duplicate mu+trk pairs WILL be allowed, charge ordering WILL NOT be done. Tag track will be first in each candidate");
67 bool illogicalOptions(
false);
69 ATH_MSG_WARNING(
"You are requesting incompatible combinations of muons and tracks in the pairs. JpsiCandidates will be EMPTY!");
70 illogicalOptions=
true;
73 ATH_MSG_WARNING(
"You are requesting Tag and Probe analysis but have not requested mu+trk mode. This is impossible. JpsiCandidates will be EMPTY!");
74 illogicalOptions=
true;
77 ATH_MSG_WARNING(
"You are requesting a combined muon measurement to be used with pairs involving non-muon tracks. Not permitted. JpsiCandidates will be EMPTY!");
78 illogicalOptions=
true;
81 ATH_MSG_WARNING(
"You are requesting incompatible combinations of combined muons non-combined muons in the pairs. JpsiCandidates will be EMPTY!");
82 illogicalOptions=
true;
85 ATH_MSG_WARNING(
"You are requesting at least one muon to be combined in a tag and probe analysis. This doesn't make sense. JpsiCandidates will be EMPTY!");
86 illogicalOptions=
true;
89 ATH_MSG_WARNING(
"You are requesting incompatible combinations of charges in the pairs. JpsiCandidates will be EMPTY!");
90 illogicalOptions=
true;
94 ATH_MSG_WARNING(
"You are requesting same-sign or all-sign combinations in a tag and probe analysis. This doesn't make sense. JpsiCandidates will be EMPTY!");
95 illogicalOptions=
true;
98 if (illogicalOptions)
return StatusCode::FAILURE;;
103 return StatusCode::SUCCESS;
114 m_atLeastOneComb(true),
115 m_useCombMeasurement(false),
116 m_useV0Fitter(false),
122 m_trkThresholdPt(0.0),
123 m_invMassUpper(100000.0),
125 m_collAngleTheta(0.0),
131 m_iVertexFitter(
"Trk::TrkVKalVrtFitter"),
132 m_iV0VertexFitter(
"Trk::V0VertexFitter"),
133 m_trkSelector(
"InDet::TrackSelectorTool"),
134 m_vertexEstimator(
"InDet::VertexPointEstimator"),
136 m_doTagAndProbe(false),
137 m_forceTagAndProbe(false)
140 declareInterface<JpsiFinder>(
this);
184 return StatusCode::FAILURE;
191 std::vector<const xAOD::TrackParticleContainer*> importedMuonTrackCollections;
195 if(!handle.isValid()){
196 ATH_MSG_WARNING(
"No muon TrackParticle collection with name " << handle.key() <<
" found in StoreGate!");
197 return StatusCode::FAILURE;
199 ATH_MSG_DEBUG(
"Found muon TrackParticle collection " << handle.key() <<
" in StoreGate!");
200 ATH_MSG_DEBUG(
"Muon TrackParticle container size "<< handle->size());
201 importedMuonTrackCollections.push_back(handle.cptr());
210 ATH_MSG_WARNING(
"No TrackParticle collection with name " << handle.
key() <<
" found in StoreGate!");
211 return StatusCode::FAILURE;
213 importedTrackCollection = handle.
cptr();
214 ATH_MSG_DEBUG(
"Found TrackParticle collection " << handle.
key() <<
" in StoreGate!");
219 typedef std::vector<const xAOD::TrackParticle*>
TrackBag;
220 typedef std::vector<const xAOD::Muon*>
MuonBag;
227 for (trkCItr=importedTrackCollection->begin(); trkCItr!=importedTrackCollection->end(); ++trkCItr) {
231 theIDTracksAfterSelection.push_back(TP);
233 if (theIDTracksAfterSelection.size() == 0)
return StatusCode::SUCCESS;;
234 ATH_MSG_DEBUG(
"Number of tracks after ID track selection: " << theIDTracksAfterSelection.size());
238 MuonBag theMuonsAfterSelection;
240 for (
auto muItr=importedMuonCollection->
begin(); muItr!=importedMuonCollection->
end(); ++muItr) {
241 if ( *muItr == NULL )
continue;
242 if (!(*muItr)->inDetTrackParticleLink().isValid())
continue;
244 if ( muonTrk==NULL)
continue;
249 if ( (*muItr)->muonType() == xAOD::Muon::SiliconAssociatedForwardMuon && !
m_useCombMeasurement)
continue;
250 theMuonsAfterSelection.push_back(*muItr);
252 if (theMuonsAfterSelection.size() == 0)
return StatusCode::SUCCESS;;
253 ATH_MSG_DEBUG(
"Number of muons after selection: " << theMuonsAfterSelection.size());
257 std::vector<JpsiCandidate> jpsiCandidates;
265 std::vector<JpsiCandidate> selectCandidates;
266 for(
auto &cand : jpsiCandidates) {
if(cand.muonTypes!=
TT) selectCandidates.push_back(cand); }
267 selectCandidates.swap(jpsiCandidates);
268 ATH_MSG_DEBUG(
"Number of candidates after requirement of at least 1 combined muon: " << jpsiCandidates.size() );
276 for (
auto jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
277 (*jpsiItr).collection1 = importedTrackCollection;
278 (*jpsiItr).collection2 = importedTrackCollection;
283 for (
auto jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
285 (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
286 (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
287 (*jpsiItr).collection1 = importedTrackCollection;
288 (*jpsiItr).collection2 = importedTrackCollection;
291 if (!(*jpsiItr).muon1->combinedTrackParticleLink().isValid()) {
292 (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
293 (*jpsiItr).collection1 = importedTrackCollection;
296 if (!(*jpsiItr).muon2->combinedTrackParticleLink().isValid()) {
297 (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
298 (*jpsiItr).collection2 = importedTrackCollection;
301 if ((*jpsiItr).muon1->combinedTrackParticleLink().isValid()) {
302 (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::CombinedTrackParticle );
303 bool foundCollection(
false);
305 for (
auto muTrkCollItr=importedMuonTrackCollections.begin(); muTrkCollItr!=importedMuonTrackCollections.end(); ++muTrkCollItr) {
306 if (
isContainedIn((*jpsiItr).trackParticle1,*muTrkCollItr)) { (*jpsiItr).collection1 = *muTrkCollItr; foundCollection=
true;
break;}
308 if (!foundCollection) {
309 (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
310 (*jpsiItr).collection1 = importedTrackCollection;
311 ATH_MSG_WARNING(
"Muon track from muon of author " << (*jpsiItr).muon1->author() <<
" not found in muon track collections you have provided.");
312 ATH_MSG_WARNING(
"Defaulting to ID track collection - combined measurement will not be used");
316 if ((*jpsiItr).muon2->combinedTrackParticleLink().isValid()) {
317 (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::CombinedTrackParticle );
318 bool foundCollection(
false);
320 for (
auto muTrkCollItr=importedMuonTrackCollections.begin(); muTrkCollItr!=importedMuonTrackCollections.end(); ++muTrkCollItr) {
321 if (
isContainedIn((*jpsiItr).trackParticle2,*muTrkCollItr)) { (*jpsiItr).collection2 = *muTrkCollItr; foundCollection=
true;
break;}
323 if (!foundCollection) {
324 (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
325 (*jpsiItr).collection2 = importedTrackCollection;
326 ATH_MSG_WARNING(
"Muon track from muon of author " << (*jpsiItr).muon2->author() <<
" not found in muon track collections you have provided.");
327 ATH_MSG_WARNING(
"Defaulting to ID track collection - combined measurement will not be used");
337 std::vector<JpsiCandidate> selectCandidates;
338 for(
auto& cand : jpsiCandidates){
339 bool reject = (fabs(cand.trackParticle1->pt()) <
m_higherPt) && (fabs(cand.trackParticle2->pt()) <
m_higherPt);
340 if(!reject) selectCandidates.push_back(cand);
342 selectCandidates.swap(jpsiCandidates);
343 ATH_MSG_DEBUG(
"Number of candidates after higherPt cut: " << jpsiCandidates.size() );
347 std::vector<JpsiCandidate> sortedJpsiCandidates;
350 ATH_MSG_DEBUG(
"Number of candidates after charge selection: " << sortedJpsiCandidates.size() );
354 std::vector<JpsiCandidate> selectCandidates;
355 for(
auto& cand : sortedJpsiCandidates){
356 double deltatheta = fabs( cand.trackParticle1->theta() - cand.trackParticle2->theta() );
359 if(!reject) selectCandidates.push_back(cand);
361 sortedJpsiCandidates.swap(selectCandidates);
362 ATH_MSG_DEBUG(
"Number of collimated candidates: " << sortedJpsiCandidates.size() );
368 std::vector<JpsiCandidate> selectCandidates;
369 for(
auto& cand : sortedJpsiCandidates){
371 bool reject = invMass < m_invMassLower || invMass >
m_invMassUpper;
372 if(!reject) selectCandidates.push_back(cand);
374 selectCandidates.swap(sortedJpsiCandidates);
375 ATH_MSG_DEBUG(
"Number of candidates passing invariant mass selection: " << sortedJpsiCandidates.size() );
378 ATH_MSG_DEBUG(
"Number of pairs passing all selections and going to vertexing: " << sortedJpsiCandidates.size() );
379 if (sortedJpsiCandidates.size() == 0)
return StatusCode::SUCCESS;;
380 std::vector<const xAOD::TrackParticle*> theTracks;
381 std::vector<const xAOD::Muon*> theStoredMuons;
383 for(
auto jpsiItr=sortedJpsiCandidates.begin(); jpsiItr!=sortedJpsiCandidates.end(); ++jpsiItr) {
385 theTracks.push_back((*jpsiItr).trackParticle1);
386 theTracks.push_back((*jpsiItr).trackParticle2);
387 std::unique_ptr<xAOD::Vertex> myVxCandidate {
fit(theTracks,importedTrackCollection)};
390 double chi2 = myVxCandidate->chiSquared();
396 if(!validtrk)
ATH_MSG_WARNING(
"Problem setting tracks " << __FILE__ <<
':' << __LINE__);
398 theStoredMuons.clear();
399 theStoredMuons.push_back((*jpsiItr).muon1);
400 if (
m_mumu) theStoredMuons.push_back((*jpsiItr).muon2);
401 bool valid = jpsiHelper.
setMuons(theStoredMuons,importedMuonCollection);
405 vxContainer.
push_back(std::move(myVxCandidate));
416 return StatusCode::SUCCESS;;
431 if(concreteVertexFitter == 0) {
432 ATH_MSG_FATAL(
"The vertex fitter passed is not a V0 Vertex Fitter");
442 if (errorcode != 0) {startingPoint(0) = 0.0; startingPoint(1) = 0.0; startingPoint(2) = 0.0;}
447 if(myVxCandidate != 0){
448 std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
452 newLinkVector.push_back( mylink ); }
460 return myVxCandidate;
465 if(myVxCandidate != 0){
466 std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
470 newLinkVector.push_back( mylink ); }
477 return myVxCandidate;
493 std::vector<JpsiCandidate>
JpsiFinder::getPairs(
const std::vector<const xAOD::TrackParticle*> &TracksIn)
const {
495 std::vector<JpsiCandidate> myPairs;
497 std::vector<const xAOD::TrackParticle*>::const_iterator outerItr;
498 std::vector<const xAOD::TrackParticle*>::const_iterator innerItr;
500 if(TracksIn.size()>=2){
501 for(outerItr=TracksIn.begin();outerItr<TracksIn.end();++outerItr){
502 for(innerItr=(outerItr+1);innerItr!=TracksIn.end();++innerItr){
506 myPairs.push_back(pair);
520 std::vector<JpsiCandidate> myPairs;
522 std::vector<const xAOD::Muon*>::const_iterator outerItr;
523 std::vector<const xAOD::Muon*>::const_iterator innerItr;
525 if(muonsIn.size()>=2){
526 for(outerItr=muonsIn.begin();outerItr<muonsIn.end();++outerItr){
527 for(innerItr=(outerItr+1);innerItr!=muonsIn.end();++innerItr){
528 pair.
muon1 = *innerItr;
529 pair.
muon2 = *outerItr;
534 if ( (mu1Comb && !mu2Comb) || (!mu1Comb && mu2Comb) ) pair.
muonTypes =
CT;
536 myPairs.push_back(pair);
550 std::vector<JpsiCandidate>
JpsiFinder::getPairs2Colls(
const std::vector<const xAOD::TrackParticle*> &tracks,
const std::vector<const xAOD::Muon*> &muons,
bool tagAndProbe)
const {
552 std::vector<JpsiCandidate> myPairs;
556 std::vector<const xAOD::TrackParticle*> tracksToKeep;
558 if(tracks.size()>=1 && muons.size()>=1){
560 bool trackIsMuon(
false);
562 auto& link =
mu->inDetTrackParticleLink();
563 if ( link.isValid() && *link == trk ) {
568 if (!trackIsMuon) tracksToKeep.push_back(trk);
571 }
else {tracksToKeep = tracks;}
573 if(tracksToKeep.size()>=1 && muons.size()>=1){
578 pair.
trackParticle1 =
mu->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
581 myPairs.push_back(pair);
607 return (mu1+mu2).M();
619 bool opposite(
false),
same(
false),
all(
false);
625 std::vector<JpsiCandidate> jpsis;
628 for(
auto jpsiItr=jpsisIn.cbegin();jpsiItr!=jpsisIn.cend();jpsiItr++){
629 bool oppCh(
false),sameCh(
false);
632 qOverP2=(*jpsiItr).trackParticle2->qOverP();
633 if(qOverP1*qOverP2<0.0) oppCh=
true;
634 if(qOverP1*qOverP2>0.0) sameCh=
true;
640 tmpJpsi.
muon1 = (*jpsiItr).muon2;
641 tmpJpsi.
muon2 = (*jpsiItr).muon1;
645 if (oppCh && (opposite ||
all) ) jpsis.push_back(tmpJpsi);
646 if (sameCh && (
same ||
all) ) jpsis.push_back(tmpJpsi);
659 return muon->passesIDCuts();
668 return std::find(theCollection->
begin(), theCollection->
end(), theTrack) != theCollection->
end();
677 double px = 0.,
py = 0.,
pz = 0.;
678 if (0 != vxCandidate) {