ATLAS Offline Software
Loading...
Searching...
No Matches
TFCS2DFunctionHistogram.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include <algorithm>
7#include <iostream>
8#include "TMath.h"
9#include "TCanvas.h"
10#include "TH2F.h"
11#include "TRandom.h"
12#include "TFile.h"
13
14//=============================================
15//======= TFCS2DFunctionHistogram =========
16//=============================================
17
19 Int_t nbinsx = hist->GetNbinsX();
20 Int_t nbinsy = hist->GetNbinsY();
21 Int_t nbins = nbinsx * nbinsy;
22
23 float integral = 0;
24 m_HistoBorders.resize(nbinsx + 1);
25 m_HistoBordersy.resize(nbinsy + 1);
26 m_HistoContents.resize(nbins);
27 int ibin = 0;
28 for (int iy = 1; iy <= nbinsy; iy++) {
29 for (int ix = 1; ix <= nbinsx; ix++) {
30 float binval = hist->GetBinContent(ix, iy);
31 if (binval < 0) {
32 // Can't work if a bin is negative, forcing bins to 0 in this case
33 double fraction = binval / hist->Integral();
34 if (TMath::Abs(fraction) > 1e-5) {
35 ATH_MSG_WARNING("bin content is negative in histogram "
36 << hist->GetName() << " : " << hist->GetTitle()
37 << " binval=" << binval << " " << fraction * 100
38 << "% of integral=" << hist->Integral()
39 << ". Forcing bin to 0.");
40 }
41 binval = 0;
42 }
43 integral += binval;
45 ++ibin;
46 }
47 }
48 if (integral <= 0) {
49 ATH_MSG_ERROR("histogram " << hist->GetName() << " : " << hist->GetTitle()
50 << " integral=" << integral << " is <=0");
51 m_HistoBorders.resize(0);
52 m_HistoBordersy.resize(0);
53 m_HistoContents.resize(0);
54 return;
55 }
56
57 for (int ix = 1; ix <= nbinsx; ix++)
58 m_HistoBorders[ix - 1] = hist->GetXaxis()->GetBinLowEdge(ix);
59 m_HistoBorders[nbinsx] = hist->GetXaxis()->GetXmax();
60
61 for (int iy = 1; iy <= nbinsy; iy++)
62 m_HistoBordersy[iy - 1] = hist->GetYaxis()->GetBinLowEdge(iy);
63 m_HistoBordersy[nbinsy] = hist->GetYaxis()->GetXmax();
64
65 for (ibin = 0; ibin < nbins; ++ibin)
67}
68
69void TFCS2DFunctionHistogram::rnd_to_fct(float &valuex, float &valuey,
70 float rnd0, float rnd1) const {
71 if (m_HistoContents.empty()) {
72 valuex = 0;
73 valuey = 0;
74 return;
75 }
76 auto it =
77 std::upper_bound(m_HistoContents.begin(), m_HistoContents.end(), rnd0);
78 int ibin = std::distance(m_HistoContents.begin(), it);
79 if (ibin >= (int)m_HistoContents.size())
80 ibin = m_HistoContents.size() - 1;
81 Int_t nbinsx = m_HistoBorders.size() - 1;
82 Int_t biny = ibin / nbinsx;
83 Int_t binx = ibin - nbinsx * biny;
84
85 float basecont = 0;
86 if (ibin > 0)
87 basecont = m_HistoContents[ibin - 1];
88
89 float dcont = m_HistoContents[ibin] - basecont;
90 if (dcont > 0) {
91 valuex = m_HistoBorders[binx] +
92 (m_HistoBorders[binx + 1] - m_HistoBorders[binx]) *
93 (rnd0 - basecont) / dcont;
94 } else {
95 valuex = m_HistoBorders[binx] +
96 (m_HistoBorders[binx + 1] - m_HistoBorders[binx]) / 2;
97 }
98 valuey = m_HistoBordersy[biny] +
99 (m_HistoBordersy[biny + 1] - m_HistoBordersy[biny]) * rnd1;
100}
101
102void TFCS2DFunctionHistogram::unit_test ATLAS_NOT_THREAD_SAFE(TH2 *hist) {
104 int nbinsx;
105 int nbinsy;
106 if (hist == nullptr) {
107 // hist=new TH2F("test2D","test2D",5,0,5,5,0,10);
108 nbinsx = 64;
109 nbinsy = 64;
110 hist = new TH2F("test2D", "test2D", nbinsx, 0, 1, nbinsy, 0, 1);
111 hist->Sumw2();
112 for (int ix = 1; ix <= nbinsx; ++ix) {
113 for (int iy = 1; iy <= nbinsy; ++iy) {
114 hist->SetBinContent(ix, iy,
115 (0.5 + gRandom->Rndm()) * (nbinsx + ix) *
116 (nbinsy * nbinsy / 2 + iy * iy));
117 if (gRandom->Rndm() < 0.1)
118 hist->SetBinContent(ix, iy, 0);
119 hist->SetBinError(ix, iy, 0);
120 }
121 }
122 }
123 TFCS2DFunctionHistogram rtof(hist);
124 nbinsx = hist->GetNbinsX();
125 nbinsy = hist->GetNbinsY();
126
127 float value[2];
128 float rnd[2];
129 //cppcheck-suppress uninitvar
130 for (rnd[0] = 0; rnd[0] < 0.9999; rnd[0] += 0.25) {
131 for (rnd[1] = 0; rnd[1] < 0.9999; rnd[1] += 0.25) {
132 rtof.rnd_to_fct(value, rnd);
133 ATH_MSG_NOCLASS(logger, "rnd0=" << rnd[0] << " rnd1=" << rnd[1]
134 << " -> x=" << value[0]
135 << " y=" << value[1]);
136 }
137 }
138
139 // TH2F* hist_val=new
140 // TH2F("val2D","val2D",16,hist->GetXaxis()->GetXmin(),hist->GetXaxis()->GetXmax(),
141 // 16,hist->GetYaxis()->GetXmin(),hist->GetYaxis()->GetXmax());
142 TH2F *hist_val = (TH2F *)hist->Clone("hist_val");
143 hist_val->Reset();
144 int nrnd = 100000000;
145 float weight = hist->Integral() / nrnd;
146 hist_val->Sumw2();
147 for (int i = 0; i < nrnd; ++i) {
148 rnd[0] = gRandom->Rndm();
149 rnd[1] = gRandom->Rndm();
150 rtof.rnd_to_fct(value, rnd);
151 hist_val->Fill(value[0], value[1], weight);
152 }
153 hist_val->Add(hist, -1);
154
155 TH1F *hist_pull = new TH1F("pull", "pull", 80, -4, 4);
156 for (int ix = 1; ix <= nbinsx; ++ix) {
157 for (int iy = 1; iy <= nbinsy; ++iy) {
158 float val = hist_val->GetBinContent(ix, iy);
159 float err = hist_val->GetBinError(ix, iy);
160 if (err > 0)
161 hist_pull->Fill(val / err);
162 ATH_MSG_NOCLASS(logger, "val=" << val << " err=" << err);
163 }
164 }
165
166 std::unique_ptr<TFile> outputfile(
167 TFile::Open("TFCS2DFunctionHistogram_unit_test.root", "RECREATE"));
168 if (outputfile != nullptr) {
169 hist->Write();
170 hist_val->Write();
171 hist_pull->Write();
172 outputfile->ls();
173 outputfile->Close();
174 }
175
176// Screen output in athena won't make sense and would require linking of
177// additional libraries
178#if defined(__FastCaloSimStandAlone__)
179 new TCanvas("input", "Input");
180 hist->Draw("colz");
181
182 new TCanvas("validation", "Validation");
183 hist_val->Draw("colz");
184
185 new TCanvas("pull", "Pull");
186 hist_pull->Draw();
187#endif
188}
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
ofstream outputfile
static TRandom * rnd
#define ATH_MSG_NOCLASS(logger_name, x)
Definition MLogging.h:52
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
Cut down AthMessaging.
Definition MLogging.h:176
virtual void rnd_to_fct(float &valuex, float &valuey, float rnd0, float rnd1) const
std::vector< float > m_HistoBorders
std::vector< float > m_HistoBordersy
std::vector< float > m_HistoContents
double integral(TH1 *h)
Definition computils.cxx:59
static Root::TMsgLogger logger("iLumiCalc")