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