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#include <sstream>
6#include "GaudiKernel/PhysicalConstants.h"
9
10#include "DiMuMon.h"
11
13
14#include <cmath>
15
16#include "TF1.h"
17#include "TCanvas.h"
18#include "TStyle.h"
19
20#include "RooRealVar.h"
21#include "RooDataHist.h"
22#include "RooPlot.h"
23#include "RooBreitWigner.h"
24#include "RooCBShape.h"
25#include "RooFFTConvPdf.h"
26#include "RooGlobalFunc.h"
27#include "RooArgList.h"
28#include "RooFitResult.h"
29
30
31//using namespace Analysis;
32//using namespace Rec;
33
34DiMuMon::DiMuMon( const std::string & type, const std::string & name, const IInterface* parent )
35 : ManagedMonitorToolBase( type, name, parent )
36 , m_triggerChainName("NoTrig")
37{
38 declareProperty( "resonName", m_resonName = "Zmumu" );
39 declareProperty( "triggerChainName", m_triggerChainName = "NoTrig" );
40 declareProperty( "setDebug", m_setDebug = false );
41 declareProperty( "minInvmass", m_minInvmass = 60.);
42 declareProperty( "maxInvmass", m_maxInvmass = 120.);
43 declareProperty( "regions", m_regions );
44 declareProperty( "nVarBins", m_nVarBins = 10);
45 declareProperty( "nPtBins", m_nPtBins = 100);
46 declareProperty( "nEtaBins", m_nEtaBins = 32);
47 declareProperty( "nPhiBins", m_nPhiBins = 36);
48 declareProperty( "nMassBins", m_nMassBins = 60);
49 declareProperty( "varsVSmean", m_varsVSmean);
50 declareProperty( "varsVSwidth", m_varsVSwidth);
51 declareProperty( "varsDistr", m_varsDistr);
52 declareProperty( "doSaveFits", m_doSaveFits = false );
53 declareProperty( "doFits", m_doFits = false );
54 declareProperty( "ptCut", m_ptCut = 0.);//GeV
55 declareProperty( "etaCut", m_etaCut = 2.5);
56}
57
58
59DiMuMon::~DiMuMon() = default;
60
62
64 ATH_CHECK( m_muonCollection.initialize() );
65
66 if (m_regions.empty()) {
67 m_regions.emplace_back("All");
68 }
69 // m_variables[] = {"eta","etaAll","etaPos","etaNeg","phi","phiAll","phiPos","phiNeg","pt","ptAll","ptPos","ptNeg","etaDiff","etaSumm","phiDiff","phiSumm","crtDiff"};
70 m_varLabels["eta"] = "Dimuon #eta";
71 m_varLabels["etaAll"] = "#eta (all #mu)";
72 m_varLabels["etaPos"] = "#eta(+)";
73 m_varLabels["etaNeg"] = "#eta(-)";
74
75 m_varLabels["phi"] = "Dimuon #phi";
76 m_varLabels["phiAll"] = "#phi (all #mu)";
77 m_varLabels["phiPos"] = "#phi(+)";
78 m_varLabels["phiNeg"] = "#phi(-)";
79
80 m_varLabels["pt"] = "Dimuon p_{T}";
81 m_varLabels["ptAll"] = "p_{T} (all #mu)";
82 m_varLabels["ptPos"] = "p_{T}(+) [GeV]";
83 m_varLabels["ptNeg"] = "p_{T}(-) [GeV]";
84
85 m_varLabels["etaDiff"] = "#eta(+)-#eta(-)";
86 m_varLabels["etaSumm"] = "#eta(+)+#eta(-)";
87 m_varLabels["phiDiff"] = "#phi(+)-#phi(-)";
88 m_varLabels["phiSumm"] = "#phi(+)+#phi(-)";
89 m_varLabels["crtDiff"] = "1/p_{T}(+) - 1/p_{T}(-) [GeV^{-1}]";
90
91 //resonance independent
92 // for eta these are filled as the histograms are declared due to the dependence between region and eta
93 m_varRanges["phi"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
94 m_varRanges["phiAll"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
95 m_varRanges["phiPos"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
96 m_varRanges["phiNeg"] = std::make_pair(-Gaudi::Units::pi,Gaudi::Units::pi);
97 m_varRanges["etaSumm"] = std::make_pair(-5.,5.);
98
99 //resonance dependent
100 double ptMax = 0.;
101 if (m_resonName=="Jpsi" || m_resonName=="Upsi"){
102 m_varRanges["eta"] = std::make_pair(-3.,3.);
103 m_varRanges["phiDiff"] = std::make_pair(0.,1.);
104 m_varRanges["etaDiff"] = std::make_pair(-1.,1.);
105 m_varRanges["crtDiff"] = std::make_pair(-0.15,0.15);
106 m_varRanges["phiSumm"] = std::make_pair(-6.,6.);
107 if (m_ptCut == 0.) m_ptCut = 4.0;
108 ptMax = 18.;
109 } else if (m_resonName=="Zmumu") {
110 m_varRanges["eta"] = std::make_pair(-5.,5.);
111 m_varRanges["phiDiff"] = std::make_pair(0.,Gaudi::Units::pi);
112 m_varRanges["etaDiff"] = std::make_pair(-3.,3.);
113 m_varRanges["crtDiff"] = std::make_pair(-0.03,0.03);
114 m_varRanges["phiSumm"] = std::make_pair(-3.5,3.5);
115 if (m_ptCut == 0.) m_ptCut = 20.0;
116 ptMax = 100.;
117 }
118 m_varRanges["pt"] = std::make_pair(0.,ptMax);
119 m_varRanges["ptAll"] = std::make_pair(m_ptCut,ptMax);
120 m_varRanges["ptPos"] = std::make_pair(m_ptCut,ptMax);
121 m_varRanges["ptNeg"] = std::make_pair(m_ptCut,ptMax);
122
123
124 m_coneSize = 0.4;
125 m_isolationCut = 0.2;
126
127 return StatusCode::SUCCESS;
128
129}
130
132{
133
134
135 MonGroup dimuMonObj_shift( this, "DiMuMon/"+m_resonName+"/" + m_triggerChainName, run );
136 MonGroup dimuMonObj_expert( this, "DiMuMon/"+m_resonName+"/" + m_triggerChainName + "_detail", run );
137
139 // book histograms that are only made in the online environment...
140 }
141
143 // book histograms that are only relevant for cosmics data...
144 }
145
146
147
148
149 if( newRunFlag() ) {
150
151
152 m_chi2 = new TH1F("chi2","chi2",100,0.,10.);
153 RegisterHisto(dimuMonObj_expert,m_chi2);
154
155 const int nCuts = 8;
156 m_stat = new TH1F("statistics","Statistics",nCuts, 0., double(nCuts));
157 static const std::string binLabels[] ={"MuonIdTrk","TrkIsoPt40/Pt<.2","CombMuon","MCPgoodTrk","MuPtOK","eta<2.5","OppChargePair","InvMassOK"};
158 for(int ilabel=0;ilabel<nCuts;ilabel++){
159 m_stat->GetXaxis()->SetBinLabel(ilabel+1,binLabels[ilabel].c_str());
160 }
161 RegisterHisto(dimuMonObj_expert,m_stat);
162
163 //create histos for each region
164 for (const std::string& reg : m_regions) {
165
166 //declare region-dependent eta range
167 if (reg == "BB") {
168 m_varRanges["etaAll"] = std::make_pair(-1.05,1.05);
169 m_varRanges["etaPos"] = std::make_pair(-1.05,1.05);
170 m_varRanges["etaNeg"] = std::make_pair(-1.05,1.05);
171 } else if (reg == "EAEA") {
172 m_varRanges["etaAll"] = std::make_pair(1.05,2.5);
173 m_varRanges["etaPos"] = std::make_pair(1.05,2.5);
174 m_varRanges["etaNeg"] = std::make_pair(1.05,2.5);
175 } else if (reg == "ECEC") {
176 m_varRanges["etaAll"] = std::make_pair(-2.5,-1.05);
177 m_varRanges["etaPos"] = std::make_pair(-2.5,-1.05);
178 m_varRanges["etaNeg"] = std::make_pair(-2.5,-1.05);
179 } else {
180 m_varRanges["etaAll"] = std::make_pair(-2.5,2.5);
181 m_varRanges["etaPos"] = std::make_pair(-2.5,2.5);
182 m_varRanges["etaNeg"] = std::make_pair(-2.5,2.5);
183 }
184
185 //mass plots
186 std::string hname = m_resonName + "_invmass_" + reg;
187 std::string htitle = hname + "; Invmass[GeV/c^{2}]";
188 m_invmass[reg] = new TH1F(hname.c_str(), htitle.c_str(), m_nMassBins, m_minInvmass, m_maxInvmass);
189 RegisterHisto(dimuMonObj_shift,m_invmass[reg]);
190
191 //for each var vs mass plot
192 for (const std::string& varM : m_varsVSmean) {
193 hname = m_resonName + "_2DinvmassVS" + varM + "_" + reg;
194 htitle = hname + ";" + m_varLabels[varM] + ";Invmass[GeV/c^{2}]";
195 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);
196 RegisterHisto(dimuMonObj_shift,m_2DinvmassVSx[reg][varM]);
197
198 hname = m_resonName + "_invmassVS" + varM + "_" + reg;
199 htitle = hname + ";" + m_varLabels[varM] + ";Invmass[GeV/c^{2}]";
200 m_invmassVSx[reg][varM] = new TH1F(hname.c_str(), htitle.c_str(), m_nVarBins,m_varRanges[varM].first, m_varRanges[varM].second);
201 RegisterHisto(dimuMonObj_shift,m_invmassVSx[reg][varM]);
202 }
203
204 //for each var vs width plot
205 for (const std::string& varW : m_varsVSwidth) {
206 //book the corresponding 2D histo if it hasn't already been booked
207 if (m_2DinvmassVSx[reg].find(varW)==m_2DinvmassVSx[reg].end()){
208 hname = m_resonName + "_2DinvmassVS" + varW + "_" + reg;
209 htitle = hname + ";" + m_varLabels[varW] + ";Invmass[GeV/c^{2}]";
210 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);
211 RegisterHisto(dimuMonObj_shift,m_2DinvmassVSx[reg][varW]);
212 }
213
214 hname = m_resonName + "_widthVS" + varW + "_" + reg;
215 htitle = hname + ";" + m_varLabels[varW] + ";Width[GeV/c^{2}]";
216 m_widthVSx[reg][varW] = new TH1F(hname.c_str(),htitle.c_str() ,m_nVarBins,m_varRanges[varW].first, m_varRanges[varW].second);
217 RegisterHisto(dimuMonObj_expert,m_widthVSx[reg][varW]);
218
219 }
220
221 //for the each variable's distribution
222 for (const std::string& varD: m_varsDistr) {
223 hname = m_resonName + "_" + varD + "_" + reg;
224 htitle = hname + ";" + m_varLabels[varD];
225 if (varD == "eta" || varD == "etaAll" || varD == "etaPos" || varD == "etaNeg" ){
226 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nEtaBins, m_varRanges[varD].first, m_varRanges[varD].second);
227 } else if (varD == "pt" || varD == "ptAll" || varD == "ptPos" || varD == "ptNeg" ){
228 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nPtBins, m_varRanges[varD].first, m_varRanges[varD].second);
229 } else if (varD == "phi" || varD == "phiAll" || varD == "phiPos" || varD == "phiNeg" ){
230 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nPhiBins, m_varRanges[varD].first, m_varRanges[varD].second);
231 } else {
232 m_xDistr[reg][varD] = new TH1F(hname.c_str(), htitle.c_str(), m_nVarBins, m_varRanges[varD].first, m_varRanges[varD].second);
233 }
234 RegisterHisto(dimuMonObj_expert,m_xDistr[reg][varD]);
235 }
236 }
237 }
238
239 return StatusCode::SUCCESS;
240}
241
242
243StatusCode DiMuMon::fillHistograms(const EventContext& ctx)
244{
245
246 const double muonMass = ParticleConstants::muonMassInMeV;
247 //retrieve all muons
249 if(!muons.isValid()){
250 ATH_MSG_WARNING("Could not retrieve muon container");
251 return StatusCode::FAILURE;
252 } else ATH_MSG_DEBUG("Muon container successfully retrieved.");
253
254 //make a new container
256
257 //pick out the good muon tracks and store in the new container
258 for(const auto* muon : *muons ) {
259 const xAOD::TrackParticle *idTrk = muon->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
260 if (!idTrk) continue;
261 m_stat->Fill("MuonIdTrk",1);
262 double idTrkPt(0),ptSum(0);
263 float iso_pt40(0);
264 if( !muon->isolation(iso_pt40, xAOD::Iso::ptcone40) ) {
265 return StatusCode::FAILURE;
266 }
267 else {
268 idTrkPt = idTrk->pt();
269 ptSum = xAOD::Iso::ptcone40;
270 }
271 if(m_resonName=="Zmumu" && ptSum/idTrkPt > m_isolationCut) continue;
272 m_stat->Fill("TrkIsoPt40/Pt<.2",1);
273 if (!muon->trackParticle(xAOD::Muon::TrackParticleType::CombinedTrackParticle)) continue;
274 m_stat->Fill("CombMuon",1);
275
276 if (!trackQuality(idTrk)) continue;
277 m_stat->Fill("MCPgoodTrk",1);
278
279 if (idTrkPt < m_ptCut*1000) continue;
280 m_stat->Fill("MuPtOK",1);
281
282 double idTrkEta = idTrk->eta();
283 if (std::abs(idTrkEta)>2.5) continue;
284 m_stat->Fill("eta<2.5",1);
285
286 goodMuons.push_back(muon);
287 }
288
289 //pair up the tracks of the good muons and fill histograms
290 int nMuons = goodMuons.size();
291
292 if (nMuons>1){
294 xAOD::MuonContainer::const_iterator muEnd = goodMuons.end();
295 for (; mu1!=muEnd;++mu1){
296 const xAOD::TrackParticle *id1 = (*mu1)->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
298 for (; mu2!=muEnd; ++mu2){
299 const xAOD::TrackParticle *id2 = (*mu2)->trackParticle(xAOD::Muon::TrackParticleType::InnerDetectorTrackParticle);
300 //consider only opposite sign muons
301 double q1 = id1->charge();
302 double q2 = id2->charge();
303 if (q1*q2>0) continue;
304 m_stat->Fill("OppChargePair",1);
305 const xAOD::TrackParticle *idPos = id1;
306 const xAOD::TrackParticle *idNeg = id2;
307 if (q1<0){
308 idPos = id2;
309 idNeg = id1;
310 }
311
312 //cut on the pair invariant mass
313 double invmass = getInvmass(id1,id2,muonMass);
314 if (invmass<m_minInvmass || invmass>m_maxInvmass) continue;
315 m_stat->Fill("InvMassOK",1);
316
317 //compute variables
318 m_varValues["eta"] = getEta(idPos,idNeg);
319 double etaPos = idPos->eta();
320 m_varValues["etaPos"] = etaPos;
321 double etaNeg = idNeg->eta();
322 m_varValues["etaNeg"] = etaNeg;
323 m_varValues["phi"] = getPhi(idPos,idNeg);
324 double phiPos = idPos->phi();
325 m_varValues["phiPos"] = phiPos;
326 double phiNeg = idNeg->phi();
327 m_varValues["phiNeg"] = phiNeg;
328 m_varValues["pt"] = getPt(idPos,idNeg);
329 double ptPos = idPos->pt()/Gaudi::Units::GeV;
330 m_varValues["ptPos"] = ptPos;
331 double ptNeg = idNeg->pt()/Gaudi::Units::GeV;
332 m_varValues["ptNeg"] = ptNeg;
333
334 m_varValues["crtDiff"] = getCrtDiff(idPos,idNeg);
335 m_varValues["etaDiff"] = etaPos - etaNeg;
336 double phiDiff = std::abs(phiPos - phiNeg);
337 if (phiDiff>Gaudi::Units::pi) phiDiff = 2*(Gaudi::Units::pi) - phiDiff;
338 m_varValues["phiDiff"] = phiDiff;
339 m_varValues["etaSumm"] = etaPos + etaNeg;
340 m_varValues["phiSumm"] = phiPos + phiNeg;
341
342 //determine which region muons are in
343 std::string region = "";
344 if ((std::abs(etaPos)<1.05 || std::abs(etaPos)==1.05) && (std::abs(etaNeg)<1.05 || std::abs(etaNeg)==1.05)) region="BB";
345 else if ((etaPos>1.05 && etaPos<2.5) && (etaNeg>1.05 && etaNeg<2.5)) region="EAEA";
346 else if ((etaPos<-1.05 && etaPos>-2.5) && (etaNeg<-1.05 && etaNeg>-2.5)) region="ECEC";
347
348 //do we care about hese muons?
349 bool fillAll = m_invmass.find("All")!=m_invmass.end();
350 bool fillReg = false;
351 if (region!=""){
352 if (m_invmass.find(region)!=m_invmass.end()) fillReg=true;
353 }
354 if (!fillAll && !fillReg) continue;
355
356
357 //fill invmass histos
358 if (fillAll) m_invmass["All"]->Fill(invmass);
359 if (fillReg) m_invmass[region]->Fill(invmass);
360
361 //fill 2D histos
362 //first, retrieve the overlap of the width and mean variable lists which by construction is the list of vars in the 2D histos map
363 std::map<std::string, TH2F*>* allVars = nullptr;
364 if (fillAll){
365 allVars = &m_2DinvmassVSx["All"];
366 } else { //fillReg=true
367 allVars = &m_2DinvmassVSx[region];
368 }
369
370 for (const std::pair<const std::string, TH2F*>& p : *allVars) {
371 if (p.first!="etaAll" && p.first!="phiAll" && p.first!="ptAll"){
372 if (fillAll) m_2DinvmassVSx["All"][p.first]->Fill(m_varValues[p.first],invmass);
373 if (fillReg) m_2DinvmassVSx[region][p.first]->Fill(m_varValues[p.first],invmass);
374 } else if (p.first=="etaAll"){
375 if (fillAll){
376 m_2DinvmassVSx["All"]["etaAll"]->Fill(etaPos,invmass);
377 m_2DinvmassVSx["All"]["etaAll"]->Fill(etaNeg,invmass);
378 }
379 if (fillReg){
380 m_2DinvmassVSx[region]["etaAll"]->Fill(etaPos,invmass);
381 m_2DinvmassVSx[region]["etaAll"]->Fill(etaNeg,invmass);
382 }
383 } else if (p.first=="phiAll"){
384 if (fillAll){
385 m_2DinvmassVSx["All"]["phiAll"]->Fill(phiPos,invmass);
386 m_2DinvmassVSx["All"]["phiAll"]->Fill(phiNeg,invmass);
387 }
388 if (fillReg){
389 m_2DinvmassVSx[region]["phiAll"]->Fill(phiPos,invmass);
390 m_2DinvmassVSx[region]["phiAll"]->Fill(phiNeg,invmass);
391 }
392 } else if (p.first=="ptAll"){
393 if (fillAll){
394 m_2DinvmassVSx["All"]["ptAll"]->Fill(ptPos,invmass);
395 m_2DinvmassVSx["All"]["ptAll"]->Fill(ptNeg,invmass);
396 }
397 if (fillReg){
398 m_2DinvmassVSx[region]["ptAll"]->Fill(ptPos,invmass);
399 m_2DinvmassVSx[region]["ptAll"]->Fill(ptNeg,invmass);
400 }
401 }
402 }
403
404 //fill var distributions
405 //here we already know the list of variables so no need for gymnastics
406 for (const std::string& varD : m_varsDistr) {
407 if (varD!="etaAll" && varD!="phiAll" && varD!="ptAll"){
408 if (fillAll) m_xDistr["All"][varD]->Fill(m_varValues[varD]);
409 if (fillReg) m_xDistr[region][varD]->Fill(m_varValues[varD]);
410 } else if (varD=="etaAll"){
411 if (fillAll){
412 m_xDistr["All"]["etaAll"]->Fill(etaPos);
413 m_xDistr["All"]["etaAll"]->Fill(etaNeg);
414 }
415 if (fillReg){
416 m_xDistr[region]["etaAll"]->Fill(etaPos);
417 m_xDistr[region]["etaAll"]->Fill(etaNeg);
418 }
419 } else if (varD=="phiAll"){
420 if (fillAll){
421 m_xDistr["All"]["phiAll"]->Fill(phiPos);
422 m_xDistr["All"]["phiAll"]->Fill(phiNeg);
423 }
424 if (fillReg){
425 m_xDistr[region]["phiAll"]->Fill(phiPos);
426 m_xDistr[region]["phiAll"]->Fill(phiNeg);
427 }
428 } else if (varD=="ptAll"){
429 if (fillAll){
430 m_xDistr["All"]["ptAll"]->Fill(ptPos);
431 m_xDistr["All"]["ptAll"]->Fill(ptNeg);
432 }
433 if (fillReg){
434 m_xDistr[region]["ptAll"]->Fill(ptPos);
435 m_xDistr[region]["ptAll"]->Fill(ptNeg);
436 }
437 }
438 }
439
440
441 }// mu2 loop
442 }// mu1 loop
443 }// do we have more than 1 good muon?
444 return StatusCode::SUCCESS;
445}
446
447
449{
450
451
452 if(endOfRunFlag() && m_doFits) {
453 for (const std::string& reg : m_regions) {
454 for (const std::pair<const std::string, TH2F*>& p : m_2DinvmassVSx[reg]) {
455 int mode = 999.; //0 = both, 1 = mean only, 2 = wdth only
456 std::vector<TH1F*> hout;//1D histograms for fit results
457 if (m_invmassVSx[reg].find(p.first)!=m_invmassVSx[reg].end()){
458 if (m_widthVSx[reg].find(p.first)!=m_widthVSx[reg].end()) {
459 mode =0;
460 hout.push_back(m_invmassVSx[reg][p.first]);
461 hout.push_back(m_widthVSx[reg][p.first]);
462 } else {
463 mode = 1;
464 hout.push_back(m_invmassVSx[reg][p.first]);
465 }
466 } else {
467 mode = 2;
468 hout.push_back(m_widthVSx[reg][p.first]);
469 }
470 iterativeGausFit(m_2DinvmassVSx[reg][p.first],hout,mode);
471 } //variables
472 } //regions
473 } //isEndOfRun
474 return StatusCode::SUCCESS;
475}
476
477
478void DiMuMon::iterativeGausFit (TH2F* hin, const std::vector<TH1F*>& hout, int mode){
479 // a canvas may be needed when implmenting this into the post-processing file
480 std::string hname = hin->GetName();
481 std::string psName = hname + m_triggerChainName + ".ps";
482 TCanvas* ctemp = new TCanvas("ctemp","ctemp",500,500);
483 if (m_doSaveFits) ctemp->Print((psName+"[").c_str());
484 hin->SetMarkerSize(1.2);
485 hin->Draw();
486 if (m_doSaveFits) ctemp->Print(psName.c_str());
487 int nbins=hin->GetNbinsX();
488 for (int i=0; i<nbins;i++){
489 std::ostringstream o; o<<i;
490 std::string projName = hname + o.str();
491 TH1D* htemp = (TH1D*) (hin->ProjectionY(projName.c_str(),i+1,i+1)->Clone());
492 htemp->SetTitle(projName.c_str());
493 htemp->Sumw2();
494 if (htemp->GetEntries()>50){
495 double mean = 999., meanErr = 999., sigma = 999., sigmaErr = 999., chi2=0;
496 if (m_resonName == "Jpsi" || m_resonName == "Upsi"){
497 mean = htemp->GetMean();
498 sigma= htemp->GetRMS();
499 TF1* fn = new TF1("fn","gaus",mean-2*sigma,mean+2*sigma);
500 fn->SetParameters(float(htemp->GetEntries())/10.,mean,sigma);
501 htemp->Fit("fn","RMLQN");
502 mean = fn->GetParameter(1);
503 sigma= fn->GetParameter(2);
504 fn->SetRange(mean-1.2*sigma,mean+1.2*sigma);
505 fn->SetParameters(float(htemp->GetEntries())/10.,mean,sigma);
506 //gStyle->SetOptStat(1); // not thread-safe
507 if (m_doSaveFits) {
508 htemp->Fit("fn","RML");
509 ctemp->Print(psName.c_str());
510 } else htemp->Fit("fn","RMLQN");
511 double frange = 2.4*sigma;
512 double hrange = htemp->GetXaxis()->GetXmax()-htemp->GetXaxis()->GetXmin();
513 double ndf = frange/hrange*(htemp->GetNbinsX()) - 3;//substract the fit parameters
514 chi2 = (fn->GetChisquare())/ndf;
515 //fill results
516 mean = fn->GetParameter(1);
517 meanErr = fn->GetParError(1);
518 sigma = fn->GetParameter(2);
519 sigmaErr = fn->GetParError(2);
520 delete fn;
521 } else {
522 //fit Z peak with a convolution of BreitWigner and Crystal Ball fns, fit by Louise, implementation by Jike taken from IDPerfMon
523 RooMsgService::instance().setGlobalKillBelow(RooFit::FATAL);
524 RooRealVar m("mass", "dimuon invariant mass", 91.2, 71., 111., "GeV");
525 RooDataHist *data = nullptr;
526 data = new RooDataHist("data", "data", m, htemp);
527 RooRealVar bwm0("bw_#mu", "bw_#mu", 91.2, 85.2, 97.2) ;
528 RooRealVar bwsg("bw_#sigma","bw_#sigma", 2.4952) ;
529 RooBreitWigner bw("bw","bw", m, bwm0, bwsg);
530
531 RooRealVar cbm0("cb_#mu", "cb_#mu", 0 ) ;
532 RooRealVar cbsg("cb_#sigma", "cb_#sigma", 3., 1., 10.) ;
533 RooRealVar cbal("cb_#alpha", "cb_#alpha", 2.0) ;
534 RooRealVar cbn( "cb_n", "cb_n", 1., 0.05, 3.) ;
535 RooCBShape cb( "cb", "cb", m, cbm0, cbsg, cbal, cbn);
536
537 m.setBins(5000);
538 RooFFTConvPdf bxc("bxc", "BW (X) CB", m, bw, cb) ;
539 bxc.fitTo(*data, RooFit::PrintLevel(-1), RooFit::PrintEvalErrors(-1));
540 RooPlot* frame = m.frame();
541 data->plotOn(frame, RooFit::MarkerSize(0.9));
542 bxc.paramOn(frame, RooFit::Format("NELU", RooFit::AutoPrecision(2)), RooFit::Layout(0.1,0.4,0.9));
543 bxc.plotOn (frame, RooFit::LineColor(kBlue));
544 if (m_doSaveFits) {
545 frame->Draw();
546 ctemp->Print(psName.c_str());
547 }
548 mean = bwm0.getVal();
549 meanErr = bwm0.getError();
550 sigma = cbsg.getVal();
551 sigmaErr = cbsg.getError();
552 chi2 = frame->chiSquare();
553 delete data;
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.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
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:478
bool m_doFits
Definition DiMuMon.h:68
virtual StatusCode bookHistograms()
An inheriting class should either override this function or bookHists().
Definition DiMuMon.cxx:131
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:61
bool trackQuality(const xAOD::TrackParticle *idTrk)
Definition DiMuMon.cxx:589
double m_etaCut
Definition DiMuMon.h:62
std::map< std::string, TH1F * > m_invmass
Definition DiMuMon.h:83
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:243
double m_isolationCut
Definition DiMuMon.h:58
std::vector< std::string > m_varsVSwidth
Definition DiMuMon.h:75
virtual StatusCode procHistograms()
An inheriting class should either override this function or finalHists().
Definition DiMuMon.cxx:448
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:34
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].