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 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 }
553 //fill results
554 m_chi2->Fill(chi2);
555 if (mode == 0){//plot both invmass and width vs variable
556 hout.at(0)->SetBinContent(i+1,mean);
557 hout.at(0)->SetBinError(i+1,meanErr);
558 hout.at(1)->SetBinContent(i+1,sigma);
559 hout.at(1)->SetBinError(i+1,sigmaErr);
560 } else if (mode==1){//plot only invmass vs variable
561 hout.at(0)->SetBinContent(i+1,mean);
562 hout.at(0)->SetBinError(i+1,meanErr);
563 } else if (mode==2){//plot only width vs variable
564 hout.at(0)->SetBinContent(i+1,sigma);
565 hout.at(0)->SetBinError(i+1,sigmaErr);
566 }
567
568 }// more than 50 events
569
570 delete htemp;
571 }
572 hout.at(0)->Sumw2();
573 if (hout.size()==2) hout.at(1)->Sumw2();
574 if (m_doSaveFits) ctemp->Print((psName+"]").c_str());
575 delete ctemp;
576}
577
578template<class T>
579void DiMuMon::RegisterHisto(MonGroup& mon, T* histo) {
580
581 StatusCode sc = mon.regHist(histo);
582 if (sc.isFailure() ) {
583 ATH_MSG_WARNING( "Cannot book histogram:" );
584 }
585}
586
588 int countPass = 0;
589 // https://twiki.cern.ch/twiki/bin/view/AtlasProtected/MCPAnalysisGuidelinesEPS2011
590 if (idTrk) {
591 uint8_t dummy(-1);
592 bool eBLhits = idTrk->summaryValue( dummy, xAOD::expectInnermostPixelLayerHit )? dummy :false;
593 int nBLhits = idTrk->summaryValue( dummy, xAOD::numberOfInnermostPixelLayerHits )? dummy :-1;
594 int nhitsPIX = idTrk->summaryValue( dummy, xAOD::numberOfPixelHits )? dummy :-1;
595 int nPIXDS = idTrk->summaryValue( dummy, xAOD::numberOfPixelDeadSensors )? dummy :-1;
596 int nhitsSCT = idTrk->summaryValue( dummy, xAOD::numberOfSCTHits )? dummy :-1;
597 int nSCTDS = idTrk->summaryValue( dummy, xAOD::numberOfSCTDeadSensors )? dummy :-1;
598 int nPIXH = idTrk->summaryValue( dummy, xAOD::numberOfPixelHoles )? dummy :-1;
599 int nSCTH = idTrk->summaryValue( dummy, xAOD::numberOfSCTHoles )? dummy :-1;
600
601 if (nBLhits>0 || !(eBLhits)) countPass+=1;
602 if ((nhitsPIX+nPIXDS)>1) countPass+=1;
603 if ((nhitsSCT+nSCTDS)>5) countPass+=1;
604 if ((nPIXH+nSCTH)<3) countPass+=1;
605 int nTRTout = idTrk->summaryValue( dummy, xAOD::numberOfTRTOutliers )? dummy :-1;
606 int nTRThits = idTrk->summaryValue( dummy, xAOD::numberOfTRTHits )? dummy :-1;
607 int n = nTRTout + nTRThits;
608 if (std::abs(idTrk->eta())<1.9){
609 if (n>5 && nTRTout<(0.9*n)) countPass+=1;
610 } else {
611 if (n>5){
612 if (nTRTout<(0.9*n)) countPass+=1;
613 } else countPass+=1;
614 }
615 }
616 else{
617 ATH_MSG_WARNING("Trying to check trackquality but no xAOD::TrackParticle available!");
618 }
619 return countPass==5;
620}
621
622//methods from IDPerformanceMoniroting by Weina
623double DiMuMon::getInvmass(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2, double Mass) const {
624 TLorentzVector particle1,particle2,v;
625 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)));
626 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)));
627 v=particle1+particle2;
628 double invmass = v.Mag()/Gaudi::Units::GeV;
629 return invmass;
630}
631
632double DiMuMon::getPt(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
633 double transmom;
634 double px = id1->p4().Px()+id2->p4().Px();
635 double py = id1->p4().Py()+id2->p4().Py();
636 transmom=sqrt(px*px+py*py);
637 return transmom/Gaudi::Units::GeV; //Gev
638}
639
640double DiMuMon::getEta(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
641 double eta;
642 double px=id1->p4().Px()+id2->p4().Px();
643 double py = id1->p4().Py()+id2->p4().Py();
644 double pz = id1->p4().Pz()+id2->p4().Pz();
645 double p=sqrt(px*px+py*py+pz*pz);
646 eta=0.5*log((p+pz)/(p-pz));
647 return eta;
648}
649
650double DiMuMon::getPhi(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
651 double px=id1->p4().Px()+id2->p4().Px();
652 double py = id1->p4().Py()+id2->p4().Py();
653 double p=sqrt(px*px+py*py);
654 double phi=acos(px/p);
655 if (py<0.) phi=-1.*phi;
656 return phi;
657}
658//curvature difference unit 1/GeV
659double DiMuMon::getCrtDiff(const xAOD::TrackParticle* id1, const xAOD::TrackParticle* id2 ) const {
660 double qoverpt1=id1->charge()/id1->pt();
661 double qoverpt2=id2->charge()/id2->pt();
662 double asym;
663 asym=std::abs(qoverpt1)-std::abs(qoverpt2);
664 return asym*1000;
665}
666
667
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:587
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:659
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:579
double getEta(const xAOD::TrackParticle *id1, const xAOD::TrackParticle *id2) const
Definition DiMuMon.cxx:640
double getPhi(const xAOD::TrackParticle *id1, const xAOD::TrackParticle *id2) const
Definition DiMuMon.cxx:650
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:632
double getInvmass(const xAOD::TrackParticle *track1, const xAOD::TrackParticle *track2, double Mass) const
Definition DiMuMon.cxx:623
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].