ATLAS Offline Software
Loading...
Searching...
No Matches
TFCS1DFunctionSpline.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
7#include <algorithm>
8#include <iostream>
9#include "TMath.h"
10#include "TCanvas.h"
11#include "TH2F.h"
12#include "TRandom.h"
13#include "TFile.h"
14
15//=============================================
16//======= TFCS1DFunctionSpline =========
17//=============================================
18
19double TFCS1DFunctionSpline::Initialize(TH1 *hist, double maxdevgoal,
20 double maxeffsiggoal, int maxnp) {
21 double max_penalty_best = -1;
22 TSpline3 sp_best;
23 for (int np = 3; np <= maxnp; ++np) {
24 ATH_MSG_INFO("========== Spline #=" << np << " ==============");
25 double max_penalty;
26 if (max_penalty_best > 0) {
27 max_penalty =
28 InitializeFromSpline(hist, sp_best, maxdevgoal, maxeffsiggoal);
29 if (max_penalty_best < 0 || max_penalty < max_penalty_best) {
30 max_penalty_best = max_penalty;
31 sp_best = m_spline;
32 }
33 }
34
35 max_penalty = InitializeEqualDistance(hist, maxdevgoal, maxeffsiggoal, np);
36 if (max_penalty_best < 0 || max_penalty < max_penalty_best) {
37 max_penalty_best = max_penalty;
38 sp_best = m_spline;
39 }
40
41 max_penalty =
42 InitializeEqualProbability(hist, maxdevgoal, maxeffsiggoal, np);
43 if (max_penalty_best < 0 || max_penalty < max_penalty_best) {
44 max_penalty_best = max_penalty;
45 sp_best = m_spline;
46 }
47
48 ATH_MSG_INFO("========== Spline #=" << np << " max_penalty_best="
49 << max_penalty_best
50 << " ==============");
51 ATH_MSG(INFO) << "==== Best spline init | ";
52 for (int i = 0; i < sp_best.GetNp(); ++i) {
53 double p, x;
54 sp_best.GetKnot(i, p, x);
55 ATH_MSG(INFO) << i << " : p=" << p << " x=" << x << " ; ";
56 }
57 ATH_MSG(INFO) << " =====" << END_MSG(INFO);
58
59 if (max_penalty_best < 2)
60 break;
61 }
62 m_spline = sp_best;
63
64 return max_penalty_best;
65}
66
67double TFCS1DFunctionSpline::InitializeFromSpline(TH1 *hist, const TSpline3 &sp,
68 double maxdevgoal,
69 double maxeffsiggoal) {
70 TFCS1DFunctionInt32Histogram hist_fct(hist);
71
72 double maxeffsig;
73 double p_maxdev;
74 double p_maxeffsig;
75 double maxdev = get_maxdev(hist, sp, maxeffsig, p_maxdev, p_maxeffsig);
76 double p_improve;
77 if (maxdev / maxdevgoal > maxeffsig / maxeffsiggoal)
78 p_improve = p_maxdev;
79 else
80 p_improve = p_maxeffsig;
81
82 int nsplinepoints = sp.GetNp();
83 std::vector<double> nprop(nsplinepoints + 1);
84 int ind = 0;
85 ATH_MSG(INFO) << "Spline init p_improve=" << p_improve << " | ";
86 for (int i = 0; i < nsplinepoints; ++i) {
87 double p, x;
88 sp.GetKnot(i, p, x);
89 if (i == 0 && p_improve < p) {
90 nprop[ind] = (0 + p) / 2;
91 ATH_MSG(INFO) << ind << " : pi=" << nprop[ind] << " ; ";
92 ++ind;
93 }
94
95 nprop[ind] = p;
96 ATH_MSG(INFO) << ind << " : p=" << nprop[ind] << " ; ";
97 ++ind;
98
99 if (i == nsplinepoints - 1 && p_improve > p) {
100 nprop[ind] = (1 + p) / 2;
101 ATH_MSG(INFO) << ind << " : pi=" << nprop[ind] << " ; ";
102 ++ind;
103 }
104 if (i < nsplinepoints - 1) {
105 double pn, xn;
106 sp.GetKnot(i + 1, pn, xn);
107 if (p_improve > p && p_improve < pn) {
108 nprop[ind] = (p + pn) / 2;
109 ATH_MSG(INFO) << ind << " : pi=" << nprop[ind] << " ; ";
110 ++ind;
111 }
112 }
113 }
114 ATH_MSG(INFO) << END_MSG(INFO);
115 nsplinepoints = ind;
116 nprop.resize(nsplinepoints);
117
118 double max_penalty =
119 optimize(m_spline, nprop, hist, hist_fct, maxdevgoal, maxeffsiggoal);
120 maxdev = get_maxdev(hist, m_spline, maxeffsig, p_maxdev, p_maxeffsig);
121 ATH_MSG_INFO("Spline init spline #=" << nsplinepoints << " : maxdev="
122 << maxdev << " p_maxdev=" << p_maxdev
123 << " maxeffsig=" << maxeffsig
124 << " p_maxeffsig=" << p_maxeffsig
125 << " max_penalty=" << max_penalty);
126 ATH_MSG(INFO) << " ";
127 for (int i = 0; i < m_spline.GetNp(); ++i) {
128 double p, x;
129 m_spline.GetKnot(i, p, x);
130 ATH_MSG(INFO) << i << " : p=" << p << " x=" << x << " ; ";
131 }
132 ATH_MSG(INFO) << END_MSG(INFO);
133 return max_penalty;
134}
135
137 double maxdevgoal,
138 double maxeffsiggoal,
139 int nsplinepoints) {
140 TFCS1DFunctionInt32Histogram hist_fct(hist);
141
142 double xmin = 0;
143 double xmax = 0;
144 for (int i = 1; i <= hist->GetNbinsX(); i++) {
145 xmin = hist->GetXaxis()->GetBinLowEdge(i);
146 if (hist->GetBinContent(i) > 0)
147 break;
148 }
149 for (int i = hist->GetNbinsX(); i >= 1; i--) {
150 xmax = hist->GetXaxis()->GetBinUpEdge(i);
151 if (hist->GetBinContent(i) > 0)
152 break;
153 }
154 // ATH_MSG_INFO("xmin="<<xmin<<" xmax="<<xmax);
155
156 double dx = (xmax - xmin) / (nsplinepoints - 1);
157
158 std::vector<double> nprop(nsplinepoints);
159 std::vector<double> nx(nsplinepoints);
160 nprop[0] = 0;
161 nx[0] = hist_fct.rnd_to_fct(nprop[0]);
162 // ATH_MSG_INFO(0<<" p="<<nprop[0]<<" x="<<nx[0]);
163 for (int i = 1; i < nsplinepoints; ++i) {
164 nx[i] = xmin + i * dx;
165 double p_min = 0;
166 double p_max = 1;
167 double p_test;
168 double tx;
169 do {
170 p_test = 0.5 * (p_min + p_max);
171 tx = hist_fct.rnd_to_fct(p_test);
172 if (nx[i] < tx)
173 p_max = p_test;
174 else
175 p_min = p_test;
176 if ((p_max - p_min) < 0.0000001)
177 break;
178 } while (TMath::Abs(tx - nx[i]) > dx / 10);
179 // ATH_MSG_INFO(i<<" p="<<p_test<<" x="<<tx);
180 nprop[i] = p_test;
181 }
182
183 double max_penalty =
184 optimize(m_spline, nprop, hist, hist_fct, maxdevgoal, maxeffsiggoal);
185 double maxeffsig;
186 double p_maxdev;
187 double p_maxeffsig;
188 double maxdev = get_maxdev(hist, m_spline, maxeffsig, p_maxdev, p_maxeffsig);
189 ATH_MSG_INFO("Spline init equ. dist. #=" << nsplinepoints << " : maxdev="
190 << maxdev << " p_maxdev=" << p_maxdev
191 << " maxeffsig=" << maxeffsig
192 << " p_maxeffsig=" << p_maxeffsig
193 << " max_penalty=" << max_penalty);
194 ATH_MSG(INFO) << " ";
195 for (int i = 0; i < m_spline.GetNp(); ++i) {
196 double p, x;
197 m_spline.GetKnot(i, p, x);
198 ATH_MSG(INFO) << i << " : p=" << p << " x=" << x << " ; ";
199 }
200 ATH_MSG(INFO) << END_MSG(INFO);
201 return max_penalty;
202}
203
205 double maxdevgoal,
206 double maxeffsiggoal,
207 int nsplinepoints) {
208 TFCS1DFunctionInt32Histogram hist_fct(hist);
209
210 double dprop = 1.0 / (nsplinepoints - 1);
211 std::vector<double> nprop(nsplinepoints);
212 for (int i = 0; i < nsplinepoints; ++i) {
213 nprop[i] = i * dprop;
214 }
215
216 double max_penalty =
217 optimize(m_spline, nprop, hist, hist_fct, maxdevgoal, maxeffsiggoal);
218 double maxeffsig;
219 double p_maxdev;
220 double p_maxeffsig;
221 double maxdev = get_maxdev(hist, m_spline, maxeffsig, p_maxdev, p_maxeffsig);
222 ATH_MSG_INFO("Spline init equ. prob. #=" << nsplinepoints << " : maxdev="
223 << maxdev << " p_maxdev=" << p_maxdev
224 << " maxeffsig=" << maxeffsig
225 << " p_maxeffsig=" << p_maxeffsig
226 << " max_penalty=" << max_penalty);
227 ATH_MSG(INFO) << " ";
228 for (int i = 0; i < m_spline.GetNp(); ++i) {
229 double p, x;
230 m_spline.GetKnot(i, p, x);
231 ATH_MSG(INFO) << i << " : p=" << p << " x=" << x << " ; ";
232 }
233 ATH_MSG(INFO) << END_MSG(INFO);
234 return max_penalty;
235}
236
237double TFCS1DFunctionSpline::optimize(TSpline3 &sp_best,
238 std::vector<double> &nprop,
239 const TH1 *hist,
241 double maxdevgoal, double maxeffsiggoal) {
242 int nsplinepoints = (int)nprop.size();
243 // double xmin=hist->GetXaxis()->GetXmin();
244 // double xmax=hist->GetXaxis()->GetXmax();
245 std::vector<double> nx(nsplinepoints);
246 std::vector<double> nprop_try = nprop;
247 double max_penalty = -1;
248 double p_gotobest = 0.5 / nsplinepoints;
249 int ntry = 200 / p_gotobest;
250 // int itrytot=0;
251 for (double dproploop = 0.4 / nsplinepoints; dproploop > 0.02 / nsplinepoints;
252 dproploop /= 2) {
253 double dprop = dproploop;
254 int n_nogain = 0;
255 for (int itry = 0; itry < ntry; ++itry) {
256 // itrytot++;
257 for (int i = 0; i < nsplinepoints; ++i) {
258 nx[i] = hist_fct.rnd_to_fct(nprop_try[i]);
259 }
260 TSpline3 sp("1Dspline", nprop_try.data(), nx.data(), nsplinepoints,
261 "b2e2", 0, 0);
262 double maxeffsig;
263 double p_maxdev;
264 double p_maxeffsig;
265 double maxdev = get_maxdev(hist, sp, maxeffsig, p_maxdev, p_maxeffsig);
266 double penalty = maxdev / maxdevgoal + maxeffsig / maxeffsiggoal;
267 if (max_penalty < 0 || penalty < max_penalty) {
268 max_penalty = penalty;
269 nprop = nprop_try;
270 sp_best = sp;
271 /*
272 ATH_MSG(INFO) <<"#="<<nsplinepoints<<" try="<<itrytot-1<<" | ";
273 for(int i=0;i<nsplinepoints;++i) {
274 ATH_MSG(INFO) <<i<<":p="<<nprop_try[i]<<" x="<<nx[i]<<" ; ";
275 }
276 ATH_MSG(INFO) <<"new maxdev="<<maxdev<<" maxeffsig="<<maxeffsig<<"
277 max_penalty="<<max_penalty<<END_MSG(INFO);
278 */
279 n_nogain = 0;
280 } else {
281 if (gRandom->Rndm() < p_gotobest)
282 nprop_try = nprop;
283 ++n_nogain;
284 // allow ~20 times retrying from the best found spline before aborting
285 if (n_nogain > 20 / p_gotobest)
286 break;
287 }
288 int ip = 1 + gRandom->Rndm() * (nsplinepoints - 1);
289 if (ip > nsplinepoints - 1)
290 ip = nsplinepoints - 1;
291 double d = dprop;
292 if (gRandom->Rndm() > 0.5)
293 d = -dprop;
294 double nprop_new = nprop_try[ip] + d;
295 if (ip > 0)
296 if (nprop_try[ip - 1] + dprop / 2 > nprop_new) {
297 nprop_new = nprop_try[ip];
298 dprop /= 2;
299 }
300 if (ip < nsplinepoints - 1)
301 if (nprop_new > nprop_try[ip + 1] - dprop / 2) {
302 nprop_new = nprop_try[ip];
303 dprop /= 2;
304 }
305 if (nprop_new < 0) {
306 nprop_new = 0;
307 dprop /= 2;
308 }
309 if (nprop_new > 1) {
310 nprop_new = 1;
311 dprop /= 2;
312 }
313 nprop_try[ip] = nprop_new;
314 }
315 nprop_try = nprop;
316 }
317 return max_penalty;
318}
319
320double TFCS1DFunctionSpline::get_maxdev(const TH1 *hist, const TSpline3 &sp,
321 double &maxeffsig, double &p_maxdev,
322 double &p_maxeffsig, int ntoy) {
323 double maxdev = 0;
324 maxeffsig = 0;
325
326 TH1 *hist_clone = (TH1 *)hist->Clone("hist_clone");
327 hist_clone->SetDirectory(nullptr);
328 hist_clone->Reset();
329 double interr = 0;
330 double integral = hist->IntegralAndError(1, hist->GetNbinsX(), interr);
331 double effN = integral / interr;
332 effN *= effN;
333 // ATH_MSG_INFO("integral="<<integral<<" +- "<<interr<<"
334 // relerr="<<interr/integral); ATH_MSG_INFO("effN="<<effN<<" +-
335 // "<<TMath::Sqrt(effN)<<" relerr="<<1/TMath::Sqrt(effN));
336 double toyweight = 1.0 / ntoy;
337 for (int itoy = 0; itoy < ntoy; ++itoy) {
338 double prop = itoy * toyweight;
339 hist_clone->Fill(sp.Eval(prop), toyweight);
340 }
341
342 double int1 = 0;
343 double int2 = 0;
344 for (int i = 0; i <= hist->GetNbinsX() + 1; i++) {
345 int1 += hist->GetBinContent(i) / integral;
346 int2 += hist_clone->GetBinContent(i);
347 double val = TMath::Abs(int1 - int2);
348 if (val > maxdev) {
349 maxdev = val;
350 p_maxdev = int1;
351 }
352
353 // now view the normalized integral as selection efficiency from a total
354 // sample of sizze effN
355 double int1err = TMath::Sqrt(int1 * (1 - int1) / effN);
356 double valsig = 0;
357 if (int1err > 0)
358 valsig = val / int1err;
359 if (valsig > maxeffsig) {
360 maxeffsig = valsig;
361 p_maxeffsig = int1;
362 }
363
364 // ATH_MSG_INFO(i<<": diff="<<int1-int2<<" sig(diff)="<<valsig<<"
365 // int1="<<int1<<" +- "<<int1err<<" int2="<<int2<<" maxdev="<<maxdev<<"
366 // maxeffsig="<<maxeffsig);
367 }
368
369 delete hist_clone;
370
371 return maxdev;
372}
373
375 return m_spline.Eval(rnd);
376}
377
378void TFCS1DFunctionSpline::unit_test ATLAS_NOT_THREAD_SAFE(TH1 *hist) {
380 int nbinsx;
381 TH1 *histfine = nullptr;
382 if (hist == nullptr) {
383 nbinsx = 50;
384 double xmin = 1;
385 double xpeak = 1.5;
386 double sigma = 0.6;
387 double xmax = 5;
388 hist = new TH1D("test1D", "test1D", nbinsx, xmin, xmax);
389 histfine = new TH1D("test1Dfine", "test1Dfine", 10 * nbinsx, xmin, xmax);
390 hist->Sumw2();
391 for (int i = 1; i <= 100000; ++i) {
392 double x = gRandom->Gaus(xpeak, sigma);
393 if (x >= xmin && x < xmax) {
394 // hist->Fill(TMath::Sqrt(x));
395 hist->Fill(x);
396 if (histfine)
397 histfine->Fill(x, 10);
398 }
399 }
400 }
401 if (!histfine)
402 histfine = hist;
403 TFCS1DFunctionSpline rtof(histfine, 0.01, 2, 15);
404 nbinsx = hist->GetNbinsX();
405
406 float value[2];
407 float rnd[2];
408 //cppcheck-suppress uninitvar
409 for (rnd[0] = 0; rnd[0] < 0.9999; rnd[0] += 0.25) {
410 rtof.rnd_to_fct(value, rnd);
411 ATH_MSG_NOCLASS(logger, "rnd0=" << rnd[0] << " -> x=" << value[0]);
412 }
413
414 TH1 *hist_val = (TH1 *)histfine->Clone("hist_val");
415 hist_val->SetTitle("toy simulation");
416 hist_val->Reset();
417 hist_val->SetLineColor(2);
418 TH1 *hist_diff = (TH1 *)hist->Clone("hist_diff");
419 hist_diff->SetTitle("difference");
420 hist_diff->Reset();
421 int nrnd = 5000000;
422 double weight = histfine->Integral() / nrnd;
423 double weightdiff = hist->Integral() / nrnd;
424 hist_val->Sumw2();
425 hist_diff->Sumw2();
426 for (int i = 0; i < nrnd; ++i) {
427 rnd[0] = gRandom->Rndm();
428 rtof.rnd_to_fct(value, rnd);
429 hist_val->Fill(value[0], weight);
430 hist_diff->Fill(value[0], weightdiff);
431 }
432 hist_diff->Add(hist, -1);
433
434 TH1F *hist_pull = new TH1F("pull", "pull", 200, -10, 10);
435 for (int ix = 1; ix <= nbinsx; ++ix) {
436 float val = hist_diff->GetBinContent(ix);
437 float err = hist_diff->GetBinError(ix);
438 if (err > 0)
439 hist_pull->Fill(val / err);
440 // ATH_MSG_NOCLASS(logger,"val="<<val<<" err="<<err);
441 }
442
443// Screen output in athena won't make sense and would require linking of
444// additional libraries
445#if defined(__FastCaloSimStandAlone__)
446 new TCanvas("input", "Input");
447 histfine->SetLineColor(kGray);
448 histfine->Draw("hist");
449 hist->Draw("same");
450 hist_val->Draw("sameshist");
451
452 new TCanvas("spline", "spline");
453 TFCS1DFunctionInt32Histogram hist_fct(hist);
454 int ngr = 101;
455 TGraph *gr = new TGraph();
456 for (int i = 0; i < ngr; ++i) {
457 double r = i * 1.0 / (ngr - 1);
458 gr->SetPoint(i, r, hist_fct.rnd_to_fct(r));
459 }
460 gr->SetMarkerStyle(7);
461 gr->Draw("AP");
462 TSpline3 *sp = new TSpline3(rtof.spline());
463 sp->SetLineColor(2);
464 sp->SetMarkerColor(2);
465 sp->SetMarkerStyle(2);
466 sp->Draw("LPsame");
467
468 new TCanvas("difference", "difference");
469 hist_diff->Draw();
470
471 new TCanvas("pull", "Pull");
472 hist_pull->Draw();
473#endif
474}
#define ATH_MSG(lvl)
#define ATH_MSG_INFO(x)
#define gr
static Double_t sp
static TRandom * rnd
#define ATH_MSG_NOCLASS(logger_name, x)
Definition MLogging.h:52
#define END_MSG(lvl)
Definition MLogging.h:171
#define x
#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 double rnd_to_fct(double rnd) const
Function gets random number rnd in the range [0,1) as argument and returns function value according t...
const TSpline3 & spline() const
double InitializeEqualDistance(TH1 *hist, double maxdevgoal=0.01, double maxeffsiggoal=3, int nsplinepoints=5)
double InitializeEqualProbability(TH1 *hist, double maxdevgoal=0.01, double maxeffsiggoal=3, int nsplinepoints=5)
virtual double rnd_to_fct(double rnd) const
Function gets random number rnd in the range [0,1) as argument and returns function value according t...
double Initialize(TH1 *hist, double maxdevgoal=0.01, double maxeffsiggoal=3, int maxnp=20)
static double get_maxdev(const TH1 *hist, const TSpline3 &sp, double &maxeffsig, double &p_maxdev, double &p_maxeffsig, int ntoy=10000)
double InitializeFromSpline(TH1 *hist, const TSpline3 &sp, double maxdevgoal=0.01, double maxeffsiggoal=3)
static double optimize(TSpline3 &sp_best, std::vector< double > &nprop, const TH1 *hist, TFCS1DFunctionInt32Histogram &hist_fct, double maxdevgoal=0.01, double maxeffsiggoal=3)
double integral(TH1 *h)
Definition computils.cxx:59
int r
Definition globals.cxx:22
static Root::TMsgLogger logger("iLumiCalc")
double xmax
Definition listroot.cxx:61
double xmin
Definition listroot.cxx:60