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 // noVertexCountMuon is zero here
389 if (m_doDebug || true) {
390 std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices ID of the muons = " << std::endl
391 << " mu- 1 " << m_muon_vtx[0] << " pt: " << m_pxMUTrack[0]->pt() << std::endl
392 << " mu- 2 " << m_muon_vtx[1] << " pt: " << m_pxMUTrack[1]->pt() << std::endl
393 << " mu+ 1 " << m_muon_vtx[2] << " pt: " << m_pxMUTrack[2]->pt() << std::endl
394 << " mu+ 2 " << m_muon_vtx[3] << " pt: " << m_pxMUTrack[3]->pt()
395 << std::endl;
396 } // end debug
397 } // end m_workAsFourMuons
398
399 if ( m_workAsFourElectrons ) { // till here we have the electrons vertices list
400 m_nVertex = vtxListX.size();
401 if (vtxListX.size()>0) vertexstatus = true;
402 // vertexstatus value is overwritten before use if it is set here
403
404 std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices ID of the electrons = "
405 << "\n el- 1 " << m_elec_vtx[0] << " pt: " << m_pxELTrack[0]->pt() << std::endl
406 << "\n el- 2 " << m_elec_vtx[1] << " pt: " << m_pxELTrack[1]->pt() << std::endl
407 << "\n el+ 1 " << m_elec_vtx[2] << " pt: " << m_pxELTrack[2]->pt() << std::endl
408 << "\n el+ 2 " << m_elec_vtx[3] << " pt: " << m_pxELTrack[3]->pt() <<"\n";
409 }
410
411 if ( m_workAsFourLeptons ) { // till here we have the muons and electrons vertices list
412 m_nVertex = vtxListX.size();
413 if (vtxListX.size()>0) vertexstatus = true;
414 // check that the electrons are not split into too many vertices
415 // if (vtxListX.size() >= m_numberOfFullPassElectrons - 1) vertexstatus = false;
416 // and allow no electron without vertex
417 if (m_doDebug) {
418 std::cout << " * FourMuonEvent::EventSelection(" << eType <<") * vertices in event = " << vtxListX.size() << std::endl;
419 for (size_t imu=0; imu < NUM_MUONS; imu++) {
420 if (m_pxMUTrack[imu]) std::cout << " mu " << m_muon_vtx[imu] << " pt: " << m_pxMUTrack[imu]->pt() << std::endl;
421 }
422 for (size_t iel=0; iel < NUM_MUONS; iel++) {
423 if (m_pxELTrack[iel]) std::cout << " el " << m_elec_vtx[iel] << " pt: " << m_pxELTrack[iel]->pt() << std::endl;
424 }
425 }
426 }
427
428 vertexstatus = true; // Temporary fix to work on R22
429
430 if(m_doDebug) {
431 std::cout <<" * FourMuonEvent::EventSelection(" << eType <<") * Number of vertex found = " << vtxListX.size()
432 << " and mu without vertex: " << noVertexCountMuon
433 << " and elec without vertex: " << noVertexCountElec << std::endl;
434 for (unsigned int ivtx=0; ivtx < vtxListX.size(); ivtx++) {
435 std::cout << " vtx[" << ivtx << "]= "
436 << "( " << vtxListX.at(ivtx)
437 << ", " << vtxListY.at(ivtx)
438 << ", " << vtxListZ.at(ivtx)
439 << ") nparticles: " << vtxNpart.at(ivtx)
440 << std::endl;
441 }
442 }
443
444
445 eventisgood = vertexstatus;
446 }
447
448 //
449 if(m_doDebug){ std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") ** completed ** result= " << eventisgood << std::endl;}
450
451 m_doDebug = inputdebug;
452
453 return eventisgood;
454}
455//==================================================================================
457{
458 if(m_doDebug){ std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") ** started ** " << std::endl
459 << " event count: " << m_eventCount << std::endl
460 << " m_NumberOfFullPassMuons: " << m_numberOfFullPassMuons << std::endl
461 << " m_NumberOfFullPassElectrons: " << m_numberOfFullPassElectrons
462 << std::endl;
463 }
464
465 // First require two muon-id's with cuts pre-applied.
467 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Failing number of good muons and electrons == 4 :( "
469 << " = " << m_numberOfFullPassMuons << " + " << m_numberOfFullPassElectrons << std::endl;}
470 return false;
471 }
472
473 if ( m_numberOfFullPassMuons > 4 ) {
474 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Too many muons !! Failing number of good muons == 4 :( "
475 << m_numberOfFullPassMuons << std::endl;}
476 return false;
477 }
478
479 if ( m_numberOfFullPassElectrons > 4 ) {
480 if(m_doDebug) {std::cout <<" * FourMuonEvent::EventSelection(" << eType << ") * Too many electrons !! Failing number of good electrons == 4 :( "
481 << m_numberOfFullPassElectrons << std::endl;}
482 return false;
483 }
484
485 // momentum of the muons
486 double leadingMuonPt = -1., secondMuonPt=-1., thirdMuonPt=-1, fourthMuonPt=-1.; // negative pt, means not computed yet
487 switch ( eType ) {
488 case MS :
489 {
490 if (m_muonpos1 >= 0) leadingMuonPt = m_pxMSTrack[m_muonpos1]->pt();
491 if (m_muonpos2 >= 0) secondMuonPt = m_pxMSTrack[m_muonpos2]->pt();
492 if (m_muonneg1 >= 0) thirdMuonPt = m_pxMSTrack[m_muonneg1]->pt();
493 if (m_muonneg2 >= 0) fourthMuonPt = m_pxMSTrack[m_muonneg2]->pt();
494 break;
495 }
496 case ME:
497 {
498 if (m_muonpos1 >= 0) leadingMuonPt = m_pxMETrack[m_muonpos1]->pt();
499 if (m_muonpos2 >= 0) secondMuonPt = m_pxMETrack[m_muonpos2]->pt();
500 if (m_muonneg1 >= 0) thirdMuonPt = m_pxMETrack[m_muonneg1]->pt();
501 if (m_muonneg2 >= 0) fourthMuonPt = m_pxMETrack[m_muonneg2]->pt();
502 break;
503 }
504 case CB:
505 {
506 if (m_muonpos1 >= 0) leadingMuonPt = m_pxRecMuon[m_muonpos1]->pt();
507 if (m_muonpos2 >= 0) secondMuonPt = m_pxRecMuon[m_muonpos2]->pt();
508 if (m_muonneg1 >= 0) thirdMuonPt = m_pxRecMuon[m_muonneg1]->pt();
509 if (m_muonneg2 >= 0) fourthMuonPt = m_pxRecMuon[m_muonneg2]->pt();
510 break;
511 }
512 case ID:
513 {
514 if (m_muonpos1 >= 0) leadingMuonPt = m_pxIDTrack[m_muonpos1]->pt();
515 if (m_muonpos2 >= 0) secondMuonPt = m_pxIDTrack[m_muonpos2]->pt();
516 if (m_muonneg1 >= 0) thirdMuonPt = m_pxIDTrack[m_muonneg1]->pt();
517 if (m_muonneg2 >= 0) fourthMuonPt = m_pxIDTrack[m_muonneg2]->pt();
518 break;
519 }
520
521 default:
522 if (m_muonpos1 >= 0) leadingMuonPt = m_pxIDTrack[m_muonpos1]->pt();
523 if (m_muonpos2 >= 0) secondMuonPt = m_pxIDTrack[m_muonpos2]->pt();
524 if (m_muonneg1 >= 0) thirdMuonPt = m_pxIDTrack[m_muonneg1]->pt();
525 if (m_muonneg2 >= 0) fourthMuonPt = m_pxIDTrack[m_muonneg2]->pt();
526 } // end switch
527
528 // up to here the leading and second pt are not really in the right order.
529 // order the muon pt:
530 double theLeadingPt = leadingMuonPt;
531 if (secondMuonPt > theLeadingPt) { theLeadingPt = secondMuonPt;}
532 if (thirdMuonPt > theLeadingPt) { theLeadingPt = thirdMuonPt;}
533 if (fourthMuonPt > theLeadingPt) { theLeadingPt = fourthMuonPt;}
534
535 double theTrailingPt = leadingMuonPt;
536 if (secondMuonPt < theTrailingPt && secondMuonPt > 0) { theTrailingPt = secondMuonPt;}
537 if (thirdMuonPt < theTrailingPt && thirdMuonPt > 0) { theTrailingPt = thirdMuonPt;}
538 if (fourthMuonPt < theTrailingPt && fourthMuonPt > 0) { theTrailingPt = fourthMuonPt;}
539
540 if (m_doDebug || true) {
541 std::cout << " * FourMuonEvent::EventSelection * muon pt selection -- cuts: Leading: " << m_LeadingMuonPtCut*CLHEP::GeV << std::endl
542 << " 2nd: " << m_SecondMuonPtCut*CLHEP::GeV << std::endl;
543 std::cout << " Pt of muons in this event 1: " << leadingMuonPt << std::endl
544 << " 2: " << secondMuonPt << std::endl
545 << " 3: " << thirdMuonPt << std::endl
546 << " 4: " << fourthMuonPt << std::endl
547 << " leading Pt: " << theLeadingPt << std::endl
548 << " trailing Pt: " << theTrailingPt << std::endl;
549 }
550
551 // muon pt cut
552 if ( !(theLeadingPt > m_LeadingMuonPtCut*CLHEP::GeV && theTrailingPt > m_SecondMuonPtCut*CLHEP::GeV ) ) {
553 if(m_doDebug){
554 std::cout <<" * FourMuonEvent::EventSelection * Failing pt cut * Reco Pt: leading " << theLeadingPt << " --> trailing " << theTrailingPt << std::endl;
555 }
556 return false;
557 }
558 if(m_doDebug){
559 std::cout << " * FourMuonEvent::EventSelection * Event passed the pt cuts: leading muon pt: " << leadingMuonPt << std::endl;
560 std::cout << " trailing muon pt: " << theTrailingPt << std::endl;
561 }
562
563 const auto invariantMass = m_fInvariantMass.at(eType);
564 // Invariant mass window
565 if ( invariantMass < m_MassWindowLow ) {
566 if(m_doDebug) {
567 std::cout <<" * FourMuonEvent::EventSelection * Failing mass window low cut: reco m= " << invariantMass << " > " << m_MassWindowLow << std::endl;
568 }
569 return false;
570 }
571 if ( invariantMass > m_MassWindowHigh ) {
572 if(m_doDebug) {
573 std::cout <<" * FourMuonEvent * Failing mass window high cut: reco m= " << invariantMass << " > " << m_MassWindowHigh << std::endl;
574 }
575 return false;
576 }
577 if(m_doDebug){
578 std::cout <<" * FourMuonEvent::EventSelection * Event passed the mass window: " << invariantMass << std::endl;
579 }
580
581 if(m_doDebug) {
582 std::cout << " * FourMuonEvent::EventSelection( type= " << eType << ")* Good 4-muon set: pt range from " << leadingMuonPt/1000
583 << " to " << secondMuonPt/1000
584 << " GeV 4-muon invariant mass = " << m_fInvariantMass.at(eType) << " GeV \n";
585 std::cout << " * FourMuonEvent::EventSelection( type= " << eType << ")* completed * \n";
586 }
587 return true;
588}
589
590//==================================================================================
592{
595 m_passedSelectionCuts = false;
599
600
601 m_FourMuonInvMass = -1.; // flag as no reconstructed inv mass yet
602 m_muon1 = MUON1; // point to the first two
603 m_muon2 = MUON2;
604 m_muonneg1 = -1;
605 m_muonneg2 = -1;
606 m_muonpos1 = -1;
607 m_muonpos2 = -1;
608
609
610 for ( unsigned int u = 0; u < NUM_MUONS; ++u ) {
611 m_pxRecMuon[u] = nullptr;
612 m_pxMSTrack[u] = nullptr;
613 m_pxMETrack[u] = nullptr;
614 m_pxIDTrack[u] = nullptr;
615 m_pxMUTrack[u] = nullptr;
616 m_pxELTrack[u] = nullptr;
617 }
618 for ( unsigned int v = 0; v < NUM_TYPES; ++v ) {
619 m_fZPt[v] = -999.9f;
620 m_fZEtaDir[v] = -999.9f;
621 m_fZPhiDir[v] = -999.9f;
622 m_fInvariantMass[v] = -999.9f;
623 m_fMuonDispersion[v] = -999.9f;
624 }
625
626 // tell us to which vertex the muons are associated
627 m_nVertex = 0; // reset vertex count
628 m_muonneg1_vtx = 0;
629 m_muonneg2_vtx = 0;
630 m_muonpos1_vtx = 0;
631 m_muonpos2_vtx = 0;
632
633 for (size_t i=0; i < NUM_MUONS; i++) m_muon_vtx[i] = 0; // reset the vertex ID to which the electrons are associated
634 for (size_t i=0; i < NUM_MUONS; i++) m_elec_vtx[i] = 0; // reset the vertex ID to which the electrons are associated
635 return;
636}
637
638//==================================================================================
640{
641 constexpr bool thisdebug = false;
642 // This shouldn't really ever happen but just in case.
643 if ( !pxMuon ) {
644 if(m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxMuon --> EXIT "<< std::endl;}
645 return;
646 }
647
649 // The main Muon
651 if (thisdebug) {
652 std::cout <<" * FourMuonEvent * RecordMuon * m_pxRecMuon for this muon--> pt "<< m_pxRecMuon[m_numberOfFullPassMuons]->pt() << std::endl;
653 std::cout <<" d0 "<< m_pxRecMuon[m_numberOfFullPassMuons]->trackParticle(xAOD::Muon::TrackParticleType::Primary)->d0() << std::endl;
654 std::cout <<" sigma_d0 "<< m_pxRecMuon[m_numberOfFullPassMuons]->trackParticle(xAOD::Muon::TrackParticleType::Primary)->definingParametersCovMatrixVec()[0] << std::endl;
655 }
656
657 const xAOD::TrackParticle* pxMSTrack = pxMuon->trackParticle(xAOD::Muon::TrackParticleType::MuonSpectrometerTrackParticle);
658 if (!pxMSTrack) {
659 if (m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxMSmuon --> EXIT "<< std::endl;}
660 return;
661 }
663 if (thisdebug) {
664 std::cout <<" * FourMuonEvent * RecordMuon * m_pxMSTrack for this muon--> pt "<< m_pxMSTrack[m_numberOfFullPassMuons]->pt() << std::endl;
665 std::cout <<" d0 "<< m_pxMSTrack[m_numberOfFullPassMuons]->d0() << std::endl;
666 std::cout <<" sigma_d0 "<< m_pxMSTrack[m_numberOfFullPassMuons]->definingParametersCovMatrixVec()[0] << std::endl;
667 }
668
669 // ID muon
670 const xAOD::TrackParticle* pxIDTrack = pxMuon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
671 if (!pxIDTrack) {
672 if (m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * bad pxIDTrack for this muon--> EXIT "<< std::endl;}
673 return;
674 }
676 if (thisdebug) {
677 std::cout <<" * FourMuonEvent * RecordMuon * m_pxIDTrack for this muon--> pt "<< m_pxIDTrack[m_numberOfFullPassMuons]->pt() << std::endl;
678 std::cout <<" d0 "<< m_pxIDTrack[m_numberOfFullPassMuons]->d0() << std::endl;
679 std::cout <<" sigma_d0 "<< m_pxIDTrack[m_numberOfFullPassMuons]->definingParametersCovMatrixVec()[0] << std::endl;
680 }
681 //
684 }
685 // if(m_doDebug){ std::cout <<" * FourMuonEvent * RecordMuon * completed -- return with a total of " << m_numberOfFullPassMuons << std::endl;}
686 return;
687}
688
689
690//==================================================================================
692{
693 if(m_doDebug){ std::cout << " * FourMuonEvent * ReconstructKinematics * -- start -- " << std::endl; }
694 bool kinematicscomputed = false;
695
696 // Three ways. No checks here. Thus make sure the pointers are ok before this.
697 if ( m_numberOfFullPassMuons == 4 ) {
698 // crosscheck identifiers are good:
699 bool goodidentifiers = true;
700 if (m_muonneg1 < 0) goodidentifiers = false;
701 if (m_muonneg2 < 0) goodidentifiers = false;
702 if (m_muonpos1 < 0) goodidentifiers = false;
703 if (m_muonpos2 < 0) goodidentifiers = false;
704
705 if (goodidentifiers) {
706 // before computing the kinematic parameters check track particles are ok
707 bool goodtracks = true;
708 if (m_pxIDTrack[m_muonneg1] == nullptr) goodtracks = false;
709 if (m_pxIDTrack[m_muonneg2] == nullptr) goodtracks = false;
710 if (m_pxIDTrack[m_muonpos1] == nullptr) goodtracks = false;
711 if (m_pxIDTrack[m_muonpos2] == nullptr) goodtracks = false;
712
717
718 if (goodtracks) { // Everything is ready
720 m_fMuonDispersion[ID] = EvaluateAngle( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
721 m_fZPt[ID] = EvalPt( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
722 m_fZEtaDir[ID] = EvalEta( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
723 m_fZPhiDir[ID] = EvalPhi( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
724
725 kinematicscomputed = true;
726
727 if(m_doDebug){
728 std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- Muon ID Tracks -- new -- " << std::endl
729 << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl
730 << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl
731 << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl
732 << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl
733 << " invariant mass (4mu) = " << m_fInvariantMass[ID] << std::endl
734 << std::endl;
735 }
736
737 } // good tracks
738 } // goodidentifiers
739 } // goodmuons == 4
740
741 if (!kinematicscomputed) {
742 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics * -- FAILED -- " << std::endl; }
743 }
744
745 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics * -- completed -- status: " << kinematicscomputed << std::endl; }
746 return kinematicscomputed;
747}
748
749//==================================================================================
751{
752 if(m_doDebug){ std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- start -- " << std::endl; }
753 bool kinematicscomputed = false;
754
755 // Three ways. No checks here. Thus make sure the pointers are ok before this.
756 if ( m_numberOfFullPassElectrons == 4 ) {
757 // before computing the kinematic parameters check track particles are ok
758 bool goodtracks = true;
759 m_pxELTrack[0] = m_xElecID.GetElecNegTrackParticle(0);
760 m_pxELTrack[1] = m_xElecID.GetElecNegTrackParticle(1);
761 m_pxELTrack[2] = m_xElecID.GetElecPosTrackParticle(0);
762 m_pxELTrack[3] = m_xElecID.GetElecPosTrackParticle(1);
763 if (m_pxELTrack[0] == nullptr) goodtracks = false;
764 if (m_pxELTrack[1] == nullptr) goodtracks = false;
765 if (m_pxELTrack[2] == nullptr) goodtracks = false;
766 if (m_pxELTrack[3] == nullptr) goodtracks = false;
767
768 if (goodtracks) { // Everything is ready
769 // For the time being analysis is performed only with ID tracks
771 m_fMuonDispersion[ID] = EvaluateAngle( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
772 m_fZPt[ID] = EvalPt( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
773 m_fZEtaDir[ID] = EvalEta( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
774 m_fZPhiDir[ID] = EvalPhi( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
775 kinematicscomputed = true;
776
777 if(m_doDebug){
778 std::cout << " * FourMuonEvent * ReconstructKinematics4Elec * -- Electron Tracks -- " << std::endl
779 << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl
780 << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl
781 << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl
782 << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl
783 << " invariant mass (4e) = " << m_fInvariantMass[ID] << std::endl
784 << std::endl;
785 }
786 } // good tracks
787 } // goodidentifiers
788
789 if (!kinematicscomputed) {
790 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics4Elec * -- FAILED -- " << std::endl; }
791 }
792
793 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematics4Elec * -- completed -- status: " << kinematicscomputed << std::endl; }
794 return kinematicscomputed;
795}
796
797//==================================================================================
799{
800 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent * ReconstructKinematicsNew * -- START -- " << endmsg;
801
802 bool kinematicscomputed = false;
803
804 // first step get the list of TrackParticles for muons and electrons
805 // -- muons (a bit more complex than for electrons)
810 // add an extra proteccion
811 if (m_numberOfFullPassMuons < 2) {
812 for (int i=0; i<4; i++) m_pxMUTrack[i] = nullptr;
813 }
814
815 // -- electrons
816 m_pxELTrack[0] = m_xElecID.GetElecNegTrackParticle(0);
817 m_pxELTrack[1] = m_xElecID.GetElecNegTrackParticle(1);
818 m_pxELTrack[2] = m_xElecID.GetElecPosTrackParticle(0);
819 m_pxELTrack[3] = m_xElecID.GetElecPosTrackParticle(1);
820 // add an extra proteccion
822 for (int i=0; i<4; i++) m_pxELTrack[i] = nullptr;
823 }
824
825 if ( m_numberOfFullPassMuons == 4 ) {
826 bool goodtracks = true;
827 if (m_pxMUTrack[0] == nullptr) goodtracks = false;
828 if (m_pxMUTrack[1] == nullptr) goodtracks = false;
829 if (m_pxMUTrack[2] == nullptr) goodtracks = false;
830 if (m_pxMUTrack[3] == nullptr) goodtracks = false;
831
832 if (goodtracks) { // Everything is ready
834 m_fMuonDispersion[ID] = EvaluateAngle ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
835 m_fZPt[ID] = EvalPt ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
836 m_fZEtaDir[ID] = EvalEta ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
837 m_fZPhiDir[ID] = EvalPhi ( m_pxMUTrack[0], m_pxMUTrack[2]); // leading mu- and leading mu+
838 kinematicscomputed = true;
839 }
840 }
841
842 if(m_doDebug){
843 std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Muon ID Tracks -- new -- " << std::endl;
844 if (m_pxMUTrack[0] != nullptr) std::cout << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl;
845 if (m_pxMUTrack[1] != nullptr) std::cout << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl;
846 if (m_pxMUTrack[2] != nullptr) std::cout << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl;
847 if (m_pxMUTrack[3] != nullptr) std::cout << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl;
848 if (kinematicscomputed) std::cout << " invariant mass (4mu) = " << m_fInvariantMass[ID] << std::endl;
849 }
850
851 double invmass_test = -1.; // default value
852 if ( m_numberOfFullPassElectrons == 4) {
853 // before computing the kinematic parameters check track particles are ok
854 bool goodtracks = true;
855 if (m_pxELTrack[0] == nullptr) goodtracks = false;
856 if (m_pxELTrack[1] == nullptr) goodtracks = false;
857 if (m_pxELTrack[2] == nullptr) goodtracks = false;
858 if (m_pxELTrack[3] == nullptr) goodtracks = false;
859
860 if (goodtracks && !kinematicscomputed) { // Everything is ready
861 // For the time being analysis is performed only with ID tracks
863 invmass_test = m_fInvariantMass[ID];
864 m_fMuonDispersion[ID] = EvaluateAngle( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
865 m_fZPt[ID] = EvalPt( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
866 m_fZEtaDir[ID] = EvalEta( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
867 m_fZPhiDir[ID] = EvalPhi( m_pxELTrack[0], m_pxELTrack[2]); // leading e- and leading e+
868 kinematicscomputed = true;
869 } // good tracks
870 }
871 if(m_doDebug){
872 std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Electron Tracks -- " << std::endl;
873 if (m_pxELTrack[0] != nullptr) std::cout << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl;
874 if (m_pxELTrack[1] != nullptr) std::cout << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl;
875 if (m_pxELTrack[2] != nullptr) std::cout << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl;
876 if (m_pxELTrack[3] != nullptr) std::cout << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl;
877 std::cout << " invariant mass (4e) = " << invmass_test << std::endl;
878 }
879
880 if ( m_numberOfFullPassMuons >= 2 && m_numberOfFullPassElectrons >= 2 && !kinematicscomputed) {
881 // before computing the kinematic parameters check track particles are ok
882 bool goodtracks = true;
883 if (m_pxMUTrack[0] == nullptr) goodtracks = false; // leading mu-
884 if (m_pxMUTrack[2] == nullptr) goodtracks = false; // leading mu+
885 if (m_pxELTrack[0] == nullptr) goodtracks = false; // leading e-
886 if (m_pxELTrack[2] == nullptr) goodtracks = false; // leading e+
887
888 if (goodtracks && !kinematicscomputed) { // Everything is ready
889 // For the time being analysis is performed only with ID tracks
891 invmass_test = m_fInvariantMass[ID];
892 m_fMuonDispersion[ID] = EvaluateAngle ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
893 m_fZPt[ID] = EvalPt ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
894 m_fZEtaDir[ID] = EvalEta ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
895 m_fZPhiDir[ID] = EvalPhi ( m_pxMUTrack[0], m_pxELTrack[0]); // leading mu- and leading e-
896 kinematicscomputed = true;
897 } // good tracks
898 }
899 if(m_doDebug){
900 std::cout << " * FourMuonEvent * ReconstructKinematicsNew * -- Muon and Electron Tracks -- " << std::endl;
901 if (m_pxMUTrack[0] != nullptr) std::cout << " Pt(mu1-)= " << m_pxMUTrack[0]->pt() << std::endl;
902 if (m_pxMUTrack[1] != nullptr) std::cout << " Pt(mu2-)= " << m_pxMUTrack[1]->pt() << std::endl;
903 if (m_pxMUTrack[2] != nullptr) std::cout << " Pt(mu1+)= " << m_pxMUTrack[2]->pt() << std::endl;
904 if (m_pxMUTrack[3] != nullptr) std::cout << " Pt(mu2+)= " << m_pxMUTrack[3]->pt() << std::endl;
905 if (m_pxELTrack[0] != nullptr) std::cout << " Pt(e1-)= " << m_pxELTrack[0]->pt() << std::endl;
906 if (m_pxELTrack[1] != nullptr) std::cout << " Pt(e2-)= " << m_pxELTrack[1]->pt() << std::endl;
907 if (m_pxELTrack[2] != nullptr) std::cout << " Pt(e1+)= " << m_pxELTrack[2]->pt() << std::endl;
908 if (m_pxELTrack[3] != nullptr) std::cout << " Pt(e2+)= " << m_pxELTrack[3]->pt() << std::endl;
909 std::cout << " invariant mass used = " << m_fInvariantMass[ID] << std::endl;
910 std::cout << " invariant mass test = " << invmass_test << std::endl;
911 }
912
913 if (!kinematicscomputed) {
914 if(m_doDebug){ std::cout <<" * FourMuonEvent * ReconstructKinematicsNew * -- FAILED -- " << std::endl; }
915 }
916
917 (*m_msgStream) << MSG::DEBUG << " * FourMuonEvent * ReconstructKinematicsNew * -- COMPLETED -- status " << kinematicscomputed << endmsg;
918 return kinematicscomputed;
919}
920
921//==================================================================================
923{
924 // First determine what's positive
925 if ( m_numberOfFullPassMuons == 2 )
926 {
927 switch ( eType )
928 {
929 case MS :
930 {
932 }
933 case ME:
934 {
936 }
937 case CB:
938 {
940 }
941 case ID:
942 {
944 }
945 default:
946 return -999.0;
947 }
948 }
949 else
950 {
951 return -999.0;
952 }
953}
954
955//==================================================================================
957{
958 switch ( eType )
959 {
960 case MS :
961 {
962 return ( static_cast<int>( EvalCharge( m_pxMSTrack[m_muon1], m_pxMSTrack[m_muon2] ) ) );
963 }
964 case ME:
965 {
966 return ( static_cast<int>( EvalCharge( m_pxMETrack[m_muon1], m_pxMETrack[m_muon2] ) ) );
967 }
968 case CB:
969 {
970 return ( static_cast<int>( EvalCharge( m_pxRecMuon[m_muon1], m_pxRecMuon[m_muon2] ) ) );
971 }
972 case ID:
973 {
974 return ( static_cast<int>( EvalCharge( m_pxIDTrack[m_muon1], m_pxIDTrack[m_muon2] ) ) );
975 }
976 default:
977 return -999;
978 }
979}
980
981//==================================================================================
982unsigned int FourMuonEvent::getPosMuon( int eType )
983{
984 //if ( getNumberOfTaggedMuons() != 2 ) return 999;
985 //if ( getZCharge(eType) != 0 ) return 999;
986
987 unsigned int muid = m_muonpos1;
988 if (eType==2) muid = m_muonpos2;
989 return muid;
990}
991
992//==================================================================================
993unsigned int FourMuonEvent::getNegMuon( int eType )
994{
995 unsigned int muid = m_muonneg1;
996 if (eType==2) muid = m_muonneg2;
997 return muid;
998}
999
1000//==================================================================================
1001const xAOD::TrackParticle* FourMuonEvent::getLooseIDTk( unsigned int /*uPart*/ )
1002{
1003 const xAOD::TrackParticleContainer* pxTrackContainer =
1005
1006 if ( pxTrackContainer )
1007 {
1008 xAOD::TrackParticleContainer::const_iterator xTrkItr = pxTrackContainer->begin();
1009 xAOD::TrackParticleContainer::const_iterator xTrkItrE = pxTrackContainer->end();
1010 while ( xTrkItr != xTrkItrE )
1011 {
1012 const xAOD::TrackParticle* pxTrack = *xTrkItr;
1013 if ( !pxTrack ) continue;
1014 const Trk::Track* pxTrkTrack = pxTrack->track();
1015 if(!pxTrkTrack) continue;
1016 const Trk::Perigee* pxPerigee = pxTrkTrack->perigeeParameters() ;
1017 if ( !pxPerigee ) continue;
1018 const float fTrkPhi = pxPerigee->parameters()[Trk::phi];
1019 const float fTrkEta = pxPerigee->eta();
1020
1021 float fDPhi = fabs( fTrkPhi - m_pxMETrack[m_muon1]->phi() );
1022 float fDEta = fabs( fTrkEta - m_pxMETrack[m_muon2]->eta() );
1023 float fDR = sqrt( fDPhi*fDPhi + fDEta*fDEta );
1024
1025 if ( fDR < 0.3f )
1026 {
1027 return pxTrack;
1028 }
1029
1030 ++xTrkItr;
1031 }
1032 }
1033 // if ()
1034 return nullptr;
1035}
1036
1037//==================================================================================
1039{
1040 // first set the new pt cut value
1041 m_LeadingMuonPtCut = newvalue;
1042
1043 // the second muon pt cut can not be higher than the leading muon pt cut:
1045
1046 // this has to be translated to the MuonSelector
1047 // but there one has to use the minimum momentum --> second muon
1048 //this->SetMuonPtCut(m_SecondMuonPtCut);
1049 if(m_doDebug){
1050 std::cout <<" * FourMuonEvent * SetLeadingMuonPtCut * new Pt cuts: " << m_LeadingMuonPtCut << " & "
1052 << " MuonSelector: " << m_xMuonID.GetPtCut() << std::endl;
1053 }
1054 return;
1055}
1056
1057//==================================================================================
1059{
1060 m_SecondMuonPtCut = newvalue;
1061
1062 // use same for electrons
1063 m_xElecID.SetPtCut(m_SecondMuonPtCut);
1064
1065 // second muon pt shouldn't be higher than the leading muon pt
1067
1068 // this has to be translated to the MuonSelector
1070
1071 if(m_doDebug) {
1072 std::cout <<" * FourMuonEvent * SetSecondMuonPtCut * new Pt cuts: " << m_LeadingMuonPtCut
1073 << " & " << m_SecondMuonPtCut
1074 << " MuonSelector: " << m_xMuonID.GetPtCut() << std::endl;
1075 }
1076
1077 return;
1078}
1079
1080//==================================================================================
1082{
1083 // Salva: 20/January/2020 RecMuon -> IDTrack
1084 constexpr bool thisdebug = false;
1085
1086 if (m_doDebug || thisdebug) {std::cout << " * FourMuonEvent::OrderMuonList * -- start -- " << std::endl
1087 << " #muons: " << m_numberOfFullPassMuons<< std::endl;}
1088
1089 int muPlus1Id = -9;
1090 int muPlus2Id = -9;
1091 int muMinus1Id = -9;
1092 int muMinus2Id = -9;
1093 double muPlus1Pt = 0.;
1094 double muPlus2Pt = 0.;
1095 double muMinus1Pt = 0.;
1096 double muMinus2Pt = 0.;
1097
1098 int muposcount = 0;
1099 int munegcount = 0;
1100
1101 int nMuonsAtEntry = m_numberOfFullPassMuons;
1102 m_numberOfFullPassMuons = 0; // reset the number of full pass muons
1103
1104 if (nMuonsAtEntry >= 2) { // we need at least 2 muons
1105 for (int imuon=0; imuon < (int) nMuonsAtEntry; imuon++) {
1106 if(m_doDebug && false ){ std::cout << " * FourMuonEvent::OrderMuonList * testing imuon= " << imuon
1107 << " with charge= " << m_pxRecMuon[imuon]->charge()
1108 << " and pt= " << m_pxRecMuon[imuon]->pt()
1109 << std::endl;
1110 }
1111 if (m_pxIDTrack[imuon] != nullptr) {
1112
1113 if (m_pxIDTrack[imuon]->charge()==1) { // positive muon
1114 muposcount++;
1115 if (m_pxIDTrack[imuon]->pt()> muPlus1Pt) {
1116 // store 1st in 2nd
1117 muPlus2Pt = muPlus1Pt;
1118 muPlus2Id = muPlus1Id;
1119 // now store the new one in 1st place
1120 muPlus1Pt = m_pxIDTrack[imuon]->pt();
1121 muPlus1Id = imuon;
1122 }
1123 else if (m_pxIDTrack[imuon]->pt()> muPlus2Pt) {
1124 // store the new one in 2nd place
1125 muPlus2Pt = m_pxIDTrack[imuon]->pt();
1126 muPlus2Id = imuon;
1127 }
1128 }
1129 // Negative muons
1130 if (m_pxIDTrack[imuon]->charge()==-1) {
1131 munegcount++;
1132 if(m_pxIDTrack[imuon]->pt()> muMinus1Pt) {
1133 // store 1st in 2nd
1134 muMinus2Pt = muMinus1Pt;
1135 muMinus2Id = muMinus1Id;
1136 muMinus1Pt = m_pxIDTrack[imuon]->pt();
1137 muMinus1Id = imuon;
1138 }
1139 else if(m_pxRecMuon[imuon]->pt()> muMinus2Pt) {
1140 muMinus2Pt = m_pxIDTrack[imuon]->pt();
1141 muMinus2Id = imuon;
1142 }
1143 }
1144 } // muon exist
1145 } // for (int imuon)
1146 } // if (nMuonsAtEntry >= 2)
1147
1148 // require at least one opposite charge muon pair
1149 if (nMuonsAtEntry >= 2 && (muposcount == 0 || munegcount == 0)) {
1150 if (m_doDebug) std::cout << " -- FourMuonEvent::OrderMuonList -- No opposite charge muons in the " << nMuonsAtEntry << " input muons"
1151 << " #mu+ " << muposcount
1152 << " #mu- " << munegcount
1153 << " --> DISCARD ALL MUONS -- \n";
1154 muPlus1Id = -9;
1155 muPlus2Id = -9;
1156 muMinus1Id = -9;
1157 muMinus2Id = -9;
1158 }
1159
1160
1161 if (muPlus1Id>=0) {m_muonpos1 = muPlus1Id; m_numberOfFullPassMuons++;}
1162 if (muPlus2Id>=0) {m_muonpos2 = muPlus2Id; m_numberOfFullPassMuons++;}
1163 if (muMinus1Id>=0) {m_muonneg1 = muMinus1Id; m_numberOfFullPassMuons++;}
1164 if (muMinus2Id>=0) {m_muonneg2 = muMinus2Id; m_numberOfFullPassMuons++;}
1165
1166 m_muon1 = m_muonpos1; // to be deleted when no more m_muon is left
1167 m_muon2 = m_muonneg1; // to be deleted when no more m_muon is left
1168
1169 if ((m_doDebug || thisdebug) && m_numberOfFullPassMuons >= 2){
1170 std::cout << " * FourMuonEvent::OrderMuonList * taking " << m_numberOfFullPassMuons << " muons from the input list of " << nMuonsAtEntry << " muons: " << std::endl;
1171 if (muMinus1Id >= 0) std::cout << " leading mu-: " << muMinus1Id << " Pt = " << muMinus1Pt << std::endl;
1172 if (muMinus2Id >= 0) std::cout << " second mu-: " << muMinus2Id << " Pt = " << muMinus2Pt << std::endl;
1173 if (muPlus1Id >= 0) std::cout << " leading mu+: " << muPlus1Id << " Pt = " << muPlus1Pt << std::endl;
1174 if (muPlus2Id >= 0) std::cout << " second mu+: " << muPlus2Id << " Pt = " << muPlus2Pt << std::endl;
1175 }
1176 else {
1177 if (m_doDebug) std::cout << " * FourMuonEvent::OrderMuonList * This event has less than 2 muons :(" << std::endl;
1178 }
1179
1180 if (m_doDebug || thisdebug) std::cout << " * FourMuonEvent::OrderMuonList * completed * m_numberOfFullPassMuons= " << m_numberOfFullPassMuons << std::endl;
1181 return;
1182}
1183
1186{
1187 (*m_msgStream) << MSG::DEBUG << " * FourMuonsEvents::CheckMuonVertices * -- START --" << endmsg;
1188
1189 if (m_doDebug) std::cout << " -- FourMuonEvent::CheckMuonVertices -- WARNING -- MUONS DO NOT COME FROM SAME VERTEX \n" ;
1190
1191 (*m_msgStream) << MSG::DEBUG << " * FourMuonsEvents::CheckMuonVertices * -- COMPLETED -- status: " << true << endmsg;
1192 return true;
1193}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
double charge(const T &p)
Definition AtlasPID.h:1003
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".