ATLAS Offline Software
FourMuonEvent.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 // Include files...
7 //==================================================================================
8 
9 // This files header
11 
12 // Standard headers
13 
14 // Package Headers
16 
17 // ATLAS headers
19 #include "StoreGate/StoreGateSvc.h"
20 
21 //#include "muonEvent/MuonParamDefs.h"
22 
23 #include "CLHEP/Random/RandFlat.h"
24 
25 //==================================================================================
26 // Public Methods
27 //==================================================================================
28 
30 {
31  m_xSampleName = "FourMuon";
32 
33  m_container = PerfMonServices::MUON_COLLECTION; //PerfMonServices::ELECTRON_COLLECTION
34 
35  m_doDebug = false;
36  m_workAsFourMuons = false;
37  m_workAsFourElectrons = false;
38  m_workAsFourLeptons = true;
39 
40  // Setup the muon tags
41  m_uMuonTags = 4;
42  m_LeadingMuonPtCut = 20.;
43  m_SecondMuonPtCut = 15.;
44  m_MassWindowLow = 10.0;
45  m_MassWindowHigh = 125.0;
46  m_deltaXYcut = 0.1; // in mm
47  m_Z0GapCut = 5.0; // in mm
48  m_SelectMuonByIso = true;
49  m_SelectMuonByIP = true;
50  m_eventCount = 0;
54 
55  m_msgStream = new MsgStream(Athena::getMessageSvc(), "InDetPerformanceMonitoring" );
56 }
57 
58 //==================================================================================
60 {
61  delete m_msgStream;
62 }
63 
64 //==================================================================================
66 {
67  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * START *" << endmsg;
68 
69  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * initializing muon selector *" << endmsg;
70  m_xMuonID.Init();
71  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * initializing electron selector *" << endmsg;
72  m_xElecID.Init();
73 
74  if (m_workAsFourMuons) {(*m_msgStream) << MSG::INFO << " * FourMuonEvent::Init * working mode: 4 muons" << endmsg; }
75  if (m_workAsFourElectrons) {(*m_msgStream) << MSG::INFO << " * FourMuonEvent::Init * working mode: 4 electrons" << endmsg; }
76  if (m_workAsFourLeptons) {(*m_msgStream) << MSG::INFO << " * FourMuonEvent::Init * working mode: 4 leptons" << endmsg; }
77 
78  PARENT::Init();
79  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * Completed * " << endmsg;
80 
81  return;
82 }
83 
84 //==================================================================================
86 {
87  m_eventCount++;
88  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * STARTING ** New event ** eventCount " << m_eventCount << endmsg;
89 
90  // Clear out the previous events record.
91  this->Clear();
92 
93  // if muons are requested
95  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * retrieving xAOD::MuonContainer " << m_container << " of eventCount " << m_eventCount << std::endl;
96 
97  const xAOD::MuonContainer* pxMuonContainer = PerfMonServices::getContainer<xAOD::MuonContainer>( m_container );
98 
99  // check if muon container does exist
100  if (pxMuonContainer != nullptr) {
101  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * eventCount " << m_eventCount
102  << " track list has "<< pxMuonContainer->size()
103  << " combined muons in container " << m_container
104  << " container name: " << PerfMonServices::getContainerName ( m_container )
105  << endmsg;
106 
107  xAOD::MuonContainer::const_iterator xMuonItr = pxMuonContainer->begin();
108  xAOD::MuonContainer::const_iterator xMuonItrE = pxMuonContainer->end();
109  int theCount = 0;
110  while ( xMuonItr != xMuonItrE ){ // start loop on muons
111  const xAOD::Muon* pxCMuon = *xMuonItr;
112  theCount++;
113  // Apply muon cuts
114  if ( m_xMuonID.passSelection( pxCMuon)) {
115  RecordMuon( pxCMuon );
116  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco ** muon " << theCount << " is accepted " << endmsg;
117  }
118  ++xMuonItr;
119  } // end loop on muons
120 
121  // ordering of muons
122  this->OrderMuonList();
123  } // end muon container exists
124  if (!pxMuonContainer) {
125  std::cout << " * FourMuonEvent::Reco * Can't retrieve combined muon collection (container: " << m_container <<") " << std::endl;
126  return false;
127  } // end muon container does not exist
128  } // end requesting muons
129 
130  //
131  // Electron selection (in case electrons are requested)
133  // Get the electron AOD container
134  const xAOD::ElectronContainer* pxElecContainer = nullptr;
135  if (m_doDebug){ std::cout << " * FourMuonEvent::Reco * retrieving xAOD::ElectronContainer " << PerfMonServices::ELECTRON_COLLECTION << std::endl; }
136  pxElecContainer = PerfMonServices::getContainer<xAOD::ElectronContainer>( PerfMonServices::ELECTRON_COLLECTION );
137 
138  //pxElecContainer = evtStore()->retrieve( pxElecContainer, "Electrons" );
139 
140  if (pxElecContainer != nullptr) {
141  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * retrieving xAOD::ElectronContainer SUCCESS. "
143  << " size: " << pxElecContainer->size()
144  << endmsg;
145  if (pxElecContainer->size() > 0 ){
146  m_xElecID.PrepareElectronList (pxElecContainer);
149  }
150  }
151  else { // no pxElecContainer
152  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * retrieving xAOD::ElectronContainer -- FAILED -- eventcount: " << m_eventCount << endmsg;
153  }
154  }
155 
157  // reached this point one has the list of muons and electrons in this event
159 
160  // now check if the particles in the event make them to satisfy the event selection
161  if (m_workAsFourMuons) {
162  m_passedFourMuonSelection = false; // unless the event has 4 muons, assume it is not good
163 
164  if (m_numberOfFullPassMuons == 4) {
168 
170  m_FourMuonInvMass = m_fInvariantMass[ID]; // store invariant mass
171  if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is a GOOD 4-muon event " << std::endl;
172  }
173  else {
174  if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " FAILS the 4-muon event selection " << std::endl;
175  }
176  }
177  } // end of workAsFourMuons
178 
179  if (m_workAsFourElectrons) {
180  if (m_doDebug) std::cout << " * FourMuonEvent::Reco * applying 4 electron selection " << std::endl;
181  m_passedFourElectronSelection = false; // unless the event has 4 muons, assume it is not good
182 
183  if (m_numberOfFullPassElectrons == 4) {
186 
188  m_FourMuonInvMass = m_fInvariantMass[ID]; // store invariant mass
189  if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is a GOOD 4-electrom event " << std::endl;
190  }
191  else {
192  if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " FAILS the 4-electron event selection " << std::endl;
193  }
194  }
195  else {
196  if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is not a 4-electron event " << std::endl;
197  }
198  } // end of workAsFourElectrons
199 
200 
201  if (m_workAsFourLeptons) {
202  if (m_doDebug) std::cout << " * FourMuonEvent::Reco * applying 4 lepton selection " << std::endl;
204 
205  bool enoughleptons = false;
206  if (m_numberOfFullPassMuons == 4) enoughleptons = true;
207  if (m_numberOfFullPassElectrons == 4) enoughleptons = true;
208  if (m_numberOfFullPassMuons >= 2 && m_numberOfFullPassElectrons >= 2) enoughleptons = true;
209 
210  if ( enoughleptons) {
211  if (m_doDebug) {
212  std::cout << " * FourMuonEvent::Reco * Global statistics: Total number of accepted muons so far: " << m_acceptedMuonCount
213  << " & electrons: " << m_acceptedElecCount << " integrated over all events "
214  << std::endl;
215  std::cout << " * FourMuonEvent::Reco * This event has " << m_numberOfFullPassMuons
216  << " muons & " << m_numberOfFullPassElectrons << " electrons --> try kinematics, vertex and event selection"
217  << std::endl;
218  }
222 
224  m_FourMuonInvMass = m_fInvariantMass[ID]; // store invariant mass
225  (*m_msgStream) << MSG::INFO << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is a GOOD 4-lepton event with inv mass: " << m_FourMuonInvMass << endmsg;
226  }
227  else {
228  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * === Event " << m_eventCount << " -- FAILS -- the 4-lepton event selection " << endmsg;
229  }
230  }
231  else {
232  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * 4lepton selection FAILURE. Not enough muons or electrons. Event has " << m_numberOfFullPassMuons
233  << " muons & " << m_numberOfFullPassElectrons << " electrons"
234  << endmsg;
235  }
236  }
237 
238  m_passedSelectionCuts = false; // assume event is not good, but check the selection according to the use case
242 
244 
245  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * COMPLETED * Event has " << m_numberOfFullPassMuons << " muons & "
246  << m_numberOfFullPassElectrons << " electrons. "
247  << " So far: " << m_acceptedEventCount << " events were accepted out of " << m_eventCount << " tested" << endmsg;
248 
249  return m_passedSelectionCuts;
250 }
251 
252 //==================================================================================
253 // Protected Methods
254 //==================================================================================
256 {
257 }
258 
259 //==================================================================================
260 // Private Methods
261 //==================================================================================
263 {
264  bool inputdebug = m_doDebug;
265  //m_doDebug = true;
266 
267  bool eventisgood = true;
268  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::EventSelection( type= " << eType << ") ** started ** " << std::endl
269  << " event count: " << m_eventCount << std::endl
270  << " m_NumberOfFullPassMuons: " << m_numberOfFullPassMuons << std::endl
271  << " m_NumberOfFullPassElectrons: " << m_numberOfFullPassElectrons
272  << endmsg;
273 
274 
275  // Depending on mode: require a minimum of electrons or muons
276  if ( eventisgood && m_workAsFourMuons) {
277  if (m_numberOfFullPassMuons < 4) {
278  eventisgood = false;
279  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good muons == 4 :( "
280  <<" m_numberOfFullPassMuons= " << m_numberOfFullPassMuons << std::endl;
281  }
282  }
283  }
284 
285  if ( eventisgood && m_workAsFourElectrons) {
286  if (m_numberOfFullPassElectrons < 4) {
287  eventisgood = false;
288  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good electrons == 4 :( "
289  <<" m_numberOfFullPassElectrons= " << m_numberOfFullPassElectrons << std::endl;
290  }
291  }
292  }
293 
294  if ( eventisgood && m_workAsFourLeptons) {
295  bool thisselection = false;
296  if (m_numberOfFullPassMuons == 4) thisselection = true;
297  if (m_numberOfFullPassElectrons == 4) thisselection = true;
298  if (m_numberOfFullPassMuons >= 2 && m_numberOfFullPassElectrons >= 2) thisselection = true;
299  if (!thisselection) {
300  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good muons >= 2 && electrons >= 2 :( "
301  <<" m_numberOfFullPassMuons= " << m_numberOfFullPassMuons
302  <<" m_numberOfFullPassElectrons= " << m_numberOfFullPassElectrons << std::endl;
303  }
304  }
305  eventisgood = thisselection;
306  }
307 
308  //
309  // momentum of the leptons
310  // loop over the muons and electrons and count how many pass the leadingPt and secondPt cut
311  unsigned int npassleadingpt = 0;
312  unsigned int npasssecondpt = 0;
313  if ( eventisgood && (m_workAsFourMuons || m_workAsFourLeptons) ) {
314  if (m_numberOfFullPassMuons >= 2) { // electrons pt cuts if there are some electrons
315  //for (unsigned int i=0; i < m_numberOfFullPassMuons; i++) {
316  for (unsigned int i=0; i < NUM_MUONS; i++) {
317  if (m_pxIDTrack[i] == nullptr) continue;
318  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * using muon " << i << " with pt: " << m_pxIDTrack[i]->pt() << std::endl;}
319  if (m_pxIDTrack[i]->pt() > m_LeadingMuonPtCut*CLHEP::GeV) npassleadingpt++;
320  if (m_pxIDTrack[i]->pt() > m_SecondMuonPtCut*CLHEP::GeV) npasssecondpt++;
321  }
322  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #muons with pt > leading pt: " << m_LeadingMuonPtCut*CLHEP::GeV << " = " << npassleadingpt << std::endl;}
323  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #muons with pt > second pt: " << m_SecondMuonPtCut*CLHEP::GeV << " = " << npasssecondpt << std::endl;}
324  if (npassleadingpt == 0) { // at least 1 muon must pass the leading pt cut
325  eventisgood = false;
326  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing leading muon pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
327  }
328  if (npasssecondpt < m_numberOfFullPassMuons) { // all muons must pass the second pt cut
329  eventisgood = false;
330  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing second muon pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
331  }
332  }
333  }
334 
335  // four electrons case
336  if ( eventisgood && (m_workAsFourElectrons || m_workAsFourLeptons) ) {
337  npassleadingpt = 0;
338  npasssecondpt = 0;
339  if (m_numberOfFullPassElectrons >= 2) { // electrons pt cuts if there are some electrons
340  for (unsigned int i=0; i < NUM_MUONS; i++) {
341  if (m_pxELTrack[i] == nullptr) continue;
342  if (m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * using electron " << i << " with pt: " << m_pxELTrack[i]->pt() << std::endl;}
343  if (m_pxELTrack[i]->pt() > m_LeadingMuonPtCut*CLHEP::GeV) npassleadingpt++;
344  if (m_pxELTrack[i]->pt() > m_SecondMuonPtCut*CLHEP::GeV) npasssecondpt++;
345  }
346  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #elecs with pt > leading pt: " << m_LeadingMuonPtCut*CLHEP::GeV << " = " << npassleadingpt << std::endl;}
347  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #elecs with pt > second pt: " << m_SecondMuonPtCut*CLHEP::GeV << " = " << npasssecondpt << std::endl;}
348  if (npassleadingpt == 0) { // at least 1 electron must pass the leading pt cut
349  eventisgood = false;
350  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing leading electron pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
351  }
352  if (npasssecondpt < m_numberOfFullPassElectrons) { // all electrons must pass the second pt cut
353  eventisgood = false;
354  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing second electrons pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
355  }
356  } // electron pt cuts apply if there are some electrons
357  }
358 
359  // Invariant mass window
360  if (eventisgood) {
361  if ( m_fInvariantMass[eType] < m_MassWindowLow ) {
362  if(m_doDebug) {
363  std::cout <<" * FourMuonEvent::EventSelection * Failing mass window low cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowLow << std::endl;
364  }
365  eventisgood = false;
366  }
367  if ( m_fInvariantMass[eType] > m_MassWindowHigh ) {
368  if(m_doDebug) {
369  std::cout <<" * FourMuonEvent::EventSelection * Failing mass window high cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowHigh << std::endl;
370  }
371  eventisgood = false;
372  }
373  }
374 
375  // check on vertices
376  if (eventisgood) {
377  bool vertexstatus = false;
378 
379  std::vector <float> vtxListX; // coordinates of the vertex
380  std::vector <float> vtxListY;
381  std::vector <float> vtxListZ;
382  std::vector <int> vtxNpart; // count how many particles are in vertex
383 
384  int noVertexCountMuon = 0;
385  int noVertexCountElec = 0;
386  if ( m_workAsFourMuons || m_workAsFourLeptons ) { // till here we have the muon vertices list
387  // loop on muons first
388  for (unsigned int imu = 0; imu < NUM_MUONS; imu++) {
389  if (m_pxMUTrack[imu] != nullptr) {
390  /* R21 SALVA --> vertex is not available in R22 --> A FIX IS NEEDED */
391  /*
392  if (m_pxMUTrack[imu]->vertex()) {
393  if (vtxListX.size()==0) { // this is the first vertex found
394  vtxListX.push_back(m_pxMUTrack[imu]->vertex()->x());
395  vtxListY.push_back(m_pxMUTrack[imu]->vertex()->y());
396  vtxListZ.push_back(m_pxMUTrack[imu]->vertex()->z());
397  vtxNpart.push_back(0); // initialize particle count to 0
398  }
399  // loop on existing vertices. Check if this particle shares one of the existing ones. If not, add a new vertex to the list
400  for (size_t ivtx=0; ivtx < vtxListX.size(); ivtx++) {
401  float deltaX = fabs(m_pxMUTrack[imu]->vertex()->x() - vtxListX.at(ivtx));
402  float deltaY = fabs(m_pxMUTrack[imu]->vertex()->y() - vtxListY.at(ivtx));
403  float deltaZ = fabs(m_pxMUTrack[imu]->vertex()->z() - vtxListZ.at(ivtx));
404 
405  if (deltaX < m_deltaXYcut && deltaY < m_deltaXYcut && deltaZ < m_Z0GapCut) {
406  // this is an existing vertex
407  int npartinvtx = vtxNpart.at(ivtx);
408  npartinvtx++;
409  vtxNpart.at(ivtx) = npartinvtx;
410  // fill the variables that tells to which vertex is associated each muon // not very nice piece of code :(
411  m_muon_vtx[imu] = ivtx+1;
412  }
413  }
414  } // vertex exist
415 
416  else { // no vertex
417  noVertexCountMuon++;
418  }
419  */
420  } // muon exist
421  } // end of loop on muons
422  } // end of using muons
423 
424  if ( m_workAsFourElectrons || m_workAsFourLeptons ) { // till here we have the muon vertices list
425  // now loop on electrons
426  for (unsigned int iel = 0; iel < NUM_MUONS; iel++) {
427  if (m_pxELTrack[iel] != nullptr) {
428  /* R21 SALVA --> vertex is not available in R22 --> A FIX IS NEEDED */
429  /*
430  if (m_pxELTrack[iel]->vertex()) {
431  if (vtxListX.size()==0) { // this is the first vertex found
432  vtxListX.push_back(m_pxELTrack[iel]->vertex()->x());
433  vtxListY.push_back(m_pxELTrack[iel]->vertex()->y());
434  vtxListZ.push_back(m_pxELTrack[iel]->vertex()->z());
435  vtxNpart.push_back(0); // initialize particle count to 0
436  }
437  bool vertexmatchfound = false;
438  // loop on existing vertices. Check if this particle shares one of the existing ones. If not, add a new vertex to the list
439  for (unsigned int ivtx=0; ivtx < vtxListX.size(); ivtx++) {
440  float deltaX = fabs( m_pxELTrack[iel]->vertex()->x() - vtxListX.at(ivtx) );
441  float deltaY = fabs( m_pxELTrack[iel]->vertex()->y() - vtxListY.at(ivtx) );
442  float deltaZ = fabs( m_pxELTrack[iel]->vertex()->z() - vtxListZ.at(ivtx) );
443 
444  if (deltaX < m_deltaXYcut && deltaY < m_deltaXYcut && deltaZ < m_Z0GapCut) {
445  // this is an existing vertex
446  int npartinvtx = vtxNpart.at(ivtx);
447  npartinvtx++;
448  vtxNpart.at(ivtx) = npartinvtx;
449  // fill the variables that tells to which vertex is associated each muon
450  m_elec_vtx[iel] = ivtx+1;
451  vertexmatchfound = true;
452  }
453  }
454  if (!vertexmatchfound) { // the electron is not in any of the previous listed vertices
455  // this is a new vertex
456  vtxListX.push_back(m_pxELTrack[iel]->vertex()->x());
457  vtxListY.push_back(m_pxELTrack[iel]->vertex()->y());
458  vtxListZ.push_back(m_pxELTrack[iel]->vertex()->z());
459  vtxNpart.push_back(1); // initialize particle count to 1
460  m_elec_vtx[iel] = vtxListX.size(); // this electron is in this new vertex
461  }
462  } // vertex exist
463  else { // no vertex
464  noVertexCountElec++;
465  }
466  */
467  } // electron exists
468  } // end of loop on electrons
469  } // end of using electrons
470 
471  if ( m_workAsFourMuons ) { // till here we have the muon vertices list
472  m_nVertex = vtxListX.size();
473  if (vtxListX.size()>0) vertexstatus = true;
474  // check that the muons are not split into too many vertices
475  if (vtxListX.size() >= m_numberOfFullPassMuons - 1) vertexstatus = false;
476  // allow no muon without vertex
477  if (noVertexCountMuon > 0) vertexstatus = false;
478  if (m_doDebug || true) {
479  std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices ID of the muons = " << std::endl
480  << " mu- 1 " << m_muon_vtx[0] << " pt: " << m_pxMUTrack[0]->pt() << std::endl
481  << " mu- 2 " << m_muon_vtx[1] << " pt: " << m_pxMUTrack[1]->pt() << std::endl
482  << " mu+ 1 " << m_muon_vtx[2] << " pt: " << m_pxMUTrack[2]->pt() << std::endl
483  << " mu+ 2 " << m_muon_vtx[3] << " pt: " << m_pxMUTrack[3]->pt()
484  << std::endl;
485  } // end debug
486  } // end m_workAsFourMuons
487 
488  if ( m_workAsFourElectrons ) { // till here we have the electrons vertices list
489  m_nVertex = vtxListX.size();
490  if (vtxListX.size()>0) vertexstatus = true;
491  // check that the electrons are not split into too many vertices
492  if (vtxListX.size() >= m_numberOfFullPassElectrons - 1) vertexstatus = false;
493  // and allow no electron without vertex
494  if (noVertexCountElec > 0) vertexstatus = false;
495  if (m_doDebug || true) {
496  std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices ID of the electrons = " << std::endl
497  << " el- 1 " << m_elec_vtx[0] << " pt: " << m_pxELTrack[0]->pt() << std::endl
498  << " el- 2 " << m_elec_vtx[1] << " pt: " << m_pxELTrack[1]->pt() << std::endl
499  << " el+ 1 " << m_elec_vtx[2] << " pt: " << m_pxELTrack[2]->pt() << std::endl
500  << " el+ 2 " << m_elec_vtx[3] << " pt: " << m_pxELTrack[3]->pt()
501  << std::endl;
502  } // end debug
503  }
504 
505  if ( m_workAsFourLeptons ) { // till here we have the muons and electrons vertices list
506  m_nVertex = vtxListX.size();
507  if (vtxListX.size()>0) vertexstatus = true;
508  // check that the electrons are not split into too many vertices
509  // if (vtxListX.size() >= m_numberOfFullPassElectrons - 1) vertexstatus = false;
510  // and allow no electron without vertex
511  if (m_doDebug) {
512  std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices in event = " << vtxListX.size() << std::endl;
513  for (size_t imu=0; imu < NUM_MUONS; imu++) {
514  if (m_pxMUTrack[imu]) std::cout << " mu " << m_muon_vtx[imu] << " pt: " << m_pxMUTrack[imu]->pt() << std::endl;
515  }
516  for (size_t iel=0; iel < NUM_MUONS; iel++) {
517  if (m_pxELTrack[iel]) std::cout << " el " << m_elec_vtx[iel] << " pt: " << m_pxELTrack[iel]->pt() << std::endl;
518  }
519  }
520  }
521 
522  vertexstatus = true; // Temporary fix to work on R22
523 
524  if(m_doDebug) {
525  std::cout <<" * FourMuonEvent::EventSelection(" << eType <<") * Number of vertex found = " << vtxListX.size()
526  << " and mu without vertex: " << noVertexCountMuon
527  << " and elec without vertex: " << noVertexCountElec << std::endl;
528  for (unsigned int ivtx=0; ivtx < vtxListX.size(); ivtx++) {
529  std::cout << " vtx[" << ivtx << "]= "
530  << "( " << vtxListX.at(ivtx)
531  << ", " << vtxListY.at(ivtx)
532  << ", " << vtxListZ.at(ivtx)
533  << ") nparticles: " << vtxNpart.at(ivtx)
534  << std::endl;
535  }
536  }
537  //
538  if (!vertexstatus && m_doDebug) {
539  std::cout <<" * FourMuonEvent::EventSelection * FAILED * number of vertex found = " << vtxListX.size()
540  << " mu without vertex: " << noVertexCountMuon
541  << " elec without vertex: " << noVertexCountElec << std::endl;
542  }
543 
544  eventisgood = vertexstatus;
545  }
546 
547  //
548  if(m_doDebug){ std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") ** completed ** result= " << eventisgood << std::endl;}
549 
550  m_doDebug = inputdebug;
551 
552  return eventisgood;
553 }
554 //==================================================================================
556 {
557  if(m_doDebug){ std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") ** started ** " << std::endl
558  << " event count: " << m_eventCount << std::endl
559  << " m_NumberOfFullPassMuons: " << m_numberOfFullPassMuons << std::endl
560  << " m_NumberOfFullPassElectrons: " << m_numberOfFullPassElectrons
561  << std::endl;
562  }
563 
564  // First require two muon-id's with cuts pre-applied.
566  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good muons and electrons == 4 :( "
568  << " = " << m_numberOfFullPassMuons << " + " << m_numberOfFullPassElectrons << std::endl;}
569  return false;
570  }
571 
572  if ( m_numberOfFullPassMuons > 4 ) {
573  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Too many muons !! Failing number of good muons == 4 :( "
574  << m_numberOfFullPassMuons << std::endl;}
575  return false;
576  }
577 
578  if ( m_numberOfFullPassElectrons > 4 ) {
579  if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Too many electrons !! Failing number of good electrons == 4 :( "
580  << m_numberOfFullPassElectrons << std::endl;}
581  return false;
582  }
583 
584  // momentum of the muons
585  double leadingMuonPt = -1., secondMuonPt=-1., thirdMuonPt=-1, fourthMuonPt=-1.; // negative pt, means not computed yet
586  switch ( eType ) {
587  case MS :
588  {
589  if (m_muonpos1 >= 0) leadingMuonPt = m_pxMSTrack[m_muonpos1]->pt();
590  if (m_muonpos2 >= 0) secondMuonPt = m_pxMSTrack[m_muonpos2]->pt();
591  if (m_muonneg1 >= 0) thirdMuonPt = m_pxMSTrack[m_muonneg1]->pt();
592  if (m_muonneg2 >= 0) fourthMuonPt = m_pxMSTrack[m_muonneg2]->pt();
593  break;
594  }
595  case ME:
596  {
597  if (m_muonpos1 >= 0) leadingMuonPt = m_pxMETrack[m_muonpos1]->pt();
598  if (m_muonpos2 >= 0) secondMuonPt = m_pxMETrack[m_muonpos2]->pt();
599  if (m_muonneg1 >= 0) thirdMuonPt = m_pxMETrack[m_muonneg1]->pt();
600  if (m_muonneg2 >= 0) fourthMuonPt = m_pxMETrack[m_muonneg2]->pt();
601  break;
602  }
603  case CB:
604  {
605  if (m_muonpos1 >= 0) leadingMuonPt = m_pxRecMuon[m_muonpos1]->pt();
606  if (m_muonpos2 >= 0) secondMuonPt = m_pxRecMuon[m_muonpos2]->pt();
607  if (m_muonneg1 >= 0) thirdMuonPt = m_pxRecMuon[m_muonneg1]->pt();
608  if (m_muonneg2 >= 0) fourthMuonPt = m_pxRecMuon[m_muonneg2]->pt();
609  break;
610  }
611  case ID:
612  {
613  if (m_muonpos1 >= 0) leadingMuonPt = m_pxIDTrack[m_muonpos1]->pt();
614  if (m_muonpos2 >= 0) secondMuonPt = m_pxIDTrack[m_muonpos2]->pt();
615  if (m_muonneg1 >= 0) thirdMuonPt = m_pxIDTrack[m_muonneg1]->pt();
616  if (m_muonneg2 >= 0) fourthMuonPt = m_pxIDTrack[m_muonneg2]->pt();
617  break;
618  }
619 
620  default:
621  if (m_muonpos1 >= 0) leadingMuonPt = m_pxIDTrack[m_muonpos1]->pt();
622  if (m_muonpos2 >= 0) secondMuonPt = m_pxIDTrack[m_muonpos2]->pt();
623  if (m_muonneg1 >= 0) thirdMuonPt = m_pxIDTrack[m_muonneg1]->pt();
624  if (m_muonneg2 >= 0) fourthMuonPt = m_pxIDTrack[m_muonneg2]->pt();
625  } // end switch
626 
627  // up to here the leading and second pt are not really in the right order.
628  // order the muon pt:
629  double theLeadingPt = leadingMuonPt;
630  if (secondMuonPt > theLeadingPt) { theLeadingPt = secondMuonPt;}
631  if (thirdMuonPt > theLeadingPt) { theLeadingPt = thirdMuonPt;}
632  if (fourthMuonPt > theLeadingPt) { theLeadingPt = fourthMuonPt;}
633 
634  double theTrailingPt = leadingMuonPt;
635  if (secondMuonPt < theTrailingPt && secondMuonPt > 0) { theTrailingPt = secondMuonPt;}
636  if (thirdMuonPt < theTrailingPt && thirdMuonPt > 0) { theTrailingPt = thirdMuonPt;}
637  if (fourthMuonPt < theTrailingPt && fourthMuonPt > 0) { theTrailingPt = fourthMuonPt;}
638 
639  if (m_doDebug || true) {
640  std::cout << " * FourMuonEvent::EventSelection * muon pt selection -- cuts: Leading: " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl
641  << " 2nd: " << m_SecondMuonPtCut*CLHEP::GeV << std::endl;
642  std::cout << " Pt of muons in this event 1: " << leadingMuonPt << std::endl
643  << " 2: " << secondMuonPt << std::endl
644  << " 3: " << thirdMuonPt << std::endl
645  << " 4: " << fourthMuonPt << std::endl
646  << " leading Pt: " << theLeadingPt << std::endl
647  << " trailing Pt: " << theTrailingPt << std::endl;
648  }
649 
650  // muon pt cut
651  if ( !(theLeadingPt > m_LeadingMuonPtCut*CLHEP::GeV && theTrailingPt > m_SecondMuonPtCut*CLHEP::GeV ) ) {
652  if(m_doDebug){
653  std::cout <<" * FourMuonEvent::EventSelection * Failing pt cut * Reco Pt: leading " << theLeadingPt << " --> trailing " << theTrailingPt << std::endl;
654  }
655  return false;
656  }
657  if(m_doDebug){
658  std::cout << " * FourMuonEvent::EventSelection * Event passed the pt cuts: leading muon pt: " << leadingMuonPt << std::endl;
659  std::cout << " trailing muon pt: " << theTrailingPt << std::endl;
660  }
661 
662 
663  // Invariant mass window
664  if ( m_fInvariantMass[eType] < m_MassWindowLow ) {
665  if(m_doDebug) {
666  std::cout <<" * FourMuonEvent::EventSelection * Failing mass window low cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowLow << std::endl;
667  }
668  return false;
669  }
670  if ( m_fInvariantMass[eType] > m_MassWindowHigh ) {
671  if(m_doDebug) {
672  std::cout <<" * FourMuonEvent * Failing mass window high cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowHigh << std::endl;
673  }
674  return false;
675  }
676  if(m_doDebug){
677  std::cout <<" * FourMuonEvent::EventSelection * Event passed the mass window: " << m_fInvariantMass[eType] << std::endl;
678  }
679 
680 
681  // All muons should come from the same vertex
682  // if the vertex information is used, that is already guaranteed, but if not, one has to check the z0
683 
684  /* R21 SALVA --> vertex is not available in R22 --> A FIX IS NEEDED */
685  /*
686  if (eType == ID) {
687  bool vertexstatus = true;
688  if (m_pxIDTrack[m_muonpos1]->vertex() != nullptr) {
689  if(m_doDebug) {
690  std::cout <<" * FourMuonEvent::EventSelection * vertex of the muons -- ID Tracks --" << std::endl;
691  std::cout << " vertex muonpos_1 (x,y,z): (" << m_pxIDTrack[m_muonpos1]->vertex()->x()
692  << ", " << m_pxIDTrack[m_muonpos1]->vertex()->y()
693  << ", " << m_pxIDTrack[m_muonpos1]->vertex()->z()
694  << ") --> pt: " << m_pxIDTrack[m_muonpos1]->pt()
695  << std::endl;
696  }
697  }
698  else {
699  vertexstatus = false;
700  if(m_doDebug) std::cout <<" * FourMuonEvent::EventSelection * WARNING muonpos_1 (" << m_muonpos1 << ") has no vertex " << std::endl;
701  }
702  if (m_pxIDTrack[m_muonpos2]->vertex() != nullptr) {
703  if(m_doDebug) {
704  std::cout << " vertex muonpos_2 (x,y,z): (" << m_pxIDTrack[m_muonpos2]->vertex()->x()
705  << ", " << m_pxIDTrack[m_muonpos2]->vertex()->y()
706  << ", " << m_pxIDTrack[m_muonpos2]->vertex()->z()
707  << ") --> pt: " << m_pxIDTrack[m_muonpos2]->pt()
708  << std::endl;
709  }
710  }
711  else{
712  vertexstatus = false;
713  if(m_doDebug) std::cout <<" * FourMuonEvent::EventSelection * WARNING muonpos_2 (" << m_muonpos2 << ") has no vertex " << std::endl;
714  }
715  if (m_pxIDTrack[m_muonneg1]->vertex() != nullptr) {
716  if(m_doDebug) {
717  std::cout << " vertex muonneg_1 (x,y,z): (" << m_pxIDTrack[m_muonneg1]->vertex()->x()
718  << ", " << m_pxIDTrack[m_muonneg1]->vertex()->y()
719  << ", " << m_pxIDTrack[m_muonneg1]->vertex()->z()
720  << ") --> pt: " << m_pxIDTrack[m_muonneg1]->pt()
721  << std::endl;
722  }
723  }
724  else{
725  vertexstatus = false;
726  if(m_doDebug) std::cout <<" * FourMuonEvent::EventSelection * WARNING muonneg_1 (" << m_muonneg1 << ") has no vertex " << std::endl;
727  }
728 
729  if (m_pxIDTrack[m_muonneg2]->vertex() != nullptr) {
730  if(m_doDebug) {
731  std::cout << " vertex muonneg_2 (x,y,z): (" << m_pxIDTrack[m_muonneg2]->vertex()->x()
732  << ", " << m_pxIDTrack[m_muonneg2]->vertex()->y()
733  << ", " << m_pxIDTrack[m_muonneg2]->vertex()->z()
734  << ") --> pt: " << m_pxIDTrack[m_muonneg2]->pt()
735  << std::endl;
736  }
737  }
738  else{
739  vertexstatus = false;
740  if(m_doDebug) std::cout <<" * FourMuonEvent::EventSelection * WARNING muonneg_2 (" << m_muonneg2 << ") has no vertex " << std::endl;
741  }
742  if (vertexstatus) { // this means: all muons have vertex associated. Let's check it is the same.
743  if(m_doDebug) std::cout << " -- debug -- * FourMuonEvent::EventSelection * let's find the number of muon-vertices... " << std::endl;
744 
745  std::vector <float> vtxListX;
746  std::vector <float> vtxListZ;
747  float rGapCut = 0.1;
748  // add the vertex of the 1st in the list (the muonneg1)
749  vtxListX.push_back(m_pxIDTrack[m_muonneg1]->vertex()->x());
750  vtxListZ.push_back(m_pxIDTrack[m_muonneg1]->vertex()->z());
751  m_nVertex = 1; // for the time being there is just one vertex
752  m_muonneg1_vtx = m_nVertex; // and the muonneg1 is in that one
753  if(m_doDebug) {
754  std::cout << " * FourMuonEvent::EventSelection * muonneg1 in vertex: " << m_muonneg1_vtx << std::endl;
755  }
756 
757  // m_muonneg 2
758  bool thisMuonIsInExistingVertex = false;
759  for (int ivtx=0; ivtx < (int) vtxListX.size(); ivtx++) {
760  if ( fabs(vtxListX.at(ivtx) - m_pxIDTrack[m_muonneg2]->vertex()->x()) < rGapCut &&
761  fabs(vtxListZ.at(ivtx) - m_pxIDTrack[m_muonneg2]->vertex()->z()) < m_Z0GapCut) {
762  // muonneg2 in an already listed vertex
763  m_muonneg2_vtx = ivtx+1;
764  thisMuonIsInExistingVertex = true;
765  }
766  }
767  if (thisMuonIsInExistingVertex) {
768  if(m_doDebug) {
769  std::cout << " * FourMuonEvent::EventSelection * muonneg2 in vertex: " << m_muonneg2_vtx << std::endl;
770  }
771  }
772  else {
773  m_nVertex += 1; // add new vertex
774  m_muonneg2_vtx = m_nVertex;
775  vtxListX.push_back(m_pxIDTrack[m_muonneg2]->vertex()->x());
776  vtxListZ.push_back(m_pxIDTrack[m_muonneg2]->vertex()->z());
777  if(m_doDebug) {
778  std::cout << " * FourMuonEvent::EventSelection * Add a new vertex to the list. Current size: " << vtxListX.size()
779  << " vtx.x= " << m_pxIDTrack[m_muonneg2]->vertex()->x()
780  << " vtx.y= " << m_pxIDTrack[m_muonneg2]->vertex()->y()
781  << " vtx.z= " << m_pxIDTrack[m_muonneg2]->vertex()->z()
782  << std::endl;
783  std::cout << " * FourMuonEvent::EventSelection * muonneg2 in vertex: " << m_muonneg2_vtx << std::endl;
784  }
785  }
786 
787  // m_muonpos 1
788  thisMuonIsInExistingVertex = false;
789  for (int ivtx=0; ivtx < (int) vtxListX.size(); ivtx++) {
790  if ( fabs(vtxListX.at(ivtx) - m_pxIDTrack[m_muonpos1]->vertex()->x()) < rGapCut &&
791  fabs(vtxListZ.at(ivtx) - m_pxIDTrack[m_muonpos1]->vertex()->z()) < m_Z0GapCut) {
792  // muonneg2 in an already listed vertex
793  m_muonpos1_vtx = ivtx+1;
794  thisMuonIsInExistingVertex = true;
795  }
796  }
797  if (thisMuonIsInExistingVertex) {
798  if(m_doDebug) {
799  std::cout << " * FourMuonEvent::EventSelection * muonpos1 in vertex: " << m_muonpos1_vtx << std::endl;
800  }
801  }
802  else {
803  m_nVertex += 1; // add new vertex
804  m_muonpos1_vtx = m_nVertex;
805  vtxListX.push_back(m_pxIDTrack[m_muonpos1]->vertex()->x());
806  vtxListZ.push_back(m_pxIDTrack[m_muonpos1]->vertex()->z());
807  if(m_doDebug) {
808  std::cout << " * FourMuonEvent::EventSelection * Add a new vertex to the list. Current size: " << vtxListX.size()
809  << " vtx.x= " << m_pxIDTrack[m_muonpos1]->vertex()->x()
810  << " vtx.y= " << m_pxIDTrack[m_muonpos1]->vertex()->y()
811  << " vtx.z= " << m_pxIDTrack[m_muonpos1]->vertex()->z()
812  << std::endl;
813  std::cout << " * FourMuonEvent::EventSelection * muonpos1 in vertex: " << m_muonpos1_vtx << std::endl;
814  }
815  }
816 
817  // m_muonpos 2
818  thisMuonIsInExistingVertex = false;
819  for (int ivtx=0; ivtx < (int) vtxListX.size(); ivtx++) {
820  if ( fabs(vtxListX.at(ivtx) - m_pxIDTrack[m_muonpos2]->vertex()->x()) < rGapCut &&
821  fabs(vtxListZ.at(ivtx) - m_pxIDTrack[m_muonpos2]->vertex()->z()) < m_Z0GapCut) {
822  // muonneg2 in an already listed vertex
823  m_muonpos2_vtx = ivtx+1;
824  thisMuonIsInExistingVertex = true;
825  }
826  }
827  if (thisMuonIsInExistingVertex) {
828  if(m_doDebug) {
829  std::cout << " * FourMuonEvent::EventSelection * muonpos2 in vertex: " << m_muonpos1_vtx << std::endl;
830  }
831  }
832  else {
833  m_nVertex += 1; // add new vertex
834  m_muonpos2_vtx = m_nVertex;
835  vtxListX.push_back(m_pxIDTrack[m_muonpos2]->vertex()->x());
836  vtxListZ.push_back(m_pxIDTrack[m_muonpos2]->vertex()->z());
837  if(m_doDebug) {
838  std::cout << " * FourMuonEvent::EventSelection * Add a new vertex to the list. Current size: " << vtxListX.size()
839  << " vtx.x= " << m_pxIDTrack[m_muonpos2]->vertex()->x()
840  << " vtx.y= " << m_pxIDTrack[m_muonpos2]->vertex()->y()
841  << " vtx.z= " << m_pxIDTrack[m_muonpos2]->vertex()->z()
842  << std::endl;
843  std::cout << " * FourMuonEvent::EventSelection * muonpos2 in vertex: " << m_muonpos2_vtx << std::endl;
844  }
845  }
846  }
847 
848  if (vertexstatus) {
849  if(m_doDebug) std::cout << " * FourMuonEvent::EventSelection ** All muons come from some vertex. " << std::endl
850  << " N listed vertex: " << m_nVertex << std::endl
851  << " muon- 1: " << m_muonneg1_vtx << std::endl
852  << " muon- 2: " << m_muonneg2_vtx << std::endl
853  << " muon+ 1: " << m_muonpos1_vtx << std::endl
854  << " muon+ 2: " << m_muonpos2_vtx << std::endl
855  << " Cut passed :) " << std::endl;
856  }
857  else { // vertex cut failed
858  if (m_doDebug) std::cout <<" * FourMuonEvent::EventSelection ** Failing all muons coming from a primary vertex cut :(" << std::endl;
859  return false;
860  }
861  } // if (eType == ID) {
862  */
863 
864 
865  if(m_doDebug) {
866  std::cout << " * FourMuonEvent::EventSelection( type= " << eType << ")* Good 4-muon set: pt range from " << leadingMuonPt/1000
867  << " to " << secondMuonPt/1000
868  << " GeV 4-muon invariant mass = " << m_fInvariantMass[eType] << " GeV " << std::endl;
869  std::cout << " * FourMuonEvent::EventSelection( type= " << eType << ")* completed * " << std::endl;
870  }
871  return true;
872 }
873 
874 //==================================================================================
876 {
879  m_passedSelectionCuts = false;
883 
884 
885  m_FourMuonInvMass = -1.; // flag as no reconstructed inv mass yet
886  m_muon1 = MUON1; // point to the first two
887  m_muon2 = MUON2;
888  m_muonneg1 = -1;
889  m_muonneg2 = -1;
890  m_muonpos1 = -1;
891  m_muonpos2 = -1;
892 
893 
894  for ( unsigned int u = 0; u < NUM_MUONS; ++u ) {
895  m_pxRecMuon[u] = nullptr;
896  m_pxMSTrack[u] = nullptr;
897  m_pxMETrack[u] = nullptr;
898  m_pxIDTrack[u] = nullptr;
899  m_pxMUTrack[u] = nullptr;
900  m_pxELTrack[u] = nullptr;
901  }
902  for ( unsigned int v = 0; v < NUM_TYPES; ++v ) {
903  m_fZPt[v] = -999.9f;
904  m_fZEtaDir[v] = -999.9f;
905  m_fZPhiDir[v] = -999.9f;
906  m_fInvariantMass[v] = -999.9f;
907  m_fMuonDispersion[v] = -999.9f;
908  }
909 
910  // tell us to which vertex the muons are associated
911  m_nVertex = 0; // reset vertex count
912  m_muonneg1_vtx = 0;
913  m_muonneg2_vtx = 0;
914  m_muonpos1_vtx = 0;
915  m_muonpos2_vtx = 0;
916 
917  for (size_t i=0; i < NUM_MUONS; i++) m_muon_vtx[i] = 0; // reset the vertex ID to which the electrons are associated
918  for (size_t i=0; i < NUM_MUONS; i++) m_elec_vtx[i] = 0; // reset the vertex ID to which the electrons are associated
919  return;
920 }
921 
922 //==================================================================================
924 {
925  bool thisdebug = false;
926  // if(m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * started "<< std::endl;}
927  // This shouldn't really ever happen but just in case.
928  if ( !pxMuon ) {
929  if(m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxMuon --> EXIT "<< std::endl;}
930  return;
931  }
932 
934  // The main Muon
936  if (thisdebug) {
937  std::cout <<" * FourMuonEvent * RecordMuon * m_pxRecMuon for this muon--> pt "<< m_pxRecMuon[m_numberOfFullPassMuons]->pt() << std::endl;
938  std::cout <<" d0 "<< m_pxRecMuon[m_numberOfFullPassMuons]->primaryTrackParticle()->d0() << std::endl;
939  std::cout <<" sigma_d0 "<< m_pxRecMuon[m_numberOfFullPassMuons]->primaryTrackParticle()->definingParametersCovMatrixVec()[0] << std::endl;
940  }
941 
942  const xAOD::TrackParticle* pxMSTrack = pxMuon->trackParticle(xAOD::Muon::MuonSpectrometerTrackParticle);
943  if (!pxMSTrack) {
944  if (m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxMSmuon --> EXIT "<< std::endl;}
945  return;
946  }
948  if (thisdebug) {
949  std::cout <<" * FourMuonEvent * RecordMuon * m_pxMSTrack for this muon--> pt "<< m_pxMSTrack[m_numberOfFullPassMuons]->pt() << std::endl;
950  std::cout <<" d0 "<< m_pxMSTrack[m_numberOfFullPassMuons]->d0() << std::endl;
951  std::cout <<" sigma_d0 "<< m_pxMSTrack[m_numberOfFullPassMuons]->definingParametersCovMatrixVec()[0] << std::endl;
952  }
953 
954  // ID muon
955  const xAOD::TrackParticle* pxIDTrack = pxMuon->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
956  if (!pxIDTrack) {
957  if (m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxIDTrack for this muon--> EXIT "<< std::endl;}
958  return;
959  }
961  if (thisdebug) {
962  std::cout <<" * FourMuonEvent * RecordMuon * m_pxIDTrack for this muon--> pt "<< m_pxIDTrack[m_numberOfFullPassMuons]->pt() << std::endl;
963  std::cout <<" d0 "<< m_pxIDTrack[m_numberOfFullPassMuons]->d0() << std::endl;
964  std::cout <<" sigma_d0 "<< m_pxIDTrack[m_numberOfFullPassMuons]->definingParametersCovMatrixVec()[0] << std::endl;
965  }
966  //
969  }
970  // if(m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * completed -- return with a total of " << m_numberOfFullPassMuons << std::endl;}
971  return;
972 }
973 
974 
975 //==================================================================================
977 {
978  if(m_doDebug){ std::cout << " * FourMuonEvent * ReconstructKinematics * -- start -- " << std::endl; }
979  bool kinematicscomputed = false;
980 
981  // Three ways. No checks here. Thus make sure the pointers are ok before this.
982  if ( m_numberOfFullPassMuons == 4 ) {
983  // crosscheck identifiers are good:
984  bool goodidentifiers = true;
985  if (m_muonneg1 < 0) goodidentifiers = false;
986  if (m_muonneg2 < 0) goodidentifiers = false;
987  if (m_muonpos1 < 0) goodidentifiers = false;
988  if (m_muonpos2 < 0) goodidentifiers = false;
989 
990  if (goodidentifiers) {
991  // before computing the kinematic parameters check track particles are ok
992  bool goodtracks = true;
993  if (m_pxIDTrack[m_muonneg1] == nullptr) goodtracks = false;
994  if (m_pxIDTrack[m_muonneg2] == nullptr) goodtracks = false;
995  if (m_pxIDTrack[m_muonpos1] == nullptr) goodtracks = false;
996  if (m_pxIDTrack[m_muonpos2] == nullptr) goodtracks = false;
997 
998  if (m_pxIDTrack[m_muonneg1] != nullptr) m_pxMUTrack[0] = m_pxIDTrack[m_muonneg1];
999  if (m_pxIDTrack[m_muonneg2] != nullptr) m_pxMUTrack[1] = m_pxIDTrack[m_muonneg2];
1000  if (m_pxIDTrack[m_muonpos1] != nullptr) m_pxMUTrack[2] = m_pxIDTrack[m_muonpos1];
1001  if (m_pxIDTrack[m_muonpos2] != nullptr) m_pxMUTrack[3] = m_pxIDTrack[m_muonpos2];
1002 
1003  if (goodtracks) { // Everything is ready
1005  m_fMuonDispersion[ID] = EvaluateAngle( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1006  m_fZPt[ID] = EvalPt( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1007  m_fZEtaDir[ID] = EvalEta( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1008  m_fZPhiDir[ID] = EvalPhi( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1009 
1010  kinematicscomputed = true;
1011 
1012  if(m_doDebug){
1013  std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- Muon ID Tracks -- new -- " << std::endl
1014  << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl
1015  << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl
1016  << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl
1017  << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl
1018  << " invariant mass (4mu) = " << m_fInvariantMass[ID] << std::endl
1019  << std::endl;
1020  }
1021 
1022  } // good tracks
1023  } // goodidentifiers
1024  } // goodmuons == 4
1025 
1026  if (!kinematicscomputed) {
1027  if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics * -- FAILED -- " << std::endl; }
1028  }
1029 
1030  if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics * -- completed -- status: " << kinematicscomputed << std::endl; }
1031  return kinematicscomputed;
1032 }
1033 
1034 //==================================================================================
1036 {
1037  if(m_doDebug){ std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- start -- " << std::endl; }
1038  bool kinematicscomputed = false;
1039 
1040  // Three ways. No checks here. Thus make sure the pointers are ok before this.
1041  if ( m_numberOfFullPassElectrons == 4 ) {
1042  // before computing the kinematic parameters check track particles are ok
1043  bool goodtracks = true;
1048  if (m_pxELTrack[0] == nullptr) goodtracks = false;
1049  if (m_pxELTrack[1] == nullptr) goodtracks = false;
1050  if (m_pxELTrack[2] == nullptr) goodtracks = false;
1051  if (m_pxELTrack[3] == nullptr) goodtracks = false;
1052 
1053  if (goodtracks) { // Everything is ready
1054  // For the time being analysis is performed only with ID tracks
1056  m_fMuonDispersion[ID] = EvaluateAngle( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1057  m_fZPt[ID] = EvalPt( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1058  m_fZEtaDir[ID] = EvalEta( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1059  m_fZPhiDir[ID] = EvalPhi( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1060  kinematicscomputed = true;
1061 
1062  if(m_doDebug){
1063  std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- Electron Tracks -- " << std::endl
1064  << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl
1065  << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl
1066  << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl
1067  << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl
1068  << " invariant mass (4e) = " << m_fInvariantMass[ID] << std::endl
1069  << std::endl;
1070  }
1071  } // good tracks
1072  } // goodidentifiers
1073 
1074  if (!kinematicscomputed) {
1075  if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics4Elec * -- FAILED -- " << std::endl; }
1076  }
1077 
1078  if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics4Elec * -- completed -- status: " << kinematicscomputed << std::endl; }
1079  return kinematicscomputed;
1080 }
1081 
1082 //==================================================================================
1084 {
1085  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent * ReconstructKinematicsNew * -- START -- " << endmsg;
1086 
1087  bool kinematicscomputed = false;
1088 
1089  // first step get the list of TrackParticles for muons and electrons
1090  // -- muons (a bit more complex than for electrons)
1091  if (m_muonneg1 >= 0) m_pxMUTrack[0] = m_pxIDTrack[m_muonneg1];
1092  if (m_muonneg2 >= 0) m_pxMUTrack[1] = m_pxIDTrack[m_muonneg2];
1093  if (m_muonpos1 >= 0) m_pxMUTrack[2] = m_pxIDTrack[m_muonpos1];
1094  if (m_muonpos2 >= 0) m_pxMUTrack[3] = m_pxIDTrack[m_muonpos2];
1095  // add an extra proteccion
1096  if (m_numberOfFullPassMuons < 2) {
1097  for (int i=0; i<4; i++) m_pxMUTrack[i] = nullptr;
1098  }
1099 
1100  // -- electrons
1105  // add an extra proteccion
1106  if (m_numberOfFullPassElectrons < 2) {
1107  for (int i=0; i<4; i++) m_pxELTrack[i] = nullptr;
1108  }
1109 
1110  if ( m_numberOfFullPassMuons == 4 ) {
1111  bool goodtracks = true;
1112  if (m_pxMUTrack[0] == nullptr) goodtracks = false;
1113  if (m_pxMUTrack[1] == nullptr) goodtracks = false;
1114  if (m_pxMUTrack[2] == nullptr) goodtracks = false;
1115  if (m_pxMUTrack[3] == nullptr) goodtracks = false;
1116 
1117  if (goodtracks) { // Everything is ready
1119  m_fMuonDispersion[ID] = EvaluateAngle ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1120  m_fZPt[ID] = EvalPt ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1121  m_fZEtaDir[ID] = EvalEta ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1122  m_fZPhiDir[ID] = EvalPhi ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
1123  kinematicscomputed = true;
1124  }
1125  }
1126 
1127  if(m_doDebug){
1128  std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Muon ID Tracks -- new -- " << std::endl;
1129  if (m_pxMUTrack[0] != nullptr) std::cout << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl;
1130  if (m_pxMUTrack[1] != nullptr) std::cout << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl;
1131  if (m_pxMUTrack[2] != nullptr) std::cout << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl;
1132  if (m_pxMUTrack[3] != nullptr) std::cout << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl;
1133  if (kinematicscomputed) std::cout << " invariant mass (4mu) = " << m_fInvariantMass[ID] << std::endl;
1134  }
1135 
1136  double invmass_test = -1.; // default value
1137  if ( m_numberOfFullPassElectrons == 4) {
1138  // before computing the kinematic parameters check track particles are ok
1139  bool goodtracks = true;
1140  if (m_pxELTrack[0] == nullptr) goodtracks = false;
1141  if (m_pxELTrack[1] == nullptr) goodtracks = false;
1142  if (m_pxELTrack[2] == nullptr) goodtracks = false;
1143  if (m_pxELTrack[3] == nullptr) goodtracks = false;
1144 
1145  if (goodtracks && !kinematicscomputed) { // Everything is ready
1146  // For the time being analysis is performed only with ID tracks
1148  invmass_test = m_fInvariantMass[ID];
1149  m_fMuonDispersion[ID] = EvaluateAngle( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1150  m_fZPt[ID] = EvalPt( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1151  m_fZEtaDir[ID] = EvalEta( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1152  m_fZPhiDir[ID] = EvalPhi( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
1153  kinematicscomputed = true;
1154  } // good tracks
1155  }
1156  if(m_doDebug){
1157  std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Electron Tracks -- " << std::endl;
1158  if (m_pxELTrack[0] != nullptr) std::cout << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl;
1159  if (m_pxELTrack[1] != nullptr) std::cout << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl;
1160  if (m_pxELTrack[2] != nullptr) std::cout << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl;
1161  if (m_pxELTrack[3] != nullptr) std::cout << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl;
1162  std::cout << " invariant mass (4e) = " << invmass_test << std::endl;
1163  }
1164 
1165  if ( m_numberOfFullPassMuons >= 2 && m_numberOfFullPassElectrons >= 2 && !kinematicscomputed) {
1166  // before computing the kinematic parameters check track particles are ok
1167  bool goodtracks = true;
1168  if (m_pxMUTrack[0] == nullptr) goodtracks = false; // leading mu-
1169  if (m_pxMUTrack[2] == nullptr) goodtracks = false; // leading mu+
1170  if (m_pxELTrack[0] == nullptr) goodtracks = false; // leading e-
1171  if (m_pxELTrack[2] == nullptr) goodtracks = false; // leading e+
1172 
1173  if (goodtracks && !kinematicscomputed) { // Everything is ready
1174  // For the time being analysis is performed only with ID tracks
1176  invmass_test = m_fInvariantMass[ID];
1177  m_fMuonDispersion[ID] = EvaluateAngle ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
1178  m_fZPt[ID] = EvalPt ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
1179  m_fZEtaDir[ID] = EvalEta ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
1180  m_fZPhiDir[ID] = EvalPhi ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
1181  kinematicscomputed = true;
1182  } // good tracks
1183  }
1184  if(m_doDebug){
1185  std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Muon and Electron Tracks -- " << std::endl;
1186  if (m_pxMUTrack[0] != nullptr) std::cout << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl;
1187  if (m_pxMUTrack[1] != nullptr) std::cout << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl;
1188  if (m_pxMUTrack[2] != nullptr) std::cout << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl;
1189  if (m_pxMUTrack[3] != nullptr) std::cout << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl;
1190  if (m_pxELTrack[0] != nullptr) std::cout << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl;
1191  if (m_pxELTrack[1] != nullptr) std::cout << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl;
1192  if (m_pxELTrack[2] != nullptr) std::cout << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl;
1193  if (m_pxELTrack[3] != nullptr) std::cout << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl;
1194  std::cout << " invariant mass used = " << m_fInvariantMass[ID] << std::endl;
1195  std::cout << " invariant mass test = " << invmass_test << std::endl;
1196  }
1197 
1198  if (!kinematicscomputed) {
1199  if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematicsNew * -- FAILED -- " << std::endl; }
1200  }
1201 
1202  (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent * ReconstructKinematicsNew * -- COMPLETED -- status " << kinematicscomputed << endmsg;
1203  return kinematicscomputed;
1204 }
1205 
1206 //==================================================================================
1208 {
1209  // First determine what's positive
1210  if ( m_numberOfFullPassMuons == 2 )
1211  {
1212  switch ( eType )
1213  {
1214  case MS :
1215  {
1217  }
1218  case ME:
1219  {
1221  }
1222  case CB:
1223  {
1225  }
1226  case ID:
1227  {
1229  }
1230  default:
1231  return -999.0;
1232  }
1233  }
1234  else
1235  {
1236  return -999.0;
1237  }
1238 }
1239 
1240 //==================================================================================
1242 {
1243  switch ( eType )
1244  {
1245  case MS :
1246  {
1247  return ( static_cast<int>( EvalCharge( m_pxMSTrack[m_muon1], m_pxMSTrack[m_muon2] ) ) );
1248  }
1249  case ME:
1250  {
1251  return ( static_cast<int>( EvalCharge( m_pxMETrack[m_muon1], m_pxMETrack[m_muon2] ) ) );
1252  }
1253  case CB:
1254  {
1255  return ( static_cast<int>( EvalCharge( m_pxRecMuon[m_muon1], m_pxRecMuon[m_muon2] ) ) );
1256  }
1257  case ID:
1258  {
1259  return ( static_cast<int>( EvalCharge( m_pxIDTrack[m_muon1], m_pxIDTrack[m_muon2] ) ) );
1260  }
1261  default:
1262  return -999;
1263  }
1264 }
1265 
1266 //==================================================================================
1267 unsigned int FourMuonEvent::getPosMuon( int eType )
1268 {
1269  //if ( getNumberOfTaggedMuons() != 2 ) return 999;
1270  //if ( getZCharge(eType) != 0 ) return 999;
1271 
1272  unsigned int muid = m_muonpos1;
1273  if (eType==2) muid = m_muonpos2;
1274  return muid;
1275 }
1276 
1277 //==================================================================================
1278 unsigned int FourMuonEvent::getNegMuon( int eType )
1279 {
1280  unsigned int muid = m_muonneg1;
1281  if (eType==2) muid = m_muonneg2;
1282  return muid;
1283 }
1284 
1285 //==================================================================================
1286 const xAOD::TrackParticle* FourMuonEvent::getLooseIDTk( unsigned int /*uPart*/ )
1287 {
1288  const xAOD::TrackParticleContainer* pxTrackContainer =
1289  PerfMonServices::getContainer<xAOD::TrackParticleContainer>( PerfMonServices::TRK_COLLECTION );
1290 
1291  if ( pxTrackContainer )
1292  {
1293  xAOD::TrackParticleContainer::const_iterator xTrkItr = pxTrackContainer->begin();
1294  xAOD::TrackParticleContainer::const_iterator xTrkItrE = pxTrackContainer->end();
1295  while ( xTrkItr != xTrkItrE )
1296  {
1297  const xAOD::TrackParticle* pxTrack = *xTrkItr;
1298  if ( !pxTrack ) continue;
1299  const Trk::Track* pxTrkTrack = pxTrack->track();
1300  if(!pxTrkTrack) continue;
1301  const Trk::Perigee* pxPerigee = pxTrkTrack->perigeeParameters() ;
1302  if ( !pxPerigee ) continue;
1303  const float fTrkPhi = pxPerigee->parameters()[Trk::phi];
1304  const float fTrkEta = pxPerigee->eta();
1305 
1306  float fDPhi = fabs( fTrkPhi - m_pxMETrack[m_muon1]->phi() );
1307  float fDEta = fabs( fTrkEta - m_pxMETrack[m_muon2]->eta() );
1308  float fDR = sqrt( fDPhi*fDPhi + fDEta*fDEta );
1309 
1310  if ( fDR < 0.3f )
1311  {
1312  return pxTrack;
1313  }
1314 
1315  ++xTrkItr;
1316  }
1317  }
1318  // if ()
1319  return nullptr;
1320 }
1321 
1322 //==================================================================================
1324 {
1325  // first set the new pt cut value
1326  m_LeadingMuonPtCut = newvalue;
1327 
1328  // the second muon pt cut can not be higher than the leading muon pt cut:
1330 
1331  // this has to be translated to the MuonSelector
1332  // but there one has to use the minimum momentum --> second muon
1333  //this->SetMuonPtCut(m_SecondMuonPtCut);
1334  if(m_doDebug){
1335  std::cout <<" * FourMuonEvent * SetLeadingMuonPtCut * new Pt cuts: " << m_LeadingMuonPtCut << " & "
1336  << m_SecondMuonPtCut
1337  << " MuonSelector: " << m_xMuonID.GetPtCut() << std::endl;
1338  }
1339  return;
1340 }
1341 
1342 //==================================================================================
1343 void FourMuonEvent::SetSecondMuonPtCut (double newvalue)
1344 {
1345  m_SecondMuonPtCut = newvalue;
1346 
1347  // use same for electrons
1349 
1350  // second muon pt shouldn't be higher than the leading muon pt
1352 
1353  // this has to be translated to the MuonSelector
1355 
1356  if(m_doDebug) {
1357  std::cout <<" * FourMuonEvent * SetSecondMuonPtCut * new Pt cuts: " << m_LeadingMuonPtCut
1358  << " & " << m_SecondMuonPtCut
1359  << " MuonSelector: " << m_xMuonID.GetPtCut() << std::endl;
1360  }
1361 
1362  return;
1363 }
1364 
1365 //==================================================================================
1367 {
1368  // Salva: 20/January/2020 RecMuon -> IDTrack
1369  bool thisdebug = false;
1370 
1371  if (m_doDebug || thisdebug) {std::cout << " * FourMuonEvent::OrderMuonList * -- start -- " << std::endl
1372  << " #muons: " << m_numberOfFullPassMuons<< std::endl;}
1373 
1374  int muPlus1Id = -9;
1375  int muPlus2Id = -9;
1376  int muMinus1Id = -9;
1377  int muMinus2Id = -9;
1378  double muPlus1Pt = 0.;
1379  double muPlus2Pt = 0.;
1380  double muMinus1Pt = 0.;
1381  double muMinus2Pt = 0.;
1382 
1383  int muposcount = 0;
1384  int munegcount = 0;
1385 
1386  int nMuonsAtEntry = m_numberOfFullPassMuons;
1387  m_numberOfFullPassMuons = 0; // reset the number of full pass muons
1388 
1389  if (nMuonsAtEntry >= 2) { // we need at least 2 muons
1390  for (int imuon=0; imuon < (int) nMuonsAtEntry; imuon++) {
1391  if(m_doDebug && false ){ std::cout << " * FourMuonEvent::OrderMuonList * testing imuon= " << imuon
1392  << " with charge= " << m_pxRecMuon[imuon]->charge()
1393  << " and pt= " << m_pxRecMuon[imuon]->pt()
1394  << std::endl;
1395  }
1396  if (m_pxIDTrack[imuon] != nullptr) {
1397 
1398  if (m_pxIDTrack[imuon]->charge()==1) { // positive muon
1399  muposcount++;
1400  if (m_pxIDTrack[imuon]->pt()> muPlus1Pt) {
1401  // store 1st in 2nd
1402  muPlus2Pt = muPlus1Pt;
1403  muPlus2Id = muPlus1Id;
1404  // now store the new one in 1st place
1405  muPlus1Pt = m_pxIDTrack[imuon]->pt();
1406  muPlus1Id = imuon;
1407  }
1408  else if (m_pxIDTrack[imuon]->pt()> muPlus2Pt) {
1409  // store the new one in 2nd place
1410  muPlus2Pt = m_pxIDTrack[imuon]->pt();
1411  muPlus2Id = imuon;
1412  }
1413  }
1414  // Negative muons
1415  if (m_pxIDTrack[imuon]->charge()==-1) {
1416  munegcount++;
1417  if(m_pxIDTrack[imuon]->pt()> muMinus1Pt) {
1418  // store 1st in 2nd
1419  muMinus2Pt = muMinus1Pt;
1420  muMinus2Id = muMinus1Id;
1421  muMinus1Pt = m_pxIDTrack[imuon]->pt();
1422  muMinus1Id = imuon;
1423  }
1424  else if(m_pxRecMuon[imuon]->pt()> muMinus2Pt) {
1425  muMinus2Pt = m_pxIDTrack[imuon]->pt();
1426  muMinus2Id = imuon;
1427  }
1428  }
1429  } // muon exist
1430  } // for (int imuon)
1431  } // if (nMuonsAtEntry >= 2)
1432 
1433  // require at least one opposite charge muon pair
1434  if (nMuonsAtEntry >= 2 && (muposcount == 0 || munegcount == 0)) {
1435  if (m_doDebug) std::cout << " -- FourMuonEvent::OrderMuonList -- No opposite charge muons in the " << nMuonsAtEntry << " input muons"
1436  << " #mu+ " << muposcount
1437  << " #mu- " << munegcount
1438  << " --> DISCARD ALL MUONS -- " << std::endl;
1439  muPlus1Id = -1;
1440  muPlus1Id = -9;
1441  muPlus2Id = -9;
1442  muMinus1Id = -9;
1443  muMinus2Id = -9;
1444  }
1445 
1446 
1447  if (muPlus1Id>=0) {m_muonpos1 = muPlus1Id; m_numberOfFullPassMuons++;}
1448  if (muPlus2Id>=0) {m_muonpos2 = muPlus2Id; m_numberOfFullPassMuons++;}
1449  if (muMinus1Id>=0) {m_muonneg1 = muMinus1Id; m_numberOfFullPassMuons++;}
1450  if (muMinus2Id>=0) {m_muonneg2 = muMinus2Id; m_numberOfFullPassMuons++;}
1451 
1452  m_muon1 = m_muonpos1; // to be deleted when no more m_muon is left
1453  m_muon2 = m_muonneg1; // to be deleted when no more m_muon is left
1454 
1455  if ((m_doDebug || thisdebug) && m_numberOfFullPassMuons >= 2){
1456  std::cout << " * FourMuonEvent::OrderMuonList * taking " << m_numberOfFullPassMuons << " muons from the input list of " << nMuonsAtEntry << " muons: " << std::endl;
1457  if (muMinus1Id >= 0) std::cout << " leading mu-: " << muMinus1Id << " Pt = " << muMinus1Pt << std::endl;
1458  if (muMinus2Id >= 0) std::cout << " second mu-: " << muMinus2Id << " Pt = " << muMinus2Pt << std::endl;
1459  if (muPlus1Id >= 0) std::cout << " leading mu+: " << muPlus1Id << " Pt = " << muPlus1Pt << std::endl;
1460  if (muPlus2Id >= 0) std::cout << " second mu+: " << muPlus2Id << " Pt = " << muPlus2Pt << std::endl;
1461  }
1462  else {
1463  if (m_doDebug) std::cout << " * FourMuonEvent::OrderMuonList * This event has less than 2 muons :(" << std::endl;
1464  }
1465 
1466  if (m_doDebug || thisdebug) std::cout << " * FourMuonEvent::OrderMuonList * completed * m_numberOfFullPassMuons= " << m_numberOfFullPassMuons << std::endl;
1467  return;
1468 }
1469 
1472 {
1473  (*m_msgStream) << MSG::DEBUG << " * FourMuonsEvents::CheckMuonVertices * -- START --" << endmsg;
1474 
1475  bool goodvertices = false;
1476  goodvertices = true; // R22 set true by default. Needs to be revisited
1477  int nverticesfound = 0;
1478 
1479  // loop on mu-, and for each mu-, loop on mu+ and check at least one mu+ and mu- come from the same vertex
1480  // mu- indices are 0 or 1
1481  for (unsigned int imuneg = 0; imuneg <= 1; imuneg++) {
1482  if (m_pxMUTrack[imuneg] != nullptr) {
1483  /* R21 SALVA --> vertex is not available in R22 --> A FIX IS NEEDED */
1484  /*
1485  if (m_pxMUTrack[imuneg]->vertex()) {
1486 
1487  if (m_doDebug) std::cout << " mu-(" << imuneg <<")->vertex()->v= (" << m_pxMUTrack[imuneg]->vertex()->x()
1488  << ", " << m_pxMUTrack[imuneg]->vertex()->y()
1489  << ", " << m_pxMUTrack[imuneg]->vertex()->z()
1490  << ") " << std::endl;
1491 
1492  for (unsigned int imupos = 2; imupos <= 3; imupos++) { // mu+ indices are 2 and 3
1493  if (m_pxMUTrack[imupos] != nullptr) {
1494  if (m_pxMUTrack[imupos]->vertex()) {
1495  if (m_doDebug) std::cout << " mu+(" << imupos <<")->vertex()->v= (" << m_pxMUTrack[imupos]->vertex()->x()
1496  << ", " << m_pxMUTrack[imupos]->vertex()->y()
1497  << ", " << m_pxMUTrack[imupos]->vertex()->z()
1498  << ") " << std::endl;
1499 
1500  float delta_x = fabs( m_pxMUTrack[imuneg]->vertex()->x() - m_pxMUTrack[imupos]->vertex()->x());
1501  float delta_y = fabs( m_pxMUTrack[imuneg]->vertex()->y() - m_pxMUTrack[imupos]->vertex()->y());
1502  float delta_z = fabs( m_pxMUTrack[imuneg]->vertex()->z() - m_pxMUTrack[imupos]->vertex()->z());
1503 
1504  if (delta_x < m_deltaXYcut && delta_y < m_deltaXYcut && delta_z < m_Z0GapCut) {
1505  nverticesfound++;
1506  if (m_doDebug) std::cout << " MUON-BINGO !!! mu+mu- pair in same vertex !!! mu-[" << imuneg
1507  << "] mu+[" << imupos<< "] count: " << nverticesfound << std::endl;
1508  } // vertex is the same
1509  } // mu+ has vertex
1510  } // mu+ exists
1511  } // loop on mu+
1512  } // mu- has vertex
1513  */
1514  } // mu- exists
1515  } // loop on mu-
1516 
1517  if (nverticesfound >= 1) goodvertices = true;
1518 
1519  if (nverticesfound == 0) if (m_doDebug) std::cout << " -- FourMuonEvent::CheckMuonVertices -- WARNING -- MUONS DO NOT COME FROM SAME VERTEX " << std::endl;
1520 
1521  (*m_msgStream) << MSG::DEBUG << " * FourMuonsEvents::CheckMuonVertices * -- COMPLETED -- status: " << goodvertices << endmsg;
1522  return goodvertices;
1523 }
EventAnalysis::EvaluateAngle
static float EvaluateAngle(const T *pxP1, const T *pxP2)
Definition: EventAnalysis.h:163
ElectronSelector::GetElecNegTrackParticle
const xAOD::TrackParticle * GetElecNegTrackParticle(size_t i)
Definition: ElectronSelector.cxx:349
FourMuonEvent::NUM_TYPES
@ NUM_TYPES
Definition: FourMuonEvent.h:66
xAOD::TrackParticle_v1::pt
virtual double pt() const override final
The transverse momentum ( ) of the particle.
Definition: TrackParticle_v1.cxx:73
FourMuonEvent::Init
void Init()
Definition: FourMuonEvent.cxx:65
FourMuonEvent::ReconstructKinematics
bool ReconstructKinematics()
Definition: FourMuonEvent.cxx:976
GeV
#define GeV
Definition: PhysicsAnalysis/TauID/TauAnalysisTools/Root/HelperFunctions.cxx:17
FourMuonEvent::m_acceptedElecCount
int m_acceptedElecCount
Definition: FourMuonEvent.h:199
DataModel_detail::const_iterator
Const iterator class for DataVector/DataList.
Definition: DVLIterator.h:82
FourMuonEvent::m_acceptedEventCount
int m_acceptedEventCount
Definition: FourMuonEvent.h:196
PerfMonServices::getContainerName
static const std::string & getContainerName(CONTAINERS eContainer)
Definition: PerfMonServices.h:52
FourMuonEvent::EventSelectionNew
bool EventSelectionNew(ZTYPE eType)
Definition: FourMuonEvent.cxx:262
FourMuonEvent::m_muon_vtx
int m_muon_vtx[NUM_MUONS]
Definition: FourMuonEvent.h:218
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:67
getMessageSvc.h
singleton-like access to IMessageSvc via open function and helper
ID
std::vector< Identifier > ID
Definition: CalibHitIDCheck.h:24
Trk::Track
The ATLAS Track class.
Definition: Tracking/TrkEvent/TrkTrack/TrkTrack/Track.h:73
FourMuonEvent::m_fZEtaDir
float m_fZEtaDir[NUM_TYPES]
Definition: FourMuonEvent.h:178
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
xAOD::Muon_v1::trackParticle
const TrackParticle * trackParticle(TrackParticleType type) const
Returns a pointer (which can be NULL) to the TrackParticle used in identification of this muon.
Definition: Muon_v1.cxx:486
ElectronSelector::GetElecPosTrackParticle
const xAOD::TrackParticle * GetElecPosTrackParticle(size_t i)
Definition: ElectronSelector.cxx:358
FourMuonEvent::m_SelectMuonByIP
bool m_SelectMuonByIP
Definition: FourMuonEvent.h:192
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:83
FourMuonEvent::m_xElecID
ElectronSelector m_xElecID
Definition: FourMuonEvent.h:140
FourMuonEvent::m_SecondMuonPtCut
double m_SecondMuonPtCut
Definition: FourMuonEvent.h:148
FourMuonEvent::m_pxIDTrack
const xAOD::TrackParticle * m_pxIDTrack[NUM_MUONS]
Definition: FourMuonEvent.h:171
FourMuonEvent::CheckMuonVertices
bool CheckMuonVertices()
Definition: FourMuonEvent.cxx:1471
Trk::ParametersT
Dummy class used to allow special convertors to be called for surfaces owned by a detector element.
Definition: EMErrorDetail.h:25
FourMuonEvent::OrderMuonList
void OrderMuonList()
Definition: FourMuonEvent.cxx:1366
EventAnalysis::EvalFourMuInvMass
static float EvalFourMuInvMass(const T *pxP1, const T *pxP2, const T *pxP3, const T *pxP4)
Definition: EventAnalysis.h:123
FourMuonEvent::ZTYPE
ZTYPE
Definition: FourMuonEvent.h:61
FourMuonEvent::m_muonpos1
int m_muonpos1
Definition: FourMuonEvent.h:206
FourMuonEvent::Reco
bool Reco()
Definition: FourMuonEvent.cxx:85
FourMuonEvent::m_msgStream
MsgStream * m_msgStream
Definition: FourMuonEvent.h:136
FourMuonEvent::NUM_MUONS
@ NUM_MUONS
Definition: FourMuonEvent.h:49
FourMuonEvent::m_muonneg2_vtx
int m_muonneg2_vtx
Definition: FourMuonEvent.h:214
test_pyathena.pt
pt
Definition: test_pyathena.py:11
FourMuonEvent::m_numberOfFullPassMuons
unsigned int m_numberOfFullPassMuons
Definition: FourMuonEvent.h:161
FourMuonEvent::ID
@ ID
Definition: FourMuonEvent.h:64
xAOD::TrackParticle_v1::definingParametersCovMatrixVec
std::vector< float > definingParametersCovMatrixVec() const
Returns the length 6 vector containing the elements of defining parameters covariance matrix.
Definition: TrackParticle_v1.cxx:385
FourMuonEvent::getZCharge
int getZCharge(ZTYPE eType)
Definition: FourMuonEvent.cxx:1241
FourMuonEvent::MUON2
@ MUON2
Definition: FourMuonEvent.h:46
FourMuonEvent::ReconstructKinematicsNew
bool ReconstructKinematicsNew()
Definition: FourMuonEvent.cxx:1083
FourMuonEvent::m_muonneg1_vtx
int m_muonneg1_vtx
Definition: FourMuonEvent.h:213
FourMuonEvent::RecordMuon
void RecordMuon(const xAOD::Muon *pxMuon)
Definition: FourMuonEvent.cxx:923
ElectronSelector::SetPtCut
void SetPtCut(float newpt)
Definition: ElectronSelector.h:48
EventAnalysis::EvalCharge
static float EvalCharge(const T *pxP1, const T *pxP2)
Definition: EventAnalysis.h:238
PerfMonServices.h
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:77
Athena::getMessageSvc
IMessageSvc * getMessageSvc(bool quiet=false)
Definition: getMessageSvc.cxx:20
xAOD::Muon_v1
Class describing a Muon.
Definition: Muon_v1.h:38
FourMuonEvent::m_passedFourLeptonSelection
bool m_passedFourLeptonSelection
Definition: FourMuonEvent.h:166
xAOD::TrackParticle_v1::d0
float d0() const
Returns the parameter.
FourMuonEvent::m_elec_vtx
int m_elec_vtx[NUM_MUONS]
Definition: FourMuonEvent.h:219
FourMuonEvent::m_workAsFourElectrons
bool m_workAsFourElectrons
Definition: FourMuonEvent.h:157
FourMuonEvent::m_muon2
int m_muon2
Definition: FourMuonEvent.h:204
xAOD::Muon_v1::charge
float charge() const
FourMuonEvent::ME
@ ME
Definition: FourMuonEvent.h:63
FourMuonEvent::m_muonpos1_vtx
int m_muonpos1_vtx
Definition: FourMuonEvent.h:215
FourMuonEvent::m_MassWindowHigh
double m_MassWindowHigh
Definition: FourMuonEvent.h:150
FourMuonEvent::getNegMuon
unsigned int getNegMuon(int eType)
Definition: FourMuonEvent.cxx:1278
FourMuonEvent::getPosMuon
unsigned int getPosMuon(int eType)
Definition: FourMuonEvent.cxx:1267
EventAnalysis::EvalPtDiff
static float EvalPtDiff(const T *pxP1, const T *pxP2)
Definition: EventAnalysis.h:173
lumiFormat.i
int i
Definition: lumiFormat.py:85
PerfMonServices::ELECTRON_COLLECTION
@ ELECTRON_COLLECTION
Definition: PerfMonServices.h:30
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
ElectronSelector::PrepareElectronList
void PrepareElectronList(const xAOD::ElectronContainer *pxElecContainer)
Definition: ElectronSelector.cxx:94
FourMuonEvent::getLooseIDTk
const xAOD::TrackParticle * getLooseIDTk(unsigned int uPart)
Definition: FourMuonEvent.cxx:1286
MuonSelector::Init
virtual void Init()
Definition: MuonSelector.cxx:112
FourMuonEvent::m_numberOfFullPassElectrons
unsigned int m_numberOfFullPassElectrons
Definition: FourMuonEvent.h:162
FourMuonEvent::SetLeadingMuonPtCut
void SetLeadingMuonPtCut(double newvalue)
Definition: FourMuonEvent.cxx:1323
FourMuonEvent::m_xMuonID
MuonSelector m_xMuonID
Definition: FourMuonEvent.h:139
xAOD::Muon_v1::pt
virtual double pt() const
The transverse momentum ( ) of the particle.
FourMuonEvent::m_passedFourElectronSelection
bool m_passedFourElectronSelection
Definition: FourMuonEvent.h:165
FourMuonEvent::m_doDebug
bool m_doDebug
Definition: FourMuonEvent.h:155
hist_file_dump.f
f
Definition: hist_file_dump.py:135
FourMuonEvent::m_fZPt
float m_fZPt[NUM_TYPES]
Definition: FourMuonEvent.h:177
FourMuonEvent::m_container
PerfMonServices::CONTAINERS m_container
Definition: FourMuonEvent.h:141
FourMuonEvent::MS
@ MS
Definition: FourMuonEvent.h:62
MuonSelector::GetPtCut
double GetPtCut()
Definition: MuonSelector.h:55
FourMuonEvent::m_eventCount
int m_eventCount
Definition: FourMuonEvent.h:195
FourMuonEvent::FourMuonEvent
FourMuonEvent()
Definition: FourMuonEvent.cxx:29
FourMuonEvent::getPtImbalance
float getPtImbalance(ZTYPE eType)
Definition: FourMuonEvent.cxx:1207
PerfMonServices::TRK_COLLECTION
@ TRK_COLLECTION
Definition: PerfMonServices.h:42
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
FourMuonEvent::m_nVertex
int m_nVertex
Definition: FourMuonEvent.h:212
FourMuonEvent::BookHistograms
void BookHistograms()
Definition: FourMuonEvent.cxx:255
FourMuonEvent::m_pxMETrack
const xAOD::TrackParticle * m_pxMETrack[NUM_MUONS]
Definition: FourMuonEvent.h:169
Trk::Track::perigeeParameters
const Perigee * perigeeParameters() const
return Perigee.
Definition: Tracking/TrkEvent/TrkTrack/src/Track.cxx:163
FourMuonEvent::MUON1
@ MUON1
Definition: FourMuonEvent.h:45
ElectronSelector::GetElectronCollectionSize
unsigned int GetElectronCollectionSize()
Definition: ElectronSelector.h:43
charge
double charge(const T &p)
Definition: AtlasPID.h:756
EventAnalysis::EvalEta
static float EvalEta(const T *pxP1, const T *pxP2)
Definition: EventAnalysis.h:229
FourMuonEvent::m_LeadingMuonPtCut
double m_LeadingMuonPtCut
Definition: FourMuonEvent.h:147
FourMuonEvent::Clear
void Clear()
Definition: FourMuonEvent.cxx:875
FourMuonEvent::m_fMuonDispersion
float m_fMuonDispersion[NUM_TYPES]
Definition: FourMuonEvent.h:181
FourMuonEvent::m_workAsFourLeptons
bool m_workAsFourLeptons
Definition: FourMuonEvent.h:158
MuonSelector::passSelection
bool passSelection(const xAOD::Muon *pxMuon)
Definition: MuonSelector.cxx:136
EventAnalysis::EvalPt
static float EvalPt(const T *pxP1, const T *pxP2)
Definition: EventAnalysis.h:211
FourMuonEvent::m_passedFourMuonSelection
bool m_passedFourMuonSelection
Definition: FourMuonEvent.h:164
FourMuonEvent::m_muonneg2
int m_muonneg2
Definition: FourMuonEvent.h:209
FourMuonEvent::m_workAsFourMuons
bool m_workAsFourMuons
Definition: FourMuonEvent.h:156
DataVector::end
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
python.PyAthena.v
v
Definition: PyAthena.py:154
FourMuonEvent::m_pxELTrack
const xAOD::TrackParticle * m_pxELTrack[NUM_MUONS]
Definition: FourMuonEvent.h:173
FourMuonEvent::m_fZPhiDir
float m_fZPhiDir[NUM_TYPES]
Definition: FourMuonEvent.h:179
FourMuonEvent.h
FourMuonEvent::m_MassWindowLow
double m_MassWindowLow
Definition: FourMuonEvent.h:149
FourMuonEvent::ReconstructKinematics4Elec
bool ReconstructKinematics4Elec()
Definition: FourMuonEvent.cxx:1035
FourMuonEvent::m_fInvariantMass
float m_fInvariantMass[NUM_TYPES]
Definition: FourMuonEvent.h:180
FourMuonEvent::m_Z0GapCut
double m_Z0GapCut
Definition: FourMuonEvent.h:153
FourMuonEvent::m_muonpos2_vtx
int m_muonpos2_vtx
Definition: FourMuonEvent.h:216
FourMuonEvent::m_muon1
int m_muon1
Definition: FourMuonEvent.h:203
DEBUG
#define DEBUG
Definition: page_access.h:11
FourMuonEvent::m_pxMSTrack
const xAOD::TrackParticle * m_pxMSTrack[NUM_MUONS]
Definition: FourMuonEvent.h:170
FourMuonEvent::m_pxRecMuon
const xAOD::Muon * m_pxRecMuon[NUM_MUONS]
Definition: FourMuonEvent.h:168
FourMuonEvent::m_passedSelectionCuts
bool m_passedSelectionCuts
Definition: FourMuonEvent.h:163
FourMuonEvent::m_muonpos2
int m_muonpos2
Definition: FourMuonEvent.h:207
FourMuonEvent::~FourMuonEvent
virtual ~FourMuonEvent()
Definition: FourMuonEvent.cxx:59
EventAnalysis::EvalPhi
static float EvalPhi(const T *pxP1, const T *pxP2)
Definition: EventAnalysis.h:220
FourMuonEvent::SetMuonPtCut
void SetMuonPtCut(double newvalue)
Definition: FourMuonEvent.h:112
Trk::phi
@ phi
Definition: ParamDefs.h:75
xAOD::Muon_v1::primaryTrackParticle
const TrackParticle * primaryTrackParticle() const
Returns a pointer (which should not usually be NULL, but might be if the muon has been stripped of in...
Definition: Muon_v1.cxx:400
FourMuonEvent::m_pxMUTrack
const xAOD::TrackParticle * m_pxMUTrack[NUM_MUONS]
Definition: FourMuonEvent.h:174
xAOD::TrackParticle_v1
Class describing a TrackParticle.
Definition: TrackParticle_v1.h:43
xAOD::TrackParticle_v1::track
const Trk::Track * track() const
Returns a pointer (which can be NULL) to the Trk::Track which was used to make this TrackParticle.
Definition: TrackParticle_v1.cxx:805
FourMuonEvent::m_uMuonTags
unsigned int m_uMuonTags
Definition: FourMuonEvent.h:144
EventAnalysis::Init
virtual void Init()
Definition: EventAnalysis.cxx:44
FourMuonEvent::m_muonneg1
int m_muonneg1
Definition: FourMuonEvent.h:208
FourMuonEvent::m_FourMuonInvMass
double m_FourMuonInvMass
Definition: FourMuonEvent.h:145
EventAnalysis::m_xSampleName
std::string m_xSampleName
Definition: EventAnalysis.h:80
ElectronSelector::Init
void Init()
Definition: ElectronSelector.cxx:53
StoreGateSvc.h
MooRTT_summarizeCPU.muid
int muid
Definition: MooRTT_summarizeCPU.py:44
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
FourMuonEvent::m_acceptedMuonCount
int m_acceptedMuonCount
Definition: FourMuonEvent.h:198
FourMuonEvent::m_SelectMuonByIso
bool m_SelectMuonByIso
Definition: FourMuonEvent.h:191
FourMuonEvent::SetSecondMuonPtCut
void SetSecondMuonPtCut(double newvalue)
Definition: FourMuonEvent.cxx:1343
FourMuonEvent::EventSelection
bool EventSelection(ZTYPE eType)
Definition: FourMuonEvent.cxx:555
PerfMonServices::MUON_COLLECTION
@ MUON_COLLECTION
Definition: PerfMonServices.h:26
DataVector::begin
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
FourMuonEvent::m_deltaXYcut
double m_deltaXYcut
Definition: FourMuonEvent.h:152
FourMuonEvent::CB
@ CB
Definition: FourMuonEvent.h:65