ATLAS Offline Software
Loading...
Searching...
No Matches
TFCS1DFunctionHistogram.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
6#include "TMath.h"
7#include "TFile.h"
8#include <iostream>
9
10using namespace std;
11
12//=============================================
13//======= TFCS1DFunctionHistogram =========
14//=============================================
15
17 Initialize(hist, cut_maxdev);
18}
19
20void TFCS1DFunctionHistogram::Initialize(TH1 *hist, double cut_maxdev) {
21 smart_rebin_loop(hist, cut_maxdev);
22}
23
24std::unique_ptr<double[]>
26
27 TH1D *h_clone = (TH1D *)hist->Clone("h_clone");
28 h_clone->Scale(1.0 / h_clone->Integral());
29
30 auto histoVals = std::make_unique<double[]>(h_clone->GetNbinsX());
31 histoVals[0] = h_clone->GetBinContent(1);
32 for (int i = 1; i < h_clone->GetNbinsX(); i++) {
33 histoVals[i] = histoVals[i - 1] + h_clone->GetBinContent(i + 1);
34 }
35 delete h_clone;
36 return histoVals;
37}
38
39double TFCS1DFunctionHistogram::sample_from_histo(TH1 *hist, double random) {
40
41 auto histoVals = histo_to_array(hist);
42 double value = 0.0;
43 int chosenBin =
44 (int)TMath::BinarySearch(hist->GetNbinsX(), histoVals.get(), random);
45 value = hist->GetBinCenter(chosenBin + 2);
46
47 // cleanup
48
49 return value;
50}
51
53 double value = 0.0;
54
55 TH1 *hist = vector_to_histo();
56 hist->SetName("hist");
57 auto histoVals = histo_to_array(hist);
58 int chosenBin =
59 (int)TMath::BinarySearch(hist->GetNbinsX(), histoVals.get(), random);
60 value = hist->GetBinCenter(chosenBin + 2);
61
62 return value;
63}
64
66
67 double *bins = new double[m_HistoBorders.size()];
68 for (unsigned int i = 0; i < m_HistoBorders.size(); i++)
69 bins[i] = m_HistoBorders[i];
70
71 TH1 *h_out = new TH1D("h_out", "h_out", m_HistoBorders.size() - 1, bins);
72 for (int b = 1; b <= h_out->GetNbinsX(); b++)
73 h_out->SetBinContent(b, m_HistoContents[b - 1]);
74
75 delete[] bins;
76
77 return h_out;
78}
79
80void TFCS1DFunctionHistogram::smart_rebin_loop(TH1 *hist, double cut_maxdev) {
81
82 m_HistoContents.clear();
83 m_HistoBorders.clear();
84
85 double change =
86 get_change(hist) * 1.000001; // increase slighlty for comparison of floats
87
88 double maxdev = -1;
89
90 TH1D *h_input = (TH1D *)hist->Clone("h_input");
91 TH1D *h_output = nullptr;
92
93 int i = 0;
94 while (1) {
95
96 TH1D *h_out;
97 if (i == 0) {
98 h_out = (TH1D *)h_input->Clone("h_out");
99 } else {
100 h_out = smart_rebin(h_input);
101 h_out->SetName("h_out");
102 }
103
104 maxdev = get_maxdev(hist, h_out);
105 maxdev *= 100.0;
106
107 if (i % 100 == 0)
108 ATH_MSG_INFO("Iteration nr. " << i << " -----> change " << change
109 << " bins " << h_out->GetNbinsX()
110 << " -> maxdev=" << maxdev);
111
112 if (maxdev < cut_maxdev && h_out->GetNbinsX() > 5 && i < 1000) {
113 delete h_input;
114 h_input = (TH1D *)h_out->Clone("h_input");
115 change = get_change(h_input) * 1.000001;
116 delete h_out;
117 i++;
118 } else {
119 h_output = (TH1D *)h_input->Clone("h_output");
120 delete h_out;
121 break;
122 }
123 }
124
125 ATH_MSG_INFO("Info: Rebinned histogram has " << h_output->GetNbinsX()
126 << " bins.");
127
128 // store:
129
130 for (int b = 1; b <= h_output->GetNbinsX(); b++)
131 m_HistoBorders.push_back((float)h_output->GetBinLowEdge(b));
132 m_HistoBorders.push_back((float)h_output->GetXaxis()->GetXmax());
133
134 for (int b = 1; b < h_output->GetNbinsX(); b++)
135 m_HistoContents.push_back(h_output->GetBinContent(b));
136 m_HistoContents.push_back(1);
137}
138
139double TFCS1DFunctionHistogram::get_maxdev(TH1 *h_in, TH1D *h_out) {
140
141 double maxdev = 0;
142 for (int i = 1; i <= h_in->GetNbinsX(); i++) {
143 int bin = h_out->FindBin(h_in->GetBinCenter(i));
144 double val = fabs(h_out->GetBinContent(bin) - h_in->GetBinContent(i));
145 if (val > maxdev)
146 maxdev = val;
147 }
148 return maxdev;
149}
150
152 // return the smallest change between 2 bin contents, but don't check the last
153 // bin, because that one never gets merged
154 double minchange = 100.0;
155 for (int b = 2; b < histo->GetNbinsX(); b++) {
156 double diff = histo->GetBinContent(b) - histo->GetBinContent(b - 1);
158 minchange = diff;
159 }
160
161 return minchange;
162}
163
165
166 TH1D *h_out1 = (TH1D *)h_input->Clone("h_out1");
167
168 // get the smallest change
169 double change = get_change(h_out1) * 1.00001;
170
171 vector<double> content;
172 vector<double> binborder;
173
174 binborder.push_back(h_out1->GetXaxis()->GetXmin());
175
176 int merged = 0;
177 int skip = 0;
178 int secondlastbin_merge = 0;
179 for (int b = 1; b < h_out1->GetNbinsX() - 1; b++) // never touch the last bin
180 {
181 double thisBin = h_out1->GetBinContent(b);
182 double nextBin = h_out1->GetBinContent(b + 1);
183 double width = h_out1->GetBinWidth(b);
184 double nextwidth = h_out1->GetBinWidth(b + 1);
185 double diff = fabs(nextBin - thisBin);
186 if (!skip && (diff > change || merged)) {
187 binborder.push_back(h_out1->GetBinLowEdge(b + 1));
188 content.push_back(thisBin);
189 }
190 skip = 0;
191 if (diff <= change && !merged) {
192 double sum = thisBin * width + nextBin * nextwidth;
193 double sumwidth = width + nextwidth;
194 binborder.push_back(h_out1->GetBinLowEdge(b + 2));
195 content.push_back(sum / sumwidth);
196 merged = 1;
197 skip = 1;
198 if (b == (h_out1->GetNbinsX() - 2))
199 secondlastbin_merge = 1;
200 }
201 } // for b
202 if (!secondlastbin_merge) {
203 binborder.push_back(h_out1->GetBinLowEdge(h_out1->GetNbinsX()));
204 content.push_back(h_out1->GetBinContent(h_out1->GetNbinsX() - 1));
205 }
206 binborder.push_back(h_out1->GetXaxis()->GetXmax());
207 content.push_back(h_out1->GetBinContent(h_out1->GetNbinsX()));
208
209 double *bins = new double[content.size() + 1];
210 for (unsigned int i = 0; i < binborder.size(); i++)
211 bins[i] = binborder[i];
212
213 TH1D *h_out2 = new TH1D("h_out2", "h_out2", content.size(), bins);
214 for (unsigned int b = 1; b <= content.size(); b++)
215 h_out2->SetBinContent(b, content[b - 1]);
216
217 delete[] bins;
218 delete h_out1;
219
220 return h_out2;
221}
222
224
225 double value2 = get_inverse(rnd);
226
227 return value2;
228}
229
230double TFCS1DFunctionHistogram::linear(double y1, double y2, double x1,
231 double x2, double y) {
232 double x = -1;
233
234 double eps = 0.0000000001;
235 if ((y2 - y1) < eps)
236 x = x1;
237 else {
238 double m = (y2 - y1) / (x2 - x1);
239 double n = y1 - m * x1;
240 x = (y - n) / m;
241 }
242
243 return x;
244}
245
246double TFCS1DFunctionHistogram::non_linear(double y1, double y2, double x1,
247 double x2, double y) {
248 double x = -1;
249 double eps = 0.0000000001;
250 if ((y2 - y1) < eps)
251 x = x1;
252 else {
253 double b = (x1 - x2) / (sqrt(y1) - sqrt(y2));
254 double a = x1 - b * sqrt(y1);
255 x = a + b * sqrt(y);
256 }
257 return x;
258}
259
261
262 double value = 0.;
263
264 if (rnd < m_HistoContents[0]) {
265 double x1 = m_HistoBorders[0];
266 double x2 = m_HistoBorders[1];
267 double y1 = 0;
268 double y2 = m_HistoContents[0];
269 double x = non_linear(y1, y2, x1, x2, rnd);
270 value = x;
271 } else {
272 // find the first HistoContent element that is larger than rnd:
273 vector<float>::const_iterator larger_element =
274 std::upper_bound(m_HistoContents.begin(), m_HistoContents.end(), rnd);
275 size_t index = larger_element - m_HistoContents.begin();
276 if (index >= m_HistoContents.size()) {
277 --index;
278 }
279 double y = m_HistoContents[index];
280 double x1 = m_HistoBorders[index];
281 double x2 = m_HistoBorders[index + 1];
282 double y1 = m_HistoContents[index - 1];
283 double y2 = y;
284 if ((index + 1) == (m_HistoContents.size() - 1)) {
285 x2 = m_HistoBorders[m_HistoBorders.size() - 1];
286 y2 = m_HistoContents[m_HistoContents.size() - 1];
287 }
288 double x = non_linear(y1, y2, x1, x2, rnd);
289 value = x;
290 }
291
292 return value;
293}
#define ATH_MSG_INFO(x)
static Double_t a
static TRandom * rnd
static const std::vector< std::string > bins
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
const double width
#define y
#define x
static double linear(double y1, double y2, double x1, double x2, double x)
std::vector< float > m_HistoBorders
virtual double rnd_to_fct(double rnd) const
Function gets random number rnd in the range [0,1) as argument and returns function value.
static std::unique_ptr< double[]> histo_to_array(TH1 *)
double get_inverse(double rnd) const
static double get_maxdev(TH1 *, TH1D *)
static double sample_from_histo(TH1 *hist, double)
void Initialize(TH1 *hist, double)
std::vector< float > m_HistoContents
static double non_linear(double y1, double y2, double x1, double x2, double x)
void smart_rebin_loop(TH1 *hist, double)
Definition index.py:1
STL namespace.