22 #include "GaudiKernel/IPartPropSvc.h"
23 #include "AthLinks/ElementLink.h"
24 #include "HepPDT/ParticleDataTable.hh"
58 const HepPDT::ParticleData* pd_el = particleDataTable->particle(MC::ELECTRON);
63 if (
m_doTagAndProbe)
ATH_MSG_WARNING(
"You have requested tag and probe mode. Duplicate mu+trk pairs WILL be allowed, charge ordering WILL NOT be done. Tag track will be first in each candidate");
67 bool illogicalOptions(
false);
69 ATH_MSG_WARNING(
"You are requesting incompatible combinations of muons and tracks in the pairs. JpsiEECandidates will be EMPTY!");
70 illogicalOptions=
true;
73 ATH_MSG_WARNING(
"You are requesting Tag and Probe analysis but have not requested mu+trk mode. This is impossible. JpsiEECandidates will be EMPTY!");
74 illogicalOptions=
true;
77 ATH_MSG_WARNING(
"You are requesting incompatible combinations of charges in the pairs. JpsiEECandidates will be EMPTY!");
78 illogicalOptions=
true;
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;
84 if (illogicalOptions)
return StatusCode::FAILURE;
90 return StatusCode::SUCCESS;
99 m_allElectrons(false),
100 m_useTrackMeasurement(true),
101 m_useV0Fitter(false),
107 m_trkThresholdPt(0.0),
108 m_invMassUpper(100000.0),
110 m_collAngleTheta(0.0),
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"),
123 m_elSelection(
"d0_or_nod0"),
124 m_doTagAndProbe(false)
127 declareInterface<JpsiFinder_ee>(
this);
177 return StatusCode::SUCCESS;;
179 importedElectronCollection = ehandle.
cptr();
189 return StatusCode::SUCCESS;;
191 importedTrackCollection = thandle.
cptr();
195 typedef std::vector<const xAOD::TrackParticle*>
TrackBag;
196 typedef std::vector<const xAOD::Electron*> ElectronBag;
203 for (trkCItr=importedTrackCollection->
begin(); trkCItr!=importedTrackCollection->
end(); ++trkCItr) {
207 theIDTracksAfterSelection.push_back(TP);
209 if (theIDTracksAfterSelection.size() == 0)
return StatusCode::SUCCESS;;
210 ATH_MSG_DEBUG(
"Number of tracks after ID track selection: " << theIDTracksAfterSelection.size());
214 ElectronBag theElectronsAfterSelection;
217 for (elItr=importedElectronCollection->
begin(); elItr!=importedElectronCollection->
end(); ++elItr) {
218 if ( *elItr == NULL )
continue;
219 if (!(*elItr)->trackParticleLink().isValid())
continue;
225 if (!refittedTrackLink.
isValid())
continue;
226 elTrk = *refittedTrackLink;
228 if (!(*elItr)->trackParticleLink().isValid())
continue;
229 elTrk = (*elItr)->trackParticleLink().cachedElement();
232 if ( elTrk==NULL)
continue;
237 theElectronsAfterSelection.push_back(*elItr);
239 if (theElectronsAfterSelection.size() == 0)
return StatusCode::SUCCESS;;
240 ATH_MSG_DEBUG(
"Number of electrons after selection: " << theElectronsAfterSelection.size());
244 std::vector<JpsiEECandidate> jpsiCandidates;
245 if (
m_elel) jpsiCandidates =
getPairs(theElectronsAfterSelection);
249 ATH_MSG_DEBUG(
"Number of pairs with ee from a B decay: " << jpsiCandidates.size() );
261 for (jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
262 (*jpsiItr).collection1 = importedTrackCollection;
263 (*jpsiItr).collection2 = importedTrackCollection;
268 for (jpsiItr=jpsiCandidates.begin(); jpsiItr!=jpsiCandidates.end(); ++jpsiItr) {
275 (*jpsiItr).trackParticle1 = *refittedTrackLink1;
276 (*jpsiItr).trackParticle2 = *refittedTrackLink2;
278 (*jpsiItr).trackParticle1 = (*jpsiItr).el1->trackParticleLink().
cachedElement();
279 (*jpsiItr).trackParticle2 = (*jpsiItr).el2->trackParticleLink().cachedElement();
281 (*jpsiItr).collection1 = importedTrackCollection;
282 (*jpsiItr).collection2 = importedTrackCollection;
284 ATH_MSG_WARNING(
"Not setup for non-track electron measurements yet....");
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);
298 for (ii=listToDelete.rbegin(); ii!=listToDelete.rend(); ++ii) {
299 jpsiCandidates.erase(jpsiCandidates.begin() + (*ii) );
301 ATH_MSG_DEBUG(
"Number of candidates after higherPt cut: " << jpsiCandidates.size() );
305 std::vector<JpsiEECandidate> sortedJpsiEECandidates;
309 ATH_MSG_DEBUG(
"Number of candidates after charge selection: " << sortedJpsiEECandidates.size() );
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() );
319 double deltaphi = std::abs(
xAOD::P4Helpers::deltaPhi((*jpsiItr).trackParticle1->phi0() , (*jpsiItr).trackParticle2->phi0()));
323 for (ii=listToDelete.rbegin(); ii!=listToDelete.rend(); ++ii) {
324 sortedJpsiEECandidates.erase(sortedJpsiEECandidates.begin() + (*ii) );
326 ATH_MSG_DEBUG(
"Number of collimated candidates: " << sortedJpsiEECandidates.size() );
330 std::vector<double> trkMasses;
335 std::vector<int> listToDelete;
336 std::vector<int>::reverse_iterator ii;
337 for(jpsiItr=sortedJpsiEECandidates.begin(); jpsiItr!=sortedJpsiEECandidates.end(); ++jpsiItr,++
index) {
341 listToDelete.push_back(
index);
344 for (ii=listToDelete.rbegin(); ii!=listToDelete.rend(); ++ii) {
345 sortedJpsiEECandidates.erase(sortedJpsiEECandidates.begin() + (*ii) );
347 ATH_MSG_DEBUG(
"Number of candidates passing invariant mass selection: " << sortedJpsiEECandidates.size() );
350 if (sortedJpsiEECandidates.size() == 0)
return StatusCode::SUCCESS;;
354 for(jpsiItr=sortedJpsiEECandidates.begin(); jpsiItr!=sortedJpsiEECandidates.end(); ++jpsiItr) {
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)};
361 if (myVxCandidate != 0) {
363 double chi2 = myVxCandidate->chiSquared();
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);
376 vxContainer.
push_back(std::move(myVxCandidate));
387 return StatusCode::SUCCESS;;
403 if(concreteVertexFitter == 0) {
404 ATH_MSG_FATAL(
"The vertex fitter passed is not a V0 Vertex Fitter");
414 if (errorcode != 0) {startingPoint(0) = 0.0; startingPoint(1) = 0.0; startingPoint(2) = 0.0;}
419 if(myVxCandidate != 0){
420 std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
424 newLinkVector.push_back( mylink ); }
432 return myVxCandidate;
435 ATH_MSG_DEBUG(
"Initial fit was a success! " << myVxCandidate);
437 if(myVxCandidate != 0){
438 std::vector<ElementLink<DataVector<xAOD::TrackParticle> > > newLinkVector;
442 newLinkVector.push_back( mylink );
450 return myVxCandidate;
468 std::vector<JpsiEECandidate> myPairs;
470 std::vector<const xAOD::TrackParticle*>::const_iterator outerItr;
471 std::vector<const xAOD::TrackParticle*>::const_iterator innerItr;
473 if(TracksIn.size()>=2){
474 for(outerItr=TracksIn.begin();outerItr<TracksIn.end();++outerItr){
475 for(innerItr=(outerItr+1);innerItr!=TracksIn.end();++innerItr){
479 myPairs.push_back(pair);
495 std::vector<JpsiEECandidate> myPairs;
497 std::vector<const xAOD::Electron*>::const_iterator outerItr;
498 std::vector<const xAOD::Electron*>::const_iterator innerItr;
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;
506 myPairs.push_back(pair);
522 std::vector<JpsiEECandidate> myPairs;
524 ATH_MSG_FATAL(
"GSFCaloContainer mode not implemented in getPairs2Colls.");
530 std::vector<const xAOD::TrackParticle*> tracksToKeep;
532 if(tracks.size()>=1 &&
electrons.size()>=1){
534 bool trackIsElectron(
false);
536 if ( ele->trackParticleLink().cachedElement() == trk ) {
537 trackIsElectron=
true;
541 if (!trackIsElectron) tracksToKeep.push_back(trk);
544 }
else {tracksToKeep = tracks;}
546 if(tracksToKeep.size()>=1 &&
electrons.size()>=1){
554 myPairs.push_back(pair);
571 double mass1 = massHypotheses.at(0);
572 double mass2 = massHypotheses.at(1);
582 return (mu1+mu2).M();
594 bool opposite(
false),
same(
false),
all(
false);
595 if (
selection==
"OPPOSITE") opposite=
true;
600 std::vector<JpsiEECandidate> jpsis;
603 for(
auto jpsiItr=jpsisIn.cbegin();jpsiItr!=jpsisIn.cend();jpsiItr++){
604 bool oppCh(
false),sameCh(
false);
607 qOverP2=(*jpsiItr).trackParticle2->qOverP();
608 if(qOverP1*qOverP2<0.0) oppCh=
true;
609 if(qOverP1*qOverP2>0.0) sameCh=
true;
615 tmpJpsi.
el1 = (*jpsiItr).el2;
616 tmpJpsi.
el2 = (*jpsiItr).el1;
620 if (oppCh && (opposite ||
all) ) jpsis.push_back(tmpJpsi);
621 if (sameCh && (
same ||
all) ) jpsis.push_back(tmpJpsi);
638 bool passesLHVLoose = isLHVeryLoose(*
electron);
639 bool passesLHVLoosenod0 = isLHVeryLoosenod0(*
electron);
657 return std::find(theCollection->
begin(), theCollection->
end(), theTrack) != theCollection->
end();
666 double px = 0.,
py = 0.,
pz = 0.;
667 if (0 != vxCandidate) {