ATLAS Offline Software
Loading...
Searching...
No Matches
MuonSelector.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//
7// ZMM_Event.cxx : Class designed to reconstruct di-boson events
8// in particular Z0 -> mu+ mu- events.
9// Author : Kyle Stevenson, QMUL
10// Date : 7th December 2007
11//
12//==================================================================================
13
14//==================================================================================
15// Include files...
16//==================================================================================
17
18// This files header
20// Package Headers
21#include <sstream>
22// ATLAS headers
25#include "CLHEP/Random/RandFlat.h"
26
27#include "xAODMuon/Muon.h"
29
30using CLHEP::GeV;
31
32// Local debug variables. Global scope, but only accessible by this file.
33//static const float CGeV = 1.0e-3; // Conversion factor to remove evil MeV
34 // nonsense.
35
36// Static declarations
37// unsigned int MuonSelector::m_uNumInstances;
38
39//==================================================================================
40// Public Methods
41//==================================================================================
42
44 m_muonSelectionTool("CP::MuonSelectionTool/MuonSelectionTool"),
45 m_doDebug ( false ),
46 m_doQualSelection ( false ),
47 m_doIsoSelection ( false ),
48 m_doPtSelection ( true ),
49 m_doIPSelection ( true ),
50 m_doMCPSelection ( true )
51{
52 // SOC commented by Salva -- R22 test --
53 //++s_uNumInstances;
54 //std::stringstream xTmp; xTmp << s_uNumInstances;
55 //m_xSampleName = "MuID_" + xTmp.str();
56 // EOC commented by Salva -- R22 test --
57 unsigned int inst = ++m_uNumInstances;
58 m_xSampleName = "MuID_" + std::to_string(inst);
59 m_pxMuon = nullptr;
60 m_bLock = false;
61
62
63 // requested muon tag (tight, medium, loose..)
64 m_requestedMuonQuality = xAOD::Muon::Medium;
65
66
67 m_coneSize = 0.4;
68 m_ucJMuon_Cut = 0; //not used
69 m_IsoCut = 0.2;
70
71 m_bCutOnCombKine = false; //not used
72 m_fEtaCut = 2.5;
73 //m_fEtaCut = 1.9;
74 m_combPtCut = 15.0*CLHEP::GeV; // GeV/c
75 // m_combPtCut = .01*CLHEP::GeV; // GeV/c
76
77 //m_ptMSCut = 10.0*CLHEP::GeV;
78 m_ptMSCut = 0.0*CLHEP::GeV;
79 m_diffZCut = 1.5*CLHEP::mm; // mm --> used to be 10.0*CLHEP::mm // Changed by Salva 26/january/2016
80 m_diffPtCut = 15.0*CLHEP::GeV; // not used
81 m_pVZCut = 150.0*CLHEP::mm; // mm
82
83 m_fIDPtCut = 0.0; // GeV/c
85 m_IDSiHitsCut = 8;
86 m_ucID_PIXCut = 1; // Hits
87 m_ucID_SCTCut = 4; // Hits
88 m_ucID_TRTCut = 0; // Hits
89
90 m_msgStream = new MsgStream(Athena::getMessageSvc(), "InDetPerformanceMonitoring");
91
92 // stats
93 m_testedmuons = 0;
94 m_passqual = 0;
95 m_passiso = 0;
96 m_passpt = 0;
97 m_passip = 0;
98 m_passmcp = 0;
99 m_passall = 0;
100
101 // done
102}
103
110
113{
114
115 // check muon selection tool is available
116 if (m_muonSelectionTool.retrieve().isSuccess()) {
117 ( *m_msgStream) << MSG::INFO << " * MuonSelector::Init * m_muonSelectionTool.initialize() success :)" << endmsg;
118 if(m_doDebug){ std::cout << " * MuonSelector::Init * m_muonSelectionTool.initialize() success :)" << std::endl;}
119 }
120 else {
121 (*m_msgStream) << MSG::ERROR << " * MuonSelector::Init * FAILURE * Muon selction tool retrieving failed :( " << endmsg;
122 }
123
124 PARENT::Init();
125}
126
127
128
130{
131 return true;
132}
133
135//bool MuonSelector::passSelection( const Analysis::Muon* pxMuon )
137{
138 if(m_doDebug){ std::cout << " * MuonSelector::passSelection * START * new muon " << pxMuon << " with pt: " << pxMuon->pt() << std::endl; }
139
140 std::vector<bool> passes;
141 passes.reserve(8);
142 bool pass = true;
143 if ( pxMuon ) {
144 // Save local copy of muon address if it's ok.
145 m_pxMuon = pxMuon;
147
148 // Test muon pass conditions in turn
150 pass = passQualCuts();
151 passes.push_back(pass);
152 if (m_doDebug && !pass) std::cout <<" * MuonSelector::passSelection * Muon Fails QualSelection"<<std::endl;
153 if (pass) m_passqual++;
154 }
155
156 if (m_doIsoSelection){
157 pass = passIsolCuts();
158 passes.push_back(pass);
159 if (m_doDebug && !pass) std::cout<<" * MuonSelector::passSelection * Muon Fails Iso Selection"<<std::endl;
160 if (pass) m_passiso++;
161 }
162
163
164 if (m_doPtSelection){
165 pass = passPtCuts();
166 passes.push_back(pass);
167 if (m_doDebug && !pass) std::cout<<" * MuonSelector::passSelection * Muon Fails pT Selection"<<std::endl;
168 if (pass) m_passpt++;
169 }
170
171 if (m_doIPSelection){
172 pass = passIPCuts();
173 passes.push_back(pass);
174 if (m_doDebug && !pass) std::cout<<" * MuonSelector::passSelection * Muon Fails IP Selection"<<std::endl;
175 if (pass) m_passip++;
176 }
177
178 if (m_doMCPSelection) {
179 xAOD::Muon::Quality my_quality=m_muonSelectionTool->getQuality(*pxMuon);
180 if (m_doDebug) std::cout << " * MuonSelector::passSelection * muon quality from muonsSelectionTool: " << my_quality << std::endl;
181
182 pass = true;
183 if (m_requestedMuonQuality == xAOD::Muon::Tight && my_quality > xAOD::Muon::Tight) pass = false;
184 if (m_requestedMuonQuality == xAOD::Muon::Medium && my_quality > xAOD::Muon::Medium) pass = false;
185 if (m_requestedMuonQuality == xAOD::Muon::Loose && my_quality > xAOD::Muon::Loose) pass = false;
186 if (m_requestedMuonQuality == xAOD::Muon::VeryLoose && my_quality > xAOD::Muon::VeryLoose) pass = false;
187
188 passes.push_back(pass);
189 if (m_doDebug && pass) std::cout<<" * MuonSelector::passSelection * Muon Passes official m_muonSelectionTool (medium) Selection :)" << std::endl;
190 if (m_doDebug && !pass) std::cout<<" * MuonSelector::passSelection * Muon Fails official m_muonSelectionTool (medium) Selection" << std::endl;
191 if (pass) m_passmcp++;
192 }
193
194 // check if the muon failed some of the cuts
195 for (int i=0; i < int(passes.size()); i++)
196 if (!passes[i]){
197 if(m_doDebug) std::cout << " * MuonSelector::passSelection * BAD MUON * muon haven't passed the " << i+1 << "th selection " << std::endl;
198 return false;
199 }
200 } // if pxMuon exists
201
202 // reached this point, the muon passed all selection criteria. This muon is good
203 m_passall++;
204 if(m_doDebug){ std::cout << " * MuonSelector::passSelection * completed. GOOD MUON " << std::endl; }
205 return true;
206}
207
208
209//==================================================================================
210// Protected Methods
211//==================================================================================
215
216
217//==================================================================================
218// Private Methods
219//==================================================================================
221{
222 bool goodTrack = false;
223
224 // First get the muon track, then the summary
225 const xAOD::TrackParticle* IDTrk = m_pxMuon->trackParticle(xAOD::Muon::InnerDetectorTrackParticle); // use the Inner Detector segment
226
227 if (IDTrk) {
228 uint8_t dummy(-1);
229 bool eBLhits = IDTrk->summaryValue( dummy, xAOD::expectBLayerHit ) ? true : false;
230 int nBLhits = IDTrk->summaryValue( dummy, xAOD::numberOfBLayerHits ) ? dummy :-1;
231
232 int nhitsPIX = IDTrk->summaryValue( dummy, xAOD::numberOfPixelHits ) ? dummy :-1;
233 int nhitsSCT = IDTrk->summaryValue( dummy, xAOD::numberOfSCTHits ) ? dummy :-1;
234 int nhitsTRT = IDTrk->summaryValue( dummy, xAOD::numberOfTRTHits ) ? dummy :-1;
235
236 int nPIXDS = IDTrk->summaryValue( dummy, xAOD::numberOfPixelDeadSensors ) ? dummy :-1;
237 int nSCTDS = IDTrk->summaryValue( dummy, xAOD::numberOfSCTDeadSensors ) ? dummy :-1;
238
239 int nPIXH = IDTrk->summaryValue( dummy, xAOD::numberOfPixelHoles )? dummy :-1;
240 int nSCTH = IDTrk->summaryValue( dummy, xAOD::numberOfSCTHoles )? dummy :-1;
241 int nTRTH = IDTrk->summaryValue( dummy, xAOD::numberOfTRTHoles )? dummy :-1;
242
243 int nContribPixLayers = IDTrk->summaryValue( dummy, xAOD::numberOfContribPixelLayers )? dummy :-1;
244
245 if(m_doDebug) std::cout << " * MuonSelector * passQualCuts() * eBLhits: " << eBLhits
246 << " nBLhits: " << nBLhits
247 << " nhitsPIX: " << nhitsPIX
248 << " nPIXLayers: " << nContribPixLayers
249 << " nhitsSCT: " << nhitsSCT
250 << " Silicon holes: " << nPIXH + nSCTH
251 << " nhitsTRT: " << nhitsTRT
252 << " nTRTholes: " << nTRTH
253 << std::endl;
254
255 if (((!eBLhits) || (nBLhits > 0))
256 && (nhitsPIX + nPIXDS > 1 )
257 && (nhitsSCT + nSCTDS >=6 )
258 && (nPIXH + nSCTH < 2 ) ) {
259 goodTrack = true;
260 }
261 }
262
263 if (m_doDebug) {
264 if (goodTrack) {
265 std::cout << " * MuonSelector * passQualCuts() * this muon satisfies the hits number QualCuts " << std::endl;
266 }
267 else {
268 std::cout << " * MuonSelector * passQualCuts() * this muon did not pass the hits number QualCuts " << std::endl;
269 }
270 }
271 return goodTrack;
272}
273
276{
277
278 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * START *" << std::endl;
279
280 const xAOD::TrackParticle* pxMuonID = m_pxMuon->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
281 const xAOD::TrackParticle* pxMuonMS = m_pxMuon->trackParticle(xAOD::Muon::MuonSpectrometerTrackParticle);
282 const xAOD::TrackParticle* pxMuonCB = m_pxMuon->trackParticle(xAOD::Muon::CombinedTrackParticle);
283
284 double pt = 0, ptID, ptMS,ptCB;
285
286 if ( !(pxMuonID || pxMuonMS || pxMuonCB)){
287 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * NO inDetTrackParticle && muonSpectrometerTrackParticle && CombinedTrackParticle: " << std::endl;
288 }
289
290 else {
291
292 pt = m_pxMuon->pt();
293 ptID = pxMuonID ? pxMuonID->pt() : 0.0 ;
294 ptMS = pxMuonMS ? pxMuonMS->pt() : 0.0 ;
295 ptCB = pxMuonCB ? pxMuonCB->pt() : 0.0 ;
296 double fMEta = std::abs( m_pxMuon->eta() );
297
298 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * pt of each segments of this muon pxMuon: " << pt << std::endl
299 << " ptID: " << ptID << std::endl
300 << " ptMS: " << ptMS << std::endl
301 << " ptCB: " << ptCB << std::endl
302 << " fMEta pxMuon->eta(): " << fMEta << std::endl;
303
304
305 if ( (fMEta < m_fEtaCut)
306 && (pt > m_combPtCut)
307 && (ptMS > m_ptMSCut || !pxMuonMS)
308 && (ptID > m_ptMSCut || !pxMuonID)
309 ){
310 // warning one can check also the difference of pt: std::abs(ptMS - ptID) < m_diffPtCut
311 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * this muon is in eta range |eta|= " << fMEta << " < EtaCut(" << m_fEtaCut << ") " << std::endl
312 << " and passed the PtCuts (" << m_combPtCut <<") "<< std::endl;
313 return true;
314 }
315 }
316 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * this muon did not pass the PtCuts (reco pt=" << pt << ") or Eta cut " << m_fEtaCut << std::endl;
317 return false;
318}
319
322{
323 float iso_pt40(0);
324 if( !m_pxMuon->isolation(iso_pt40, xAOD::Iso::ptcone40) ) {
325 if(m_doDebug) {
326 std::cout << " * MuonSelector::passIsolCuts * WARNING * No isolation variable stored on the muon" << std::endl;
327 std::cout << " * MuonSelector::passIsolCuts * this muon did not pass the IsoCuts " << std::endl;
328 }
329 return false;
330 }
331
332 else {
333 double pt = m_pxMuon->pt();
334 double ptSum = xAOD::Iso::ptcone40;
335 if(m_doDebug) std::cout <<" * MuonSelector::passIsolCuts * muon pt: " << pt <<" ptSum(ptcone40): "<< ptSum << std::endl;
336 if (ptSum/pt < m_IsoCut ){
337 if(m_doDebug) std::cout << " * MuonSelector::passIsolCuts * this muon passed the IsoCuts ptcone40 / pt= "
338 << ptSum << " / " << pt << " = " << ptSum / pt
339 << " < IsoCut(" << m_IsoCut << ") " << std::endl;
340 return true;
341 }
342 }
343
344 if(m_doDebug) std::cout << " * MuonSelector::passIsolCuts * this muon did not pass the IsoCuts:" << std::endl;
345 return false;
346}
347
348
351{
352 float extd0 = 0.0 ;
353 float extz0 = 0.0 ;
354
355 //I'm not really sure of this logic.
356 if (m_pxMuon->inDetTrackParticleLink().isValid()) {
357 const xAOD::TrackParticle* IDTrk = m_pxMuon->trackParticle(xAOD::Muon::InnerDetectorTrackParticle);
358 if (!IDTrk) {
359 if (m_doDebug) std::cout << " * MuonSelector::passIPCuts * no IDTrk --> IP failure" << std::endl;
360 return false;
361 }
362 extd0 = IDTrk->d0();
363 extz0 = IDTrk->z0()+IDTrk->vz();
364 if(m_doDebug){
365 std::cout << " * MuonSelector::passIPCuts *"
366 << " the IDTrack muon d0: " << extd0
367 << " the IDTrack muon z0: " << extz0 << " = " << IDTrk->z0() << " + " << IDTrk->vz() << std::endl;
368 }
369 }
370 else {
371 if(m_doDebug) std::cout << " * MuonSelector * passIPCuts() * no valid inDetTrackParticleLink(). Will use the combined muon IPs" << std::endl;
372
373 const xAOD::TrackParticle* CBTrk = m_pxMuon->trackParticle(xAOD::Muon::CombinedTrackParticle);
374 if (!CBTrk) {
375 if(m_doDebug) std::cout << " * MuonSelector * passIPCuts() * no valid CombinedTrackParticle. Giving up." << std::endl;
376 return false;
377 }
378 else {
379 extd0 = CBTrk->d0();
380 extz0 = CBTrk->z0()+CBTrk->vz();
381 if(m_doDebug){
382 std::cout << " * MuonSelector * passIPCuts() *"
383 << " the CBTrack muon d0: " << extd0
384 << " the CBTrack muon z0: " << extz0 << " = " << CBTrk->z0() << " + " << CBTrk->vz()<< std::endl;
385 }
386 }
387 }
388
389 // retrieve the vertices
390 const xAOD::VertexContainer * vxContainer(nullptr);
392 if (!vxContainer){
393 if(m_doDebug) std::cout << " * MuonSelector::passIPCuts ** fails because NO vertex collection "<< std::endl;
394 return false;
395 }
396
397 if ( vxContainer->size()>1 ) {
398 if(m_doDebug) {
399 std::cout << " * MuonSelector::passIPCuts ** vertex container is filled with " << vxContainer->size() << " vertices" << std::endl;
400
401 // loop on vertices to check their coordinates:
402 for (int ivtx=0; ivtx < (int) vxContainer->size(); ivtx++) {
403 const xAOD::Vertex* thisVtx = (*vxContainer)[ivtx];
404 std::cout << " vertex " << ivtx+1 << " (x,y,z) = (" << thisVtx->position().x()
405 << ", " << thisVtx->position().y()
406 << ", " << thisVtx->position().z()
407 << ") type= " << thisVtx->vertexType()
408 << " Npart= " << thisVtx->nTrackParticles()
409 << std::endl;
410 }
411 }
412
413 // new method
414 if (true) {
415 bool goodmuonIP = false; // by default think the IP is not good
416 float minDeltaZ = 99999.; // large number
417 // loop on vertices and check the muon may come from one of them
418 for (int ivtx=0; ivtx < (int) vxContainer->size(); ivtx++) {
419 const xAOD::Vertex* thisVtx = (*vxContainer)[ivtx];
420 // if ( (thisVtx->vertexType() == 1) && thisVtx->nTrackParticles()>2 ) {
421 if ( thisVtx->nTrackParticles()>2 ) {
422 if (std::abs(extz0 - thisVtx->position().z()) < minDeltaZ) minDeltaZ = std::abs(extz0 - thisVtx->position().z());
423
424 // check the vertex is in the accepted Z range and that the muon is not far from the vertex
425 if (m_doDebug) {
426 std::cout << " testing vtx: " << ivtx << " vtx.z= " << thisVtx->position().z() << " trk.z= " << extz0 << " deltaZ= " << std::abs(extz0 - thisVtx->position().z()) << " minDeltaZ= " << minDeltaZ << std::endl;
427 }
428 if (std::abs(thisVtx->position().z()) < m_pVZCut && std::abs(extz0 - thisVtx->position().z()) < m_diffZCut){
429 goodmuonIP = true;
430 if(m_doDebug) std::cout << " * MuonSelector::passIPCuts * this muon has passed the IPCuts for vertex " << ivtx+1
431 << " pVZcut= " << std::abs(extz0 - thisVtx->position().z()) << " < " << m_diffZCut << std::endl
432 << " vtx (x,y,z): "
433 << " (" << thisVtx->position().x()
434 << ", " << thisVtx->position().y()
435 << ", " << thisVtx->position().z()
436 << ") type: " << thisVtx->vertexType()
437 << " Npart: " << thisVtx->nTrackParticles() << std::endl;
438 }
439 }
440 }
441 if (goodmuonIP) {
442 if(m_doDebug) std::cout <<" * MuonSelector::passIPCuts * this muon has passed the IPCuts. Zcut: "<< m_pVZCut << " m_diffZCut " << m_diffZCut << std::endl;
443 return true;
444 }
445 } // end new method
446 }
447 if(m_doDebug) std::cout <<" * MuonSelector * passIPCuts() * this muon has not passed the IPCuts: " << std::endl;
448 return false;
449}
450
453{
454 // statistics report
455 std::cout << " * MuonSelector* -- STATS -- " << std::endl
456 << " tested : " << m_testedmuons << std::endl;
457 if (m_doQualSelection) std::cout << " passQual: " << m_passqual << std::endl;
458 if (m_doIsoSelection) std::cout << " passIso : " << m_passiso << std::endl;
459 if (m_doPtSelection) std::cout << " passpt : " << m_passpt << std::endl;
460 if (m_doIPSelection) std::cout << " passip : " << m_passip << std::endl;
461 if (m_doMCPSelection) std::cout << " passmcp : " << m_passmcp << std::endl;
462 std::cout << " passall : " << m_passall << std::endl
463 << std::endl;
464
465 return;
466}
467
470{
471 int qualityvalue = xAOD::Muon::Tight;
472
473 for_each (newname.begin(), newname.end(), [](char & c) {c = std::toupper(c);} );
474
475 if (newname.find("TIGHT") != std::string::npos) qualityvalue = xAOD::Muon::Tight;
476 if (newname.find("MEDIUM") != std::string::npos) qualityvalue = xAOD::Muon::Medium;
477 if (newname.find("LOOSE") != std::string::npos) qualityvalue = xAOD::Muon::Loose;
478 if (newname.find("VERYLOOSE")!= std::string::npos) qualityvalue = xAOD::Muon::VeryLoose;
479
480 m_requestedMuonQuality = qualityvalue;
481
482 std::cout << " ** MuonSelector::SetMuonQualityRequirement(" << newname <<") = " << m_requestedMuonQuality << std::endl;
483
484 return;
485}
486
#define endmsg
size_type size() const noexcept
Returns the number of elements in the collection.
virtual void Init()
std::string m_xSampleName
double m_coneSize
unsigned int m_testedmuons
unsigned int m_passiso
const xAOD::Muon * m_pxMuon
virtual void Init()
float m_diffPtCut
virtual void BookHistograms()
bool m_bCutOnCombKine
bool m_doIsoSelection
int m_requestedMuonQuality
unsigned char m_ucID_TRTCut
ToolHandle< CP::IMuonSelectionTool > m_muonSelectionTool
unsigned char m_ucID_PIXCut
unsigned int m_passip
float m_fIDChiPerDofCut
double m_IsoCut
unsigned int m_uNumInstances
unsigned int m_passpt
bool m_doQualSelection
unsigned char m_ucJMuon_Cut
unsigned char m_ucID_SCTCut
bool m_doMCPSelection
virtual void finalize()
double m_combPtCut
MsgStream * m_msgStream
unsigned int m_passqual
void SetMuonQualityRequirement(std::string newname)
unsigned int m_passmcp
virtual bool Reco()
unsigned int m_passall
bool passSelection(const xAOD::Muon *pxMuon)
static const T * getContainer(CONTAINERS eContainer)
virtual double pt() const
The transverse momentum ( ) of the particle.
float z0() const
Returns the parameter.
float vz() const
The z origin for the parameters.
float d0() const
Returns the parameter.
bool summaryValue(uint8_t &value, const SummaryType &information) const
Accessor for TrackSummary values.
virtual double pt() const override final
The transverse momentum ( ) of the particle.
size_t nTrackParticles() const
Get the number of tracks associated with this vertex.
VxType::VertexType vertexType() const
The type of the vertex.
const Amg::Vector3D & position() const
Returns the 3-pos.
singleton-like access to IMessageSvc via open function and helper
IMessageSvc * getMessageSvc(bool quiet=false)
TrackParticle_v1 TrackParticle
Reference the current persistent version:
VertexContainer_v1 VertexContainer
Definition of the current "Vertex container version".
Vertex_v1 Vertex
Define the latest version of the vertex class.
Muon_v1 Muon
Reference the current persistent version:
@ numberOfPixelHoles
number of pixel layers on track with absence of hits [unit8_t].
@ numberOfContribPixelLayers
number of contributing layers of the pixel detector [unit8_t].
@ numberOfTRTHits
number of TRT hits [unit8_t].
@ numberOfTRTHoles
number of TRT holes [unit8_t].
@ numberOfBLayerHits
these are the hits in the first pixel layer, i.e.
@ numberOfSCTDeadSensors
number of dead SCT sensors crossed [unit8_t].
@ expectBLayerHit
Do we expect a b-layer hit for this track?
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
@ numberOfPixelDeadSensors
number of dead pixel sensors crossed [unit8_t].
@ numberOfSCTHoles
number of SCT holes [unit8_t].