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