ATLAS Offline Software
JpsiFinder_ee.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_ee
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"
22 #include "GaudiKernel/IPartPropSvc.h"
23 #include "AthLinks/ElementLink.h"
24 #include "HepPDT/ParticleDataTable.hh"
25 #include "xAODTracking/Vertex.h"
30 namespace Analysis {
31 
33 
34  // Initialize the ReadHandles
37 
38  // Initialize ReadDecorHandles
39  ATH_CHECK(m_gsfCaloLinkKey.initialize());
40 
41  // retrieving vertex Fitter
42  ATH_CHECK(m_iVertexFitter.retrieve());
43 
44  // retrieving V0 Fitter
45  ATH_CHECK(m_iV0VertexFitter.retrieve(DisableTool{!m_useV0Fitter }));
46  // Get the track selector tool from ToolSvc
47  ATH_CHECK(m_trkSelector.retrieve());
48 
49 
50  // Get the vertex point estimator tool from ToolSvc
51  ATH_CHECK(m_vertexEstimator.retrieve());
52 
53 
54  if (m_diElectrons) {
55  // Get the Particle Properties Service
56  ATH_CHECK(m_partPropSvc.retrieve());
57  auto particleDataTable = m_partPropSvc->PDT();
58  const HepPDT::ParticleData* pd_el = particleDataTable->particle(MC::ELECTRON);
59  m_trk1M = pd_el->mass();
60  m_trk2M = pd_el->mass();
61  }
62 
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");
64 
65 
66 // // Check that the user's settings are sensible
67  bool illogicalOptions(false);
68  if ( (m_elel && m_eltrk) || (m_elel && m_trktrk) || (m_eltrk && m_trktrk) ) {
69  ATH_MSG_WARNING("You are requesting incompatible combinations of muons and tracks in the pairs. JpsiEECandidates will be EMPTY!");
70  illogicalOptions=true;
71  };
72  if ( (m_doTagAndProbe && m_elel) || (m_doTagAndProbe && m_trktrk) ) {
73  ATH_MSG_WARNING("You are requesting Tag and Probe analysis but have not requested mu+trk mode. This is impossible. JpsiEECandidates will be EMPTY!");
74  illogicalOptions=true;
75  };
77  ATH_MSG_WARNING("You are requesting incompatible combinations of charges in the pairs. JpsiEECandidates will be EMPTY!");
78  illogicalOptions=true;
79  };
81  ATH_MSG_WARNING("You are requesting same-sign or all-sign combinations in a tag and probe analysis. This doesn't make sense. JpsiEECandidates will be EMPTY!");
82  illogicalOptions=true;
83  }
84  if (illogicalOptions) return StatusCode::FAILURE;
85 
86 
87 
88  ATH_MSG_DEBUG("Initialize successful");
89 
90  return StatusCode::SUCCESS;
91 
92  }
93 
94 
95  JpsiFinder_ee::JpsiFinder_ee(const std::string& t, const std::string& n, const IInterface* p) : AthAlgTool(t,n,p),
96  m_elel(true),
97  m_eltrk(false),
98  m_trktrk(false),
99  m_allElectrons(false),
100  m_useTrackMeasurement(true),
101  m_useV0Fitter(false),
102  m_diElectrons(true),
105  m_thresholdPt(0.0),
106  m_higherPt(0.0),
107  m_trkThresholdPt(0.0),
108  m_invMassUpper(100000.0),
109  m_invMassLower(0.0),
110  m_collAngleTheta(0.0),
111  m_collAnglePhi(0.0),
112  m_Chi2Cut(50.),
113  m_oppChOnly(true),
114  m_sameChOnly(false),
115  m_allChCombs(false),
116  m_electronCollectionKey("Electrons"),
117  m_TrkParticleCollection("InDetTrackParticles"),
118  m_iVertexFitter("Trk::TrkVKalVrtFitter"),
119  m_iV0VertexFitter("Trk::V0VertexFitter"),
120  m_trkSelector("InDet::TrackSelectorTool"),
121  m_vertexEstimator("InDet::VertexPointEstimator"),
122  m_egammaCuts(true),
123  m_elSelection("d0_or_nod0"),
124  m_doTagAndProbe(false)
125 
126  {
127  declareInterface<JpsiFinder_ee>(this);
128  declareProperty("elAndEl",m_elel);
129  declareProperty("elAndTrack",m_eltrk);
130  declareProperty("TrackAndTrack",m_trktrk);
131  declareProperty("allElectrons",m_allElectrons);
132  declareProperty("useElectronTrackMeasurement",m_useTrackMeasurement);
133  declareProperty("useV0Fitter",m_useV0Fitter);
134  declareProperty("assumeDiElectrons",m_diElectrons);
135 // declareProperty("electronLHValue",m_electronLHValue);
136  declareProperty("track1Mass",m_trk1M);
137  declareProperty("track2Mass",m_trk2M);
138  declareProperty("elThresholdPt",m_thresholdPt);
139  declareProperty("higherPt",m_higherPt);
140  declareProperty("trackThresholdPt",m_trkThresholdPt);
141  declareProperty("invMassUpper",m_invMassUpper);
142  declareProperty("invMassLower",m_invMassLower);
143  declareProperty("collAngleTheta",m_collAngleTheta);
144  declareProperty("collAnglePhi",m_collAnglePhi);
145  declareProperty("Chi2Cut",m_Chi2Cut);
146  declareProperty("oppChargesOnly",m_oppChOnly);
147  declareProperty("sameChargesOnly",m_sameChOnly);
148  declareProperty("allChargeCombinations",m_allChCombs);
149  declareProperty("electronCollectionKey",m_electronCollectionKey);
150  declareProperty("TrackParticleCollection",m_TrkParticleCollection);
151  declareProperty("TrkVertexFitterTool",m_iVertexFitter);
152  declareProperty("V0VertexFitterTool",m_iV0VertexFitter);
153  declareProperty("TrackSelectorTool",m_trkSelector);
154  declareProperty("VertexPointEstimator",m_vertexEstimator);
155  declareProperty("useEgammaCuts",m_egammaCuts);
156  declareProperty("doTagAndProbe",m_doTagAndProbe);
157  declareProperty("ElectronSelection",m_elSelection);
158  }
159 
161 
162  //-------------------------------------------------------------------------------------
163  // Find the candidates
164  //-------------------------------------------------------------------------------------
165 
166 
167  StatusCode JpsiFinder_ee::performSearch(const EventContext& ctx, xAOD::VertexContainer& vxContainer) const
168  {
169  ATH_MSG_DEBUG( "JpsiFinder_ee::performSearch" );
170 
171 
172  // Get the electrons from StoreGate
173  const xAOD::ElectronContainer* importedElectronCollection=nullptr;
175  if(!ehandle.isValid()){
176  ATH_MSG_WARNING("No electron collection with key " << m_electronCollectionKey.key() << " found in StoreGate. JpsiEECandidates will be EMPTY!");
177  return StatusCode::SUCCESS;;
178  }else{
179  importedElectronCollection = ehandle.cptr();
180  ATH_MSG_DEBUG("Found electron collections with key "<<m_electronCollectionKey.key());
181  }
182  ATH_MSG_DEBUG("Electron container size "<<importedElectronCollection->size());
183 
184  // Get ID tracks
186  const xAOD::TrackParticleContainer* importedTrackCollection(0);
187  if(!thandle.isValid()){
188  ATH_MSG_WARNING("No TrackParticle collection with name " << m_TrkParticleCollection << " found in StoreGate!");
189  return StatusCode::SUCCESS;;
190  } else {
191  importedTrackCollection = thandle.cptr();
192  }
193 
194  // Typedef for vectors of tracks and muons
195  typedef std::vector<const xAOD::TrackParticle*> TrackBag;
196  typedef std::vector<const xAOD::Electron*> ElectronBag;
197 
198  // Select the inner detector tracks
199  const xAOD::Vertex* vx = 0;
200  TrackBag theIDTracksAfterSelection;
201  if (m_trktrk || m_eltrk) {
203  for (trkCItr=importedTrackCollection->begin(); trkCItr!=importedTrackCollection->end(); ++trkCItr) {
204  const xAOD::TrackParticle* TP = (*trkCItr);
205  if ( fabs(TP->pt())<m_trkThresholdPt ) continue;
206  if ( !m_trkSelector->decision(*TP, vx) ) continue;
207  theIDTracksAfterSelection.push_back(TP);
208  }
209  if (theIDTracksAfterSelection.size() == 0) return StatusCode::SUCCESS;;
210  ATH_MSG_DEBUG("Number of tracks after ID track selection: " << theIDTracksAfterSelection.size());
211  }
212 
213  // Select the muons
214  ElectronBag theElectronsAfterSelection;
216  if (m_elel || m_eltrk) {
217  for (elItr=importedElectronCollection->begin(); elItr!=importedElectronCollection->end(); ++elItr) {
218  if ( *elItr == NULL ) continue;
219  if (!(*elItr)->trackParticleLink().isValid()) continue; // No electrons without ID tracks
220  const xAOD::TrackParticle* elTrk(0);
221  if (m_TrkParticleCollection.key() == "GSFCaloContainer") {
223  refittedTrackParticleLink(m_gsfCaloLinkKey, ctx);
224  const ElementLink<xAOD::TrackParticleContainer>& refittedTrackLink = refittedTrackParticleLink(*(*elItr));
225  if (!refittedTrackLink.isValid()) continue;
226  elTrk = *refittedTrackLink;
227  } else {
228  if (!(*elItr)->trackParticleLink().isValid()) continue;
229  elTrk = (*elItr)->trackParticleLink().cachedElement();
230  }
231 
232  if ( elTrk==NULL) continue;
233  if ( !m_trkSelector->decision(*elTrk, vx) ) continue; // all ID tracks must pass basic tracking cuts
234  if ( fabs(elTrk->pt())<m_thresholdPt ) continue; // higher pt cut if needed
235 
236  if ( m_egammaCuts && !passesEgammaCuts(*elItr)) continue; // egamma cuts
237  theElectronsAfterSelection.push_back(*elItr);
238  }
239  if (theElectronsAfterSelection.size() == 0) return StatusCode::SUCCESS;;
240  ATH_MSG_DEBUG("Number of electrons after selection: " << theElectronsAfterSelection.size());
241  }
242 
243  // Sort into pairs - end result will be a vector of JpsiEECandidate structs
244  std::vector<JpsiEECandidate> jpsiCandidates;
245  if (m_elel) jpsiCandidates = getPairs(theElectronsAfterSelection);
246  if (m_trktrk) jpsiCandidates = getPairs(theIDTracksAfterSelection);
247  if (m_eltrk) jpsiCandidates = getPairs2Colls(theIDTracksAfterSelection,theElectronsAfterSelection,m_doTagAndProbe);
248 
249  ATH_MSG_DEBUG("Number of pairs with ee from a B decay: " << jpsiCandidates.size() );
250 
251  // Pair-wise selections
253 
254  // (1) Enforce one combined muon [deleted, no electron equivalent]
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  // el+trk or trk+trk - always ID track collection
260  if (m_eltrk || m_trktrk) {
261  for (jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
262  (*jpsiItr).collection1 = importedTrackCollection;
263  (*jpsiItr).collection2 = importedTrackCollection;
264  }
265  }
266 
267  if (m_elel) {
268  for (jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
269  if ( m_useTrackMeasurement ) {
270  if (m_TrkParticleCollection.key() == "GSFCaloContainer") {
272  refittedTrackParticleLink(m_gsfCaloLinkKey, ctx);
273  const ElementLink<xAOD::TrackParticleContainer>& refittedTrackLink1 = refittedTrackParticleLink(*((*jpsiItr).el1));
274  const ElementLink<xAOD::TrackParticleContainer>& refittedTrackLink2 = refittedTrackParticleLink(*((*jpsiItr).el2));
275  (*jpsiItr).trackParticle1 = *refittedTrackLink1;
276  (*jpsiItr).trackParticle2 = *refittedTrackLink2;
277  } else {
278  (*jpsiItr).trackParticle1 = (*jpsiItr).el1->trackParticleLink().cachedElement();
279  (*jpsiItr).trackParticle2 = (*jpsiItr).el2->trackParticleLink().cachedElement();
280  }
281  (*jpsiItr).collection1 = importedTrackCollection;
282  (*jpsiItr).collection2 = importedTrackCollection;
283  } else {
284  ATH_MSG_WARNING("Not setup for non-track electron measurements yet....");
285  }
286  } // iteration over candidates
287  }
288 
289 
290  // (3) Enforce higher track pt if requested
291  if (m_higherPt>0.0) {
292  int index(0);
293  std::vector<int> listToDelete;
294  std::vector<int>::reverse_iterator ii;
295  for(jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end();++jpsiItr,++index) {
296  if( (fabs((*jpsiItr).trackParticle1->pt()) < m_higherPt) && (fabs((*jpsiItr).trackParticle2->pt()) < m_higherPt) ) listToDelete.push_back(index);
297  }
298  for (ii=listToDelete.rbegin(); ii!=listToDelete.rend(); ++ii) {
299  jpsiCandidates.erase(jpsiCandidates.begin() + (*ii) );
300  }
301  ATH_MSG_DEBUG("Number of candidates after higherPt cut: " << jpsiCandidates.size() );
302  }
303 
304  // (4) Select all opp/same charged track pairs
305  std::vector<JpsiEECandidate> sortedJpsiEECandidates;
306  if (m_oppChOnly) sortedJpsiEECandidates = selectCharges(jpsiCandidates,"OPPOSITE");
307  if (m_sameChOnly) sortedJpsiEECandidates = selectCharges(jpsiCandidates,"SAME");
308  if (m_allChCombs) sortedJpsiEECandidates = selectCharges(jpsiCandidates,"ALL");
309  ATH_MSG_DEBUG("Number of candidates after charge selection: " << sortedJpsiEECandidates.size() );
310 
311  // (5) Select for decay angle, if requested
312  if (m_collAnglePhi>0.0 && m_collAngleTheta>0.0) {
313  int index(0);
314  std::vector<int> listToDelete;
315  std::vector<int>::reverse_iterator ii;
316  for(jpsiItr=sortedJpsiEECandidates.begin(); jpsiItr!=sortedJpsiEECandidates.end();++jpsiItr,++index) {
317  double deltatheta = fabs( (*jpsiItr).trackParticle1->theta() - (*jpsiItr).trackParticle2->theta() );
318  // -3.14 < phi < +3.14 ==> correction
319  double deltaphi = std::abs(xAOD::P4Helpers::deltaPhi((*jpsiItr).trackParticle1->phi0() , (*jpsiItr).trackParticle2->phi0()));
320  // perform the angle cuts
321  if ((deltatheta > m_collAngleTheta) || (deltaphi > m_collAnglePhi)) listToDelete.push_back(index);
322  }
323  for (ii=listToDelete.rbegin(); ii!=listToDelete.rend(); ++ii) {
324  sortedJpsiEECandidates.erase(sortedJpsiEECandidates.begin() + (*ii) );
325  }
326  ATH_MSG_DEBUG("Number of collimated candidates: " << sortedJpsiEECandidates.size() );
327  }
328 
329  // (6) Select for invariant mass, if requested
330  std::vector<double> trkMasses;
331  trkMasses.push_back(m_trk1M);
332  trkMasses.push_back(m_trk2M);
333  if ( (m_invMassLower > 0.0) || (m_invMassUpper > 0.0) ) {
334  int index(0);
335  std::vector<int> listToDelete;
336  std::vector<int>::reverse_iterator ii;
337  for(jpsiItr=sortedJpsiEECandidates.begin(); jpsiItr!=sortedJpsiEECandidates.end(); ++jpsiItr,++index) {
338  double invMass = getInvariantMass(*jpsiItr,trkMasses);
339  // std::cout << "inv. mass: " << invMass << std::endl;
340  if ( invMass < m_invMassLower || invMass > m_invMassUpper ) {
341  listToDelete.push_back(index);
342  }
343  }
344  for (ii=listToDelete.rbegin(); ii!=listToDelete.rend(); ++ii) {
345  sortedJpsiEECandidates.erase(sortedJpsiEECandidates.begin() + (*ii) );
346  }
347  ATH_MSG_DEBUG("Number of candidates passing invariant mass selection: " << sortedJpsiEECandidates.size() );
348  }
349 
350  if (sortedJpsiEECandidates.size() == 0) return StatusCode::SUCCESS;;
351 
352  // Fit each pair of tracks to a vertex
353  int itritn = 0;
354  for(jpsiItr=sortedJpsiEECandidates.begin(); jpsiItr!=sortedJpsiEECandidates.end(); ++jpsiItr) {
355  ATH_MSG_DEBUG("jpsiItr: " << itritn); itritn++;
356  std::vector<const xAOD::TrackParticle*> theTracks; theTracks.clear();
357  theTracks.push_back((*jpsiItr).trackParticle1);
358  theTracks.push_back((*jpsiItr).trackParticle2);
359  ATH_MSG_DEBUG("theTracks size (should be two!) " << theTracks.size() << " being vertexed with tracks " << importedTrackCollection);
360  std::unique_ptr<xAOD::Vertex> myVxCandidate{fit(theTracks,importedTrackCollection)}; // This line actually does the fitting and object making
361  if (myVxCandidate != 0) {
362  // Chi2 cut if requested
363  double chi2 = myVxCandidate->chiSquared();
364  ATH_MSG_DEBUG("chi2 is: " << chi2);
365  if (m_Chi2Cut == 0.0 || chi2 <= m_Chi2Cut) {
366  // decorate the candidate with refitted tracks and muons via the BPhysHelper
367  xAOD::BPhysHelper jpsiHelper(myVxCandidate.get());
368  jpsiHelper.setRefTrks();
369  if (m_elel || m_eltrk) {
370  std::vector<const xAOD::Electron*> theStoredElectrons;
371  theStoredElectrons.push_back((*jpsiItr).el1);
372  if (m_elel) theStoredElectrons.push_back((*jpsiItr).el2);
373  jpsiHelper.setElectrons(theStoredElectrons,importedElectronCollection);
374  }
375  // Retain the vertex
376  vxContainer.push_back(std::move(myVxCandidate));
377  }
378  } else { // fit failed
379  ATH_MSG_DEBUG("Fitter failed!");
380  // Don't try to delete the object, since we arrived here,
381  // because this pointer is null...
382  //delete myVxCandidate;
383  }
384  }
385  ATH_MSG_DEBUG("vxContainer size " << vxContainer.size());
386 
387  return StatusCode::SUCCESS;;
388  }
389 
390  // *********************************************************************************
391 
392  // ---------------------------------------------------------------------------------
393  // fit - does the fit
394  // ---------------------------------------------------------------------------------
395 
396  xAOD::Vertex* JpsiFinder_ee::fit(const std::vector<const xAOD::TrackParticle*> &inputTracks,const xAOD::TrackParticleContainer* importedTrackCollection) const {
397  ATH_MSG_DEBUG("inside JpsiFinder_ee::fit");
398  const Trk::TrkV0VertexFitter* concreteVertexFitter=0;
399  if (m_useV0Fitter) {
400  ATH_MSG_DEBUG("using v0 fitter");
401  // making a concrete fitter for the V0Fitter
402  concreteVertexFitter = dynamic_cast<const Trk::TrkV0VertexFitter * >(m_iV0VertexFitter.get());
403  if(concreteVertexFitter == 0) {
404  ATH_MSG_FATAL("The vertex fitter passed is not a V0 Vertex Fitter");
405  return NULL;
406  }
407  }
408 
409  const Trk::Perigee& aPerigee1 = inputTracks[0]->perigeeParameters();
410  const Trk::Perigee& aPerigee2 = inputTracks[1]->perigeeParameters();
411  int sflag = 0;
412  int errorcode = 0;
413  Amg::Vector3D startingPoint = m_vertexEstimator->getCirclesIntersectionPoint(&aPerigee1,&aPerigee2,sflag,errorcode);
414  if (errorcode != 0) {startingPoint(0) = 0.0; startingPoint(1) = 0.0; startingPoint(2) = 0.0;}
415  if (m_useV0Fitter) {
416  xAOD::Vertex* myVxCandidate = concreteVertexFitter->fit(inputTracks, startingPoint);
417  ATH_MSG_DEBUG("Initial fit was a success!");
418  // Added by ASC
419  if(myVxCandidate != 0){
420  std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
421  for(unsigned int i=0; i< myVxCandidate->trackParticleLinks().size(); i++)
422  { ElementLink<DataVector<xAOD::TrackParticle> > mylink=myVxCandidate->trackParticleLinks()[i]; //makes a copy (non-const)
423  mylink.setStorableObject(*importedTrackCollection, true);
424  newLinkVector.push_back( mylink ); }
425 
426  myVxCandidate->clearTracks();
427  myVxCandidate->setTrackParticleLinks( newLinkVector );
428  }
429 
430 
431 
432  return myVxCandidate;
433  } else {
434  xAOD::Vertex* myVxCandidate = m_iVertexFitter->fit(inputTracks, startingPoint);
435  ATH_MSG_DEBUG("Initial fit was a success! " << myVxCandidate);
436  // Added by ASC
437  if(myVxCandidate != 0){
438  std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
439  for(unsigned int i=0; i< myVxCandidate->trackParticleLinks().size(); i++){
440  ElementLink<DataVector<xAOD::TrackParticle> > mylink=myVxCandidate->trackParticleLinks()[i]; //makes a copy (non-const)
441  mylink.setStorableObject(*importedTrackCollection, true);
442  newLinkVector.push_back( mylink );
443  ATH_MSG_DEBUG("Set a link!");
444  }
445  myVxCandidate->clearTracks();
446  myVxCandidate->setTrackParticleLinks( newLinkVector );
447  ATH_MSG_DEBUG("Set all links");
448  }
449 
450  return myVxCandidate;
451  }
452 
453 
454 
455  return NULL;
456 
457  } // End of fit method
458 
459 
460  // *********************************************************************************
461 
462  // ---------------------------------------------------------------------------------
463  // getPairs: forms up 2-plets of tracks
464  // ---------------------------------------------------------------------------------
465 
466  std::vector<JpsiEECandidate> JpsiFinder_ee::getPairs(const std::vector<const xAOD::TrackParticle*> &TracksIn) const {
467 
468  std::vector<JpsiEECandidate> myPairs;
469  JpsiEECandidate pair;
470  std::vector<const xAOD::TrackParticle*>::const_iterator outerItr;
471  std::vector<const xAOD::TrackParticle*>::const_iterator innerItr;
472 
473  if(TracksIn.size()>=2){
474  for(outerItr=TracksIn.begin();outerItr<TracksIn.end();++outerItr){
475  for(innerItr=(outerItr+1);innerItr!=TracksIn.end();++innerItr){
476  pair.trackParticle1 = *innerItr;
477  pair.trackParticle2 = *outerItr;
478  pair.pairType = TRK2;
479  myPairs.push_back(pair);
480  }
481  }
482  }
483 
484  return(myPairs);
485  }
486 
487  // *********************************************************************************
488 
489  // ---------------------------------------------------------------------------------
490  // getPairs: forms up 2-plets of electrons
491  // ---------------------------------------------------------------------------------
492 
493  std::vector<JpsiEECandidate> JpsiFinder_ee::getPairs(const std::vector<const xAOD::Electron*> &electronsIn) const {
494 
495  std::vector<JpsiEECandidate> myPairs;
496  JpsiEECandidate pair;
497  std::vector<const xAOD::Electron*>::const_iterator outerItr;
498  std::vector<const xAOD::Electron*>::const_iterator innerItr;
499 
500  if(electronsIn.size()>=2){
501  for(outerItr=electronsIn.begin();outerItr<electronsIn.end();++outerItr){
502  for(innerItr=(outerItr+1);innerItr!=electronsIn.end();++innerItr){
503  pair.el1 = *innerItr;
504  pair.el2 = *outerItr;
505  pair.pairType = ELEL;
506  myPairs.push_back(pair);
507  }
508  }
509  }
510 
511  return(myPairs);
512  }
513 
514  // *********************************************************************************
515 
516  // ---------------------------------------------------------------------------------
517  // getPairs2Colls: forms up 2-plets of tracks from two independent collections
518  // ---------------------------------------------------------------------------------
519 
520  std::vector<JpsiEECandidate> JpsiFinder_ee::getPairs2Colls(const std::vector<const xAOD::TrackParticle*> &tracks, const std::vector<const xAOD::Electron*> &electrons, bool tagAndProbe) const {
521 
522  std::vector<JpsiEECandidate> myPairs;
523  if (m_TrkParticleCollection.key() == "GSFCaloContainer") {
524  ATH_MSG_FATAL("GSFCaloContainer mode not implemented in getPairs2Colls.");
525  return myPairs;
526  }
527  JpsiEECandidate pair;
528 
529  // Unless user is running in tag and probe mode, remove tracks which are also identified as muons
530  std::vector<const xAOD::TrackParticle*> tracksToKeep;
531  if (!tagAndProbe) {
532  if(tracks.size()>=1 && electrons.size()>=1){
533  for (const xAOD::TrackParticle* trk : tracks) {
534  bool trackIsElectron(false);
535  for (const xAOD::Electron* ele : electrons) {
536  if ( ele->trackParticleLink().cachedElement() == trk ) {
537  trackIsElectron=true;
538  break;
539  }
540  }
541  if (!trackIsElectron) tracksToKeep.push_back(trk);
542  }
543  }
544  } else {tracksToKeep = tracks;}
545 
546  if(tracksToKeep.size()>=1 && electrons.size()>=1){
547  for (const xAOD::TrackParticle* trk : tracks) {
548  for (const xAOD::Electron* ele : electrons) {
549  pair.el1 = ele;
550  // Muon track 1st
551  pair.trackParticle1 = ele->trackParticleLink().cachedElement();
552  pair.trackParticle2 = trk;
553  pair.pairType = ELTRK;
554  myPairs.push_back(pair);
555  }
556  }
557  }
558 
559  return(myPairs);
560  }
561 
562 
563 
564  // *********************************************************************************
565 
566  // ---------------------------------------------------------------------------------
567  // getInvariantMass: returns invariant mass
568  // ---------------------------------------------------------------------------------
569 
570  double JpsiFinder_ee::getInvariantMass(const JpsiEECandidate &jpsiIn, const std::vector<double> &massHypotheses) const {
571  double mass1 = massHypotheses.at(0);
572  double mass2 = massHypotheses.at(1);
573 
574  // construct 4-vectors from track perigee parameters using given mass hypotheses.
575  // NOTE: in new data model (xAOD) the defining parameters are expressed as perigee parameters w.r.t. the beamspot
576  // NOTE2: TrackParticle::p4() method already returns TLorentzVector, however, we want to enforce our own mass hypothesis
577  TLorentzVector mu1;
578  TLorentzVector mu2;
579  mu1.SetVectM(jpsiIn.trackParticle1->p4().Vect(), mass1);
580  mu2.SetVectM(jpsiIn.trackParticle2->p4().Vect(), mass2);
581 
582  return (mu1+mu2).M();
583 
584  }
585 
586  // ---------------------------------------------------------------------------------
587  // selectCharges: selects track pairs with opposite charge / store + before -
588  // Boolean argument is to decide whether to accept oppositely or identically charged
589  // particles (true for oppositely charged)
590  // ---------------------------------------------------------------------------------
591 
592  std::vector<JpsiEECandidate> JpsiFinder_ee::selectCharges(const std::vector<JpsiEECandidate> &jpsisIn, const std::string &selection) const {
593 
594  bool opposite(false),same(false),all(false);
595  if (selection=="OPPOSITE") opposite=true;
596  if (selection=="SAME") same=true;
597  if (selection=="ALL") all=true;
598 
599  JpsiEECandidate tmpJpsi;
600  std::vector<JpsiEECandidate> jpsis;
601  double qOverP1=0.;
602  double qOverP2=0.;
603  for(auto jpsiItr=jpsisIn.cbegin();jpsiItr!=jpsisIn.cend();jpsiItr++){
604  bool oppCh(false),sameCh(false);
605  tmpJpsi = *jpsiItr;
606  qOverP1=(*jpsiItr).trackParticle1->qOverP();
607  qOverP2=(*jpsiItr).trackParticle2->qOverP();
608  if(qOverP1*qOverP2<0.0) oppCh=true; // product charge < 0
609  if(qOverP1*qOverP2>0.0) sameCh=true; // product charge > 0
610  // +ve should be first so swap
611  // Don't do it for tag and probe analyses (because tag muon must not change position)
612  if (oppCh && qOverP1<0.0 && !m_doTagAndProbe) {
613  tmpJpsi.trackParticle1 = (*jpsiItr).trackParticle2;
614  tmpJpsi.trackParticle2 = (*jpsiItr).trackParticle1;
615  tmpJpsi.el1 = (*jpsiItr).el2;
616  tmpJpsi.el2 = (*jpsiItr).el1;
617  tmpJpsi.collection1 = (*jpsiItr).collection2;
618  tmpJpsi.collection2 = (*jpsiItr).collection1;
619  }
620  if (oppCh && (opposite || all) ) jpsis.push_back(tmpJpsi);
621  if (sameCh && (same || all) ) jpsis.push_back(tmpJpsi);
622 
623  } // end of for loop
624 
625  return(jpsis);
626  }
627 
628  // ---------------------------------------------------------------------------------
629  // Apply the current cuts of the MCP group recommendation.
630  // ---------------------------------------------------------------------------------
631 
633 
634  static const SG::AuxElement::ConstAccessor<char> isLHVeryLoosenod0("DFCommonElectronsLHVeryLoosenod0");
635  static const SG::AuxElement::ConstAccessor<char> isLHVeryLoose("DFCommonElectronsLHVeryLoose");
636 
637  bool passesSelection = false;
638  bool passesLHVLoose = isLHVeryLoose(*electron);
639  bool passesLHVLoosenod0 = isLHVeryLoosenod0(*electron);
640 
641  if(m_elSelection == "d0") passesSelection = passesLHVLoose;
642  else if(m_elSelection == "nod0") passesSelection = passesLHVLoosenod0;
643  else if(m_elSelection == "d0_or_nod0") passesSelection = passesLHVLoose || passesLHVLoosenod0;
644  else ATH_MSG_ERROR("Invalid electron selection " << m_elSelection);
645 
646  ATH_MSG_DEBUG("Electron with pT, eta: " << electron->pt() << " " << electron->eta() << " passes " << m_elSelection << " " << passesSelection);
647  return passesSelection;
648 
649  }
650 
651 
652  // ---------------------------------------------------------------------------------
653  // Checks whether a TPB is in the collection
654  // ---------------------------------------------------------------------------------
655 
656  bool JpsiFinder_ee::isContainedIn(const xAOD::TrackParticle* theTrack, const xAOD::TrackParticleContainer* theCollection) const {
657  return std::find(theCollection->begin(), theCollection->end(), theTrack) != theCollection->end();
658  }
659 
660  // ---------------------------------------------------------------------------------
661  // trackMomentum: returns refitted track momentum
662  // ---------------------------------------------------------------------------------
663 
664  TVector3 JpsiFinder_ee::trackMomentum(const xAOD::Vertex * vxCandidate, int trkIndex) const
665  {
666  double px = 0., py = 0., pz = 0.;
667  if (0 != vxCandidate) {
668  const Trk::TrackParameters* aPerigee = vxCandidate->vxTrackAtVertex()[trkIndex].perigeeAtVertex();
669  px = aPerigee->momentum()[Trk::px];
670  py = aPerigee->momentum()[Trk::py];
671  pz = aPerigee->momentum()[Trk::pz];
672  }
673  TVector3 mom(px,py,pz);
674  return mom;
675  }
676 
677 }
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:74
Analysis::JpsiFinder_ee::m_invMassUpper
double m_invMassUpper
Definition: JpsiFinder_ee.h:94
Trk::py
@ py
Definition: ParamDefs.h:60
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::JpsiEECandidate::trackParticle1
const xAOD::TrackParticle * trackParticle1
Definition: JpsiFinder_ee.h:49
xAOD::BPhysHelper
Definition: BPhysHelper.h:71
test_pyathena.px
px
Definition: test_pyathena.py:18
JpsiFinder_ee.h
Analysis::JpsiFinder_ee::m_trkSelector
ToolHandle< Trk::ITrackSelectorTool > m_trkSelector
Definition: JpsiFinder_ee.h:111
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
VertexPointEstimator.h
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
Analysis::JpsiFinder_ee::getPairs2Colls
std::vector< JpsiEECandidate > getPairs2Colls(const std::vector< const xAOD::TrackParticle * > &, const std::vector< const xAOD::Electron * > &, bool) const
Definition: JpsiFinder_ee.cxx:520
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:67
index
Definition: index.py:1
xAODP4Helpers.h
Analysis::JpsiFinder_ee::~JpsiFinder_ee
~JpsiFinder_ee()
Definition: JpsiFinder_ee.cxx:160
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_ee::m_TrkParticleCollection
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_TrkParticleCollection
Definition: JpsiFinder_ee.h:103
Analysis::JpsiFinder_ee::m_useTrackMeasurement
bool m_useTrackMeasurement
Definition: JpsiFinder_ee.h:86
xAOD::P4Helpers::deltaPhi
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
Definition: xAODP4Helpers.h:69
Analysis::JpsiFinder_ee::m_sameChOnly
bool m_sameChOnly
Definition: JpsiFinder_ee.h:100
SG::ConstAccessor
Helper class to provide constant type-safe access to aux data.
Definition: ConstAccessor.h:55
Analysis::JpsiEECandidate::trackParticle2
const xAOD::TrackParticle * trackParticle2
Definition: JpsiFinder_ee.h:50
Analysis::JpsiFinder_ee::m_collAnglePhi
double m_collAnglePhi
Definition: JpsiFinder_ee.h:97
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
Analysis::JpsiFinder_ee::JpsiFinder_ee
JpsiFinder_ee(const std::string &t, const std::string &n, const IInterface *p)
Definition: JpsiFinder_ee.cxx:95
SG::VarHandleKey::key
const std::string & key() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:141
Analysis::JpsiFinder_ee::m_elSelection
std::string m_elSelection
Definition: JpsiFinder_ee.h:115
Analysis::JpsiFinder_ee::m_electronCollectionKey
SG::ReadHandleKey< xAOD::ElectronContainer > m_electronCollectionKey
Definition: JpsiFinder_ee.h:102
Trk::pz
@ pz
global momentum (cartesian)
Definition: ParamDefs.h:61
python.TrigEgammaFastCaloHypoTool.same
def same(val, tool)
Definition: TrigEgammaFastCaloHypoTool.py:10
Analysis::JpsiFinder_ee::m_doTagAndProbe
bool m_doTagAndProbe
Definition: JpsiFinder_ee.h:116
Analysis::JpsiFinder_ee::initialize
virtual StatusCode initialize() override
Definition: JpsiFinder_ee.cxx:32
Analysis::JpsiEECandidate
Definition: JpsiFinder_ee.h:48
TrkVKalVrtFitter.h
Analysis::JpsiEECandidate::el2
const xAOD::Electron * el2
Definition: JpsiFinder_ee.h:52
Analysis::JpsiFinder_ee::passesEgammaCuts
bool passesEgammaCuts(const xAOD::Electron *) const
Definition: JpsiFinder_ee.cxx:632
Analysis::JpsiFinder_ee::m_trk2M
double m_trk2M
Definition: JpsiFinder_ee.h:90
Analysis::JpsiFinder_ee::getPairs
std::vector< JpsiEECandidate > getPairs(const std::vector< const xAOD::TrackParticle * > &) const
Definition: JpsiFinder_ee.cxx:466
Analysis::JpsiFinder_ee::m_trkThresholdPt
double m_trkThresholdPt
Definition: JpsiFinder_ee.h:93
Analysis::JpsiFinder_ee::fit
xAOD::Vertex * fit(const std::vector< const xAOD::TrackParticle * > &, const xAOD::TrackParticleContainer *importedTrackCollection) const
Definition: JpsiFinder_ee.cxx:396
Analysis::ELEL
@ ELEL
Definition: JpsiFinder_ee.h:46
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:130
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
ParticleGun_EoverP_Config.mom
mom
Definition: ParticleGun_EoverP_Config.py:63
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
Analysis::JpsiFinder_ee::m_invMassLower
double m_invMassLower
Definition: JpsiFinder_ee.h:95
SG::ReadDecorHandle
Handle class for reading a decoration on an object.
Definition: StoreGate/StoreGate/ReadDecorHandle.h:94
python.TrigInDetConfig.inputTracks
inputTracks
Definition: TrigInDetConfig.py:191
Analysis::JpsiFinder_ee::m_thresholdPt
double m_thresholdPt
Definition: JpsiFinder_ee.h:91
lumiFormat.i
int i
Definition: lumiFormat.py:85
Analysis::JpsiFinder_ee::m_allChCombs
bool m_allChCombs
Definition: JpsiFinder_ee.h:101
Analysis::JpsiFinder_ee::performSearch
virtual StatusCode performSearch(const EventContext &ctx, xAOD::VertexContainer &vxContainer) const override
Definition: JpsiFinder_ee.cxx:167
Analysis::JpsiFinder_ee::trackMomentum
TVector3 trackMomentum(const xAOD::Vertex *vxCandidate, int trkIndex) const
Definition: JpsiFinder_ee.cxx:664
beamspotman.n
n
Definition: beamspotman.py:727
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
AthCommonDataStore< AthCommonMsg< AlgTool > >::declareProperty
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
Definition: AthCommonDataStore.h:145
Analysis::JpsiFinder_ee::m_partPropSvc
ServiceHandle< IPartPropSvc > m_partPropSvc
Definition: JpsiFinder_ee.h:113
ParticleConstants
Definition: ParticleConstants.h:22
Analysis::JpsiFinder_ee::m_Chi2Cut
double m_Chi2Cut
Definition: JpsiFinder_ee.h:98
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:525
Analysis::JpsiFinder_ee::m_diElectrons
bool m_diElectrons
Definition: JpsiFinder_ee.h:88
Trk::px
@ px
Definition: ParamDefs.h:59
Amg::pz
@ pz
Definition: GeoPrimitives.h:40
Analysis::JpsiFinder_ee::m_trktrk
bool m_trktrk
Definition: JpsiFinder_ee.h:84
PlotRamps.passesSelection
def passesSelection(gain, offset)
Definition: PlotRamps.py:8
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
DerivationFramework::TrackBag
std::vector< const xAOD::TrackParticle * > TrackBag
Definition: JpsiPlusDpstCascade.cxx:25
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
Analysis::JpsiFinder_ee::selectCharges
std::vector< JpsiEECandidate > selectCharges(const std::vector< JpsiEECandidate > &, const std::string &) const
Definition: JpsiFinder_ee.cxx:592
Analysis::JpsiEECandidate::collection1
const xAOD::TrackParticleContainer * collection1
Definition: JpsiFinder_ee.h:53
Analysis::JpsiFinder_ee::m_vertexEstimator
ToolHandle< InDet::VertexPointEstimator > m_vertexEstimator
Definition: JpsiFinder_ee.h:112
Analysis::JpsiEECandidate::el1
const xAOD::Electron * el1
Definition: JpsiFinder_ee.h:51
xAOD::BPhysHelper::setElectrons
bool setElectrons(const std::vector< const xAOD::Electron * > &electrons, const xAOD::ElectronContainer *electronContainer)
Definition: BPhysHelper.cxx:559
DataVector
Derived DataVector<T>.
Definition: DataVector.h:795
Vertex.h
Analysis::JpsiFinder_ee::m_iVertexFitter
ToolHandle< Trk::IVertexFitter > m_iVertexFitter
Definition: JpsiFinder_ee.h:109
Analysis::JpsiFinder_ee::m_egammaCuts
bool m_egammaCuts
Definition: JpsiFinder_ee.h:114
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Analysis::JpsiEECandidate::pairType
PairTypeEE pairType
Definition: JpsiFinder_ee.h:55
Analysis::JpsiFinder_ee::isContainedIn
bool isContainedIn(const xAOD::TrackParticle *, const xAOD::TrackParticleContainer *) const
Definition: JpsiFinder_ee.cxx:656
Analysis::JpsiFinder_ee::m_higherPt
double m_higherPt
Definition: JpsiFinder_ee.h:92
Analysis::JpsiFinder_ee::m_oppChOnly
bool m_oppChOnly
Definition: JpsiFinder_ee.h:99
Amg::py
@ py
Definition: GeoPrimitives.h:39
xAOD::TrackParticle_v1::qOverP
float qOverP() const
Returns the parameter.
selection
const std::string selection
Definition: fbtTestBasics.cxx:75
Analysis
The namespace of all packages in PhysicsAnalysis/JetTagging.
Definition: BTaggingCnvAlg.h:20
Analysis::JpsiFinder_ee::m_trk1M
double m_trk1M
Definition: JpsiFinder_ee.h:89
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
Amg::Vector3D
Eigen::Matrix< double, 3, 1 > Vector3D
Definition: GeoPrimitives.h:47
xAOD::Electron_v1
Definition: Electron_v1.h:34
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67
IVertexFitter.h
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.
DeMoScan.index
string index
Definition: DeMoScan.py:362
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
Analysis::JpsiFinder_ee::getInvariantMass
double getInvariantMass(const JpsiEECandidate &, const std::vector< double > &) const
Definition: JpsiFinder_ee.cxx:570
xAOD::Vertex_v1
Class describing a Vertex.
Definition: Vertex_v1.h:42
Analysis::JpsiFinder_ee::m_collAngleTheta
double m_collAngleTheta
Definition: JpsiFinder_ee.h:96
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
Analysis::JpsiFinder_ee::m_elel
bool m_elel
Definition: JpsiFinder_ee.h:82
xAOD::EgammaParameters::electron
@ electron
Definition: EgammaEnums.h:18
Analysis::ELTRK
@ ELTRK
Definition: JpsiFinder_ee.h:46
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_ee::m_eltrk
bool m_eltrk
Definition: JpsiFinder_ee.h:83
xAOD::Vertex_v1::vxTrackAtVertex
std::vector< Trk::VxTrackAtVertex > & vxTrackAtVertex()
Non-const access to the VxTrackAtVertex vector.
Definition: Vertex_v1.cxx:181
AthAlgTool
Definition: AthAlgTool.h:26
Analysis::JpsiFinder_ee::m_allElectrons
bool m_allElectrons
Definition: JpsiFinder_ee.h:85
Analysis::TRK2
@ TRK2
Definition: JpsiFinder_ee.h:46
Analysis::JpsiFinder_ee::m_iV0VertexFitter
ToolHandle< Trk::IVertexFitter > m_iV0VertexFitter
Definition: JpsiFinder_ee.h:110
ITrackSelectorTool.h
Analysis::JpsiFinder_ee::m_gsfCaloLinkKey
SG::ReadDecorHandleKey< xAOD::ElectronContainer > m_gsfCaloLinkKey
Definition: JpsiFinder_ee.h:104
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
Analysis::JpsiEECandidate::collection2
const xAOD::TrackParticleContainer * collection2
Definition: JpsiFinder_ee.h:54
Analysis::JpsiFinder_ee::m_useV0Fitter
bool m_useV0Fitter
Definition: JpsiFinder_ee.h:87
InDetDD::electrons
@ electrons
Definition: InDetDD_Defs.h:17
HepMCHelpers.h
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
ParticleConstants::PDG2011::electronMassInMeV
constexpr double electronMassInMeV
the mass of the electron (in MeV)
Definition: ParticleConstants.h:26