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