ATLAS Offline Software
Loading...
Searching...
No Matches
DiMuMon.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 "GaudiKernel/PhysicalConstants.h"
9
10#include "DiMuMon.h"
11
13
14#include "TF1.h"
15#include "TCanvas.h"
16#include "TStyle.h"
17
18#include "RooRealVar.h"
19#include "RooDataHist.h"
20#include "RooPlot.h"
21#include "RooBreitWigner.h"
22#include "RooCBShape.h"
23#include "RooFFTConvPdf.h"
24#include "RooGlobalFunc.h"
25#include "RooArgList.h"
26#include "RooFitResult.h"
27#include <cmath>
28#include <sstream>
29
30
31DiMuMon::DiMuMon( const std::string & type, const std::string & name, const IInterface* parent )
32 : ManagedMonitorToolBase( type, name, parent )
33 , m_triggerChainName("NoTrig")
34{
35 declareProperty( "resonName", m_resonName = "Zmumu" );
36 declareProperty( "triggerChainName", m_triggerChainName = "NoTrig" );
37 declareProperty( "setDebug", m_setDebug = false );
38 declareProperty( "minInvmass", m_minInvmass = 60.);
39 declareProperty( "maxInvmass", m_maxInvmass = 120.);
40 declareProperty( "regions", m_regions );
41 declareProperty( "nVarBins", m_nVarBins = 10);
42 declareProperty( "nPtBins", m_nPtBins = 100);
43 declareProperty( "nEtaBins", m_nEtaBins = 32);
44 declareProperty( "nPhiBins", m_nPhiBins = 36);
45 declareProperty( "nMassBins", m_nMassBins = 60);
46 declareProperty( "varsVSmean", m_varsVSmean);
47 declareProperty( "varsVSwidth", m_varsVSwidth);
48 declareProperty( "varsDistr", m_varsDistr);
49 declareProperty( "doSaveFits", m_doSaveFits = false );
50 declareProperty( "doFits", m_doFits = false );
51 declareProperty( "ptCut", m_ptCut = 0.);//GeV
52 declareProperty( "etaCut", m_etaCut = 2.5);
53}
54
55
56DiMuMon::~DiMuMon() = default;
57
59
61 ATH_CHECK( m_muonCollection.initialize() );
62
63 if (m_regions.empty()) {
64 m_regions.emplace_back("All");
65 }
66 // m_variables[] = {"eta","etaAll","etaPos","etaNeg","phi","phiAll","phiPos","phiNeg","pt","ptAll","ptPos","ptNeg","etaDiff","etaSumm","phiDiff","phiSumm","crtDiff"};
67 m_varLabels["eta"] = "Dimuon #eta";
68 m_varLabels["etaAll"] = "#eta (all #mu)";
69 m_varLabels["etaPos"] = "#eta(+)";
70 m_varLabels["etaNeg"] = "#eta(-)";
71
72 m_varLabels["phi"] = "Dimuon #phi";
73 m_varLabels["phiAll"] = "#phi (all #mu)";
74 m_varLabels["phiPos"] = "#phi(+)";
75 m_varLabels["phiNeg"] = "#phi(-)";
76
77 m_varLabels["pt"] = "Dimuon p_{T}";
78 m_varLabels["ptAll"] = "p_{T} (all #mu)";
79 m_varLabels["ptPos"] = "p_{T}(+) [GeV]";
80 m_varLabels["ptNeg"] = "p_{T}(-) [GeV]";
81
82 m_varLabels["etaDiff"] = "#eta(+)-#eta(-)";
83 m_varLabels["etaSumm"] = "#eta(+)+#eta(-)";
84 m_varLabels["phiDiff"] = "#phi(+)-#phi(-)";
85 m_varLabels["phiSumm"] = "#phi(+)+#phi(-)";
86 m_varLabels["crtDiff"] = "1/p_{T}(+) - 1/p_{T}(-) [GeV^{-1}]";
87
88 //resonance independent
89 // for eta these are filled as the histograms are declared due to the dependence between region and eta
90 m_varRanges["phi"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
91 m_varRanges["phiAll"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
92 m_varRanges["phiPos"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
93 m_varRanges["phiNeg"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
94 m_varRanges["etaSumm"] = std::make_pair(-5.,5.);
95
96 //resonance dependent
97 double ptMax = 0.;
98 if (m_resonName=="Jpsi" || m_resonName=="Upsi"){
99 m_varRanges["eta"] = std::make_pair(-3.,3.);
100 m_varRanges["phiDiff"] = std::make_pair(0.,1.);
101 m_varRanges["etaDiff"] = std::make_pair(-1.,1.);
102 m_varRanges["crtDiff"] = std::make_pair(-0.15,0.15);
103 m_varRanges["phiSumm"] = std::make_pair(-6.,6.);
104 if (m_ptCut == 0.) m_ptCut = 4.0;
105 ptMax = 18.;
106 } else if (m_resonName=="Zmumu") {
107 m_varRanges["eta"] = std::make_pair(-5.,5.);
108 m_varRanges["phiDiff"] = std::make_pair(0.,Gaudi::Units::pi);
109 m_varRanges["etaDiff"] = std::make_pair(-3.,3.);
110 m_varRanges["crtDiff"] = std::make_pair(-0.03,0.03);
111 m_varRanges["phiSumm"] = std::make_pair(-3.5,3.5);
112 if (m_ptCut == 0.) m_ptCut = 20.0;
113 ptMax = 100.;
114 }
115 m_varRanges["pt"] = std::make_pair(0.,ptMax);
116 m_varRanges["ptAll"] = std::make_pair(m_ptCut,ptMax);
117 m_varRanges["ptPos"] = std::make_pair(m_ptCut,ptMax);
118 m_varRanges["ptNeg"] = std::make_pair(m_ptCut,ptMax);
119
120
121 m_coneSize = 0.4;
122 m_isolationCut = 0.2;
123
124 return StatusCode::SUCCESS;
125
126}
127
129{
130
131
132 MonGroup dimuMonObj_shift( this, "DiMuMon/"+m_resonName+"/" + m_triggerChainName, run );
133 MonGroup dimuMonObj_expert( this, "DiMuMon/"+m_resonName+"/" + m_triggerChainName + "_detail", run );
134
136 // book histograms that are only made in the online environment...
137 }
138
140 // book histograms that are only relevant for cosmics data...
141 }
142
143
144
145
146 if( newRunFlag() ) {
147
148
149 m_chi2 = new TH1F("chi2","chi2",100,0.,10.);
150 RegisterHisto(dimuMonObj_expert,m_chi2);
151
152 const int nCuts = 8;
153 m_stat = new TH1F("statistics","Statistics",nCuts, 0., double(nCuts));
154 static const std::string binLabels[] ={"MuonIdTrk","TrkIsoPt40/Pt<.2","CombMuon","MCPgoodTrk","MuPtOK","eta<2.5","OppChargePair","InvMassOK"};
155 for(int ilabel=0;ilabel<nCuts;ilabel++){
156 m_stat->GetXaxis()->SetBinLabel(ilabel+1,binLabels[ilabel].c_str());
157 }
158 RegisterHisto(dimuMonObj_expert,m_stat);
159
160 //create histos for each region
161 for (const std::string& reg : m_regions) {
162
163 //declare region-dependent eta range
164 if (reg == "BB") {
165 m_varRanges["etaAll"] = std::make_pair(-1.05,1.05);
166 m_varRanges["etaPos"] = std::make_pair(-1.05,1.05);
167 m_varRanges["etaNeg"] = std::make_pair(-1.05,1.05);
168 } else if (reg == "EAEA") {
169 m_varRanges["etaAll"] = std::make_pair(1.05,2.5);
170 m_varRanges["etaPos"] = std::make_pair(1.05,2.5);
171 m_varRanges["etaNeg"] = std::make_pair(1.05,2.5);
172 } else if (reg == "ECEC") {
173 m_varRanges["etaAll"] = std::make_pair(-2.5,-1.05);
174 m_varRanges["etaPos"] = std::make_pair(-2.5,-1.05);
175 m_varRanges["etaNeg"] = std::make_pair(-2.5,-1.05);
176 } else {
177 m_varRanges["etaAll"] = std::make_pair(-2.5,2.5);
178 m_varRanges["etaPos"] = std::make_pair(-2.5,2.5);
179 m_varRanges["etaNeg"] = std::make_pair(-2.5,2.5);
180 }
181
182 //mass plots
183 std::string hname = m_resonName + "_invmass_" + reg;
184 std::string htitle = hname + "; Invmass[GeV/c^{2}]";
185 m_invmass[reg] = new TH1F(hname.c_str(), htitle.c_str(), m_nMassBins, m_minInvmass, m_maxInvmass);
186 RegisterHisto(dimuMonObj_shift,m_invmass[reg]);
187
188 //for each var vs mass plot
189 for (const std::string& varM : m_varsVSmean) {
190 hname = m_resonName + "_2DinvmassVS" + varM + "_" + reg;
191 htitle = hname + ";" + m_varLabels[varM] + ";Invmass[GeV/c^{2}]";
192 m_2DinvmassVSx[reg][varM] = new TH2F(hname.c_str(), htitle.c_str() ,m_nVarBins,m_varRanges[varM].first, m_varRanges[varM].second, m_nMassBins, m_minInvmass, m_maxInvmass);
193 RegisterHisto(dimuMonObj_shift,m_2DinvmassVSx[reg][varM]);
194
195 hname = m_resonName + "_invmassVS" + varM + "_" + reg;
196 htitle = hname + ";" + m_varLabels[varM] + ";Invmass[GeV/c^{2}]";
197 m_invmassVSx[reg][varM] = new TH1F(hname.c_str(), htitle.c_str(), m_nVarBins,m_varRanges[varM].first, m_varRanges[varM].second);
198 RegisterHisto(dimuMonObj_shift,m_invmassVSx[reg][varM]);
199 }
200
201 //for each var vs width plot
202 for (const std::string& varW : m_varsVSwidth) {
203 //book the corresponding 2D histo if it hasn't already been booked
204 if (m_2DinvmassVSx[reg].find(varW)==m_2DinvmassVSx[reg].end()){
205 hname = m_resonName + "_2DinvmassVS" + varW + "_" + reg;
206 htitle = hname + ";" + m_varLabels[varW] + ";Invmass[GeV/c^{2}]";
207 m_2DinvmassVSx[reg][varW] = new TH2F(hname.c_str(), htitle.c_str() ,m_nVarBins, m_varRanges[varW].first, m_varRanges[varW].second, m_nMassBins, m_minInvmass, m_maxInvmass);
208 RegisterHisto(dimuMonObj_shift,m_2DinvmassVSx[reg][varW]);
209 }
210
211 hname = m_resonName + "_widthVS" + varW + "_" + reg;
212 htitle = hname + ";" + m_varLabels[varW] + ";Width[GeV/c^{2}]";
213 m_widthVSx[reg][varW] = new TH1F(hname.c_str(),htitle.c_str() ,m_nVarBins,m_varRanges[varW].first, m_varRanges[varW].second);
214 RegisterHisto(dimuMonObj_expert,m_widthVSx[reg][varW]);
215
216 }
217
218 //for the each variable's distribution
219 for (const std::string& varD: m_varsDistr) {
220 hname = m_resonName + "_" + varD + "_" + reg;
221 htitle = hname + ";" + m_varLabels[varD];
222 if (varD == "eta" || varD == "etaAll" || varD == "etaPos" || varD == "etaNeg" ){
223 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nEtaBins, m_varRanges[varD].first, m_varRanges[varD].second);
224 } else if (varD == "pt" || varD == "ptAll" || varD == "ptPos" || varD == "ptNeg" ){
225 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nPtBins, m_varRanges[varD].first, m_varRanges[varD].second);
226 } else if (varD == "phi" || varD == "phiAll" || varD == "phiPos" || varD == "phiNeg" ){
227 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nPhiBins, m_varRanges[varD].first, m_varRanges[varD].second);
228 } else {
229 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nVarBins, m_varRanges[varD].first, m_varRanges[varD].second);
230 }
231 RegisterHisto(dimuMonObj_expert,m_xDistr[reg][varD]);
232 }
233 }
234 }
235
236 return StatusCode::SUCCESS;
237}
238
239
240StatusCode DiMuMon::fillHistograms(const EventContext& ctx)
241{
242
243 const double muonMass = ParticleConstants::muonMassInMeV;
244 //retrieve all muons
246 if(!muons.isValid()){
247 ATH_MSG_WARNING("Could not retrieve muon container");
248 return StatusCode::FAILURE;
249 } else ATH_MSG_DEBUG("Muon container successfully retrieved.");
250
251 //make a new container
253
254 //pick out the good muon tracks and store in the new container
255 for(const auto* muon : *muons ) {
256 const xAOD::TrackParticle *idTrk = muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
257 if (!idTrk) continue;
258 m_stat->Fill("MuonIdTrk",1);
259 double idTrkPt(0),ptSum(0);
260 float iso_pt40(0);
261 if( !muon->isolation(iso_pt40, xAOD::Iso::ptcone40) ) {
262 return StatusCode::FAILURE;
263 }
264 else {
265 idTrkPt = idTrk->pt();
266 ptSum = xAOD::Iso::ptcone40;
267 }
268 if(m_resonName=="Zmumu" && ptSum/idTrkPt > m_isolationCut) continue;
269 m_stat->Fill("TrkIsoPt40/Pt<.2",1);
270 if (!muon->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) continue;
271 m_stat->Fill("CombMuon",1);
272
273 if (!trackQuality(idTrk)) continue;
274 m_stat->Fill("MCPgoodTrk",1);
275
276 if (idTrkPt < m_ptCut*1000) continue;
277 m_stat->Fill("MuPtOK",1);
278
279 double idTrkEta = idTrk->eta();
280 if (std::abs(idTrkEta)>2.5) continue;
281 m_stat->Fill("eta<2.5",1);
282
283 goodMuons.push_back(muon);
284 }
285
286 //pair up the tracks of the good muons and fill histograms
287 int nMuons = goodMuons.size();
288
289 if (nMuons>1){
291 xAOD::MuonContainer::const_iterator muEnd = goodMuons.end();
292 for (; mu1!=muEnd;++mu1){
293 const xAOD::TrackParticle *id1 = (*mu1)->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
295 for (; mu2!=muEnd; ++mu2){
296 const xAOD::TrackParticle *id2 = (*mu2)->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
297 //consider only opposite sign muons
298 double q1 = id1->charge();
299 double q2 = id2->charge();
300 if (q1*q2>0) continue;
301 m_stat->Fill("OppChargePair",1);
302 const xAOD::TrackParticle *idPos = id1;
303 const xAOD::TrackParticle *idNeg = id2;
304 if (q1<0){
305 idPos = id2;
306 idNeg = id1;
307 }
308
309 //cut on the pair invariant mass
310 double invmass = getInvmass(id1,id2,muonMass);
311 if (invmass<m_minInvmass || invmass>m_maxInvmass) continue;
312 m_stat->Fill("InvMassOK",1);
313
314 //compute variables
315 m_varValues["eta"] = getEta(idPos,idNeg);
316 double etaPos = idPos->eta();
317 m_varValues["etaPos"] = etaPos;
318 double etaNeg = idNeg->eta();
319 m_varValues["etaNeg"] = etaNeg;
320 m_varValues["phi"] = getPhi(idPos,idNeg);
321 double phiPos = idPos->phi();
322 m_varValues["phiPos"] = phiPos;
323 double phiNeg = idNeg->phi();
324 m_varValues["phiNeg"] = phiNeg;
325 m_varValues["pt"] = getPt(idPos,idNeg);
326 double ptPos = idPos->pt()/Gaudi::Units::GeV;
327 m_varValues["ptPos"] = ptPos;
328 double ptNeg = idNeg->pt()/Gaudi::Units::GeV;
329 m_varValues["ptNeg"] = ptNeg;
330
331 m_varValues["crtDiff"] = getCrtDiff(idPos,idNeg);
332 m_varValues["etaDiff"] = etaPos - etaNeg;
333 double phiDiff = std::abs(phiPos - phiNeg);
334 if (phiDiff>Gaudi::Units::pi) phiDiff = 2*(Gaudi::Units::pi) - phiDiff;
335 m_varValues["phiDiff"] = phiDiff;
336 m_varValues["etaSumm"] = etaPos + etaNeg;
337 m_varValues["phiSumm"] = phiPos + phiNeg;
338
339 //determine which region muons are in
340 std::string region{};
341 if ((std::abs(etaPos)<1.05 || std::abs(etaPos)==1.05) && (std::abs(etaNeg)<1.05 || std::abs(etaNeg)==1.05)) region="BB";
342 else if ((etaPos>1.05 && etaPos<2.5) && (etaNeg>1.05 && etaNeg<2.5)) region="EAEA";
343 else if ((etaPos<-1.05 && etaPos>-2.5) && (etaNeg<-1.05 && etaNeg>-2.5)) region="ECEC";
344
345 //do we care about hese muons?
346 bool fillAll = m_invmass.find("All")!=m_invmass.end();
347 bool fillReg = false;
348 if (!region.empty()){
349 if (m_invmass.find(region)!=m_invmass.end()) fillReg=true;
350 }
351 if (!fillAll && !fillReg) continue;
352
353
354 //fill invmass histos
355 if (fillAll) m_invmass["All"]->Fill(invmass);
356 if (fillReg) m_invmass[region]->Fill(invmass);
357
358 //fill 2D histos
359 //first, retrieve the overlap of the width and mean variable lists which by construction is the list of vars in the 2D histos map
360 std::map<std::string, TH2F*>* allVars = nullptr;
361 if (fillAll){
362 allVars = &m_2DinvmassVSx["All"];
363 } else { //fillReg=true
364 allVars = &m_2DinvmassVSx[region];
365 }
366
367 for (const std::pair<const std::string, TH2F*>& p : *allVars) {
368 if (p.first!="etaAll" && p.first!="phiAll" && p.first!="ptAll"){
369 if (fillAll) m_2DinvmassVSx["All"][p.first]->Fill(m_varValues[p.first],invmass);
370 if (fillReg) m_2DinvmassVSx[region][p.first]->Fill(m_varValues[p.first],invmass);
371 } else if (p.first=="etaAll"){
372 if (fillAll){
373 m_2DinvmassVSx["All"]["etaAll"]->Fill(etaPos,invmass);
374 m_2DinvmassVSx["All"]["etaAll"]->Fill(etaNeg,invmass);
375 }
376 if (fillReg){
377 m_2DinvmassVSx[region]["etaAll"]->Fill(etaPos,invmass);
378 m_2DinvmassVSx[region]["etaAll"]->Fill(etaNeg,invmass);
379 }
380 } else if (p.first=="phiAll"){
381 if (fillAll){
382 m_2DinvmassVSx["All"]["phiAll"]->Fill(phiPos,invmass);
383 m_2DinvmassVSx["All"]["phiAll"]->Fill(phiNeg,invmass);
384 }
385 if (fillReg){
386 m_2DinvmassVSx[region]["phiAll"]->Fill(phiPos,invmass);
387 m_2DinvmassVSx[region]["phiAll"]->Fill(phiNeg,invmass);
388 }
389 } else if (p.first=="ptAll"){
390 if (fillAll){
391 m_2DinvmassVSx["All"]["ptAll"]->Fill(ptPos,invmass);
392 m_2DinvmassVSx["All"]["ptAll"]->Fill(ptNeg,invmass);
393 }
394 if (fillReg){
395 m_2DinvmassVSx[region]["ptAll"]->Fill(ptPos,invmass);
396 m_2DinvmassVSx[region]["ptAll"]->Fill(ptNeg,invmass);
397 }
398 }
399 }
400
401 //fill var distributions
402 //here we already know the list of variables so no need for gymnastics
403 for (const std::string& varD : m_varsDistr) {
404 if (varD!="etaAll" && varD!="phiAll" && varD!="ptAll"){
405 if (fillAll) m_xDistr["All"][varD]->Fill(m_varValues[varD]);
406 if (fillReg) m_xDistr[region][varD]->Fill(m_varValues[varD]);
407 } else if (varD=="etaAll"){
408 if (fillAll){
409 m_xDistr["All"]["etaAll"]->Fill(etaPos);
410 m_xDistr["All"]["etaAll"]->Fill(etaNeg);
411 }
412 if (fillReg){
413 m_xDistr[region]["etaAll"]->Fill(etaPos);
414 m_xDistr[region]["etaAll"]->Fill(etaNeg);
415 }
416 } else if (varD=="phiAll"){
417 if (fillAll){
418 m_xDistr["All"]["phiAll"]->Fill(phiPos);
419 m_xDistr["All"]["phiAll"]->Fill(phiNeg);
420 }
421 if (fillReg){
422 m_xDistr[region]["phiAll"]->Fill(phiPos);
423 m_xDistr[region]["phiAll"]->Fill(phiNeg);
424 }
425 } else if (varD=="ptAll"){
426 if (fillAll){
427 m_xDistr["All"]["ptAll"]->Fill(ptPos);
428 m_xDistr["All"]["ptAll"]->Fill(ptNeg);
429 }
430 if (fillReg){
431 m_xDistr[region]["ptAll"]->Fill(ptPos);
432 m_xDistr[region]["ptAll"]->Fill(ptNeg);
433 }
434 }
435 }
436
437
438 }// mu2 loop
439 }// mu1 loop
440 }// do we have more than 1 good muon?
441 return StatusCode::SUCCESS;
442}
443
444
446{
447
448
449 if(endOfRunFlag() && m_doFits) {
450 for (const std::string& reg : m_regions) {
451 for (const std::pair<const std::string, TH2F*>& p : m_2DinvmassVSx[reg]) {
452 int mode = 999.; //0 = both, 1 = mean only, 2 = wdth only
453 std::vector<TH1F*> hout;//1D histograms for fit results
454 if (m_invmassVSx[reg].find(p.first)!=m_invmassVSx[reg].end()){
455 if (m_widthVSx[reg].find(p.first)!=m_widthVSx[reg].end()) {
456 mode =0;
457 hout.push_back(m_invmassVSx[reg][p.first]);
458 hout.push_back(m_widthVSx[reg][p.first]);
459 } else {
460 mode = 1;
461 hout.push_back(m_invmassVSx[reg][p.first]);
462 }
463 } else {
464 mode = 2;
465 hout.push_back(m_widthVSx[reg][p.first]);
466 }
467 iterativeGausFit(m_2DinvmassVSx[reg][p.first],hout,mode);
468 } //variables
469 } //regions
470 } //isEndOfRun
471 return StatusCode::SUCCESS;
472}
473
474
475void DiMuMon::iterativeGausFit (TH2F* hin, const std::vector<TH1F*>& hout, int mode){
476 // a canvas may be needed when implmenting this into the post-processing file
477 std::string hname = hin->GetName();
478 std::string psName = hname + m_triggerChainName + ".ps";
479 TCanvas* ctemp = new TCanvas("ctemp","ctemp",500,500);
480 if (m_doSaveFits) ctemp->Print((psName+"[").c_str());
481 hin->SetMarkerSize(1.2);
482 hin->Draw();
483 if (m_doSaveFits) ctemp->Print(psName.c_str());
484 int nbins=hin->GetNbinsX();
485 for (int i=0; i<nbins;i++){
486 std::ostringstream o; o<<i;
487 std::string projName = hname + o.str();
488 TH1D* htemp = (TH1D*) (hin->ProjectionY(projName.c_str(),i+1,i+1)->Clone());
489 htemp->SetTitle(projName.c_str());
490 htemp->Sumw2();
491 if (htemp->GetEntries()>50){
492 double mean = 999., meanErr = 999., sigma = 999., sigmaErr = 999., chi2=0;
493 if (m_resonName == "Jpsi" || m_resonName == "Upsi"){
494 mean = htemp->GetMean();
495 sigma= htemp->GetRMS();
496 TF1* fn = new TF1("fn","gaus",mean-2*sigma,mean+2*sigma);
497 fn->SetParameters(float(htemp->GetEntries())/10.,mean,sigma);
498 htemp->Fit("fn","RMLQN");
499 mean = fn->GetParameter(1);
500 sigma= fn->GetParameter(2);
501 fn->SetRange(mean-1.2*sigma,mean+1.2*sigma);
502 fn->SetParameters(float(htemp->GetEntries())/10.,mean,sigma);
503 //gStyle->SetOptStat(1); // not thread-safe
504 if (m_doSaveFits) {
505 htemp->Fit("fn","RML");
506 ctemp->Print(psName.c_str());
507 } else htemp->Fit("fn","RMLQN");
508 double frange = 2.4*sigma;
509 double hrange = htemp->GetXaxis()->GetXmax()-htemp->GetXaxis()->GetXmin();
510 double ndf = frange/hrange*(htemp->GetNbinsX()) - 3;//substract the fit parameters
511 chi2 = (fn->GetChisquare())/ndf;
512 //fill results
513 mean = fn->GetParameter(1);
514 meanErr = fn->GetParError(1);
515 sigma = fn->GetParameter(2);
516 sigmaErr = fn->GetParError(2);
517 delete fn;
518 } else {
519 //fit Z peak with a convolution of BreitWigner and Crystal Ball fns, fit by Louise, implementation by Jike taken from IDPerfMon
520 RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
521 RooRealVar m("mass", "dimuon invariant mass", 91.2, 71., 111., "GeV");
522 RooDataHist *data = nullptr;
523 data = new RooDataHist("data", "data", m, htemp);
524 RooRealVar bwm0("bw_#mu", "bw_#mu", 91.2, 85.2, 97.2) ;
525 RooRealVar bwsg("bw_#sigma","bw_#sigma", 2.4952) ;
526 RooBreitWigner bw("bw","bw", m, bwm0, bwsg);
527
528 RooRealVar cbm0("cb_#mu", "cb_#mu", 0 ) ;
529 RooRealVar cbsg("cb_#sigma", "cb_#sigma", 3., 1., 10.) ;
530 RooRealVar cbal("cb_#alpha", "cb_#alpha", 2.0) ;
531 RooRealVar cbn( "cb_n", "cb_n", 1., 0.05, 3.) ;
532 RooCBShape cb( "cb", "cb", m, cbm0, cbsg, cbal, cbn);
533
534 m.setBins(5000);
535 RooFFTConvPdf bxc("bxc", "BW (X) CB", m, bw, cb) ;
536 [[maybe_unused]] auto owningPtr = bxc.fitTo(*data, RooFit::PrintLevel(-1), RooFit::PrintEvalErrors(-1));
537 RooPlot* frame = m.frame();
538 data->plotOn(frame, RooFit::MarkerSize(0.9));
539 bxc.paramOn(frame, RooFit::Format("NELU", RooFit::AutoPrecision(2)), RooFit::Layout(0.1,0.4,0.9));
540 bxc.plotOn (frame, RooFit::LineColor(kBlue));
541 if (m_doSaveFits) {
542 frame->Draw();
543 ctemp->Print(psName.c_str());
544 }
545 mean = bwm0.getVal();
546 meanErr = bwm0.getError();
547 sigma = cbsg.getVal();
548 sigmaErr = cbsg.getError();
549 chi2 = frame->chiSquare();
550 delete data;
551 delete frame;
552 //maybe I misunderstand the Root OwningPointer; coverity still thinks it leaks here?
553 //coverity[[RESOURCE_LEAK]]
554 }
555 //fill results
556 m_chi2->Fill(chi2);
557 if (mode == 0){//plot both invmass and width vs variable
558 hout.at(0)->SetBinContent(i+1,mean);
559 hout.at(0)->SetBinError(i+1,meanErr);
560 hout.at(1)->SetBinContent(i+1,sigma);
561 hout.at(1)->SetBinError(i+1,sigmaErr);
562 } else if (mode==1){//plot only invmass vs variable
563 hout.at(0)->SetBinContent(i+1,mean);
564 hout.at(0)->SetBinError(i+1,meanErr);
565 } else if (mode==2){//plot only width vs variable
566 hout.at(0)->SetBinContent(i+1,sigma);
567 hout.at(0)->SetBinError(i+1,sigmaErr);
568 }
569
570 }// more than 50 events
571
572 delete htemp;
573 }
574 hout.at(0)->Sumw2();
575 if (hout.size()==2) hout.at(1)->Sumw2();
576 if (m_doSaveFits) ctemp->Print((psName+"]").c_str());
577 delete ctemp;
578}
579
580template<class T>
581void DiMuMon::RegisterHisto(MonGroup& mon, T* histo) {
582
583 StatusCode sc = mon.regHist(histo);
584 if (sc.isFailure() ) {
585 ATH_MSG_WARNING( "Cannot book histogram:" );
586 }
587}
588
590 int countPass = 0;
591 // https://twiki.cern.ch/twiki/bin/view/AtlasProtected/MCPAnalysisGuidelinesEPS2011
592 if (idTrk) {
593 uint8_t dummy(-1);
594 bool eBLhits = idTrk->summaryValue( dummy, xAOD::expectInnermostPixelLayerHit )? dummy :false;
595 int nBLhits = idTrk->summaryValue( dummy, xAOD::numberOfInnermostPixelLayerHits )? dummy :-1;
596 int nhitsPIX = idTrk->summaryValue( dummy, xAOD::numberOfPixelHits )? dummy :-1;
597 int nPIXDS = idTrk->summaryValue( dummy, xAOD::numberOfPixelDeadSensors )? dummy :-1;
598 int nhitsSCT = idTrk->summaryValue( dummy, xAOD::numberOfSCTHits )? dummy :-1;
599 int nSCTDS = idTrk->summaryValue( dummy, xAOD::numberOfSCTDeadSensors )? dummy :-1;
600 int nPIXH = idTrk->summaryValue( dummy, xAOD::numberOfPixelHoles )? dummy :-1;
601 int nSCTH = idTrk->summaryValue( dummy, xAOD::numberOfSCTHoles )? dummy :-1;
602
603 if (nBLhits>0 || !(eBLhits)) countPass+=1;
604 if ((nhitsPIX+nPIXDS)>1) countPass+=1;
605 if ((nhitsSCT+nSCTDS)>5) countPass+=1;
606 if ((nPIXH+nSCTH)<3) countPass+=1;
607 int nTRTout = idTrk->summaryValue( dummy, xAOD::numberOfTRTOutliers )? dummy :-1;
608 int nTRThits = idTrk->summaryValue( dummy, xAOD::numberOfTRTHits )? dummy :-1;
609 int n = nTRTout + nTRThits;
610 if (std::abs(idTrk->eta())<1.9){
611 if (n>5 && nTRTout<(0.9*n)) countPass+=1;
612 } else {
613 if (n>5){
614 if (nTRTout<(0.9*n)) countPass+=1;
615 } else countPass+=1;
616 }
617 }
618 else{
619 ATH_MSG_WARNING("Trying to check trackquality but no xAOD::TrackParticle available!");
620 }
621 return countPass==5;
622}
623
624//methods from IDPerformanceMoniroting by Weina
625double DiMuMon::getInvmass(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2, double Mass) const {
626 TLorentzVector particle1,particle2,v;
627 particle1.SetPtEtaPhiE(id1->pt(),id1->eta(),id1->phi(),sqrt(pow(Mass,2)+pow(id1->p4().Px(),2)+pow(id1->p4().Py(),2)+pow(id1->p4().Pz(),2)));
628 particle2.SetPtEtaPhiE(id2->pt(),id2->eta(),id2->phi(),sqrt(pow(Mass,2)+pow(id2->p4().Px(),2)+pow(id2->p4().Py(),2)+pow(id2->p4().Pz(),2)));
629 v=particle1+particle2;
630 double invmass = v.Mag()/Gaudi::Units::GeV;
631 return invmass;
632}
633
634double DiMuMon::getPt(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
635 double transmom;
636 double px = id1->p4().Px()+id2->p4().Px();
637 double py = id1->p4().Py()+id2->p4().Py();
638 transmom=sqrt(px*px+py*py);
639 return transmom/Gaudi::Units::GeV; //Gev
640}
641
642double DiMuMon::getEta(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
643 double eta;
644 double px=id1->p4().Px()+id2->p4().Px();
645 double py = id1->p4().Py()+id2->p4().Py();
646 double pz = id1->p4().Pz()+id2->p4().Pz();
647 double p=sqrt(px*px+py*py+pz*pz);
648 eta=0.5*log((p+pz)/(p-pz));
649 return eta;
650}
651
652double DiMuMon::getPhi(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
653 double px=id1->p4().Px()+id2->p4().Px();
654 double py = id1->p4().Py()+id2->p4().Py();
655 double p=sqrt(px*px+py*py);
656 double phi=acos(px/p);
657 if (py<0.) phi=-1.*phi;
658 return phi;
659}
660//curvature difference unit 1/GeV
661double DiMuMon::getCrtDiff(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
662 double qoverpt1=id1->charge()/id1->pt();
663 double qoverpt2=id2->charge()/id2->pt();
664 double asym;
665 asym=std::abs(qoverpt1)-std::abs(qoverpt2);
666 return asym*1000;
667}
668
669
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
DataVector adapter that acts like it holds const pointers.
static Double_t sc
A number of constexpr particle constants to avoid hardcoding them directly in various places.
Define macros for attributes used to control the static checker.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
static Environment_t environment()
Returns the running environment of the monitoring application to help ManagedMonitorToolBase objects ...
static DataType_t dataType()
Returns the data type that the monitoring application is running over to help ManagedMonitorToolBase ...
DataVector adapter that acts like it holds const pointers.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
iterator begin() noexcept
Return an iterator pointing at the beginning of the collection.
iterator end() noexcept
Return an iterator pointing past the end of the collection.
DataModel_detail::const_iterator< DataVector > const_iterator
Definition DataVector.h:838
std::map< std::string, std::map< std::string, TH2F * > > m_2DinvmassVSx
Definition DiMuMon.h:84
double m_maxInvmass
Definition DiMuMon.h:60
std::map< std::string, std::pair< double, double > > m_varRanges
Definition DiMuMon.h:77
std::string m_resonName
Definition DiMuMon.h:64
std::map< std::string, double > m_varValues
Definition DiMuMon.h:78
int m_nVarBins
Definition DiMuMon.h:52
std::map< std::string, std::map< std::string, TH1F * > > m_xDistr
Definition DiMuMon.h:87
std::map< std::string, std::map< std::string, TH1F * > > m_invmassVSx
Definition DiMuMon.h:85
void iterativeGausFit(TH2F *hin, const std::vector< TH1F * > &hout, int mode)
Definition DiMuMon.cxx:475
bool m_doFits
Definition DiMuMon.h:68
virtual StatusCode bookHistograms()
An inheriting class should either override this function or bookHists().
Definition DiMuMon.cxx:128
double m_coneSize
Definition DiMuMon.h:57
int m_nPhiBins
Definition DiMuMon.h:55
std::map< std::string, std::map< std::string, TH1F * > > m_widthVSx
Definition DiMuMon.h:86
virtual ~DiMuMon()
virtual StatusCode initialize()
Definition DiMuMon.cxx:58
bool trackQuality(const xAOD::TrackParticle *idTrk)
Definition DiMuMon.cxx:589
double m_etaCut
Definition DiMuMon.h:62
int m_nMassBins
Definition DiMuMon.h:51
double getCrtDiff(const xAOD::TrackParticle *id1, const xAOD::TrackParticle *id2) const
Definition DiMuMon.cxx:661
int m_nEtaBins
Definition DiMuMon.h:54
std::string m_triggerChainName
Definition DiMuMon.h:65
int m_nPtBins
Definition DiMuMon.h:53
virtual StatusCode fillHistograms(const EventContext &ctx)
An inheriting class should either override this function or fillHists().
Definition DiMuMon.cxx:240
double m_isolationCut
Definition DiMuMon.h:58
std::vector< std::string > m_varsVSwidth
Definition DiMuMon.h:75
std::map< std::string, TH1F *, std::less<> > m_invmass
Definition DiMuMon.h:83
virtual StatusCode procHistograms()
An inheriting class should either override this function or finalHists().
Definition DiMuMon.cxx:445
std::vector< std::string > m_regions
Definition DiMuMon.h:73
bool m_setDebug
Definition DiMuMon.h:70
void RegisterHisto(MonGroup &mon, T *histo)
Definition DiMuMon.cxx:581
double getEta(const xAOD::TrackParticle *id1, const xAOD::TrackParticle *id2) const
Definition DiMuMon.cxx:642
double getPhi(const xAOD::TrackParticle *id1, const xAOD::TrackParticle *id2) const
Definition DiMuMon.cxx:652
TH1F * m_stat
Definition DiMuMon.h:82
SG::ReadHandleKey< xAOD::MuonContainer > m_muonCollection
Definition DiMuMon.h:66
DiMuMon(const std::string &type, const std::string &name, const IInterface *parent)
Definition DiMuMon.cxx:31
TH1F * m_chi2
Definition DiMuMon.h:81
double m_ptCut
Definition DiMuMon.h:61
double getPt(const xAOD::TrackParticle *id1, const xAOD::TrackParticle *id2) const
Definition DiMuMon.cxx:634
double getInvmass(const xAOD::TrackParticle *track1, const xAOD::TrackParticle *track2, double Mass) const
Definition DiMuMon.cxx:625
bool m_doSaveFits
Definition DiMuMon.h:69
std::vector< std::string > m_varsDistr
Definition DiMuMon.h:76
std::map< std::string, std::string > m_varLabels
Definition DiMuMon.h:79
double m_minInvmass
Definition DiMuMon.h:59
std::vector< std::string > m_varsVSmean
Definition DiMuMon.h:74
A container of information describing a monitoring object.
ManagedMonitorToolBase(const std::string &type, const std::string &name, const IInterface *parent)
virtual bool isValid() override final
Can the handle be successfully dereferenced?
virtual FourMom_t p4() const override final
The full 4-momentum of the particle.
virtual double phi() const override final
The azimuthal angle ( ) of the particle (has range to .).
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.
virtual double eta() const override final
The pseudorapidity ( ) of the particle.
float charge() const
Returns the charge.
double chi2(TH1 *h0, TH1 *h1)
void mean(std::vector< double > &bins, std::vector< double > &values, const std::vector< std::string > &files, const std::string &histname, const std::string &tplotname, const std::string &label="")
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:140
constexpr double muonMassInMeV
the mass of the muon (in MeV)
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
TrackParticle_v1 TrackParticle
Reference the current persistent version:
@ expectInnermostPixelLayerHit
Do we expect a 0th-layer barrel hit for this track?
@ numberOfPixelHoles
number of pixel layers on track with absence of hits [unit8_t].
@ numberOfTRTHits
number of TRT hits [unit8_t].
@ numberOfSCTDeadSensors
number of dead SCT sensors crossed [unit8_t].
@ numberOfSCTHits
number of hits in SCT [unit8_t].
@ numberOfInnermostPixelLayerHits
these are the hits in the 0th pixel barrel layer
@ numberOfPixelHits
these are the pixel hits, including the b-layer [unit8_t].
@ numberOfTRTOutliers
number of TRT outliers [unit8_t].
@ numberOfPixelDeadSensors
number of dead pixel sensors crossed [unit8_t].
@ numberOfSCTHoles
number of SCT holes [unit8_t].