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