ATLAS Offline Software
Loading...
Searching...
No Matches
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
22#include "GaudiKernel/IPartPropSvc.h"
23#include "AthLinks/ElementLink.h"
24#include "HepPDT/ParticleDataTable.hh"
25#include "xAODTracking/Vertex.h"
30namespace 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 };
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),
101 m_useV0Fitter(false),
102 m_diElectrons(true),
103 m_trk1M(ParticleConstants::electronMassInMeV),
104 m_trk2M(ParticleConstants::electronMassInMeV),
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
252 std::vector<JpsiEECandidate>::iterator jpsiItr;
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;
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;
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 }
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}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
: B-physics xAOD helpers.
ATLAS-specific HepMC functions.
bool isContainedIn(const xAOD::TrackParticle *, const xAOD::TrackParticleContainer *) const
bool passesEgammaCuts(const xAOD::Electron *) const
std::vector< JpsiEECandidate > getPairs(const std::vector< const xAOD::TrackParticle * > &) const
SG::ReadHandleKey< xAOD::ElectronContainer > m_electronCollectionKey
ToolHandle< Trk::ITrackSelectorTool > m_trkSelector
ServiceHandle< IPartPropSvc > m_partPropSvc
std::vector< JpsiEECandidate > selectCharges(const std::vector< JpsiEECandidate > &, const std::string &) const
SG::ReadDecorHandleKey< xAOD::ElectronContainer > m_gsfCaloLinkKey
xAOD::Vertex * fit(const std::vector< const xAOD::TrackParticle * > &, const xAOD::TrackParticleContainer *importedTrackCollection) const
SG::ReadHandleKey< xAOD::TrackParticleContainer > m_TrkParticleCollection
virtual StatusCode initialize() override
JpsiFinder_ee(const std::string &t, const std::string &n, const IInterface *p)
virtual StatusCode performSearch(const EventContext &ctx, xAOD::VertexContainer &vxContainer) const override
ToolHandle< InDet::VertexPointEstimator > m_vertexEstimator
TVector3 trackMomentum(const xAOD::Vertex *vxCandidate, int trkIndex) const
double getInvariantMass(const JpsiEECandidate &, const std::vector< double > &) const
ToolHandle< Trk::IVertexFitter > m_iV0VertexFitter
ToolHandle< Trk::IVertexFitter > m_iVertexFitter
std::vector< JpsiEECandidate > getPairs2Colls(const std::vector< const xAOD::TrackParticle * > &, const std::vector< const xAOD::Electron * > &, bool) const
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
value_type push_back(value_type pElem)
Add an element to the end of the collection.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
SG::ConstAccessor< T, ALLOC > ConstAccessor
Definition AuxElement.h:569
Handle class for reading a decoration on an object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
const Amg::Vector3D & momentum() const
Access method for the momentum.
This class implements a vertex fitting algorithm optimised for V0 finding.
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.
STL class.
bool setElectrons(const std::vector< const xAOD::Electron * > &electrons, const xAOD::ElectronContainer *electronContainer)
bool setRefTrks(std::vector< float > px, std::vector< float > py, std::vector< float > pz)
Sets refitted track momenta.
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
float qOverP() const
Returns the parameter.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
void setTrackParticleLinks(const TrackParticleLinks_t &trackParticles)
Set all track particle links at once.
void clearTracks()
Remove all tracks from the vertex.
const TrackParticleLinks_t & trackParticleLinks() const
Get all the particles associated with the vertex.
std::vector< Trk::VxTrackAtVertex > & vxTrackAtVertex()
Non-const access to the VxTrackAtVertex vector.
double chi2(TH1 *h0, TH1 *h1)
const std::string selection
Eigen::Matrix< double, 3, 1 > Vector3D
The namespace of all packages in PhysicsAnalysis/JetTagging.
static const int ELECTRON
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ pz
global momentum (cartesian)
Definition ParamDefs.h:61
@ px
Definition ParamDefs.h:59
@ py
Definition ParamDefs.h:60
ParametersBase< TrackParametersDim, Charged > TrackParameters
Definition index.py:1
double deltaPhi(double phiA, double phiB)
delta Phi in range [-pi,pi[
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
Electron_v1 Electron
Definition of the current "egamma version".
const xAOD::TrackParticleContainer * collection2
const xAOD::TrackParticleContainer * collection1
const xAOD::TrackParticle * trackParticle2
const xAOD::Electron * el2
const xAOD::Electron * el1
const xAOD::TrackParticle * trackParticle1