ATLAS Offline Software
Loading...
Searching...
No Matches
FourMuonEvent.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5//==================================================================================
6// Include files...
7//==================================================================================
8
9// This files header
11
12// Package Headers
14
15// ATLAS headers
18
19#include "CLHEP/Random/RandFlat.h"
20
21//==================================================================================
22// Public Methods
23//==================================================================================
24
26{
27 m_xSampleName = "FourMuon";
28
29 m_container = PerfMonServices::MUON_COLLECTION; //PerfMonServices::ELECTRON_COLLECTION
30
31 m_doDebug = false;
32 m_workAsFourMuons = false;
35
36 // Setup the muon tags
37 m_uMuonTags = 4;
38 m_LeadingMuonPtCut = 20.;
40 m_MassWindowLow = 10.0;
41 m_MassWindowHigh = 125.0;
42 m_deltaXYcut = 0.1; // in mm
43 m_Z0GapCut = 5.0; // in mm
44 m_SelectMuonByIso = true;
45 m_SelectMuonByIP = true;
46 m_eventCount = 0;
50
51 m_msgStream = new MsgStream(Athena::getMessageSvc(), "InDetPerformanceMonitoring" );
52}
53
54//==================================================================================
59
60//==================================================================================
62{
63 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * START *" << endmsg;
64
65 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * initializing muon selector *" << endmsg;
66 m_xMuonID.Init();
67 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * initializing electron selector *" << endmsg;
68 m_xElecID.Init();
69
70 if (m_workAsFourMuons) {(*m_msgStream) << MSG::INFO << " * FourMuonEvent::Init * working mode: 4 muons" << endmsg; }
71 if (m_workAsFourElectrons) {(*m_msgStream) << MSG::INFO << " * FourMuonEvent::Init * working mode: 4 electrons" << endmsg; }
72 if (m_workAsFourLeptons) {(*m_msgStream) << MSG::INFO << " * FourMuonEvent::Init * working mode: 4 leptons" << endmsg; }
73
75 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Init * Completed * " << endmsg;
76
77 return;
78}
79
80//==================================================================================
82{
84 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * STARTING ** New event ** eventCount " << m_eventCount << endmsg;
85
86 // Clear out the previous events record.
87 this->Clear();
88
89 // if muons are requested
91 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * retrieving xAOD::MuonContainer " << m_container << " of eventCount " << m_eventCount << std::endl;
92
94
95 // check if muon container does exist
96 if (pxMuonContainer != nullptr) {
97 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * eventCount " << m_eventCount
98 << " track list has "<< pxMuonContainer->size()
99 << " combined muons in container " << m_container
100 << " container name: " << PerfMonServices::getContainerName ( m_container )
101 << endmsg;
102
103 xAOD::MuonContainer::const_iterator xMuonItr = pxMuonContainer->begin();
104 xAOD::MuonContainer::const_iterator xMuonItrE = pxMuonContainer->end();
105 int theCount = 0;
106 while ( xMuonItr != xMuonItrE ){ // start loop on muons
107 const xAOD::Muon* pxCMuon = *xMuonItr;
108 theCount++;
109 // Apply muon cuts
110 if ( m_xMuonID.passSelection( pxCMuon)) {
111 RecordMuon( pxCMuon );
112 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco ** muon " << theCount << " is accepted " << endmsg;
113 }
114 ++xMuonItr;
115 } // end loop on muons
116
117 // ordering of muons
118 this->OrderMuonList();
119 } // end muon container exists
120 if (!pxMuonContainer) {
121 std::cout << " * FourMuonEvent::Reco * Can't retrieve combined muon collection (container: " << m_container <<") " << std::endl;
122 return false;
123 } // end muon container does not exist
124 } // end requesting muons
125
126 //
127 // Electron selection (in case electrons are requested)
129 // Get the electron AOD container
130 const xAOD::ElectronContainer* pxElecContainer = nullptr;
131 if (m_doDebug){ std::cout << " * FourMuonEvent::Reco * retrieving xAOD::ElectronContainer " << PerfMonServices::ELECTRON_COLLECTION << std::endl; }
133
134 //pxElecContainer = evtStore()->retrieve( pxElecContainer, "Electrons" );
135
136 if (pxElecContainer != nullptr) {
137 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * retrieving xAOD::ElectronContainer SUCCESS. "
139 << " size: " << pxElecContainer->size()
140 << endmsg;
141 if (pxElecContainer->size() > 0 ){
142 m_xElecID.PrepareElectronList (pxElecContainer);
143 m_numberOfFullPassElectrons = m_xElecID.GetElectronCollectionSize();
145 }
146 }
147 else { // no pxElecContainer
148 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * retrieving xAOD::ElectronContainer -- FAILED -- eventcount: " << m_eventCount << endmsg;
149 }
150 }
151
153 // reached this point one has the list of muons and electrons in this event
155
156 // now check if the particles in the event make them to satisfy the event selection
157 if (m_workAsFourMuons) {
158 m_passedFourMuonSelection = false; // unless the event has 4 muons, assume it is not good
159
160 if (m_numberOfFullPassMuons == 4) {
164
166 m_FourMuonInvMass = m_fInvariantMass[ID]; // store invariant mass
167 if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is a GOOD 4-muon event " << std::endl;
168 }
169 else {
170 if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " FAILS the 4-muon event selection " << std::endl;
171 }
172 }
173 } // end of workAsFourMuons
174
176 if (m_doDebug) std::cout << " * FourMuonEvent::Reco * applying 4 electron selection " << std::endl;
177 m_passedFourElectronSelection = false; // unless the event has 4 muons, assume it is not good
178
182
184 m_FourMuonInvMass = m_fInvariantMass[ID]; // store invariant mass
185 if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is a GOOD 4-electrom event " << std::endl;
186 }
187 else {
188 if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " FAILS the 4-electron event selection " << std::endl;
189 }
190 }
191 else {
192 if (m_doDebug) std::cout << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is not a 4-electron event " << std::endl;
193 }
194 } // end of workAsFourElectrons
195
196
198 if (m_doDebug) std::cout << " * FourMuonEvent::Reco * applying 4 lepton selection " << std::endl;
200
201 bool enoughleptons = false;
202 if (m_numberOfFullPassMuons == 4) enoughleptons = true;
203 if (m_numberOfFullPassElectrons == 4) enoughleptons = true;
204 if (m_numberOfFullPassMuons >= 2 && m_numberOfFullPassElectrons >= 2) enoughleptons = true;
205
206 if ( enoughleptons) {
207 if (m_doDebug) {
208 std::cout << " * FourMuonEvent::Reco * Global statistics: Total number of accepted muons so far: " << m_acceptedMuonCount
209 << " & electrons: " << m_acceptedElecCount << " integrated over all events "
210 << std::endl;
211 std::cout << " * FourMuonEvent::Reco * This event has " << m_numberOfFullPassMuons
212 << " muons & " << m_numberOfFullPassElectrons << " electrons --> try kinematics, vertex and event selection"
213 << std::endl;
214 }
218
220 m_FourMuonInvMass = m_fInvariantMass[ID]; // store invariant mass
221 (*m_msgStream) << MSG::INFO << " * FourMuonEvent::Reco * === Event " << m_eventCount << " is a GOOD 4-lepton event with inv mass: " << m_FourMuonInvMass << endmsg;
222 }
223 else {
224 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * === Event " << m_eventCount << " -- FAILS -- the 4-lepton event selection " << endmsg;
225 }
226 }
227 else {
228 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * 4lepton selection FAILURE. Not enough muons or electrons. Event has " << m_numberOfFullPassMuons
229 << " muons & " << m_numberOfFullPassElectrons << " electrons"
230 << endmsg;
231 }
232 }
233
234 m_passedSelectionCuts = false; // assume event is not good, but check the selection according to the use case
238
240
241 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::Reco * COMPLETED * Event has " << m_numberOfFullPassMuons << " muons & "
242 << m_numberOfFullPassElectrons << " electrons. "
243 << " So far: " << m_acceptedEventCount << " events were accepted out of " << m_eventCount << " tested" << endmsg;
244
246}
247
248//==================================================================================
249// Protected Methods
250//==================================================================================
254
255//==================================================================================
256// Private Methods
257//==================================================================================
259{
260 bool inputdebug = m_doDebug;
261 //m_doDebug = true;
262
263 bool eventisgood = true;
264 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent::EventSelection( type= " << eType << ") ** started ** " << std::endl
265 << " event count: " << m_eventCount << std::endl
266 << " m_NumberOfFullPassMuons: " << m_numberOfFullPassMuons << std::endl
267 << " m_NumberOfFullPassElectrons: " << m_numberOfFullPassElectrons
268 << endmsg;
269
270
271 // Depending on mode: require a minimum of electrons or muons
272 if ( eventisgood && m_workAsFourMuons) {
273 if (m_numberOfFullPassMuons < 4) {
274 eventisgood = false;
275 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good muons == 4 :( "
276 <<" m_numberOfFullPassMuons= " << m_numberOfFullPassMuons << std::endl;
277 }
278 }
279 }
280
281 if ( eventisgood && m_workAsFourElectrons) {
283 eventisgood = false;
284 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good electrons == 4 :( "
285 <<" m_numberOfFullPassElectrons= " << m_numberOfFullPassElectrons << std::endl;
286 }
287 }
288 }
289
290 if ( eventisgood && m_workAsFourLeptons) {
291 bool thisselection = false;
292 if (m_numberOfFullPassMuons == 4) thisselection = true;
293 if (m_numberOfFullPassElectrons == 4) thisselection = true;
294 if (m_numberOfFullPassMuons >= 2 && m_numberOfFullPassElectrons >= 2) thisselection = true;
295 if (!thisselection) {
296 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good muons >= 2 && electrons >= 2 :( "
297 <<" m_numberOfFullPassMuons= " << m_numberOfFullPassMuons
298 <<" m_numberOfFullPassElectrons= " << m_numberOfFullPassElectrons << std::endl;
299 }
300 }
301 eventisgood = thisselection;
302 }
303
304 //
305 // momentum of the leptons
306 // loop over the muons and electrons and count how many pass the leadingPt and secondPt cut
307 unsigned int npassleadingpt = 0;
308 unsigned int npasssecondpt = 0;
309 if ( eventisgood && (m_workAsFourMuons || m_workAsFourLeptons) ) {
310 if (m_numberOfFullPassMuons >= 2) { // electrons pt cuts if there are some electrons
311 //for (unsigned int i=0; i < m_numberOfFullPassMuons; i++) {
312 for (unsigned int i=0; i < NUM_MUONS; i++) {
313 if (m_pxIDTrack[i] == nullptr) continue;
314 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * using muon " << i << " with pt: " << m_pxIDTrack[i]->pt() << std::endl;}
315 if (m_pxIDTrack[i]->pt() > m_LeadingMuonPtCut*CLHEP::GeV) npassleadingpt++;
316 if (m_pxIDTrack[i]->pt() > m_SecondMuonPtCut*CLHEP::GeV) npasssecondpt++;
317 }
318 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #muons with pt > leading pt: " << m_LeadingMuonPtCut*CLHEP::GeV << " = " << npassleadingpt << std::endl;}
319 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #muons with pt > second pt: " << m_SecondMuonPtCut*CLHEP::GeV << " = " << npasssecondpt << std::endl;}
320 if (npassleadingpt == 0) { // at least 1 muon must pass the leading pt cut
321 eventisgood = false;
322 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing leading muon pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
323 }
324 if (npasssecondpt < m_numberOfFullPassMuons) { // all muons must pass the second pt cut
325 eventisgood = false;
326 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing second muon pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
327 }
328 }
329 }
330
331 // four electrons case
332 if ( eventisgood && (m_workAsFourElectrons || m_workAsFourLeptons) ) {
333 npassleadingpt = 0;
334 npasssecondpt = 0;
335 if (m_numberOfFullPassElectrons >= 2) { // electrons pt cuts if there are some electrons
336 for (unsigned int i=0; i < NUM_MUONS; i++) {
337 if (m_pxELTrack[i] == nullptr) continue;
338 if (m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * using electron " << i << " with pt: " << m_pxELTrack[i]->pt() << std::endl;}
339 if (m_pxELTrack[i]->pt() > m_LeadingMuonPtCut*CLHEP::GeV) npassleadingpt++;
340 if (m_pxELTrack[i]->pt() > m_SecondMuonPtCut*CLHEP::GeV) npasssecondpt++;
341 }
342 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #elecs with pt > leading pt: " << m_LeadingMuonPtCut*CLHEP::GeV << " = " << npassleadingpt << std::endl;}
343 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * #elecs with pt > second pt: " << m_SecondMuonPtCut*CLHEP::GeV << " = " << npasssecondpt << std::endl;}
344 if (npassleadingpt == 0) { // at least 1 electron must pass the leading pt cut
345 eventisgood = false;
346 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing leading electron pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
347 }
348 if (npasssecondpt < m_numberOfFullPassElectrons) { // all electrons must pass the second pt cut
349 eventisgood = false;
350 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing second electrons pt cut " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl;}
351 }
352 } // electron pt cuts apply if there are some electrons
353 }
354
355 // Invariant mass window
356 if (eventisgood) {
357 if ( m_fInvariantMass[eType] < m_MassWindowLow ) {
358 if(m_doDebug) {
359 std::cout <<" * FourMuonEvent::EventSelection * Failing mass window low cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowLow << std::endl;
360 }
361 eventisgood = false;
362 }
363 if ( m_fInvariantMass[eType] > m_MassWindowHigh ) {
364 if(m_doDebug) {
365 std::cout <<" * FourMuonEvent::EventSelection * Failing mass window high cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowHigh << std::endl;
366 }
367 eventisgood = false;
368 }
369 }
370
371 // check on vertices
372 if (eventisgood) {
373 bool vertexstatus = false;
374
375 std::vector <float> vtxListX; // coordinates of the vertex
376 std::vector <float> vtxListY;
377 std::vector <float> vtxListZ;
378 std::vector <int> vtxNpart; // count how many particles are in vertex
379
380 int noVertexCountMuon = 0;
381 int noVertexCountElec = 0;
382 //
383 if ( m_workAsFourMuons ) { // till here we have the muon vertices list
384 m_nVertex = vtxListX.size();
385 if (vtxListX.size()>0) vertexstatus = true;
386 // check that the muons are not split into too many vertices
387 if (vtxListX.size() >= m_numberOfFullPassMuons - 1) vertexstatus = false;
388 // allow no muon without vertex
389 if (noVertexCountMuon > 0) vertexstatus = false;
390 if (m_doDebug || true) {
391 std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices ID of the muons = " << std::endl
392 << " mu- 1 " << m_muon_vtx[0] << " pt: " << m_pxMUTrack[0]->pt() << std::endl
393 << " mu- 2 " << m_muon_vtx[1] << " pt: " << m_pxMUTrack[1]->pt() << std::endl
394 << " mu+ 1 " << m_muon_vtx[2] << " pt: " << m_pxMUTrack[2]->pt() << std::endl
395 << " mu+ 2 " << m_muon_vtx[3] << " pt: " << m_pxMUTrack[3]->pt()
396 << std::endl;
397 } // end debug
398 } // end m_workAsFourMuons
399
400 if ( m_workAsFourElectrons ) { // till here we have the electrons vertices list
401 m_nVertex = vtxListX.size();
402 if (vtxListX.size()>0) vertexstatus = true;
403 // check that the electrons are not split into too many vertices
404 if (vtxListX.size() >= m_numberOfFullPassElectrons - 1) vertexstatus = false;
405
406 std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices ID of the electrons = "
407 << "\n el- 1 " << m_elec_vtx[0] << " pt: " << m_pxELTrack[0]->pt() << std::endl
408 << "\n el- 2 " << m_elec_vtx[1] << " pt: " << m_pxELTrack[1]->pt() << std::endl
409 << "\n el+ 1 " << m_elec_vtx[2] << " pt: " << m_pxELTrack[2]->pt() << std::endl
410 << "\n el+ 2 " << m_elec_vtx[3] << " pt: " << m_pxELTrack[3]->pt() <<"\n";
411 }
412
413 if ( m_workAsFourLeptons ) { // till here we have the muons and electrons vertices list
414 m_nVertex = vtxListX.size();
415 if (vtxListX.size()>0) vertexstatus = true;
416 // check that the electrons are not split into too many vertices
417 // if (vtxListX.size() >= m_numberOfFullPassElectrons - 1) vertexstatus = false;
418 // and allow no electron without vertex
419 if (m_doDebug) {
420 std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices in event = " << vtxListX.size() << std::endl;
421 for (size_t imu=0; imu < NUM_MUONS; imu++) {
422 if (m_pxMUTrack[imu]) std::cout << " mu " << m_muon_vtx[imu] << " pt: " << m_pxMUTrack[imu]->pt() << std::endl;
423 }
424 for (size_t iel=0; iel < NUM_MUONS; iel++) {
425 if (m_pxELTrack[iel]) std::cout << " el " << m_elec_vtx[iel] << " pt: " << m_pxELTrack[iel]->pt() << std::endl;
426 }
427 }
428 }
429
430 vertexstatus = true; // Temporary fix to work on R22
431
432 if(m_doDebug) {
433 std::cout <<" * FourMuonEvent::EventSelection(" << eType <<") * Number of vertex found = " << vtxListX.size()
434 << " and mu without vertex: " << noVertexCountMuon
435 << " and elec without vertex: " << noVertexCountElec << std::endl;
436 for (unsigned int ivtx=0; ivtx < vtxListX.size(); ivtx++) {
437 std::cout << " vtx[" << ivtx << "]= "
438 << "( " << vtxListX.at(ivtx)
439 << ", " << vtxListY.at(ivtx)
440 << ", " << vtxListZ.at(ivtx)
441 << ") nparticles: " << vtxNpart.at(ivtx)
442 << std::endl;
443 }
444 }
445
446
447 eventisgood = vertexstatus;
448 }
449
450 //
451 if(m_doDebug){ std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") ** completed ** result= " << eventisgood << std::endl;}
452
453 m_doDebug = inputdebug;
454
455 return eventisgood;
456}
457//==================================================================================
459{
460 if(m_doDebug){ std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") ** started ** " << std::endl
461 << " event count: " << m_eventCount << std::endl
462 << " m_NumberOfFullPassMuons: " << m_numberOfFullPassMuons << std::endl
463 << " m_NumberOfFullPassElectrons: " << m_numberOfFullPassElectrons
464 << std::endl;
465 }
466
467 // First require two muon-id's with cuts pre-applied.
469 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good muons and electrons == 4 :( "
471 << " = " << m_numberOfFullPassMuons << " + " << m_numberOfFullPassElectrons << std::endl;}
472 return false;
473 }
474
475 if ( m_numberOfFullPassMuons > 4 ) {
476 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Too many muons !! Failing number of good muons == 4 :( "
477 << m_numberOfFullPassMuons << std::endl;}
478 return false;
479 }
480
481 if ( m_numberOfFullPassElectrons > 4 ) {
482 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Too many electrons !! Failing number of good electrons == 4 :( "
483 << m_numberOfFullPassElectrons << std::endl;}
484 return false;
485 }
486
487 // momentum of the muons
488 double leadingMuonPt = -1., secondMuonPt=-1., thirdMuonPt=-1, fourthMuonPt=-1.; // negative pt, means not computed yet
489 switch ( eType ) {
490 case MS :
491 {
492 if (m_muonpos1 >= 0) leadingMuonPt = m_pxMSTrack[m_muonpos1]->pt();
493 if (m_muonpos2 >= 0) secondMuonPt = m_pxMSTrack[m_muonpos2]->pt();
494 if (m_muonneg1 >= 0) thirdMuonPt = m_pxMSTrack[m_muonneg1]->pt();
495 if (m_muonneg2 >= 0) fourthMuonPt = m_pxMSTrack[m_muonneg2]->pt();
496 break;
497 }
498 case ME:
499 {
500 if (m_muonpos1 >= 0) leadingMuonPt = m_pxMETrack[m_muonpos1]->pt();
501 if (m_muonpos2 >= 0) secondMuonPt = m_pxMETrack[m_muonpos2]->pt();
502 if (m_muonneg1 >= 0) thirdMuonPt = m_pxMETrack[m_muonneg1]->pt();
503 if (m_muonneg2 >= 0) fourthMuonPt = m_pxMETrack[m_muonneg2]->pt();
504 break;
505 }
506 case CB:
507 {
508 if (m_muonpos1 >= 0) leadingMuonPt = m_pxRecMuon[m_muonpos1]->pt();
509 if (m_muonpos2 >= 0) secondMuonPt = m_pxRecMuon[m_muonpos2]->pt();
510 if (m_muonneg1 >= 0) thirdMuonPt = m_pxRecMuon[m_muonneg1]->pt();
511 if (m_muonneg2 >= 0) fourthMuonPt = m_pxRecMuon[m_muonneg2]->pt();
512 break;
513 }
514 case ID:
515 {
516 if (m_muonpos1 >= 0) leadingMuonPt = m_pxIDTrack[m_muonpos1]->pt();
517 if (m_muonpos2 >= 0) secondMuonPt = m_pxIDTrack[m_muonpos2]->pt();
518 if (m_muonneg1 >= 0) thirdMuonPt = m_pxIDTrack[m_muonneg1]->pt();
519 if (m_muonneg2 >= 0) fourthMuonPt = m_pxIDTrack[m_muonneg2]->pt();
520 break;
521 }
522
523 default:
524 if (m_muonpos1 >= 0) leadingMuonPt = m_pxIDTrack[m_muonpos1]->pt();
525 if (m_muonpos2 >= 0) secondMuonPt = m_pxIDTrack[m_muonpos2]->pt();
526 if (m_muonneg1 >= 0) thirdMuonPt = m_pxIDTrack[m_muonneg1]->pt();
527 if (m_muonneg2 >= 0) fourthMuonPt = m_pxIDTrack[m_muonneg2]->pt();
528 } // end switch
529
530 // up to here the leading and second pt are not really in the right order.
531 // order the muon pt:
532 double theLeadingPt = leadingMuonPt;
533 if (secondMuonPt > theLeadingPt) { theLeadingPt = secondMuonPt;}
534 if (thirdMuonPt > theLeadingPt) { theLeadingPt = thirdMuonPt;}
535 if (fourthMuonPt > theLeadingPt) { theLeadingPt = fourthMuonPt;}
536
537 double theTrailingPt = leadingMuonPt;
538 if (secondMuonPt < theTrailingPt && secondMuonPt > 0) { theTrailingPt = secondMuonPt;}
539 if (thirdMuonPt < theTrailingPt && thirdMuonPt > 0) { theTrailingPt = thirdMuonPt;}
540 if (fourthMuonPt < theTrailingPt && fourthMuonPt > 0) { theTrailingPt = fourthMuonPt;}
541
542 if (m_doDebug || true) {
543 std::cout << " * FourMuonEvent::EventSelection * muon pt selection -- cuts: Leading: " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl
544 << " 2nd: " << m_SecondMuonPtCut*CLHEP::GeV << std::endl;
545 std::cout << " Pt of muons in this event 1: " << leadingMuonPt << std::endl
546 << " 2: " << secondMuonPt << std::endl
547 << " 3: " << thirdMuonPt << std::endl
548 << " 4: " << fourthMuonPt << std::endl
549 << " leading Pt: " << theLeadingPt << std::endl
550 << " trailing Pt: " << theTrailingPt << std::endl;
551 }
552
553 // muon pt cut
554 if ( !(theLeadingPt > m_LeadingMuonPtCut*CLHEP::GeV && theTrailingPt > m_SecondMuonPtCut*CLHEP::GeV ) ) {
555 if(m_doDebug){
556 std::cout <<" * FourMuonEvent::EventSelection * Failing pt cut * Reco Pt: leading " << theLeadingPt << " --> trailing " << theTrailingPt << std::endl;
557 }
558 return false;
559 }
560 if(m_doDebug){
561 std::cout << " * FourMuonEvent::EventSelection * Event passed the pt cuts: leading muon pt: " << leadingMuonPt << std::endl;
562 std::cout << " trailing muon pt: " << theTrailingPt << std::endl;
563 }
564
565
566 // Invariant mass window
567 if ( m_fInvariantMass[eType] < m_MassWindowLow ) {
568 if(m_doDebug) {
569 std::cout <<" * FourMuonEvent::EventSelection * Failing mass window low cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowLow << std::endl;
570 }
571 return false;
572 }
573 if ( m_fInvariantMass[eType] > m_MassWindowHigh ) {
574 if(m_doDebug) {
575 std::cout <<" * FourMuonEvent * Failing mass window high cut: reco m= " << m_fInvariantMass[eType] << " > " << m_MassWindowHigh << std::endl;
576 }
577 return false;
578 }
579 if(m_doDebug){
580 std::cout <<" * FourMuonEvent::EventSelection * Event passed the mass window: " << m_fInvariantMass[eType] << std::endl;
581 }
582
583 if(m_doDebug) {
584 std::cout << " * FourMuonEvent::EventSelection( type= " << eType << ")* Good 4-muon set: pt range from " << leadingMuonPt/1000
585 << " to " << secondMuonPt/1000
586 << " GeV 4-muon invariant mass = " << m_fInvariantMass.at(eType) << " GeV \n";
587 std::cout << " * FourMuonEvent::EventSelection( type= " << eType << ")* completed * \n";
588 }
589 return true;
590}
591
592//==================================================================================
594{
597 m_passedSelectionCuts = false;
601
602
603 m_FourMuonInvMass = -1.; // flag as no reconstructed inv mass yet
604 m_muon1 = MUON1; // point to the first two
605 m_muon2 = MUON2;
606 m_muonneg1 = -1;
607 m_muonneg2 = -1;
608 m_muonpos1 = -1;
609 m_muonpos2 = -1;
610
611
612 for ( unsigned int u = 0; u < NUM_MUONS; ++u ) {
613 m_pxRecMuon[u] = nullptr;
614 m_pxMSTrack[u] = nullptr;
615 m_pxMETrack[u] = nullptr;
616 m_pxIDTrack[u] = nullptr;
617 m_pxMUTrack[u] = nullptr;
618 m_pxELTrack[u] = nullptr;
619 }
620 for ( unsigned int v = 0; v < NUM_TYPES; ++v ) {
621 m_fZPt[v] = -999.9f;
622 m_fZEtaDir[v] = -999.9f;
623 m_fZPhiDir[v] = -999.9f;
624 m_fInvariantMass[v] = -999.9f;
625 m_fMuonDispersion[v] = -999.9f;
626 }
627
628 // tell us to which vertex the muons are associated
629 m_nVertex = 0; // reset vertex count
630 m_muonneg1_vtx = 0;
631 m_muonneg2_vtx = 0;
632 m_muonpos1_vtx = 0;
633 m_muonpos2_vtx = 0;
634
635 for (size_t i=0; i < NUM_MUONS; i++) m_muon_vtx[i] = 0; // reset the vertex ID to which the electrons are associated
636 for (size_t i=0; i < NUM_MUONS; i++) m_elec_vtx[i] = 0; // reset the vertex ID to which the electrons are associated
637 return;
638}
639
640//==================================================================================
642{
643 constexpr bool thisdebug = false;
644 // This shouldn't really ever happen but just in case.
645 if ( !pxMuon ) {
646 if(m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxMuon --> EXIT "<< std::endl;}
647 return;
648 }
649
651 // The main Muon
653 if (thisdebug) {
654 std::cout <<" * FourMuonEvent * RecordMuon * m_pxRecMuon for this muon--> pt "<< m_pxRecMuon[m_numberOfFullPassMuons]->pt() << std::endl;
655 std::cout <<" d0 "<< m_pxRecMuon[m_numberOfFullPassMuons]->trackParticle(xAOD::Muon::TrackParticleType::Primary)->d0() << std::endl;
656 std::cout <<" sigma_d0 "<< m_pxRecMuon[m_numberOfFullPassMuons]->trackParticle(xAOD::Muon::TrackParticleType::Primary)->definingParametersCovMatrixVec()[0] << std::endl;
657 }
658
659 const xAOD::TrackParticle* pxMSTrack = pxMuon->trackParticle(xAOD::Muon::TrackParticleType::MuonSpectrometerTrackParticle);
660 if (!pxMSTrack) {
661 if (m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxMSmuon --> EXIT "<< std::endl;}
662 return;
663 }
665 if (thisdebug) {
666 std::cout <<" * FourMuonEvent * RecordMuon * m_pxMSTrack for this muon--> pt "<< m_pxMSTrack[m_numberOfFullPassMuons]->pt() << std::endl;
667 std::cout <<" d0 "<< m_pxMSTrack[m_numberOfFullPassMuons]->d0() << std::endl;
668 std::cout <<" sigma_d0 "<< m_pxMSTrack[m_numberOfFullPassMuons]->definingParametersCovMatrixVec()[0] << std::endl;
669 }
670
671 // ID muon
672 const xAOD::TrackParticle* pxIDTrack = pxMuon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
673 if (!pxIDTrack) {
674 if (m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxIDTrack for this muon--> EXIT "<< std::endl;}
675 return;
676 }
678 if (thisdebug) {
679 std::cout <<" * FourMuonEvent * RecordMuon * m_pxIDTrack for this muon--> pt "<< m_pxIDTrack[m_numberOfFullPassMuons]->pt() << std::endl;
680 std::cout <<" d0 "<< m_pxIDTrack[m_numberOfFullPassMuons]->d0() << std::endl;
681 std::cout <<" sigma_d0 "<< m_pxIDTrack[m_numberOfFullPassMuons]->definingParametersCovMatrixVec()[0] << std::endl;
682 }
683 //
686 }
687 // if(m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * completed -- return with a total of " << m_numberOfFullPassMuons << std::endl;}
688 return;
689}
690
691
692//==================================================================================
694{
695 if(m_doDebug){ std::cout << " * FourMuonEvent * ReconstructKinematics * -- start -- " << std::endl; }
696 bool kinematicscomputed = false;
697
698 // Three ways. No checks here. Thus make sure the pointers are ok before this.
699 if ( m_numberOfFullPassMuons == 4 ) {
700 // crosscheck identifiers are good:
701 bool goodidentifiers = true;
702 if (m_muonneg1 < 0) goodidentifiers = false;
703 if (m_muonneg2 < 0) goodidentifiers = false;
704 if (m_muonpos1 < 0) goodidentifiers = false;
705 if (m_muonpos2 < 0) goodidentifiers = false;
706
707 if (goodidentifiers) {
708 // before computing the kinematic parameters check track particles are ok
709 bool goodtracks = true;
710 if (m_pxIDTrack[m_muonneg1] == nullptr) goodtracks = false;
711 if (m_pxIDTrack[m_muonneg2] == nullptr) goodtracks = false;
712 if (m_pxIDTrack[m_muonpos1] == nullptr) goodtracks = false;
713 if (m_pxIDTrack[m_muonpos2] == nullptr) goodtracks = false;
714
719
720 if (goodtracks) { // Everything is ready
722 m_fMuonDispersion[ID] = EvaluateAngle( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
723 m_fZPt[ID] = EvalPt( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
724 m_fZEtaDir[ID] = EvalEta( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
725 m_fZPhiDir[ID] = EvalPhi( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
726
727 kinematicscomputed = true;
728
729 if(m_doDebug){
730 std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- Muon ID Tracks -- new -- " << std::endl
731 << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl
732 << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl
733 << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl
734 << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl
735 << " invariant mass (4mu) = " << m_fInvariantMass[ID] << std::endl
736 << std::endl;
737 }
738
739 } // good tracks
740 } // goodidentifiers
741 } // goodmuons == 4
742
743 if (!kinematicscomputed) {
744 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics * -- FAILED -- " << std::endl; }
745 }
746
747 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics * -- completed -- status: " << kinematicscomputed << std::endl; }
748 return kinematicscomputed;
749}
750
751//==================================================================================
753{
754 if(m_doDebug){ std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- start -- " << std::endl; }
755 bool kinematicscomputed = false;
756
757 // Three ways. No checks here. Thus make sure the pointers are ok before this.
758 if ( m_numberOfFullPassElectrons == 4 ) {
759 // before computing the kinematic parameters check track particles are ok
760 bool goodtracks = true;
761 m_pxELTrack[0] = m_xElecID.GetElecNegTrackParticle(0);
762 m_pxELTrack[1] = m_xElecID.GetElecNegTrackParticle(1);
763 m_pxELTrack[2] = m_xElecID.GetElecPosTrackParticle(0);
764 m_pxELTrack[3] = m_xElecID.GetElecPosTrackParticle(1);
765 if (m_pxELTrack[0] == nullptr) goodtracks = false;
766 if (m_pxELTrack[1] == nullptr) goodtracks = false;
767 if (m_pxELTrack[2] == nullptr) goodtracks = false;
768 if (m_pxELTrack[3] == nullptr) goodtracks = false;
769
770 if (goodtracks) { // Everything is ready
771 // For the time being analysis is performed only with ID tracks
773 m_fMuonDispersion[ID] = EvaluateAngle( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
774 m_fZPt[ID] = EvalPt( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
775 m_fZEtaDir[ID] = EvalEta( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
776 m_fZPhiDir[ID] = EvalPhi( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
777 kinematicscomputed = true;
778
779 if(m_doDebug){
780 std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- Electron Tracks -- " << std::endl
781 << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl
782 << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl
783 << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl
784 << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl
785 << " invariant mass (4e) = " << m_fInvariantMass[ID] << std::endl
786 << std::endl;
787 }
788 } // good tracks
789 } // goodidentifiers
790
791 if (!kinematicscomputed) {
792 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics4Elec * -- FAILED -- " << std::endl; }
793 }
794
795 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics4Elec * -- completed -- status: " << kinematicscomputed << std::endl; }
796 return kinematicscomputed;
797}
798
799//==================================================================================
801{
802 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent * ReconstructKinematicsNew * -- START -- " << endmsg;
803
804 bool kinematicscomputed = false;
805
806 // first step get the list of TrackParticles for muons and electrons
807 // -- muons (a bit more complex than for electrons)
812 // add an extra proteccion
813 if (m_numberOfFullPassMuons < 2) {
814 for (int i=0; i<4; i++) m_pxMUTrack[i] = nullptr;
815 }
816
817 // -- electrons
818 m_pxELTrack[0] = m_xElecID.GetElecNegTrackParticle(0);
819 m_pxELTrack[1] = m_xElecID.GetElecNegTrackParticle(1);
820 m_pxELTrack[2] = m_xElecID.GetElecPosTrackParticle(0);
821 m_pxELTrack[3] = m_xElecID.GetElecPosTrackParticle(1);
822 // add an extra proteccion
824 for (int i=0; i<4; i++) m_pxELTrack[i] = nullptr;
825 }
826
827 if ( m_numberOfFullPassMuons == 4 ) {
828 bool goodtracks = true;
829 if (m_pxMUTrack[0] == nullptr) goodtracks = false;
830 if (m_pxMUTrack[1] == nullptr) goodtracks = false;
831 if (m_pxMUTrack[2] == nullptr) goodtracks = false;
832 if (m_pxMUTrack[3] == nullptr) goodtracks = false;
833
834 if (goodtracks) { // Everything is ready
836 m_fMuonDispersion[ID] = EvaluateAngle ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
837 m_fZPt[ID] = EvalPt ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
838 m_fZEtaDir[ID] = EvalEta ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
839 m_fZPhiDir[ID] = EvalPhi ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
840 kinematicscomputed = true;
841 }
842 }
843
844 if(m_doDebug){
845 std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Muon ID Tracks -- new -- " << std::endl;
846 if (m_pxMUTrack[0] != nullptr) std::cout << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl;
847 if (m_pxMUTrack[1] != nullptr) std::cout << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl;
848 if (m_pxMUTrack[2] != nullptr) std::cout << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl;
849 if (m_pxMUTrack[3] != nullptr) std::cout << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl;
850 if (kinematicscomputed) std::cout << " invariant mass (4mu) = " << m_fInvariantMass[ID] << std::endl;
851 }
852
853 double invmass_test = -1.; // default value
854 if ( m_numberOfFullPassElectrons == 4) {
855 // before computing the kinematic parameters check track particles are ok
856 bool goodtracks = true;
857 if (m_pxELTrack[0] == nullptr) goodtracks = false;
858 if (m_pxELTrack[1] == nullptr) goodtracks = false;
859 if (m_pxELTrack[2] == nullptr) goodtracks = false;
860 if (m_pxELTrack[3] == nullptr) goodtracks = false;
861
862 if (goodtracks && !kinematicscomputed) { // Everything is ready
863 // For the time being analysis is performed only with ID tracks
865 invmass_test = m_fInvariantMass[ID];
866 m_fMuonDispersion[ID] = EvaluateAngle( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
867 m_fZPt[ID] = EvalPt( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
868 m_fZEtaDir[ID] = EvalEta( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
869 m_fZPhiDir[ID] = EvalPhi( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
870 kinematicscomputed = true;
871 } // good tracks
872 }
873 if(m_doDebug){
874 std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Electron Tracks -- " << std::endl;
875 if (m_pxELTrack[0] != nullptr) std::cout << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl;
876 if (m_pxELTrack[1] != nullptr) std::cout << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl;
877 if (m_pxELTrack[2] != nullptr) std::cout << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl;
878 if (m_pxELTrack[3] != nullptr) std::cout << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl;
879 std::cout << " invariant mass (4e) = " << invmass_test << std::endl;
880 }
881
882 if ( m_numberOfFullPassMuons >= 2 && m_numberOfFullPassElectrons >= 2 && !kinematicscomputed) {
883 // before computing the kinematic parameters check track particles are ok
884 bool goodtracks = true;
885 if (m_pxMUTrack[0] == nullptr) goodtracks = false; // leading mu-
886 if (m_pxMUTrack[2] == nullptr) goodtracks = false; // leading mu+
887 if (m_pxELTrack[0] == nullptr) goodtracks = false; // leading e-
888 if (m_pxELTrack[2] == nullptr) goodtracks = false; // leading e+
889
890 if (goodtracks && !kinematicscomputed) { // Everything is ready
891 // For the time being analysis is performed only with ID tracks
893 invmass_test = m_fInvariantMass[ID];
894 m_fMuonDispersion[ID] = EvaluateAngle ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
895 m_fZPt[ID] = EvalPt ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
896 m_fZEtaDir[ID] = EvalEta ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
897 m_fZPhiDir[ID] = EvalPhi ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
898 kinematicscomputed = true;
899 } // good tracks
900 }
901 if(m_doDebug){
902 std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Muon and Electron Tracks -- " << std::endl;
903 if (m_pxMUTrack[0] != nullptr) std::cout << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl;
904 if (m_pxMUTrack[1] != nullptr) std::cout << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl;
905 if (m_pxMUTrack[2] != nullptr) std::cout << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl;
906 if (m_pxMUTrack[3] != nullptr) std::cout << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl;
907 if (m_pxELTrack[0] != nullptr) std::cout << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl;
908 if (m_pxELTrack[1] != nullptr) std::cout << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl;
909 if (m_pxELTrack[2] != nullptr) std::cout << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl;
910 if (m_pxELTrack[3] != nullptr) std::cout << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl;
911 std::cout << " invariant mass used = " << m_fInvariantMass[ID] << std::endl;
912 std::cout << " invariant mass test = " << invmass_test << std::endl;
913 }
914
915 if (!kinematicscomputed) {
916 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematicsNew * -- FAILED -- " << std::endl; }
917 }
918
919 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent * ReconstructKinematicsNew * -- COMPLETED -- status " << kinematicscomputed << endmsg;
920 return kinematicscomputed;
921}
922
923//==================================================================================
925{
926 // First determine what's positive
927 if ( m_numberOfFullPassMuons == 2 )
928 {
929 switch ( eType )
930 {
931 case MS :
932 {
934 }
935 case ME:
936 {
938 }
939 case CB:
940 {
942 }
943 case ID:
944 {
946 }
947 default:
948 return -999.0;
949 }
950 }
951 else
952 {
953 return -999.0;
954 }
955}
956
957//==================================================================================
959{
960 switch ( eType )
961 {
962 case MS :
963 {
964 return ( static_cast<int>( EvalCharge( m_pxMSTrack[m_muon1], m_pxMSTrack[m_muon2] ) ) );
965 }
966 case ME:
967 {
968 return ( static_cast<int>( EvalCharge( m_pxMETrack[m_muon1], m_pxMETrack[m_muon2] ) ) );
969 }
970 case CB:
971 {
972 return ( static_cast<int>( EvalCharge( m_pxRecMuon[m_muon1], m_pxRecMuon[m_muon2] ) ) );
973 }
974 case ID:
975 {
976 return ( static_cast<int>( EvalCharge( m_pxIDTrack[m_muon1], m_pxIDTrack[m_muon2] ) ) );
977 }
978 default:
979 return -999;
980 }
981}
982
983//==================================================================================
984unsigned int FourMuonEvent::getPosMuon( int eType )
985{
986 //if ( getNumberOfTaggedMuons() != 2 ) return 999;
987 //if ( getZCharge(eType) != 0 ) return 999;
988
989 unsigned int muid = m_muonpos1;
990 if (eType==2) muid = m_muonpos2;
991 return muid;
992}
993
994//==================================================================================
995unsigned int FourMuonEvent::getNegMuon( int eType )
996{
997 unsigned int muid = m_muonneg1;
998 if (eType==2) muid = m_muonneg2;
999 return muid;
1000}
1001
1002//==================================================================================
1003const xAOD::TrackParticle* FourMuonEvent::getLooseIDTk( unsigned int /*uPart*/ )
1004{
1005 const xAOD::TrackParticleContainer* pxTrackContainer =
1007
1008 if ( pxTrackContainer )
1009 {
1010 xAOD::TrackParticleContainer::const_iterator xTrkItr = pxTrackContainer->begin();
1011 xAOD::TrackParticleContainer::const_iterator xTrkItrE = pxTrackContainer->end();
1012 while ( xTrkItr != xTrkItrE )
1013 {
1014 const xAOD::TrackParticle* pxTrack = *xTrkItr;
1015 if ( !pxTrack ) continue;
1016 const Trk::Track* pxTrkTrack = pxTrack->track();
1017 if(!pxTrkTrack) continue;
1018 const Trk::Perigee* pxPerigee = pxTrkTrack->perigeeParameters() ;
1019 if ( !pxPerigee ) continue;
1020 const float fTrkPhi = pxPerigee->parameters()[Trk::phi];
1021 const float fTrkEta = pxPerigee->eta();
1022
1023 float fDPhi = fabs( fTrkPhi - m_pxMETrack[m_muon1]->phi() );
1024 float fDEta = fabs( fTrkEta - m_pxMETrack[m_muon2]->eta() );
1025 float fDR = sqrt( fDPhi*fDPhi + fDEta*fDEta );
1026
1027 if ( fDR < 0.3f )
1028 {
1029 return pxTrack;
1030 }
1031
1032 ++xTrkItr;
1033 }
1034 }
1035 // if ()
1036 return nullptr;
1037}
1038
1039//==================================================================================
1041{
1042 // first set the new pt cut value
1043 m_LeadingMuonPtCut = newvalue;
1044
1045 // the second muon pt cut can not be higher than the leading muon pt cut:
1047
1048 // this has to be translated to the MuonSelector
1049 // but there one has to use the minimum momentum --> second muon
1050 //this->SetMuonPtCut(m_SecondMuonPtCut);
1051 if(m_doDebug){
1052 std::cout <<" * FourMuonEvent * SetLeadingMuonPtCut * new Pt cuts: " << m_LeadingMuonPtCut << " & "
1054 << " MuonSelector: " << m_xMuonID.GetPtCut() << std::endl;
1055 }
1056 return;
1057}
1058
1059//==================================================================================
1061{
1062 m_SecondMuonPtCut = newvalue;
1063
1064 // use same for electrons
1065 m_xElecID.SetPtCut(m_SecondMuonPtCut);
1066
1067 // second muon pt shouldn't be higher than the leading muon pt
1069
1070 // this has to be translated to the MuonSelector
1072
1073 if(m_doDebug) {
1074 std::cout <<" * FourMuonEvent * SetSecondMuonPtCut * new Pt cuts: " << m_LeadingMuonPtCut
1075 << " & " << m_SecondMuonPtCut
1076 << " MuonSelector: " << m_xMuonID.GetPtCut() << std::endl;
1077 }
1078
1079 return;
1080}
1081
1082//==================================================================================
1084{
1085 // Salva: 20/January/2020 RecMuon -> IDTrack
1086 constexpr bool thisdebug = false;
1087
1088 if (m_doDebug || thisdebug) {std::cout << " * FourMuonEvent::OrderMuonList * -- start -- " << std::endl
1089 << " #muons: " << m_numberOfFullPassMuons<< std::endl;}
1090
1091 int muPlus1Id = -9;
1092 int muPlus2Id = -9;
1093 int muMinus1Id = -9;
1094 int muMinus2Id = -9;
1095 double muPlus1Pt = 0.;
1096 double muPlus2Pt = 0.;
1097 double muMinus1Pt = 0.;
1098 double muMinus2Pt = 0.;
1099
1100 int muposcount = 0;
1101 int munegcount = 0;
1102
1103 int nMuonsAtEntry = m_numberOfFullPassMuons;
1104 m_numberOfFullPassMuons = 0; // reset the number of full pass muons
1105
1106 if (nMuonsAtEntry >= 2) { // we need at least 2 muons
1107 for (int imuon=0; imuon < (int) nMuonsAtEntry; imuon++) {
1108 if(m_doDebug && false ){ std::cout << " * FourMuonEvent::OrderMuonList * testing imuon= " << imuon
1109 << " with charge= " << m_pxRecMuon[imuon]->charge()
1110 << " and pt= " << m_pxRecMuon[imuon]->pt()
1111 << std::endl;
1112 }
1113 if (m_pxIDTrack[imuon] != nullptr) {
1114
1115 if (m_pxIDTrack[imuon]->charge()==1) { // positive muon
1116 muposcount++;
1117 if (m_pxIDTrack[imuon]->pt()> muPlus1Pt) {
1118 // store 1st in 2nd
1119 muPlus2Pt = muPlus1Pt;
1120 muPlus2Id = muPlus1Id;
1121 // now store the new one in 1st place
1122 muPlus1Pt = m_pxIDTrack[imuon]->pt();
1123 muPlus1Id = imuon;
1124 }
1125 else if (m_pxIDTrack[imuon]->pt()> muPlus2Pt) {
1126 // store the new one in 2nd place
1127 muPlus2Pt = m_pxIDTrack[imuon]->pt();
1128 muPlus2Id = imuon;
1129 }
1130 }
1131 // Negative muons
1132 if (m_pxIDTrack[imuon]->charge()==-1) {
1133 munegcount++;
1134 if(m_pxIDTrack[imuon]->pt()> muMinus1Pt) {
1135 // store 1st in 2nd
1136 muMinus2Pt = muMinus1Pt;
1137 muMinus2Id = muMinus1Id;
1138 muMinus1Pt = m_pxIDTrack[imuon]->pt();
1139 muMinus1Id = imuon;
1140 }
1141 else if(m_pxRecMuon[imuon]->pt()> muMinus2Pt) {
1142 muMinus2Pt = m_pxIDTrack[imuon]->pt();
1143 muMinus2Id = imuon;
1144 }
1145 }
1146 } // muon exist
1147 } // for (int imuon)
1148 } // if (nMuonsAtEntry >= 2)
1149
1150 // require at least one opposite charge muon pair
1151 if (nMuonsAtEntry >= 2 && (muposcount == 0 || munegcount == 0)) {
1152 if (m_doDebug) std::cout << " -- FourMuonEvent::OrderMuonList -- No opposite charge muons in the " << nMuonsAtEntry << " input muons"
1153 << " #mu+ " << muposcount
1154 << " #mu- " << munegcount
1155 << " --> DISCARD ALL MUONS -- \n";
1156 muPlus1Id = -9;
1157 muPlus2Id = -9;
1158 muMinus1Id = -9;
1159 muMinus2Id = -9;
1160 }
1161
1162
1163 if (muPlus1Id>=0) {m_muonpos1 = muPlus1Id; m_numberOfFullPassMuons++;}
1164 if (muPlus2Id>=0) {m_muonpos2 = muPlus2Id; m_numberOfFullPassMuons++;}
1165 if (muMinus1Id>=0) {m_muonneg1 = muMinus1Id; m_numberOfFullPassMuons++;}
1166 if (muMinus2Id>=0) {m_muonneg2 = muMinus2Id; m_numberOfFullPassMuons++;}
1167
1168 m_muon1 = m_muonpos1; // to be deleted when no more m_muon is left
1169 m_muon2 = m_muonneg1; // to be deleted when no more m_muon is left
1170
1171 if ((m_doDebug || thisdebug) && m_numberOfFullPassMuons >= 2){
1172 std::cout << " * FourMuonEvent::OrderMuonList * taking " << m_numberOfFullPassMuons << " muons from the input list of " << nMuonsAtEntry << " muons: " << std::endl;
1173 if (muMinus1Id >= 0) std::cout << " leading mu-: " << muMinus1Id << " Pt = " << muMinus1Pt << std::endl;
1174 if (muMinus2Id >= 0) std::cout << " second mu-: " << muMinus2Id << " Pt = " << muMinus2Pt << std::endl;
1175 if (muPlus1Id >= 0) std::cout << " leading mu+: " << muPlus1Id << " Pt = " << muPlus1Pt << std::endl;
1176 if (muPlus2Id >= 0) std::cout << " second mu+: " << muPlus2Id << " Pt = " << muPlus2Pt << std::endl;
1177 }
1178 else {
1179 if (m_doDebug) std::cout << " * FourMuonEvent::OrderMuonList * This event has less than 2 muons :(" << std::endl;
1180 }
1181
1182 if (m_doDebug || thisdebug) std::cout << " * FourMuonEvent::OrderMuonList * completed * m_numberOfFullPassMuons= " << m_numberOfFullPassMuons << std::endl;
1183 return;
1184}
1185
1188{
1189 (*m_msgStream) << MSG::DEBUG << " * FourMuonsEvents::CheckMuonVertices * -- START --" << endmsg;
1190
1191 bool goodvertices = false;
1192 goodvertices = true; // R22 set true by default. Needs to be revisited
1193 int nverticesfound = 0;
1194
1195 // loop on mu-, and for each mu-, loop on mu+ and check at least one mu+ and mu- come from the same vertex
1196 // mu- indices are 0 or 1
1197 for (unsigned int imuneg = 0; imuneg <= 1; imuneg++) {
1198 if (m_pxMUTrack[imuneg] != nullptr) {
1199 /* R21 SALVA --> vertex is not available in R22 --> A FIX IS NEEDED */
1200 /*
1201 if (m_pxMUTrack[imuneg]->vertex()) {
1202
1203 if (m_doDebug) std::cout << " mu-(" << imuneg <<")->vertex()->v= (" << m_pxMUTrack[imuneg]->vertex()->x()
1204 << ", " << m_pxMUTrack[imuneg]->vertex()->y()
1205 << ", " << m_pxMUTrack[imuneg]->vertex()->z()
1206 << ") " << std::endl;
1207
1208 for (unsigned int imupos = 2; imupos <= 3; imupos++) { // mu+ indices are 2 and 3
1209 if (m_pxMUTrack[imupos] != nullptr) {
1210 if (m_pxMUTrack[imupos]->vertex()) {
1211 if (m_doDebug) std::cout << " mu+(" << imupos <<")->vertex()->v= (" << m_pxMUTrack[imupos]->vertex()->x()
1212 << ", " << m_pxMUTrack[imupos]->vertex()->y()
1213 << ", " << m_pxMUTrack[imupos]->vertex()->z()
1214 << ") " << std::endl;
1215
1216 float delta_x = fabs( m_pxMUTrack[imuneg]->vertex()->x() - m_pxMUTrack[imupos]->vertex()->x());
1217 float delta_y = fabs( m_pxMUTrack[imuneg]->vertex()->y() - m_pxMUTrack[imupos]->vertex()->y());
1218 float delta_z = fabs( m_pxMUTrack[imuneg]->vertex()->z() - m_pxMUTrack[imupos]->vertex()->z());
1219
1220 if (delta_x < m_deltaXYcut && delta_y < m_deltaXYcut && delta_z < m_Z0GapCut) {
1221 nverticesfound++;
1222 if (m_doDebug) std::cout << " MUON-BINGO !!! mu+mu- pair in same vertex !!! mu-[" << imuneg
1223 << "] mu+[" << imupos<< "] count: " << nverticesfound << std::endl;
1224 } // vertex is the same
1225 } // mu+ has vertex
1226 } // mu+ exists
1227 } // loop on mu+
1228 } // mu- has vertex
1229 */
1230 } // mu- exists
1231 } // loop on mu-
1232
1233 if (nverticesfound >= 1) goodvertices = true;
1234
1235 if (nverticesfound == 0) if (m_doDebug) std::cout << " -- FourMuonEvent::CheckMuonVertices -- WARNING -- MUONS DO NOT COME FROM SAME VERTEX " << std::endl;
1236
1237 (*m_msgStream) << MSG::DEBUG << " * FourMuonsEvents::CheckMuonVertices * -- COMPLETED -- status: " << goodvertices << endmsg;
1238 return goodvertices;
1239}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
double charge(const T &p)
Definition AtlasPID.h:997
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
static float EvaluateAngle(const T *pxP1, const T *pxP2)
static float EvalCharge(const T *pxP1, const T *pxP2)
static float EvalPhi(const T *pxP1, const T *pxP2)
static float EvalPtDiff(const T *pxP1, const T *pxP2)
virtual void Init()
static float EvalPt(const T *pxP1, const T *pxP2)
static float EvalFourMuInvMass(const T *pxP1, const T *pxP2, const T *pxP3, const T *pxP4)
static float EvalEta(const T *pxP1, const T *pxP2)
std::string m_xSampleName
const xAOD::TrackParticle * m_pxMETrack[NUM_MUONS]
void SetSecondMuonPtCut(double newvalue)
double m_MassWindowLow
double m_FourMuonInvMass
Arrayf m_fInvariantMass
bool m_passedFourLeptonSelection
void SetLeadingMuonPtCut(double newvalue)
int getZCharge(ZTYPE eType)
MuonSelector m_xMuonID
PerfMonServices::CONTAINERS m_container
virtual ~FourMuonEvent()
int m_muon_vtx[NUM_MUONS]
bool m_passedFourElectronSelection
bool ReconstructKinematics4Elec()
int m_elec_vtx[NUM_MUONS]
bool ReconstructKinematics()
bool m_workAsFourElectrons
double m_SecondMuonPtCut
double m_MassWindowHigh
MsgStream * m_msgStream
void SetMuonPtCut(double newvalue)
const xAOD::TrackParticle * m_pxIDTrack[NUM_MUONS]
bool EventSelection(ZTYPE eType)
const xAOD::TrackParticle * m_pxMUTrack[NUM_MUONS]
double m_LeadingMuonPtCut
ElectronSelector m_xElecID
unsigned int m_uMuonTags
bool m_passedFourMuonSelection
bool ReconstructKinematicsNew()
bool m_passedSelectionCuts
void RecordMuon(const xAOD::Muon *pxMuon)
const xAOD::TrackParticle * m_pxELTrack[NUM_MUONS]
Arrayf m_fMuonDispersion
float getPtImbalance(ZTYPE eType)
unsigned int getPosMuon(int eType)
unsigned int m_numberOfFullPassElectrons
const xAOD::Muon * m_pxRecMuon[NUM_MUONS]
unsigned int getNegMuon(int eType)
const xAOD::TrackParticle * m_pxMSTrack[NUM_MUONS]
const xAOD::TrackParticle * getLooseIDTk(unsigned int uPart)
bool EventSelectionNew(ZTYPE eType)
unsigned int m_numberOfFullPassMuons
static const T * getContainer(CONTAINERS eContainer)
static const std::string & getContainerName(CONTAINERS eContainer)
double eta() const
Access method for pseudorapidity - from momentum.
const Perigee * perigeeParameters() const
return Perigee.
const TrackParticle * trackParticle(TrackParticleType type) const
Returns a pointer (which can be a nullptr) to the TrackParticle used in identification of this muon.
Definition Muon_v1.cxx:422
const Trk::Track * track() const
Returns a pointer (which can be NULL) to the Trk::Track which was used to make this TrackParticle.
singleton-like access to IMessageSvc via open function and helper
IMessageSvc * getMessageSvc(bool quiet=false)
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ phi
Definition ParamDefs.h:75
ElectronContainer_v1 ElectronContainer
Definition of the current "electron container version".
TrackParticle_v1 TrackParticle
Reference the current persistent version:
TrackParticleContainer_v1 TrackParticleContainer
Definition of the current "TrackParticle container version".
Muon_v1 Muon
Reference the current persistent version:
MuonContainer_v1 MuonContainer
Definition of the current "Muon container version".