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::Quality::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 = (my_quality <= m_requestedMuonQuality);
183 passes.push_back(pass);
184 if (m_doDebug && pass) std::cout<<" * MuonSelector::passSelection * Muon Passes official m_muonSelectionTool (medium) Selection :)" << std::endl;
185 if (m_doDebug && !pass) std::cout<<" * MuonSelector::passSelection * Muon Fails official m_muonSelectionTool (medium) Selection" << std::endl;
186 if (pass) m_passmcp++;
187 }
188
189 // check if the muon failed some of the cuts
190 for (int i=0; i < int(passes.size()); i++)
191 if (!passes[i]){
192 if(m_doDebug) std::cout << " * MuonSelector::passSelection * BAD MUON * muon haven't passed the " << i+1 << "th selection " << std::endl;
193 return false;
194 }
195 } // if pxMuon exists
196
197 // reached this point, the muon passed all selection criteria. This muon is good
198 m_passall++;
199 if(m_doDebug){ std::cout << " * MuonSelector::passSelection * completed. GOOD MUON " << std::endl; }
200 return true;
201}
202
203
204//==================================================================================
205// Protected Methods
206//==================================================================================
210
211
212//==================================================================================
213// Private Methods
214//==================================================================================
216{
217 bool goodTrack = false;
218
219 // First get the muon track, then the summary
220 const xAOD::TrackParticle* IDTrk = m_pxMuon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle); // use the Inner Detector segment
221
222 if (IDTrk) {
223 uint8_t dummy(-1);
224 bool eBLhits = IDTrk->summaryValue( dummy, xAOD::expectBLayerHit ) ? true : false;
225 int nBLhits = IDTrk->summaryValue( dummy, xAOD::numberOfBLayerHits ) ? dummy :-1;
226
227 int nhitsPIX = IDTrk->summaryValue( dummy, xAOD::numberOfPixelHits ) ? dummy :-1;
228 int nhitsSCT = IDTrk->summaryValue( dummy, xAOD::numberOfSCTHits ) ? dummy :-1;
229 int nhitsTRT = IDTrk->summaryValue( dummy, xAOD::numberOfTRTHits ) ? dummy :-1;
230
231 int nPIXDS = IDTrk->summaryValue( dummy, xAOD::numberOfPixelDeadSensors ) ? dummy :-1;
232 int nSCTDS = IDTrk->summaryValue( dummy, xAOD::numberOfSCTDeadSensors ) ? dummy :-1;
233
234 int nPIXH = IDTrk->summaryValue( dummy, xAOD::numberOfPixelHoles )? dummy :-1;
235 int nSCTH = IDTrk->summaryValue( dummy, xAOD::numberOfSCTHoles )? dummy :-1;
236 int nTRTH = IDTrk->summaryValue( dummy, xAOD::numberOfTRTHoles )? dummy :-1;
237
238 int nContribPixLayers = IDTrk->summaryValue( dummy, xAOD::numberOfContribPixelLayers )? dummy :-1;
239
240 if(m_doDebug) std::cout << " * MuonSelector * passQualCuts() * eBLhits: " << eBLhits
241 << " nBLhits: " << nBLhits
242 << " nhitsPIX: " << nhitsPIX
243 << " nPIXLayers: " << nContribPixLayers
244 << " nhitsSCT: " << nhitsSCT
245 << " Silicon holes: " << nPIXH + nSCTH
246 << " nhitsTRT: " << nhitsTRT
247 << " nTRTholes: " << nTRTH
248 << std::endl;
249
250 if (((!eBLhits) || (nBLhits > 0))
251 && (nhitsPIX + nPIXDS > 1 )
252 && (nhitsSCT + nSCTDS >=6 )
253 && (nPIXH + nSCTH < 2 ) ) {
254 goodTrack = true;
255 }
256 }
257
258 if (m_doDebug) {
259 if (goodTrack) {
260 std::cout << " * MuonSelector * passQualCuts() * this muon satisfies the hits number QualCuts " << std::endl;
261 }
262 else {
263 std::cout << " * MuonSelector * passQualCuts() * this muon did not pass the hits number QualCuts " << std::endl;
264 }
265 }
266 return goodTrack;
267}
268
271{
272
273 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * START *" << std::endl;
274 using enum xAOD::Muon::TrackParticleType;
275 const xAOD::TrackParticle* pxMuonID = m_pxMuon->trackParticle(InnerDetectorTrackParticle);
276 const xAOD::TrackParticle* pxMuonMS = m_pxMuon->trackParticle(MuonSpectrometerTrackParticle);
277 const xAOD::TrackParticle* pxMuonCB = m_pxMuon->trackParticle(CombinedTrackParticle);
278
279 double pt = 0, ptID, ptMS,ptCB;
280
281 if ( !(pxMuonID || pxMuonMS || pxMuonCB)){
282 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * NO inDetTrackParticle && muonSpectrometerTrackParticle && CombinedTrackParticle: " << std::endl;
283 }
284
285 else {
286
287 pt = m_pxMuon->pt();
288 ptID = pxMuonID ? pxMuonID->pt() : 0.0 ;
289 ptMS = pxMuonMS ? pxMuonMS->pt() : 0.0 ;
290 ptCB = pxMuonCB ? pxMuonCB->pt() : 0.0 ;
291 double fMEta = std::abs( m_pxMuon->eta() );
292
293 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * pt of each segments of this muon pxMuon: " << pt << std::endl
294 << " ptID: " << ptID << std::endl
295 << " ptMS: " << ptMS << std::endl
296 << " ptCB: " << ptCB << std::endl
297 << " fMEta pxMuon->eta(): " << fMEta << std::endl;
298
299
300 if ( (fMEta < m_fEtaCut)
301 && (pt > m_combPtCut)
302 && (ptMS > m_ptMSCut || !pxMuonMS)
303 && (ptID > m_ptMSCut || !pxMuonID)
304 ){
305 // warning one can check also the difference of pt: std::abs(ptMS - ptID) < m_diffPtCut
306 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * this muon is in eta range |eta|= " << fMEta << " < EtaCut(" << m_fEtaCut << ") " << std::endl
307 << " and passed the PtCuts (" << m_combPtCut <<") "<< std::endl;
308 return true;
309 }
310 }
311 if(m_doDebug) std::cout << " * MuonSelector::passPtCuts * this muon did not pass the PtCuts (reco pt=" << pt << ") or Eta cut " << m_fEtaCut << std::endl;
312 return false;
313}
314
317{
318 float iso_pt40(0);
319 if( !m_pxMuon->isolation(iso_pt40, xAOD::Iso::ptcone40) ) {
320 if(m_doDebug) {
321 std::cout << " * MuonSelector::passIsolCuts * WARNING * No isolation variable stored on the muon" << std::endl;
322 std::cout << " * MuonSelector::passIsolCuts * this muon did not pass the IsoCuts " << std::endl;
323 }
324 return false;
325 }
326
327 else {
328 double pt = m_pxMuon->pt();
329 double ptSum = xAOD::Iso::ptcone40;
330 if(m_doDebug) std::cout <<" * MuonSelector::passIsolCuts * muon pt: " << pt <<" ptSum(ptcone40): "<< ptSum << std::endl;
331 if (ptSum/pt < m_IsoCut ){
332 if(m_doDebug) std::cout << " * MuonSelector::passIsolCuts * this muon passed the IsoCuts ptcone40 / pt= "
333 << ptSum << " / " << pt << " = " << ptSum / pt
334 << " < IsoCut(" << m_IsoCut << ") " << std::endl;
335 return true;
336 }
337 }
338
339 if(m_doDebug) std::cout << " * MuonSelector::passIsolCuts * this muon did not pass the IsoCuts:" << std::endl;
340 return false;
341}
342
343
346{
347 float extd0 = 0.0 ;
348 float extz0 = 0.0 ;
349 using enum xAOD::Muon::TrackParticleType;
350 //I'm not really sure of this logic.
351 if (const xAOD::TrackParticle* IDTrk = m_pxMuon->trackParticle(InnerDetectorTrackParticle); IDTrk != nullptr) {
352 extd0 = IDTrk->d0();
353 extz0 = IDTrk->z0()+IDTrk->vz();
354 if(m_doDebug){
355 std::cout << " * MuonSelector::passIPCuts *"
356 << " the IDTrack muon d0: " << extd0
357 << " the IDTrack muon z0: " << extz0 << " = " << IDTrk->z0() << " + " << IDTrk->vz() << std::endl;
358 }
359 } else {
360 if(m_doDebug) std::cout << " * MuonSelector * passIPCuts() * no valid inDetTrackParticleLink(). Will use the combined muon IPs" << std::endl;
361
362 const xAOD::TrackParticle* CBTrk = m_pxMuon->trackParticle(CombinedTrackParticle);
363 if (!CBTrk) {
364 if(m_doDebug) std::cout << " * MuonSelector * passIPCuts() * no valid CombinedTrackParticle. Giving up." << std::endl;
365 return false;
366 }
367 else {
368 extd0 = CBTrk->d0();
369 extz0 = CBTrk->z0()+CBTrk->vz();
370 if(m_doDebug){
371 std::cout << " * MuonSelector * passIPCuts() *"
372 << " the CBTrack muon d0: " << extd0
373 << " the CBTrack muon z0: " << extz0 << " = " << CBTrk->z0() << " + " << CBTrk->vz()<< std::endl;
374 }
375 }
376 }
377
378 // retrieve the vertices
379 const xAOD::VertexContainer * vxContainer(nullptr);
381 if (!vxContainer){
382 if(m_doDebug) std::cout << " * MuonSelector::passIPCuts ** fails because NO vertex collection "<< std::endl;
383 return false;
384 }
385
386 if ( vxContainer->size()>1 ) {
387 if(m_doDebug) {
388 std::cout << " * MuonSelector::passIPCuts ** vertex container is filled with " << vxContainer->size() << " vertices" << std::endl;
389
390 // loop on vertices to check their coordinates:
391 for (int ivtx=0; ivtx < (int) vxContainer->size(); ivtx++) {
392 const xAOD::Vertex* thisVtx = (*vxContainer)[ivtx];
393 std::cout << " vertex " << ivtx+1 << " (x,y,z) = (" << thisVtx->position().x()
394 << ", " << thisVtx->position().y()
395 << ", " << thisVtx->position().z()
396 << ") type= " << thisVtx->vertexType()
397 << " Npart= " << thisVtx->nTrackParticles()
398 << std::endl;
399 }
400 }
401
402 // new method
403 if (true) {
404 bool goodmuonIP = false; // by default think the IP is not good
405 float minDeltaZ = 99999.; // large number
406 // loop on vertices and check the muon may come from one of them
407 for (int ivtx=0; ivtx < (int) vxContainer->size(); ivtx++) {
408 const xAOD::Vertex* thisVtx = (*vxContainer)[ivtx];
409 // if ( (thisVtx->vertexType() == 1) && thisVtx->nTrackParticles()>2 ) {
410 if ( thisVtx->nTrackParticles()>2 ) {
411 if (std::abs(extz0 - thisVtx->position().z()) < minDeltaZ) minDeltaZ = std::abs(extz0 - thisVtx->position().z());
412
413 // check the vertex is in the accepted Z range and that the muon is not far from the vertex
414 if (m_doDebug) {
415 std::cout << " testing vtx: " << ivtx << " vtx.z= " << thisVtx->position().z() << " trk.z= " << extz0 << " deltaZ= " << std::abs(extz0 - thisVtx->position().z()) << " minDeltaZ= " << minDeltaZ << std::endl;
416 }
417 if (std::abs(thisVtx->position().z()) < m_pVZCut && std::abs(extz0 - thisVtx->position().z()) < m_diffZCut){
418 goodmuonIP = true;
419 if(m_doDebug) std::cout << " * MuonSelector::passIPCuts * this muon has passed the IPCuts for vertex " << ivtx+1
420 << " pVZcut= " << std::abs(extz0 - thisVtx->position().z()) << " < " << m_diffZCut << std::endl
421 << " vtx (x,y,z): "
422 << " (" << thisVtx->position().x()
423 << ", " << thisVtx->position().y()
424 << ", " << thisVtx->position().z()
425 << ") type: " << thisVtx->vertexType()
426 << " Npart: " << thisVtx->nTrackParticles() << std::endl;
427 }
428 }
429 }
430 if (goodmuonIP) {
431 if(m_doDebug) std::cout <<" * MuonSelector::passIPCuts * this muon has passed the IPCuts. Zcut: "<< m_pVZCut << " m_diffZCut " << m_diffZCut << std::endl;
432 return true;
433 }
434 } // end new method
435 }
436 if(m_doDebug) std::cout <<" * MuonSelector * passIPCuts() * this muon has not passed the IPCuts: " << std::endl;
437 return false;
438}
439
442{
443 // statistics report
444 std::cout << " * MuonSelector* -- STATS -- " << std::endl
445 << " tested : " << m_testedmuons << std::endl;
446 if (m_doQualSelection) std::cout << " passQual: " << m_passqual << std::endl;
447 if (m_doIsoSelection) std::cout << " passIso : " << m_passiso << std::endl;
448 if (m_doPtSelection) std::cout << " passpt : " << m_passpt << std::endl;
449 if (m_doIPSelection) std::cout << " passip : " << m_passip << std::endl;
450 if (m_doMCPSelection) std::cout << " passmcp : " << m_passmcp << std::endl;
451 std::cout << " passall : " << m_passall << std::endl
452 << std::endl;
453
454 return;
455}
456
459{
460 using enum xAOD::Muon::Quality;
461 std::for_each (newname.begin(), newname.end(), [](char & c) {c = std::toupper(c);} );
462
463 if (newname.find("TIGHT") != std::string::npos) m_requestedMuonQuality = Tight;
464 if (newname.find("MEDIUM") != std::string::npos) m_requestedMuonQuality = Medium;
465 if (newname.find("LOOSE") != std::string::npos) m_requestedMuonQuality = Loose;
466 if (newname.find("VERYLOOSE")!= std::string::npos) m_requestedMuonQuality = VeryLoose;
467
468 std::cout << " ** MuonSelector::SetMuonQualityRequirement(" << newname <<") = " << m_requestedMuonQuality << std::endl;
469
470 return;
471}
472
#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
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)
xAOD::Muon::Quality m_requestedMuonQuality
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].