ATLAS Offline Software
JpsiFinder.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 // JpsiFinder
8 // James Catmore <James.Catmore@cern.ch>
9 // Evelina Bouhova-Thacker <e.bouhova@cern.ch>
10 // Daniel.Scheirich <daniel.scheirich@cern.ch>
11 // Migration to xAOD
12 // ----------------------------------------------------------------------------
13 // ****************************************************************************
14 
16 #include "xAODBPhys/BPhysHelper.h"
18 #include "HepPDT/ParticleDataTable.hh"
19 #include "AthLinks/ElementLink.h"
20 #include "xAODTracking/Vertex.h"
26 namespace Analysis {
27 
29 
30  // retrieving vertex Fitter
31  ATH_CHECK(m_iVertexFitter.retrieve());
32 
33  // retrieving V0 Fitter
34  ATH_CHECK(m_iV0VertexFitter.retrieve(DisableTool{!m_useV0Fitter }));
35 
36  // Get the track selector tool from ToolSvc
37  ATH_CHECK(m_trkSelector.retrieve());
38 
39  // Get the vertex point estimator tool from ToolSvc
40  ATH_CHECK(m_vertexEstimator.retrieve());
41 
42 
43  ATH_CHECK(m_muonCollectionKey.initialize());
45  ATH_CHECK(m_MuonTrackKeys.initialize(m_MuonTrackKeys.size() != 0));
46 
47  if (m_diMuons) {
48  // Get the Particle Properties Service
49  ATH_CHECK(m_partPropSvc.retrieve());
50  auto particleDataTable = m_partPropSvc->PDT();
51  const HepPDT::ParticleData* pd_mu = particleDataTable->particle(MC::MUON);
52  m_trk1M = pd_mu->mass();
53  m_trk2M = pd_mu->mass();
54  }
55 
56  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");
57 
58 
59 // // Check that the user's settings are sensible
60  bool illogicalOptions(false);
61  if ( (m_mumu && m_mutrk) || (m_mumu && m_trktrk) || (m_mutrk && m_trktrk) ) {
62  ATH_MSG_WARNING("You are requesting incompatible combinations of muons and tracks in the pairs. JpsiCandidates will be EMPTY!");
63  illogicalOptions=true;
64  };
65  if ( (m_doTagAndProbe && m_mumu) || (m_doTagAndProbe && m_trktrk) ) {
66  ATH_MSG_WARNING("You are requesting Tag and Probe analysis but have not requested mu+trk mode. This is impossible. JpsiCandidates will be EMPTY!");
67  illogicalOptions=true;
68  };
69  if ( (m_mutrk || m_trktrk ) && m_useCombMeasurement ) {
70  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!");
71  illogicalOptions=true;
72  };
74  ATH_MSG_WARNING("You are requesting incompatible combinations of combined muons non-combined muons in the pairs. JpsiCandidates will be EMPTY!");
75  illogicalOptions=true;
76  };
78  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!");
79  illogicalOptions=true;
80  };
82  ATH_MSG_WARNING("You are requesting incompatible combinations of charges in the pairs. JpsiCandidates will be EMPTY!");
83  illogicalOptions=true;
84  };
86  if (!m_forceTagAndProbe){ //if m_forceTagAndProbe=TRUE then T&P will work with any charge combinations
87  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!");
88  illogicalOptions=true;
89  }
90  }
91  if (illogicalOptions) return StatusCode::FAILURE;;
92 
93 
94  ATH_MSG_DEBUG("Initialize successful");
95 
96  return StatusCode::SUCCESS;
97 
98  }
99 
100 
101  JpsiFinder::JpsiFinder(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t,n,p),
102  m_mumu(true),
103  m_mutrk(false),
104  m_trktrk(false),
105  m_allMuons(false),
106  m_combOnly(false),
107  m_atLeastOneComb(true),
108  m_useCombMeasurement(false),
109  m_useV0Fitter(false),
110  m_diMuons(true),
111  m_trk1M(105.66),
112  m_trk2M(105.66),
113  m_thresholdPt(0.0),
114  m_higherPt(0.0),
115  m_trkThresholdPt(0.0),
116  m_invMassUpper(100000.0),
117  m_invMassLower(0.0),
118  m_collAngleTheta(0.0),
119  m_collAnglePhi(0.0),
120  m_Chi2Cut(50.),
121  m_oppChOnly(true),
122  m_sameChOnly(false),
123  m_allChCombs(false),
124  m_mcpCuts(true),
125  m_doTagAndProbe(false),
126  m_forceTagAndProbe(false) //forcing T&P method for any charge combinations
127 
128  {
129  declareInterface<JpsiFinder>(this);
130  declareProperty("muAndMu",m_mumu);
131  declareProperty("muAndTrack",m_mutrk);
132  declareProperty("TrackAndTrack",m_trktrk);
133  declareProperty("allMuons",m_allMuons);
134  declareProperty("combOnly",m_combOnly);
135  declareProperty("atLeastOneComb",m_atLeastOneComb);
136  declareProperty("useCombinedMeasurement",m_useCombMeasurement);
137  declareProperty("useV0Fitter",m_useV0Fitter);
138  declareProperty("assumeDiMuons",m_diMuons);
139  declareProperty("track1Mass",m_trk1M);
140  declareProperty("track2Mass",m_trk2M);
141  declareProperty("muonThresholdPt",m_thresholdPt);
142  declareProperty("higherPt",m_higherPt);
143  declareProperty("trackThresholdPt",m_trkThresholdPt);
144  declareProperty("invMassUpper",m_invMassUpper);
145  declareProperty("invMassLower",m_invMassLower);
146  declareProperty("collAngleTheta",m_collAngleTheta);
147  declareProperty("collAnglePhi",m_collAnglePhi);
148  declareProperty("Chi2Cut",m_Chi2Cut);
149  declareProperty("oppChargesOnly",m_oppChOnly);
150  declareProperty("sameChargesOnly",m_sameChOnly);
151  declareProperty("allChargeCombinations",m_allChCombs);
152  declareProperty("useMCPCuts",m_mcpCuts);
153  declareProperty("doTagAndProbe",m_doTagAndProbe);
154  declareProperty("forceTagAndProbe",m_forceTagAndProbe);
155  }
156 
158 
159  //-------------------------------------------------------------------------------------
160  // Find the candidates
161  //-------------------------------------------------------------------------------------
162  StatusCode JpsiFinder::performSearch(const EventContext& ctx, xAOD::VertexContainer& vxContainer) const
163  {
164  ATH_MSG_DEBUG( "JpsiFinder::performSearch" );
165 
167  if(!muonhandle.isValid()){
168  ATH_MSG_ERROR("Could not retrieve " << m_muonCollectionKey.key());
169  return StatusCode::FAILURE;
170  }
171  // Get the muons from StoreGate
172  const xAOD::MuonContainer* importedMuonCollection = muonhandle.cptr();
173  ATH_MSG_DEBUG("Muon container size "<<importedMuonCollection->size());
174 
175  // Get muon tracks if combined measurement requested
176  std::vector<const xAOD::TrackParticleContainer*> importedMuonTrackCollections;
177  if (m_useCombMeasurement) {
178 
179  for (SG::ReadHandle<xAOD::TrackParticleContainer>& handle: m_MuonTrackKeys.makeHandles(ctx)) {
180  if(!handle.isValid()){
181  ATH_MSG_WARNING("No muon TrackParticle collection with name " << handle.key() << " found in StoreGate!");
182  return StatusCode::FAILURE;
183  } else {
184  ATH_MSG_DEBUG("Found muon TrackParticle collection " << handle.key() << " in StoreGate!");
185  ATH_MSG_DEBUG("Muon TrackParticle container size "<< handle->size());
186  importedMuonTrackCollections.push_back(handle.cptr());
187  }
188  }
189  }
190 
191  // Get ID tracks
193  const xAOD::TrackParticleContainer* importedTrackCollection{nullptr};
194  if(!handle.isValid()){
195  ATH_MSG_WARNING("No TrackParticle collection with name " << handle.key() << " found in StoreGate!");
196  return StatusCode::FAILURE;
197  } else {
198  importedTrackCollection = handle.cptr();
199  ATH_MSG_DEBUG("Found TrackParticle collection " << handle.key() << " in StoreGate!");
200  }
201  ATH_MSG_DEBUG("ID TrackParticle container size "<< handle->size());
202 
203  // Typedef for vectors of tracks and muons
204  typedef std::vector<const xAOD::TrackParticle*> TrackBag;
205  typedef std::vector<const xAOD::Muon*> MuonBag;
206 
207  // Select the inner detector tracks
208  const xAOD::Vertex* vx = nullptr;
209  TrackBag theIDTracksAfterSelection;
210  if (m_trktrk || m_mutrk) {
212  for (trkCItr=importedTrackCollection->begin(); trkCItr!=importedTrackCollection->end(); ++trkCItr) {
213  const xAOD::TrackParticle* TP = (*trkCItr);
214  if ( fabs(TP->pt())<m_trkThresholdPt ) continue;
215  if ( !m_trkSelector->decision(*TP, vx) ) continue;
216  theIDTracksAfterSelection.push_back(TP);
217  }
218  if (theIDTracksAfterSelection.size() == 0) return StatusCode::SUCCESS;;
219  ATH_MSG_DEBUG("Number of tracks after ID track selection: " << theIDTracksAfterSelection.size());
220  }
221 
222  // Select the muons
223  MuonBag theMuonsAfterSelection;
224  if (m_mumu || m_mutrk) {
225  for (auto muItr=importedMuonCollection->begin(); muItr!=importedMuonCollection->end(); ++muItr) {
226  if ( *muItr == NULL ) continue;
227  if (!(*muItr)->inDetTrackParticleLink().isValid()) continue; // No muons without ID tracks
228  const xAOD::TrackParticle* muonTrk = *((*muItr)->inDetTrackParticleLink());
229  if ( muonTrk==NULL) continue;
230  if ( !m_trkSelector->decision(*muonTrk, vx) ) continue; // all ID tracks must pass basic tracking cuts
231  if ( fabs(muonTrk->pt())<m_thresholdPt ) continue; // higher pt cut if needed
232  if ( m_mcpCuts && !passesMCPCuts(*muItr)) continue; // MCP cuts
233  if ( m_combOnly && (*muItr)->muonType() != xAOD::Muon::Combined ) continue; // require combined muons
234  if ( (*muItr)->muonType() == xAOD::Muon::SiliconAssociatedForwardMuon && !m_useCombMeasurement) continue;
235  theMuonsAfterSelection.push_back(*muItr);
236  }
237  if (theMuonsAfterSelection.size() == 0) return StatusCode::SUCCESS;;
238  ATH_MSG_DEBUG("Number of muons after selection: " << theMuonsAfterSelection.size());
239  }
240 
241  // Sort into pairs - end result will be a vector of JpsiCandidate structs
242  std::vector<JpsiCandidate> jpsiCandidates;
243  if (m_mumu) jpsiCandidates = getPairs(theMuonsAfterSelection);
244  if (m_trktrk) jpsiCandidates = getPairs(theIDTracksAfterSelection);
245  if (m_mutrk) jpsiCandidates = getPairs2Colls(theIDTracksAfterSelection,theMuonsAfterSelection,m_doTagAndProbe);
246 
247 
248  // (1) Enforce one combined muon
249  if (m_atLeastOneComb) {
250  std::vector<JpsiCandidate> selectCandidates;
251  for(auto &cand : jpsiCandidates) { if(cand.muonTypes!=TT) selectCandidates.push_back(cand); }
252  selectCandidates.swap(jpsiCandidates);
253  ATH_MSG_DEBUG("Number of candidates after requirement of at least 1 combined muon: " << jpsiCandidates.size() );
254  }
255 
256  // (2) Establish track content for candidates
257  // and set the appropriate track collections for the combined muon tracks where appropriate (for saving to persistency later)
258 
259  // mu+trk or trk+trk - always ID track collection
260  if (m_mutrk || m_trktrk) {
261  for (auto jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
262  (*jpsiItr).collection1 = importedTrackCollection;
263  (*jpsiItr).collection2 = importedTrackCollection;
264  }
265  }
266 
267  if (m_mumu) {
268  for (auto jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
270  (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
271  (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
272  (*jpsiItr).collection1 = importedTrackCollection;
273  (*jpsiItr).collection2 = importedTrackCollection;
274  }
276  if (!(*jpsiItr).muon1->combinedTrackParticleLink().isValid()) {
277  (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
278  (*jpsiItr).collection1 = importedTrackCollection;
279  }
280 
281  if (!(*jpsiItr).muon2->combinedTrackParticleLink().isValid()) {
282  (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
283  (*jpsiItr).collection2 = importedTrackCollection;
284  }
285 
286  if ((*jpsiItr).muon1->combinedTrackParticleLink().isValid()) {
287  (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::CombinedTrackParticle );
288  bool foundCollection(false);
289  // Look for correct muon track container
290  for (auto muTrkCollItr=importedMuonTrackCollections.begin(); muTrkCollItr!=importedMuonTrackCollections.end(); ++muTrkCollItr) {
291  if (isContainedIn((*jpsiItr).trackParticle1,*muTrkCollItr)) { (*jpsiItr).collection1 = *muTrkCollItr; foundCollection=true; break;}
292  }
293  if (!foundCollection) { // didn't find the correct muon track container so go back to ID
294  (*jpsiItr).trackParticle1 = (*jpsiItr).muon1->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
295  (*jpsiItr).collection1 = importedTrackCollection;
296  ATH_MSG_WARNING("Muon track from muon of author " << (*jpsiItr).muon1->author() << " not found in muon track collections you have provided.");
297  ATH_MSG_WARNING("Defaulting to ID track collection - combined measurement will not be used");
298  }
299  }
300 
301  if ((*jpsiItr).muon2->combinedTrackParticleLink().isValid()) {
302  (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::CombinedTrackParticle );
303  bool foundCollection(false);
304  // Look for correct muon track container
305  for (auto muTrkCollItr=importedMuonTrackCollections.begin(); muTrkCollItr!=importedMuonTrackCollections.end(); ++muTrkCollItr) {
306  if (isContainedIn((*jpsiItr).trackParticle2,*muTrkCollItr)) { (*jpsiItr).collection2 = *muTrkCollItr; foundCollection=true; break;}
307  }
308  if (!foundCollection) { // didn't find the correct muon track container so go back to ID
309  (*jpsiItr).trackParticle2 = (*jpsiItr).muon2->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
310  (*jpsiItr).collection2 = importedTrackCollection;
311  ATH_MSG_WARNING("Muon track from muon of author " << (*jpsiItr).muon2->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");
313  }
314  }
315  } // combined measurement
316  } // iteration over candidates
317  }
318 
319 
320  // (3) Enforce higher track pt if requested
321  if (m_higherPt>0.0) {
322  std::vector<JpsiCandidate> selectCandidates;
323  for(auto& cand : jpsiCandidates){
324  bool reject = (fabs(cand.trackParticle1->pt()) < m_higherPt) && (fabs(cand.trackParticle2->pt()) < m_higherPt);
325  if(!reject) selectCandidates.push_back(cand);
326  }
327  selectCandidates.swap(jpsiCandidates);
328  ATH_MSG_DEBUG("Number of candidates after higherPt cut: " << jpsiCandidates.size() );
329  }
330 
331  // (4) Select all opp/same charged track pairs
332  std::vector<JpsiCandidate> sortedJpsiCandidates;
333  sortedJpsiCandidates = selectCharges(jpsiCandidates);
334 
335  ATH_MSG_DEBUG("Number of candidates after charge selection: " << sortedJpsiCandidates.size() );
336 
337  // (5) Select for decay angle, if requested
338  if (m_collAnglePhi>0.0 && m_collAngleTheta>0.0) {
339  std::vector<JpsiCandidate> selectCandidates;
340  for(auto& cand : sortedJpsiCandidates){
341  double deltatheta = fabs( cand.trackParticle1->theta() - cand.trackParticle2->theta() );
342  double deltaphi = std::abs(xAOD::P4Helpers::deltaPhi(cand.trackParticle1->phi0() , cand.trackParticle2->phi0()));
343  bool reject = (deltatheta > m_collAngleTheta) || (deltaphi > m_collAnglePhi);
344  if(!reject) selectCandidates.push_back(cand);
345  }
346  sortedJpsiCandidates.swap(selectCandidates);
347  ATH_MSG_DEBUG("Number of collimated candidates: " << sortedJpsiCandidates.size() );
348  }
349 
350  // (6) Select for invariant mass, if requested
351  std::array<double,2> trkMasses{m_trk1M, m_trk2M};
352  if ( (m_invMassLower > 0.0) || (m_invMassUpper > 0.0) ) {
353  std::vector<JpsiCandidate> selectCandidates;
354  for(auto& cand : sortedJpsiCandidates){
355  double invMass = getInvariantMass(cand,trkMasses);
356  bool reject = invMass < m_invMassLower || invMass > m_invMassUpper;
357  if(!reject) selectCandidates.push_back(cand);
358  }
359  selectCandidates.swap(sortedJpsiCandidates);
360  ATH_MSG_DEBUG("Number of candidates passing invariant mass selection: " << sortedJpsiCandidates.size() );
361  }
362 
363  ATH_MSG_DEBUG("Number of pairs passing all selections and going to vertexing: " << sortedJpsiCandidates.size() );
364  if (sortedJpsiCandidates.size() == 0) return StatusCode::SUCCESS;;
365  std::vector<const xAOD::TrackParticle*> theTracks;
366  std::vector<const xAOD::Muon*> theStoredMuons;
367  // Fit each pair of tracks to a vertex
368  for(auto jpsiItr=sortedJpsiCandidates.begin(); jpsiItr!=sortedJpsiCandidates.end(); ++jpsiItr) {
369  theTracks.clear();
370  theTracks.push_back((*jpsiItr).trackParticle1);
371  theTracks.push_back((*jpsiItr).trackParticle2);
372  std::unique_ptr<xAOD::Vertex> myVxCandidate {fit(theTracks,importedTrackCollection)}; // This line actually does the fitting and object making
373  if (myVxCandidate) {
374  // Chi2 cut if requested
375  double chi2 = myVxCandidate->chiSquared();
376  ATH_MSG_DEBUG("chi2 is: " << chi2);
377  if (m_Chi2Cut <= 0.0 || chi2 <= m_Chi2Cut) {
378  // decorate the candidate with refitted tracks and muons via the BPhysHelper
379  xAOD::BPhysHelper jpsiHelper(myVxCandidate.get());
380  bool validtrk = jpsiHelper.setRefTrks();
381  if(!validtrk) ATH_MSG_WARNING("Problem setting tracks " << __FILE__ << ':' << __LINE__);
382  if (m_mumu || m_mutrk) {
383  theStoredMuons.clear();
384  theStoredMuons.push_back((*jpsiItr).muon1);
385  if (m_mumu) theStoredMuons.push_back((*jpsiItr).muon2);
386  bool valid = jpsiHelper.setMuons(theStoredMuons,importedMuonCollection);
387  if(!valid) ATH_MSG_WARNING("Problem setting muons " << __FILE__ << ':' << __LINE__);
388  }
389  // Retain the vertex
390  vxContainer.push_back(std::move(myVxCandidate));
391  }
392  } else { // fit failed
393  ATH_MSG_DEBUG("Fitter failed!");
394  // Don't try to delete the object, since we arrived here,
395  // because this pointer is null...
396  //delete myVxCandidate;
397  }
398  }
399  ATH_MSG_DEBUG("vxContainer size " << vxContainer.size());
400 
401  return StatusCode::SUCCESS;;
402  }
403 
404  // *********************************************************************************
405 
406  // ---------------------------------------------------------------------------------
407  // fit - does the fit
408  // ---------------------------------------------------------------------------------
409 
410  xAOD::Vertex* JpsiFinder::fit(const std::vector<const xAOD::TrackParticle*> &inputTracks,const xAOD::TrackParticleContainer* importedTrackCollection) const {
411 
412  const Trk::TrkV0VertexFitter* concreteVertexFitter=0;
413  if (m_useV0Fitter) {
414  // making a concrete fitter for the V0Fitter
415  concreteVertexFitter = dynamic_cast<const Trk::TrkV0VertexFitter * >(m_iV0VertexFitter.get());
416  if(concreteVertexFitter == 0) {
417  ATH_MSG_FATAL("The vertex fitter passed is not a V0 Vertex Fitter");
418  return NULL;
419  }
420  }
421 
422  const Trk::Perigee& aPerigee1 = inputTracks[0]->perigeeParameters();
423  const Trk::Perigee& aPerigee2 = inputTracks[1]->perigeeParameters();
424  int sflag = 0;
425  int errorcode = 0;
426  Amg::Vector3D startingPoint = m_vertexEstimator->getCirclesIntersectionPoint(&aPerigee1,&aPerigee2,sflag,errorcode);
427  if (errorcode != 0) {startingPoint(0) = 0.0; startingPoint(1) = 0.0; startingPoint(2) = 0.0;}
428  if (m_useV0Fitter) {
429  xAOD::Vertex* myVxCandidate = concreteVertexFitter->fit(inputTracks, startingPoint);
430 
431  // Added by ASC
432  if(myVxCandidate != 0){
433  std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
434  for(unsigned int i=0; i< myVxCandidate->trackParticleLinks().size(); i++)
435  { ElementLink<DataVector<xAOD::TrackParticle> > mylink=myVxCandidate->trackParticleLinks()[i]; //makes a copy (non-const)
436  mylink.setStorableObject(*importedTrackCollection, true);
437  newLinkVector.push_back( mylink ); }
438 
439  myVxCandidate->clearTracks();
440  myVxCandidate->setTrackParticleLinks( newLinkVector );
441  }
442 
443 
444 
445  return myVxCandidate;
446  } else {
447  xAOD::Vertex* myVxCandidate = m_iVertexFitter->fit(inputTracks, startingPoint);
448 
449  // Added by ASC
450  if(myVxCandidate != 0){
451  std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
452  for(unsigned int i=0; i< myVxCandidate->trackParticleLinks().size(); i++)
453  { ElementLink<DataVector<xAOD::TrackParticle> > mylink=myVxCandidate->trackParticleLinks()[i]; //makes a copy (non-const)
454  mylink.setStorableObject(*importedTrackCollection, true);
455  newLinkVector.push_back( mylink ); }
456 
457  myVxCandidate->clearTracks();
458  myVxCandidate->setTrackParticleLinks( newLinkVector );
459  }
460 
461 
462  return myVxCandidate;
463  }
464 
465 
466 
467  return NULL;
468 
469  } // End of fit method
470 
471 
472  // *********************************************************************************
473 
474  // ---------------------------------------------------------------------------------
475  // getPairs: forms up 2-plets of tracks
476  // ---------------------------------------------------------------------------------
477 
478  std::vector<JpsiCandidate> JpsiFinder::getPairs(const std::vector<const xAOD::TrackParticle*> &TracksIn) const {
479 
480  std::vector<JpsiCandidate> myPairs;
481  JpsiCandidate pair;
482  std::vector<const xAOD::TrackParticle*>::const_iterator outerItr;
483  std::vector<const xAOD::TrackParticle*>::const_iterator innerItr;
484 
485  if(TracksIn.size()>=2){
486  for(outerItr=TracksIn.begin();outerItr<TracksIn.end();++outerItr){
487  for(innerItr=(outerItr+1);innerItr!=TracksIn.end();++innerItr){
488  pair.trackParticle1 = *innerItr;
489  pair.trackParticle2 = *outerItr;
490  pair.pairType = TRKTRK;
491  myPairs.push_back(pair);
492  }
493  }
494  }
495 
496  return(myPairs);
497  }
498 
499  // ---------------------------------------------------------------------------------
500  // getPairs: forms up 2-plets of muons
501  // ---------------------------------------------------------------------------------
502 
503  std::vector<JpsiCandidate> JpsiFinder::getPairs(const std::vector<const xAOD::Muon*> &muonsIn) const {
504 
505  std::vector<JpsiCandidate> myPairs;
506  JpsiCandidate pair;
507  std::vector<const xAOD::Muon*>::const_iterator outerItr;
508  std::vector<const xAOD::Muon*>::const_iterator innerItr;
509 
510  if(muonsIn.size()>=2){
511  for(outerItr=muonsIn.begin();outerItr<muonsIn.end();++outerItr){
512  for(innerItr=(outerItr+1);innerItr!=muonsIn.end();++innerItr){
513  pair.muon1 = *innerItr;
514  pair.muon2 = *outerItr;
515  pair.pairType = MUMU;
516  bool mu1Comb( (*innerItr)->muonType() == xAOD::Muon::Combined );
517  bool mu2Comb( (*outerItr)->muonType() == xAOD::Muon::Combined );
518  if (mu1Comb && mu2Comb) pair.muonTypes = CC;
519  if ( (mu1Comb && !mu2Comb) || (!mu1Comb && mu2Comb) ) pair.muonTypes = CT;
520  if (!mu1Comb && !mu2Comb) pair.muonTypes = TT;
521  myPairs.push_back(pair);
522  }
523  }
524  }
525 
526  return(myPairs);
527  }
528 
529  // *********************************************************************************
530 
531  // ---------------------------------------------------------------------------------
532  // getPairs2Colls: forms up 2-plets of tracks from two independent collections
533  // ---------------------------------------------------------------------------------
534 
535  std::vector<JpsiCandidate> JpsiFinder::getPairs2Colls(const std::vector<const xAOD::TrackParticle*> &tracks, const std::vector<const xAOD::Muon*> &muons, bool tagAndProbe) const {
536 
537  std::vector<JpsiCandidate> myPairs;
538  JpsiCandidate pair;
539 
540  // Unless user is running in tag and probe mode, remove tracks which are also identified as muons
541  std::vector<const xAOD::TrackParticle*> tracksToKeep;
542  if (!tagAndProbe) {
543  if(tracks.size()>=1 && muons.size()>=1){
544  for (const xAOD::TrackParticle* trk : tracks) {
545  bool trackIsMuon(false);
546  for (const xAOD::Muon* mu : muons) {
547  auto& link = mu->inDetTrackParticleLink();
548  if ( link.isValid() && *link == trk ) {
549  trackIsMuon=true;
550  break;
551  }
552  }
553  if (!trackIsMuon) tracksToKeep.push_back(trk);
554  }
555  }
556  } else {tracksToKeep = tracks;}
557 
558  if(tracksToKeep.size()>=1 && muons.size()>=1){
559  for (const xAOD::TrackParticle* trk : tracksToKeep) {
560  for (const xAOD::Muon* mu : muons) {
561  pair.muon1 = mu;
562  // Muon track 1st
563  pair.trackParticle1 = mu->trackParticle( xAOD::Muon::InnerDetectorTrackParticle );
564  pair.trackParticle2 = trk;
565  pair.pairType = MUTRK;
566  myPairs.push_back(pair);
567  }
568  }
569  }
570 
571  return(myPairs);
572  }
573 
574 
575 
576  // *********************************************************************************
577 
578  // ---------------------------------------------------------------------------------
579  // getInvariantMass: returns invariant mass
580  // ----------------------------------------------------------getInvariantMass-----------------------
581 
582  double JpsiFinder::getInvariantMass(const JpsiCandidate &jpsiIn, std::span<const double> massHypotheses) const {
583 
584  // construct 4-vectors from track perigee parameters using given mass hypotheses.
585  // NOTE: in new data model (xAOD) the defining parameters are expressed as perigee parameters w.r.t. the beamspot
586  // NOTE2: TrackParticle::p4() method already returns TLorentzVector, however, we want to enforce our own mass hypothesis
587  TLorentzVector mu1;
588  TLorentzVector mu2;
589  mu1.SetVectM(jpsiIn.trackParticle1->p4().Vect(), massHypotheses[0]);
590  mu2.SetVectM(jpsiIn.trackParticle2->p4().Vect(), massHypotheses[1]);
591 
592  return (mu1+mu2).M();
593 
594  }
595 
596  // ---------------------------------------------------------------------------------
597  // selectCharges: selects track pairs with opposite charge / store + before -
598  // Boolean argument is to decide whether to accept oppositely or identically charged
599  // particles (true for oppositely charged)
600  // ---------------------------------------------------------------------------------
601 
602  std::vector<JpsiCandidate> JpsiFinder::selectCharges(const std::vector<JpsiCandidate> &jpsisIn) const {
603 
604  bool opposite(false),same(false),all(false);
605  opposite=m_oppChOnly;
608 
609  JpsiCandidate tmpJpsi;
610  std::vector<JpsiCandidate> jpsis;
611  double qOverP1=0.;
612  double qOverP2=0.;
613  for(auto jpsiItr=jpsisIn.cbegin();jpsiItr!=jpsisIn.cend();jpsiItr++){
614  bool oppCh(false),sameCh(false);
615  tmpJpsi = *jpsiItr;
616  qOverP1=(*jpsiItr).trackParticle1->qOverP();
617  qOverP2=(*jpsiItr).trackParticle2->qOverP();
618  if(qOverP1*qOverP2<0.0) oppCh=true; // product charge < 0
619  if(qOverP1*qOverP2>0.0) sameCh=true; // product charge > 0
620  // +ve should be first so swap
621  // Don't do it for tag and probe analyses (because tag muon must not change position)
622  if (oppCh && qOverP1<0.0 && !m_doTagAndProbe && !m_mutrk) {
623  tmpJpsi.trackParticle1 = (*jpsiItr).trackParticle2;
624  tmpJpsi.trackParticle2 = (*jpsiItr).trackParticle1;
625  tmpJpsi.muon1 = (*jpsiItr).muon2;
626  tmpJpsi.muon2 = (*jpsiItr).muon1;
627  tmpJpsi.collection1 = (*jpsiItr).collection2;
628  tmpJpsi.collection2 = (*jpsiItr).collection1;
629  }
630  if (oppCh && (opposite || all) ) jpsis.push_back(tmpJpsi);
631  if (sameCh && (same || all) ) jpsis.push_back(tmpJpsi);
632 
633  } // end of for loop
634 
635  return(jpsis);
636  }
637 
638  // ---------------------------------------------------------------------------------
639  // Apply the current cuts of the MCP group recommendation.
640  // ---------------------------------------------------------------------------------
641 
643 
644  return muon->passesIDCuts();
645 
646  }
647 
648  // ---------------------------------------------------------------------------------
649  // Checks whether a TPB is in the collection
650  // ---------------------------------------------------------------------------------
651 
652  bool JpsiFinder::isContainedIn(const xAOD::TrackParticle* theTrack, const xAOD::TrackParticleContainer* theCollection) const {
653  return std::find(theCollection->begin(), theCollection->end(), theTrack) != theCollection->end();
654  }
655 
656  // ---------------------------------------------------------------------------------
657  // trackMomentum: returns refitted track momentum
658  // ---------------------------------------------------------------------------------
659 
660  TVector3 JpsiFinder::trackMomentum(const xAOD::Vertex * vxCandidate, int trkIndex) const
661  {
662  double px = 0., py = 0., pz = 0.;
663  if (0 != vxCandidate) {
664  const Trk::TrackParameters* aPerigee = vxCandidate->vxTrackAtVertex()[trkIndex].perigeeAtVertex();
665  px = aPerigee->momentum()[Trk::px];
666  py = aPerigee->momentum()[Trk::py];
667  pz = aPerigee->momentum()[Trk::pz];
668  }
669  TVector3 mom(px,py,pz);
670  return mom;
671  }
672 
673 }
Analysis::JpsiFinder::m_invMassLower
double m_invMassLower
Definition: JpsiFinder.h:89
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
Analysis::JpsiCandidate::trackParticle1
const xAOD::TrackParticle * trackParticle1
Definition: JpsiFinder.h:39
Trk::py
@ py
Definition: ParamDefs.h:60
xAOD::muon
@ muon
Definition: TrackingPrimitives.h:195
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
Analysis::JpsiFinder::getPairs
std::vector< JpsiCandidate > getPairs(const std::vector< const xAOD::TrackParticle * > &) const
Definition: JpsiFinder.cxx:478
xAOD::BPhysHelper
Definition: BPhysHelper.h:71
test_pyathena.px
px
Definition: test_pyathena.py:18
Analysis::JpsiFinder::performSearch
virtual StatusCode performSearch(const EventContext &ctx, xAOD::VertexContainer &vxContainer) const override
Definition: JpsiFinder.cxx:162
Analysis::JpsiFinder::m_Chi2Cut
double m_Chi2Cut
Definition: JpsiFinder.h:92
P4Helpers::invMass
double invMass(const I4Momentum &pA, const I4Momentum &pB)
invariant mass from two I4momentum references
Definition: P4Helpers.h:252
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
Analysis::JpsiFinder::m_collAngleTheta
double m_collAngleTheta
Definition: JpsiFinder.h:90
Analysis::JpsiFinder::m_trktrk
bool m_trktrk
Definition: JpsiFinder.h:76
Analysis::JpsiFinder::m_iVertexFitter
PublicToolHandle< Trk::IVertexFitter > m_iVertexFitter
Definition: JpsiFinder.h:99
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
xAODP4Helpers.h
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T > &t)
Definition: AthCommonDataStore.h:145
Analysis::JpsiFinder::m_allMuons
bool m_allMuons
Definition: JpsiFinder.h:77
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
xAOD::Vertex_v1::trackParticleLinks
const TrackParticleLinks_t & trackParticleLinks() const
Get all the particles associated with the vertex.
Analysis::JpsiFinder::m_partPropSvc
ServiceHandle< IPartPropSvc > m_partPropSvc
Definition: JpsiFinder.h:103
Analysis::JpsiFinder::m_collAnglePhi
double m_collAnglePhi
Definition: JpsiFinder.h:91
Analysis::JpsiFinder::passesMCPCuts
bool passesMCPCuts(const xAOD::Muon *) const
Definition: JpsiFinder.cxx:642
xAOD::P4Helpers::deltaPhi
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition: xAODP4Helpers.h:69
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
Analysis::JpsiFinder::m_TrkParticleCollection
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_TrkParticleCollection
Definition: JpsiFinder.h:97
Analysis::CT
@ CT
Definition: JpsiFinder.h:36
Analysis::JpsiFinder::m_MuonTrackKeys
SG::ReadHandleKeyArray< xAOD::TrackParticleContainer > m_MuonTrackKeys
Definition: JpsiFinder.h:98
Trk::pz
@ pz
global momentum (cartesian)
Definition: ParamDefs.h:61
Analysis::TRKTRK
@ TRKTRK
Definition: JpsiFinder.h:35
python.TrigEgammaFastCaloHypoTool.same
def same(val, tool)
Definition: TrigEgammaFastCaloHypoTool.py:12
DerivationFramework::MuonBag
std::vector< const xAOD::Muon * > MuonBag
Definition: BPhysAddMuonBasedInvMass.h:33
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
Analysis::JpsiFinder::m_vertexEstimator
PublicToolHandle< InDet::VertexPointEstimator > m_vertexEstimator
Definition: JpsiFinder.h:102
Analysis::JpsiCandidate::muonTypes
MuonTypes muonTypes
Definition: JpsiFinder.h:46
Analysis::JpsiFinder::m_combOnly
bool m_combOnly
Definition: JpsiFinder.h:78
Analysis::JpsiFinder::isContainedIn
bool isContainedIn(const xAOD::TrackParticle *, const xAOD::TrackParticleContainer *) const
Definition: JpsiFinder.cxx:652
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
xAOD::TrackParticle_v1::p4
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
Definition: TrackParticle_v1.cxx:129
Analysis::JpsiFinder::selectCharges
std::vector< JpsiCandidate > selectCharges(const std::vector< JpsiCandidate > &) const
Definition: JpsiFinder.cxx:602
calibdata.valid
list valid
Definition: calibdata.py:45
Analysis::JpsiFinder::trackMomentum
TVector3 trackMomentum(const xAOD::Vertex *vxCandidate, int trkIndex) const
Definition: JpsiFinder.cxx:660
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
Analysis::JpsiFinder::m_mumu
bool m_mumu
Definition: JpsiFinder.h:74
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Analysis::JpsiCandidate::collection1
const xAOD::TrackParticleContainer * collection1
Definition: JpsiFinder.h:43
python.TrigInDetConfig.inputTracks
inputTracks
Definition: TrigInDetConfig.py:183
lumiFormat.i
int i
Definition: lumiFormat.py:85
Analysis::JpsiFinder::m_sameChOnly
bool m_sameChOnly
Definition: JpsiFinder.h:94
Analysis::JpsiFinder::m_useCombMeasurement
bool m_useCombMeasurement
Definition: JpsiFinder.h:80
Analysis::MUTRK
@ MUTRK
Definition: JpsiFinder.h:35
beamspotman.n
n
Definition: beamspotman.py:731
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
Analysis::JpsiFinder::m_allChCombs
bool m_allChCombs
Definition: JpsiFinder.h:95
Analysis::JpsiFinder::getInvariantMass
double getInvariantMass(const JpsiCandidate &, std::span< const double >) const
Definition: JpsiFinder.cxx:582
Analysis::JpsiCandidate::collection2
const xAOD::TrackParticleContainer * collection2
Definition: JpsiFinder.h:44
Analysis::JpsiFinder::JpsiFinder
JpsiFinder(const std::string &t, const std::string &n, const IInterface *p)
Definition: JpsiFinder.cxx:101
xAOD::Vertex_v1::setTrackParticleLinks
void setTrackParticleLinks(const TrackParticleLinks_t &trackParticles)
Set all track particle links at once.
chi2
double chi2(TH1 *h0, TH1 *h1)
Definition: comparitor.cxx:523
Trk::px
@ px
Definition: ParamDefs.h:59
Amg::pz
@ pz
Definition: GeoPrimitives.h:40
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
Analysis::JpsiFinder::m_doTagAndProbe
bool m_doTagAndProbe
Definition: JpsiFinder.h:105
Analysis::JpsiFinder::m_useV0Fitter
bool m_useV0Fitter
Definition: JpsiFinder.h:81
Analysis::JpsiCandidate::muon2
const xAOD::Muon * muon2
Definition: JpsiFinder.h:42
DerivationFramework::TrackBag
std::vector< const xAOD::TrackParticle * > TrackBag
Definition: BPhysAddMuonBasedInvMass.h:32
xAOD::Vertex_v1::clearTracks
void clearTracks()
Remove all tracks from the vertex.
Definition: Vertex_v1.cxx:331
Trk::ParametersBase
Definition: ParametersBase.h:55
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
Vertex.h
Analysis::JpsiFinder::m_muonCollectionKey
SG::ReadHandleKey< xAOD::MuonContainer > m_muonCollectionKey
Definition: JpsiFinder.h:96
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Analysis::JpsiFinder::m_trk1M
double m_trk1M
Definition: JpsiFinder.h:83
Trk::Combined
@ Combined
Definition: TrackSummaryTool.h:32
xAOD::BPhysHelper::setMuons
bool setMuons(const std::vector< const xAOD::Muon * > &muons, const xAOD::MuonContainer *muonContainer)
Set links to muons.
Definition: BPhysHelper.cxx:479
Amg::py
@ py
Definition: GeoPrimitives.h:39
Analysis::JpsiFinder::m_mutrk
bool m_mutrk
Definition: JpsiFinder.h:75
xAOD::TrackParticle_v1::qOverP
float qOverP() const
Returns the parameter.
Analysis::JpsiFinder::m_higherPt
double m_higherPt
Definition: JpsiFinder.h:86
Analysis
The namespace of all packages in PhysicsAnalysis/JetTagging.
Definition: BTaggingCnvAlg.h:20
Analysis::JpsiFinder::m_atLeastOneComb
bool m_atLeastOneComb
Definition: JpsiFinder.h:79
Analysis::JpsiFinder::m_oppChOnly
bool m_oppChOnly
Definition: JpsiFinder.h:93
Analysis::JpsiFinder::getPairs2Colls
std::vector< JpsiCandidate > getPairs2Colls(const std::vector< const xAOD::TrackParticle * > &, const std::vector< const xAOD::Muon * > &, bool) const
Definition: JpsiFinder.cxx:535
Analysis::JpsiFinder::m_trkSelector
PublicToolHandle< Trk::ITrackSelectorTool > m_trkSelector
Definition: JpsiFinder.h:101
Analysis::JpsiCandidate::trackParticle2
const xAOD::TrackParticle * trackParticle2
Definition: JpsiFinder.h:40
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
Analysis::JpsiFinder::~JpsiFinder
~JpsiFinder()
Definition: JpsiFinder.cxx:157
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
Analysis::JpsiCandidate::muon1
const xAOD::Muon * muon1
Definition: JpsiFinder.h:41
SG::VarHandleBase::key
virtual const std::string & key() const override final
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleBase.cxx:64
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
Analysis::JpsiFinder::m_iV0VertexFitter
PublicToolHandle< Trk::IVertexFitter > m_iV0VertexFitter
Definition: JpsiFinder.h:100
TrkV0VertexFitter.h
BPhysHelper.h
: B-physics xAOD helpers.
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
TrackParticle.h
xAOD::BPhysHelper::setRefTrks
bool setRefTrks(std::vector< float > px, std::vector< float > py, std::vector< float > pz)
Sets refitted track momenta.
Definition: BPhysHelper.cxx:286
Trk::ParametersBase::momentum
const Amg::Vector3D & momentum() const
Access method for the momentum.
Trk::TrkV0VertexFitter::fit
virtual xAOD::Vertex * fit(const std::vector< const xAOD::TrackParticle * > &vectorTrk, const Amg::Vector3D &startingPoint) const override
Interface for xAOD::TrackParticle with Amg::Vector3D starting point.
Definition: TrkV0VertexFitter.cxx:83
VertexContainer.h
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
JpsiFinder.h
Analysis::JpsiFinder::initialize
virtual StatusCode initialize() override
Definition: JpsiFinder.cxx:28
Analysis::JpsiFinder::m_trkThresholdPt
double m_trkThresholdPt
Definition: JpsiFinder.h:87
Analysis::JpsiFinder::m_invMassUpper
double m_invMassUpper
Definition: JpsiFinder.h:88
Trk::TrkV0VertexFitter
This class implements a vertex fitting algorithm optimised for V0 finding.
Definition: TrkV0VertexFitter.h:40
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
Analysis::JpsiFinder::m_forceTagAndProbe
bool m_forceTagAndProbe
Definition: JpsiFinder.h:106
xAOD::Vertex_v1::vxTrackAtVertex
std::vector< Trk::VxTrackAtVertex > & vxTrackAtVertex()
Non-const access to the VxTrackAtVertex vector.
Definition: Vertex_v1.cxx:181
Analysis::JpsiCandidate::pairType
PairType pairType
Definition: JpsiFinder.h:45
Analysis::MUMU
@ MUMU
Definition: JpsiFinder.h:35
AthAlgTool
Definition: AthAlgTool.h:26
Analysis::TT
@ TT
Definition: JpsiFinder.h:36
Analysis::JpsiCandidate
Definition: JpsiFinder.h:38
Analysis::JpsiFinder::m_thresholdPt
double m_thresholdPt
Definition: JpsiFinder.h:85
Analysis::JpsiFinder::m_trk2M
double m_trk2M
Definition: JpsiFinder.h:84
CaloNoise_fillDB.mu
mu
Definition: CaloNoise_fillDB.py:53
Analysis::JpsiFinder::m_diMuons
bool m_diMuons
Definition: JpsiFinder.h:82
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
TrackParticleContainer.h
Analysis::JpsiFinder::fit
xAOD::Vertex * fit(const std::vector< const xAOD::TrackParticle * > &, const xAOD::TrackParticleContainer *importedTrackCollection) const
Definition: JpsiFinder.cxx:410
Analysis::CC
@ CC
Definition: JpsiFinder.h:36
HepMCHelpers.h
Analysis::JpsiFinder::m_mcpCuts
bool m_mcpCuts
Definition: JpsiFinder.h:104
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.