BAT  0.9.4
The Bayesian analysis toolkit
 All Classes Namespaces Functions Variables Enumerations
BCFitter.cxx
1 /*
2  * Copyright (C) 2007-2014, the BAT core developer team
3  * All rights reserved.
4  *
5  * For the licensing terms see doc/COPYING.
6  * For documentation see http://mpp.mpg.de/bat
7  */
8 
9 // ---------------------------------------------------------
10 
11 #include "BCFitter.h"
12 
13 #include "BAT/BCModel.h"
14 #include "BAT/BCDataPoint.h"
15 #include "BAT/BCDataSet.h"
16 #include "BAT/BCLog.h"
17 #include "BAT/BCH1D.h"
18 
19 #include "TFile.h"
20 #include "TH1D.h"
21 #include "TH2D.h"
22 #include "TGraph.h"
23 
24 // ---------------------------------------------------------
26  , fErrorBand(0)
27  , fFlagFillErrorBand(true)
28  , fFitFunctionIndexX(-1)
29  , fFitFunctionIndexY(-1)
30  , fErrorBandContinuous(true)
31  , fErrorBandX(std::vector<double>(0))
32  , fErrorBandNbinsX(100)
33  , fErrorBandNbinsY(500)
34  , fErrorBandXY(0)
35 {
36 }
37 
38 // ---------------------------------------------------------
39 BCFitter::BCFitter(const char * name) : BCModel(name)
40  , fErrorBand(0)
41  , fFlagFillErrorBand(true)
42  , fFitFunctionIndexX(-1)
43  , fFitFunctionIndexY(-1)
44  , fErrorBandContinuous(true)
45  , fErrorBandX(std::vector<double>(0))
46  , fErrorBandNbinsX(100)
47  , fErrorBandNbinsY(500)
48  , fErrorBandXY(0)
49 {
50 }
51 
52 // ---------------------------------------------------------
54 {
55 }
56 
57 // ---------------------------------------------------------
59 {
60  // call base interface
62 
63  // fill error band
64  if (fFlagFillErrorBand)
65  FillErrorBand();
66 }
67 
68 // ---------------------------------------------------------
70 {
71  // prepare function fitting
72  double dx = 0.;
73  double dy = 0.;
74 
75  if (fFitFunctionIndexX >= 0) {
76  dx = (fDataPointUpperBoundaries->GetValue(fFitFunctionIndexX)
77  - fDataPointLowerBoundaries->GetValue(fFitFunctionIndexX))
78  / (double) fErrorBandNbinsX;
79 
80  dy = (fDataPointUpperBoundaries->GetValue(fFitFunctionIndexY)
81  - fDataPointLowerBoundaries->GetValue(fFitFunctionIndexY))
82  / (double) fErrorBandNbinsY;
83 
85  = new TH2D(TString::Format("errorbandxy_%d", BCLog::GetHIndex()), "",
86  fErrorBandNbinsX,
87  fDataPointLowerBoundaries->GetValue(fFitFunctionIndexX) - .5 * dx,
88  fDataPointUpperBoundaries->GetValue(fFitFunctionIndexX) + .5 * dx,
89  fErrorBandNbinsY,
90  fDataPointLowerBoundaries->GetValue(fFitFunctionIndexY) - .5 * dy,
91  fDataPointUpperBoundaries->GetValue(fFitFunctionIndexY) + .5 * dy);
92  fErrorBandXY->SetStats(kFALSE);
93 
94  for (unsigned ix = 1; ix <= fErrorBandNbinsX; ++ix)
95  for (unsigned iy = 1; iy <= fErrorBandNbinsX; ++iy)
96  fErrorBandXY->SetBinContent(ix, iy, 0.);
97  }
98 
99 }
100 
101 // ---------------------------------------------------------
103 {
104  // function fitting
105  if (fFitFunctionIndexX < 0)
106  return;
107 
108  // loop over all possible x values ...
109  if (fErrorBandContinuous) {
110  double x = 0;
111  for (unsigned ix = 0; ix < fErrorBandNbinsX; ix++) {
112  // calculate x
113  x = fErrorBandXY->GetXaxis()->GetBinCenter(ix + 1);
114 
115  // calculate y
116  std::vector<double> xvec;
117  xvec.push_back(x);
118 
119  // loop over all chains
120  for (unsigned ichain = 0; ichain < MCMCGetNChains(); ++ichain) {
121  // calculate y
122  double y = FitFunction(xvec, MCMCGetx(ichain));
123 
124  // fill histogram
125  fErrorBandXY->Fill(x, y);
126  }
127 
128  xvec.clear();
129  }
130  }
131  // ... or evaluate at the data point x-values
132  else {
133  unsigned ndatapoints = fErrorBandX.size();
134  double x = 0;
135 
136  for (unsigned ix = 0; ix < ndatapoints; ++ix) {
137  // calculate x
138  x = fErrorBandX.at(ix);
139 
140  // calculate y
141  std::vector<double> xvec;
142  xvec.push_back(x);
143 
144  // loop over all chains
145  for (unsigned ichain = 0; ichain < MCMCGetNChains(); ++ichain) {
146  // calculate y
147  double y = FitFunction(xvec, MCMCGetx(ichain));
148 
149  // fill histogram
150  fErrorBandXY->Fill(x, y);
151  }
152 
153  xvec.clear();
154  }
155  }
156 }
157 
158 // ---------------------------------------------------------
159 std::vector<double> BCFitter::GetErrorBand(double level) const
160 {
161  std::vector<double> errorband;
162 
163  if (!fErrorBandXY)
164  return errorband;
165 
166  int nx = fErrorBandXY->GetNbinsX();
167  errorband.assign(nx, 0.);
168 
169  // loop over x and y bins
170  for (int ix = 1; ix <= nx; ix++) {
171  TH1D * temphist = fErrorBandXY->ProjectionY("temphist", ix, ix);
172 
173  int nprobSum = 1;
174  double q[1];
175  double probSum[1];
176  probSum[0] = level;
177 
178  temphist->GetQuantiles(nprobSum, q, probSum);
179 
180  errorband[ix - 1] = q[0];
181  }
182 
183  return errorband;
184 }
185 
186 // ---------------------------------------------------------
187 TGraph * BCFitter::GetErrorBandGraph(double level1, double level2) const
188 {
189  if (!fErrorBandXY)
190  return 0;
191 
192  // define new graph
193  int nx = fErrorBandXY->GetNbinsX();
194 
195  TGraph * graph = new TGraph(2 * nx);
196  graph->SetFillStyle(1001);
197  graph->SetFillColor(kYellow);
198 
199  // get error bands
200  std::vector<double> ymin = GetErrorBand(level1);
201  std::vector<double> ymax = GetErrorBand(level2);
202 
203  for (int i = 0; i < nx; i++) {
204  graph->SetPoint(i, fErrorBandXY->GetXaxis()->GetBinCenter(i + 1), ymin[i]);
205  graph->SetPoint(nx + i, fErrorBandXY->GetXaxis()->GetBinCenter(nx - i), ymax[nx - i - 1]);
206  }
207 
208  return graph;
209 }
210 
211 // ---------------------------------------------------------
212 TH2D * BCFitter::GetErrorBandXY_yellow(double level, int nsmooth) const
213 {
214  if (!fErrorBandXY)
215  return 0;
216 
217  int nx = fErrorBandXY->GetNbinsX();
218  int ny = fErrorBandXY->GetNbinsY();
219 
220  // copy existing histogram
221  TH2D * hist_tempxy = (TH2D*) fErrorBandXY->Clone(
222  TString::Format("%s_sub_%f.2", fErrorBandXY->GetName(), level));
223  hist_tempxy->Reset();
224  hist_tempxy->SetFillColor(kYellow);
225 
226  // loop over x bins
227  for (int ix = 1; ix < nx; ix++) {
228  BCH1D * hist_temp = new BCH1D();
229 
230  TH1D * hproj = fErrorBandXY->ProjectionY("temphist", ix, ix);
231  if (nsmooth > 0)
232  hproj->Smooth(nsmooth);
233 
234  hist_temp->SetHistogram(hproj);
235 
236  TH1D * hist_temp_yellow = hist_temp->GetSmallestIntervalHistogram(level);
237 
238  for (int iy = 1; iy <= ny; ++iy)
239  hist_tempxy->SetBinContent(ix, iy, hist_temp_yellow->GetBinContent(iy));
240 
241  delete hist_temp_yellow;
242  delete hist_temp;
243  }
244 
245  return hist_tempxy;
246 }
247 
248 // ---------------------------------------------------------
249 TGraph * BCFitter::GetFitFunctionGraph(const std::vector<double> &parameters)
250 {
251  if (!fErrorBandXY)
252  return 0;
253 
254  // define new graph
255  int nx = fErrorBandXY->GetNbinsX();
256  TGraph * graph = new TGraph(nx);
257 
258  // loop over x values
259  for (int i = 0; i < nx; i++) {
260  double x = fErrorBandXY->GetXaxis()->GetBinCenter(i + 1);
261 
262  std::vector<double> xvec;
263  xvec.push_back(x);
264  double y = FitFunction(xvec, parameters);
265  xvec.clear();
266 
267  graph->SetPoint(i, x, y);
268  }
269 
270  return graph;
271 }
272 
273 // ---------------------------------------------------------
274 TGraph * BCFitter::GetFitFunctionGraph(const std::vector<double> &parameters, double xmin, double xmax, int n)
275 {
276  // define new graph
277  TGraph * graph = new TGraph(n + 1);
278 
279  double dx = (xmax - xmin) / (double) n;
280 
281  // loop over x values
282  for (int i = 0; i <= n; i++) {
283  double x = (double) i * dx + xmin;
284  std::vector<double> xvec;
285  xvec.push_back(x);
286  double y = FitFunction(xvec, parameters);
287 
288  xvec.clear();
289 
290  graph->SetPoint(i, x, y);
291  }
292 
293  return graph;
294 }
295 
296 // ---------------------------------------------------------
297 int BCFitter::ReadErrorBandFromFile(const char * file)
298 {
299  TFile * froot = TFile::Open(file);
300  if (!froot->IsOpen()) {
301  BCLog::OutError(Form("BCFitter::ReadErrorBandFromFile. Couldn't open file %s.", file));
302  return 0;
303  }
304 
305  int r = 0;
306 
307  TH2D * h2 = (TH2D*) froot->Get("errorbandxy");
308  if (h2) {
309  h2->SetDirectory(0);
310  h2->SetName(TString::Format("errorbandxy_%d", BCLog::GetHIndex()));
311  SetErrorBandHisto(h2);
312  r = 1;
313  }
314  else
315  BCLog::OutWarning(
316  Form("BCFitter::ReadErrorBandFromFile : Couldn't read histogram \"errorbandxy\" from file %s.",file));
317 
318  froot->Close();
319 
320  return r;
321 }
322 
323 // ---------------------------------------------------------
324 void BCFitter::FixDataAxis(unsigned int index, bool fixed)
325 {
326  // check if index is within range
327  if (index > fDataSet->GetDataPoint(0)->GetNValues()) {
328  BCLog::OutError("BCFitter::FixDataAxis : Index out of range.");
329  return;
330  }
331 
332  if (fDataFixedValues.size() == 0)
333  fDataFixedValues.assign(fDataSet->GetDataPoint(0)->GetNValues(),
334  false);
335 
336  fDataFixedValues[index] = fixed;
337 }
338 
339 // ---------------------------------------------------------
340 bool BCFitter::GetFixedDataAxis(unsigned int index) const
341 {
342  // check if index is within range
343  if (index > fDataSet->GetDataPoint(0)->GetNValues()) {
344  BCLog::OutError("BCFitter::GetFixedDataAxis : Index out of range.");
345  return false;
346  }
347 
348  return fDataFixedValues[index];
349 }
350 
351 // ---------------------------------------------------------
353 {
354  fErrorBandContinuous = flag;
355 
356  if (flag)
357  return;
358 
359  // clear x-values
360  fErrorBandX.clear();
361 
362  // copy data x-values
363  for (unsigned int i = 0; i < fDataSet->GetNDataPoints(); ++i)
364  fErrorBandX.push_back(fDataSet->GetDataPoint(i)->GetValue(fFitFunctionIndexX));
365 }
366 
367 // ---------------------------------------------------------
virtual double FitFunction(const std::vector< double > &, const std::vector< double > &)
Definition: BCFitter.h:135
TH2D * fErrorBandXY
Definition: BCFitter.h:206
void MarginalizePreprocess()
Definition: BCFitter.cxx:69
unsigned int GetNValues() const
Definition: BCDataPoint.h:65
The base class for all user-defined models.
Definition: BCModel.h:50
BCDataPoint * fDataPointLowerBoundaries
Definition: BCModel.h:526
static int GetHIndex()
Definition: BCLog.h:164
int ReadErrorBandFromFile(const char *file)
Definition: BCFitter.cxx:297
TH1D * GetSmallestIntervalHistogram(double level)
Definition: BCH1D.cxx:960
void FillErrorBand()
Definition: BCFitter.cxx:102
void SetHistogram(TH1D *hist)
Definition: BCH1D.h:149
void SetErrorBandContinuous(bool flag)
Definition: BCFitter.cxx:352
void MCMCIterationInterface()
Definition: BCFitter.cxx:58
double GetValue(unsigned index) const
Definition: BCDataPoint.cxx:34
void SetErrorBandHisto(TH2D *h)
Definition: BCFitter.h:97
A class for handling 1D distributions.
Definition: BCH1D.h:31
BCDataSet * fDataSet
Definition: BCModel.h:522
BCDataPoint * GetDataPoint(unsigned int index)
Definition: BCDataSet.cxx:98
TGraph * GetErrorBand()
Definition: BCFitter.h:54
unsigned int GetNDataPoints()
Definition: BCDataSet.cxx:79
virtual void MCMCIterationInterface()
BCDataPoint * fDataPointUpperBoundaries
Definition: BCModel.h:530
BCFitter()
Definition: BCFitter.cxx:25
~BCFitter()
Definition: BCFitter.cxx:53