BAT  0.9.4
The Bayesian analysis toolkit
 All Classes Namespaces Functions Variables Enumerations
BCIntegrate.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 #include <config.h>
11 
12 #include "BCIntegrate.h"
13 #include "BCLog.h"
14 #include "BCMath.h"
15 #include "BCParameter.h"
16 #include "BCH2D.h"
17 #include "BCH1D.h"
18 
19 #include <TH1D.h>
20 #include <TH2D.h>
21 #include <TH3D.h>
22 #include <TCanvas.h>
23 #include <TFile.h>
24 #include <TMinuit.h>
25 #include <TRandom3.h>
26 #include <TString.h>
27 #include <TTree.h>
28 #include <TKey.h>
29 #include <TStyle.h>
30 
31 #ifdef HAVE_CUBA_H
32 #include <cuba.h>
33 #endif
34 
35 #include <math.h>
36 #include <limits>
37 
38 namespace
39 {
43  class BCIntegrateHolder
44  {
45  private:
46  BCIntegrate * global_this;
47 
48  public:
49 
50  BCIntegrateHolder() :
51  global_this(NULL)
52  {
53  }
54 
58  static BCIntegrate * instance(BCIntegrate * obj = NULL)
59  {
60  static BCIntegrateHolder result;
61  if (obj)
62  result.global_this = obj;
63 
64  return result.global_this;
65  }
66  };
67 }
68 
69 // ---------------------------------------------------------
70 BCIntegrate::BCIntegrate() : BCEngineMCMC(),
71  fID(BCLog::GetHIndex()),
72  fMinuit(0),
73  fMinuitErrorFlag(0),
74  fFlagIgnorePrevOptimization(false),
75  fSAT0(100),
76  fSATmin(0.1),
77  fTreeSA(0),
78  fFlagWriteSAToFile(false),
79  fSANIterations(0),
80  fSATemperature(0),
81  fSALogProb(0),
82  fMarginalized1D(0),
83  fMarginalized2D(0),
84  fFlagMarginalized(false),
85  fOptimizationMethodCurrent(BCIntegrate::kOptDefault),
86  fOptimizationMethodUsed(BCIntegrate::kOptEmpty),
87  fIntegrationMethodCurrent(BCIntegrate::kIntDefault),
88  fIntegrationMethodUsed(BCIntegrate::kIntEmpty),
89  fMarginalizationMethodCurrent(BCIntegrate::kMargDefault),
90  fMarginalizationMethodUsed(BCIntegrate::kMargEmpty),
91  fSASchedule(BCIntegrate::kSACauchy),
92  fNIterationsMin(0),
93  fNIterationsMax(1000000),
94  fNIterationsPrecisionCheck(1000),
95  fNIterationsOutput(0),
96  fNIterations(0),
97  fLogMaximum(-std::numeric_limits<double>::max()),
98  fIntegral(-1),
99  fRelativePrecision(1e-2),
100  fAbsolutePrecision(1e-6),
101  fError(-999.),
102  fCubaIntegrationMethod(BCIntegrate::kCubaVegas)
103 {
104  fMinuitArglist[0] = 20000;
105  fMinuitArglist[1] = 0.01;
106 }
107 
108 // ---------------------------------------------------------
109 BCIntegrate::BCIntegrate(const BCIntegrate & other) : BCEngineMCMC(other)
110 {
111  Copy(other);
112 }
113 
114 // ---------------------------------------------------------
115 BCIntegrate & BCIntegrate::operator = (const BCIntegrate & other)
116 {
117  Copy(other);
118  return *this;
119 }
120 
121 // ---------------------------------------------------------
122 void BCIntegrate::Copy(const BCIntegrate & other)
123 {
124  BCEngineMCMC::Copy(other);
125 
126  fID = other.fID;
127  fBestFitParameters = other.fBestFitParameters;
128  fBestFitParameterErrors = other.fBestFitParameterErrors;
129  fLogMaximum = other.fLogMaximum;
130  fMinuit = new TMinuit();
131  fMinuitArglist[0] = other.fMinuitArglist[0];
132  fMinuitArglist[1] = other.fMinuitArglist[1];
133  fMinuitErrorFlag = other.fMinuitErrorFlag;
134  fFlagIgnorePrevOptimization = other.fFlagIgnorePrevOptimization;
135  fSAT0 = other.fSAT0;
136  fSATmin = other.fSATmin;
137  fTreeSA = 0;
138  fFlagWriteSAToFile = other.fFlagWriteSAToFile;
139  fSANIterations = other.fSANIterations;
140  fSATemperature = other.fSATemperature;
141  fSALogProb = other.fSALogProb;
142  fSAx = other.fSAx;
143  fMarginalized1D = other.fMarginalized1D;
144  fMarginalized2D = other.fMarginalized2D;
145  fOptimizationMethodCurrent= other.fOptimizationMethodCurrent;
146  fOptimizationMethodUsed = other.fOptimizationMethodUsed;
147  fIntegrationMethodCurrent = other.fIntegrationMethodCurrent;
148  fIntegrationMethodUsed = other.fIntegrationMethodUsed;
149  fMarginalizationMethodCurrent = other.fMarginalizationMethodCurrent;
150  fMarginalizationMethodUsed= other.fMarginalizationMethodUsed;
151  fSASchedule = other.fSASchedule;
152  fNIterationsMin = other.fNIterationsMin;
153  fNIterationsMax = other.fNIterationsMax;
154  fNIterationsPrecisionCheck= other.fNIterationsPrecisionCheck;
155  fNIterationsOutput = other.fNIterationsOutput;
156  fNIterations = other.fNIterations;
157  fIntegral = other.fIntegral;
158  fRelativePrecision = other.fRelativePrecision;
159  fAbsolutePrecision = other.fAbsolutePrecision;
160  fError = other.fError;
161  fCubaIntegrationMethod = other.fCubaIntegrationMethod;
162  fCubaVegasOptions = other.fCubaVegasOptions;
163  fCubaSuaveOptions = other.fCubaSuaveOptions;
164  fCubaDivonneOptions = other.fCubaDivonneOptions;
165  fCubaCuhreOptions = other.fCubaCuhreOptions;
166  fFlagMarginalized = other.fFlagMarginalized;
167 }
168 
169 // ---------------------------------------------------------
170 BCIntegrate::~BCIntegrate()
171 {
172  delete fMinuit;
173 }
174 
175 // ---------------------------------------------------------
176 double BCIntegrate::GetBestFitParameter(unsigned index) const
177 {
178  if( ! fParameters.ValidIndex(index))
179  return -1e+111;
180 
181  if(fBestFitParameters.empty()) {
182  BCLog::OutError("BCIntegrate::GetBestFitParameter : Mode finding not yet run, returning center of the range.");
183  return (fParameters[index]->GetUpperLimit() + fParameters[index]->GetLowerLimit() ) / 2.;
184  }
185 
186  return fBestFitParameters[index];
187 }
188 
189 // ---------------------------------------------------------
190 double BCIntegrate::GetBestFitParameterError(unsigned index) const
191 {
192  if( ! fParameters.ValidIndex(index)) {
193  BCLog::OutError("BCIntegrate::GetBestFitParameterError : Parameter index out of range, returning -1.");
194  return -1;
195  }
196 
197  /*
198  if(fBestFitParameterErrors.size()==0) {
199  BCLog::OutError("BCIntegrate::GetBestFitParameterError : Mode finding not yet run, returning -1.");
200  return -1.;
201  }
202 
203  if(fBestFitParameterErrors[index]<0.)
204  BCLog::OutWarning("BCIntegrate::GetBestFitParameterError : Parameter error not available, returning -1.");
205  */
206 
207  return fBestFitParameterErrors[index];
208 }
209 
210 // ---------------------------------------------------------
211 double BCIntegrate::Eval(const std::vector<double> & /*x*/)
212 {
213  BCLog::OutWarning( "BCIntegrate::Eval. No function. Function needs to be overloaded.");
214  return 0;
215 }
216 
217 // ---------------------------------------------------------
218 double BCIntegrate::LogEval(const std::vector<double> &x)
219 {
220  // this method should better also be overloaded
221  return log(Eval(x));
222 }
223 
224 // ---------------------------------------------------------
225 void BCIntegrate::ResetResults()
226 {
228 
229  fBestFitParameterErrors.clear();
230  fBestFitParameters.clear();
231  fLogMaximum = -std::numeric_limits<double>::max();
232 
233  // remove marginalized histograms
234  // set marginalization flag
235  fFlagMarginalized = false;
236 }
237 
238 // ---------------------------------------------------------
239 unsigned BCIntegrate::GetNIntegrationVariables() {
240  unsigned n = 0;
241  for(unsigned i = 0; i < fParameters.Size(); ++i)
242  if ( ! fParameters[i]->Fixed())
243  ++n;
244  return n;
245 }
246 
247 // ---------------------------------------------------------
248 double BCIntegrate::CalculateIntegrationVolume() {
249  double integrationVolume = -1.;
250 
251  for(unsigned i = 0; i < fParameters.Size(); i++)
252  if ( ! fParameters[i]->Fixed()) {
253  if (integrationVolume<0)
254  integrationVolume = 1;
255  integrationVolume *= fParameters[i]->GetRangeWidth();
256  }
257 
258  if (integrationVolume<0)
259  integrationVolume = 0;
260 
261  return integrationVolume;
262 }
263 
264 // ---------------------------------------------------------
265 double BCIntegrate::Integrate()
266 {
267  // check if parameters are defined
268  if (fParameters.Size() < 1) {
269  BCLog::OutError("BCIntegrate::Integrate : No parameters defined. Aborting.");
270  return -1.;
271  }
272 
273  // output
274  if (!(fIntegrationMethodCurrent == BCIntegrate::kIntDefault) && !(fIntegrationMethodCurrent == BCIntegrate::kIntEmpty))
275  BCLog::OutSummary(Form("Integrate using %s", DumpCurrentIntegrationMethod().c_str()));
276 
277  switch(fIntegrationMethodCurrent)
278  {
279 
280  // Empty
281  case BCIntegrate::kIntEmpty:
282  {
283  BCLog::OutWarning("BCIntegrate::Integrate : No integration method chosen.");
284  return 0;
285  }
286 
287 
288  // Monte Carlo Integration
289  case BCIntegrate::kIntMonteCarlo:
290  {
291  std::vector<double> sums (2,0.0);
292  sums.push_back(CalculateIntegrationVolume());
293  fIntegral = Integrate(kIntMonteCarlo,
294  &BCIntegrate::GetRandomVectorInParameterSpace,
295  &BCIntegrate::EvaluatorMC,
296  &IntegralUpdaterMC,
297  sums);
298 
299  // set used integration method
300  fIntegrationMethodUsed = BCIntegrate::kIntMonteCarlo;
301 
302  // return integral
303  return fIntegral;
304  }
305 
306  // CUBA library
307  case BCIntegrate::kIntCuba:
308  {
309  fIntegral = IntegrateCuba();
310 
311  // set used integration method
312  fIntegrationMethodUsed = BCIntegrate::kIntCuba;
313 
314  // return integral
315  return fIntegral;
316  }
317 
318  // CUBA library
319  case BCIntegrate::kIntGrid:
320  {
321  fIntegral = IntegrateSlice();
322 
323  // set used integration method
324  fIntegrationMethodUsed = BCIntegrate::kIntGrid;
325 
326  // return integral
327  return fIntegral;
328  }
329 
330  // default
331  case BCIntegrate::kIntDefault:
332  {
333  if (GetNFreeParameters() <= 2)
334  SetIntegrationMethod(BCIntegrate::kIntGrid);
335  else
336 #ifdef HAVE_CUBA_H
337  SetIntegrationMethod(BCIntegrate::kIntCuba);
338 #else
339  SetIntegrationMethod(BCIntegrate::kIntMonteCarlo);
340 #endif
341  return Integrate();
342  }
343 
344  default:
345  BCLog::OutError(TString::Format("BCIntegrate::Integrate : Invalid integration method: %d", fIntegrationMethodCurrent));
346  break;
347  }
348 
349  return 0;
350 }
351 
352 // ---------------------------------------------------------
353 double BCIntegrate::Integrate(BCIntegrationMethod intmethod)
354 {
355  // remember original method
356  BCIntegrationMethod method_temp = fIntegrationMethodCurrent;
357 
358  // set method
359  SetIntegrationMethod(intmethod);
360 
361  // run algorithm
362  double integral = Integrate();
363 
364  // re-set original method
365  SetIntegrationMethod(method_temp);
366 
367  // return integral
368  return integral;
369 
370 }
371 
372 // ---------------------------------------------------------
373 void BCIntegrate::SetBestFitParameters(const std::vector<double> &x, const double &new_value, double &old_value) {
374  if (new_value < old_value)
375  return;
376  old_value = new_value;
377  SetBestFitParameters(x);
378 }
379 
380 // ---------------------------------------------------------
381 unsigned BCIntegrate::IntegrationOutputFrequency() const
382 {
383  if (fNIterationsOutput > 0)
384  return fNIterationsOutput;
385  const unsigned nwrite = fNIterationsMax / 10;
386  if(nwrite < 10000)
387  return 1000;
388  if(nwrite < 100000)
389  return 10000;
390  if(nwrite < 1000000)
391  return 100000;
392  return 1000000;
393 }
394 
395 // ---------------------------------------------------------
396 void BCIntegrate::LogOutputAtStartOfIntegration(BCIntegrationMethod type, BCCubaMethod cubatype)
397 {
398  const unsigned NVarNow = GetNIntegrationVariables();
399 
400  BCLog::LogLevel level = BCLog::summary;
401 
402  if(fParameters.Size() != NVarNow) {
403 
404  level = BCLog::detail;
405  bool printed = false;
406 
407  if (type==kIntCuba)
408  {
409  BCLog::OutDetail(TString::Format("Running %s (%s) integration over %i dimensions out of %i.",
410  DumpIntegrationMethod(type).c_str(),
411  DumpCubaIntegrationMethod(cubatype).c_str(),
412  NVarNow, fParameters.Size()));
413  printed = true;
414  }
415 
416  if (not printed)
417  BCLog::OutDetail(TString::Format("Running %s integration over %i dimensions out of %i.",
418  DumpIntegrationMethod(type).c_str(),
419  NVarNow, fParameters.Size()));
420 
421  BCLog::OutDetail(" --> Fixed parameters:");
422  for(unsigned i = 0; i < fParameters.Size(); i++)
423  if(fParameters[i]->Fixed())
424  BCLog::OutDetail(TString::Format(" %3i : %g", i, fParameters[i]->GetFixedValue()));
425  }
426  else {
427  bool printed = false;
428 
429  if (type==kIntCuba) {
430  BCLog::OutDetail(TString::Format("Running %s (%s) integration over %i dimensions.",
431  DumpIntegrationMethod(type).c_str(),
432  DumpCubaIntegrationMethod(cubatype).c_str(),
433  NVarNow));
434  printed = true;
435  }
436 
437  if (not printed)
438  BCLog::OutDetail(TString::Format("Running %s integration over %i dimensions.",
439  DumpIntegrationMethod(type).c_str(),
440  NVarNow));
441  }
442 
443  if (GetNIterationsMin() > 0 && GetNIterationsMax() > 0 ) {
444  BCLog::Out(level, TString::Format(" --> Minimum number of iterations: %i", GetNIterationsMin()));
445  BCLog::Out(level, TString::Format(" --> Maximum number of iterations: %i", GetNIterationsMax()));
446  }
447  BCLog::Out(level, TString::Format(" --> Target relative precision: %e", GetRelativePrecision()));
448  BCLog::Out(level, TString::Format(" --> Target absolute precision: %e", GetAbsolutePrecision()));
449 }
450 
451 // ---------------------------------------------------------
452 void BCIntegrate::LogOutputAtEndOfIntegration(double integral, double absprecision, double relprecision, int nIterations)
453 {
454  BCLog::OutSummary(TString::Format(" --> Result of integration: %e +- %e", integral, absprecision));
455  BCLog::OutSummary(TString::Format(" --> Obtained relative precision: %e. ", relprecision));
456  if (nIterations >= 0)
457  BCLog::OutSummary(TString::Format(" --> Number of iterations: %i", nIterations));
458 }
459 
460 // ---------------------------------------------------------
461 void BCIntegrate::LogOutputAtIntegrationStatusUpdate(BCIntegrationMethod type, double integral, double absprecision, int nIterations)
462 {
463  BCLog::OutDetail(TString::Format("%s. Iteration %i, integral: %e +- %e.", DumpIntegrationMethod(type).c_str(), nIterations, integral, absprecision));
464 }
465 
466 // ---------------------------------------------------------
467 double BCIntegrate::Integrate(BCIntegrationMethod type, tRandomizer randomizer, tEvaluator evaluator, tIntegralUpdater updater,
468  std::vector<double> &sums)
469 {
470  LogOutputAtStartOfIntegration(type, NCubaMethods);
471 
472  // reset variables
473  double pmax = 0.;
474  double integral = 0.;
475  double absprecision = 2.*fAbsolutePrecision;
476  double relprecision = 2.*fRelativePrecision;
477 
478  std::vector<double> randx (fParameters.Size(), 0.);
479 
480  // how often to print out the info line to screen
481  int nwrite = IntegrationOutputFrequency();
482 
483  // reset number of iterations
484  fNIterations = 0;
485  bool accepted;
486 
487  // iterate while number of iterations is lower than minimum number of iterations
488  // or precision is not reached and the number of iterations is lower than maximum number of iterations
489  while ((GetRelativePrecision() < relprecision and GetAbsolutePrecision() < absprecision and GetNIterations() < GetNIterationsMax())
490  or GetNIterations() < GetNIterationsMin())
491  {
492 
493  // get random numbers
494  (this->*randomizer)(randx);
495 
496  // evaluate function at sampled point
497  // updating sums & checking for maximum probability
498 
499  SetBestFitParameters(randx, (this->*evaluator)(sums,randx,accepted), pmax);
500 
501  // increase number of iterations
502  if (accepted)
503  fNIterations++;
504 
505  // update precisions
506  if (fNIterations % fNIterationsPrecisionCheck == 0) {
507  (*updater)(sums, fNIterations, integral, absprecision);
508  relprecision = absprecision / integral;
509  }
510 
511  // write status
512  if (fNIterations % nwrite == 0) {
513  double temp_integral;
514  double temp_absprecision;
515  (*updater)(sums, fNIterations, temp_integral, temp_absprecision);
516  LogOutputAtIntegrationStatusUpdate(type, temp_integral, temp_absprecision, fNIterations);
517  }
518  }
519 
520  // calculate integral
521  (*updater)(sums, fNIterations, integral, absprecision);
522  relprecision = absprecision / integral;
523 
524  if (unsigned(fNIterations) >= fMCMCNIterationsMax)
525  BCLog::OutWarning("BCIntegrate::Integrate: Did not converge within maximum number of iterations");
526 
527  // print to log
528  LogOutputAtEndOfIntegration(integral, absprecision, relprecision, fNIterations);
529 
530  fError = absprecision;
531  return integral;
532 }
533 
534 // ---------------------------------------------------------
535 double BCIntegrate::EvaluatorMC(std::vector<double> &sums, const std::vector<double> &point, bool &accepted) {
536  const double value = Eval(point);
537 
538  // all samples accepted in sample-mean integration
539  accepted = true;
540 
541  // add value to sum and sum of squares
542  sums[0] += value;
543  sums[1] += value * value;
544 
545  return value;
546 }
547 
548 // ---------------------------------------------------------
549 void BCIntegrate::IntegralUpdaterMC(const std::vector<double> &sums, const int &nIterations, double &integral, double &absprecision) {
550  // sample mean including the volume of the parameter space
551  integral = sums[2] * sums[0] / nIterations;
552 
553  // unbiased estimate
554  absprecision = sqrt((1.0 / (nIterations - 1)) * (sums[2] * sums[2] * sums[1] / double(nIterations) - integral * integral));
555 }
556 
557 // ---------------------------------------------------------
558 bool BCIntegrate::CheckMarginalizationAvailability(BCMarginalizationMethod type) {
559  switch(type)
560  {
561  case BCIntegrate::kMargMonteCarlo:
562  return false;
563  case BCIntegrate::kMargMetropolis:
564  return true;
565  case BCIntegrate::kMargGrid:
566  return true;
567  case BCIntegrate::kMargDefault:
568  return true;
569  default:
570  BCLog::OutError(TString::Format("BCIntegrate::CheckMarginalizationAvailability. Invalid marginalization method: %d.", type));
571  break;
572  }
573  return false;
574 }
575 
576 // ---------------------------------------------------------
577 bool BCIntegrate::CheckMarginalizationIndices(TH1* hist, const std::vector<unsigned> &index) {
578  if (index.size()==0) {
579  BCLog::OutError("BCIntegrate::Marginalize : No marginalization parameters chosen.");
580  return false;
581  }
582 
583  if (index.size() >= 4 or index.size() > fParameters.Size()) {
584  BCLog::OutError("BCIntegrate::Marginalize : Too many marginalization parameters.");
585  return false;
586  }
587 
588  if ((int)index.size()<hist->GetDimension()) {
589  BCLog::OutError(TString::Format("BCIntegrate::Marginalize : Too few (%d) indices supplied for histogram dimension (%d)",(int)index.size(),hist->GetDimension()));
590  return false;
591  }
592 
593  for (unsigned i=0; i<index.size(); i++) {
594  // check if indices are in bounds
595  if ( ! fParameters.ValidIndex(index[i])) {
596  BCLog::OutError(TString::Format("BCIntegrate::Marginalize : Parameter index (%d) out of bound.",index[i]));
597  return false;
598  }
599  // check for duplicate indices
600  for (unsigned j=0; j<index.size(); j++)
601  if (i!=j and index[i]==index[j]) {
602  BCLog::OutError(TString::Format("BCIntegrate::Marginalize : Parameter index (%d) appears more than once",index[i]));
603  return false;
604  }
605  }
606  return true;
607 }
608 #if 0
609 // ---------------------------------------------------------
610 TH1D* BCIntegrate::Marginalize(BCIntegrationMethod type, unsigned index)
611 {
612  BCParameter * par = fParameters.Get(index);
613  if ( ! par)
614  return NULL;
615 
616  // create histogram
617  TH1D * hist = new TH1D(TString::Format("h1_%s", par->GetName().data()),
618  TString::Format(";%s;(unit %s)^{-1};", par->GetName().data(), par->GetName().data()),
619  par->GetNbins(), par->GetLowerLimit(), par->GetUpperLimit());
620 
621  // fill histogram
622  std::vector<unsigned> indices(1, index);
623  Marginalize(hist, type, indices);
624 
625  return hist;
626 }
627 
628 // ---------------------------------------------------------
629 TH2D* BCIntegrate::Marginalize(BCIntegrationMethod type, unsigned index1, unsigned index2)
630 {
631  BCParameter * par1 = fParameters.Get(index1);
632  BCParameter * par2 = fParameters.Get(index2);
633  if ( ! par1 || par2)
634  return NULL;
635 
636  // create histogram
637  TH2D * hist = new TH2D(TString::Format("h2_%s_%s", par1->GetName().data(), par2->GetName().data()),
638  TString::Format(";%s;%s;(unit %s)^{-1}(unit %s)^{-1}",
639  par1->GetName().data(), par2->GetName().data(),
640  par1->GetName().data(), par2->GetName().data()),
641  par1->GetNbins(), par1->GetLowerLimit(), par1->GetUpperLimit(),
642  par2->GetNbins(), par2->GetLowerLimit(), par2->GetUpperLimit());
643 
644  // fill histogram
645  std::vector<unsigned> indices;
646  indices.push_back(index1);
647  indices.push_back(index2);
648  Marginalize(hist,type,indices);
649 
650  return hist;
651 }
652 
653 // ---------------------------------------------------------
654 bool BCIntegrate::Marginalize(TH1* hist, BCIntegrationMethod type, const std::vector<unsigned> &index)
655 {
656  // debugKK: does this method really marginalize?
657 
658  // if (!CheckMarginalizationAvailability(type))
659  // return false;
660 
661  if (!CheckMarginalizationIndices(hist,index))
662  return false;
663 
664  // todo is this true?
665  // Currently this does not seem to work for Cuba integration beyond 1 dimension
666  if (type==kIntCuba and hist->GetDimension()>1) {
667  BCLog::OutError("BCIntegrate::Marginalize : Cuba integration currently only functions for 1D marginalization.");
668  return false;
669  }
670 
671  // generate string output
672  char * parnames = new char;
673  for (unsigned i=0; i<index.size(); i++) {
674  parnames = Form("%s %d (%s),",parnames,index[i],fParameters[i]->GetName().data());
675  }
676  if (index.size()==1)
677  BCLog::OutDebug(TString::Format(" --> Marginalizing model w/r/t parameter%s using %s.",parnames, DumpCurrentMarginalizationMethod().c_str()));
678  else
679  BCLog::OutDebug(TString::Format(" --> Marginalizing model w/r/t parameters%s using %s.",parnames, DumpCurrentMarginalizationMethod().c_str()));
680 
681  // Store original integration limits and fixed flags
682  // and unfix marginalization parameters;
683  std::vector<double> origMins, origMaxs;
684  std::vector<bool> origFix;
685  for (unsigned i=0; i<index.size(); i++) {
686  BCParameter * par = fParameters[index[i]];
687  origMins.push_back(par->GetLowerLimit());
688  origMaxs.push_back(par->GetUpperLimit());
689  origFix.push_back(par->Fixed());
690  par->Fix(false);
691  }
692 
693  // Set histogram title to indicate fixed variables
694  std::string title;
695  for (unsigned i=0; i < fParameters.Size(); ++i)
696  if (fParameters[i]->Fixed()) {
697  title += TString::Format(" (%s=%e)", fParameters[i]->GetName().data(), fParameters[i]->GetFixedValue());
698  }
699  if ( ! title.empty())
700  {
701  hist -> SetTitle(("Fixed: "+title).data());
702  }
703 
704  // get bin count
705  int N = hist->GetNbinsX() * hist->GetNbinsY() * hist->GetNbinsZ();
706 
707  // Store fNIterationsMax and change
708  int nIterationsMax = fNIterationsMax;
709  fNIterationsMax = fNIterationsMax / N;
710  if (fNIterationsMax<fNIterationsMin)
711  fNIterationsMax = fNIterationsMin;
712 
713  // todo not thread safe!
714  // integrate each bin
715  for (int i=1; i<=hist->GetNbinsX(); i++) {
716  fParameters[index[0]]->SetLowerLimit(hist->GetXaxis()->GetBinLowEdge(i));
717  fParameters[index[0]]->SetUpperLimit(hist->GetXaxis()->GetBinLowEdge(i+1));
718  double binwidth1d = hist -> GetXaxis() -> GetBinWidth(i);
719  if (hist->GetDimension()>1)
720  for (int j=1; j<=hist->GetNbinsY(); j++) {
721  fParameters[index[1]]->SetLowerLimit(hist -> GetYaxis() -> GetBinLowEdge(j));
722  fParameters[index[1]]->SetUpperLimit(hist -> GetYaxis() -> GetBinLowEdge(j+1));
723  double binwidth2d = binwidth1d * hist->GetYaxis()->GetBinWidth(j);
724  if (hist->GetDimension()>2)
725  for (int k=1; k<=hist->GetNbinsZ(); k++) {
726  fParameters[index[2]]->SetLowerLimit(hist -> GetZaxis() -> GetBinLowEdge(k));
727  fParameters[index[2]]->SetUpperLimit(hist -> GetZaxis() -> GetBinLowEdge(k+1));
728  double binwidth3d = binwidth2d * hist->GetZaxis()->GetBinWidth(k);
729  hist -> SetBinContent(i, j, k, Integrate(type)/binwidth3d);
730  hist -> SetBinError (i, j, k, GetError()/binwidth3d);
731  }
732  else {
733  hist -> SetBinContent(i, j, Integrate(type)/binwidth2d);
734  hist -> SetBinError (i, j, GetError()/binwidth2d);
735  }
736  }
737  else {
738  hist -> SetBinContent(i, Integrate(type)/binwidth1d);
739  hist -> SetBinError (i, GetError()/binwidth1d);
740  }
741  }
742 
743  // restore original integration limits and fixed flags
744  for (unsigned i=0; i<index.size(); i++) {
745  fParameters[index[i]]->SetLowerLimit(origMins[i]);
746  fParameters[index[i]]->SetUpperLimit(origMaxs[i]);
747  fParameters[index[i]]->Fix(origFix[i]);
748  }
749 
750  // restore original fNIterationsMax
751  fNIterationsMax = nIterationsMax;
752 
753  return true;
754 }
755 #endif
756 
757 // ---------------------------------------------------------
758 int BCIntegrate::MarginalizeAll()
759 {
760  // check if parameters are defined
761  if (fParameters.Size() < 1) {
762  BCLog::OutError("BCIntegrate::MarginalizeAll : No parameters defined. Aborting.");
763  return 0;
764  }
765 
766  // check if marginalization method is defined
767  if (!CheckMarginalizationAvailability(GetMarginalizationMethod())) {
768  BCLog::OutError(Form("BCIntegrate::MarginalizeAll : Marginalization method not implemented \'%s\'. Aborting.", DumpCurrentMarginalizationMethod().c_str()));
769  return 0;
770  }
771 
772  // output
773  if (!(fMarginalizationMethodCurrent == BCIntegrate::kMargDefault) && !(fMarginalizationMethodCurrent == BCIntegrate::kMargEmpty))
774  BCLog::OutSummary(Form("Marginalize using %s", DumpCurrentMarginalizationMethod().c_str()));
775 
776  switch (GetMarginalizationMethod())
777  {
778 
779  // Empty
780  case BCIntegrate::kMargEmpty:
781  {
782  BCLog::OutWarning("BCIntegrate::MarginalizeAll : No marginalization method chosen.");
783  return 0;
784  }
785 
786  // Markov Chain Monte Carlo
787  case BCIntegrate::kMargMetropolis:
788  {
789  // start preprocess
790  MarginalizePreprocess();
791 
792  // run the Markov chains
793  MCMCMetropolis();
794 
795  // start postprocess
796  MarginalizePostprocess();
797 
798  // set pointers to marginalized distributions
799  unsigned int npar = GetNParameters();
800 
801  fMarginalized1D.clear();
802  for (unsigned int i = 0; i < npar; ++i) {
803  fMarginalized1D.push_back(MCMCGetH1Marginalized(i));
804  }
805 
806  fMarginalized2D.clear();
807  if (npar > 1) {
808  for (unsigned int i = 0; i < npar; ++i) {
809  for (unsigned int j = 0; j < npar; ++j) {
810  if (i < j)
811  fMarginalized2D.push_back(MCMCGetH2Marginalized(i, j));
812  }
813  }
814  }
815 
816  // set used marginalization method
817  fMarginalizationMethodUsed = BCIntegrate::kMargMetropolis;
818 
819  // check if mode is better than previous one
820  if ( (!fFlagIgnorePrevOptimization) && (fLogMaximum < fMCMCLogMaximum) ) {
821  fBestFitParameters = fMCMCBestFitParameters;
822  fBestFitParameterErrors.assign(fParameters.Size(),-1.);
823  fLogMaximum = fMCMCLogMaximum;
824  fOptimizationMethodUsed = BCIntegrate::kOptMetropolis;
825  }
826 
827  break;
828  }
829 
830  // Sample Mean
831  case BCIntegrate::kMargMonteCarlo:
832  {
833  return 0;
834  }
835 
836  // Slice
837  case BCIntegrate::kMargGrid:
838  {
839  std::vector<double> fixpoint(GetNParameters());
840  for (unsigned int i = 0; i < GetNParameters(); ++i) {
841  if (fParameters[i]->Fixed())
842  fixpoint[i] = fParameters[i]->GetFixedValue();
843  else
844  fixpoint[i] = 0;
845  }
846 
847  // start preprocess
848  MarginalizePreprocess();
849 
850  // store highest probability
851  double probmax = -std::numeric_limits<double>::infinity();
852  std::vector<double> bestfit_parameters(fParameters.Size(), -std::numeric_limits<double>::infinity());
853  // correct fixed parameter values
854  // the other should have been determined above
855  for (unsigned i = 0; i < fParameters.Size(); ++i)
856  if (fParameters[i]->Fixed())
857  bestfit_parameters[i] = fParameters[i]->GetFixedValue();
858 
859  fMarginalized1D.clear();
860  if (GetNFreeParameters() == 1) {
861  for (unsigned int i = 0; i < GetNParameters(); ++i) {
862  if (!fParameters[i]->Fixed()) {
863  // calculate slice
864  BCH1D* hist_temp = GetSlice(fParameters[i], fixpoint, 0);
865  fMarginalized1D.push_back(hist_temp);
866 
867  // remember best fit before it is normalized and the value is wrong
868  const int index = hist_temp->GetHistogram()->GetMaximumBin();
869  probmax = hist_temp->GetHistogram()->GetBinContent(index);
870  bestfit_parameters.at(i) = hist_temp->GetHistogram()->GetBinCenter(index);
871 
872  // normalize to unity
873  hist_temp->GetHistogram()->Scale(1./hist_temp->GetHistogram()->Integral());
874  }
875  else
876  fMarginalized1D.push_back(0);
877  }
878 
879  fMarginalized2D.clear();
880  for (unsigned int i = 0; i < GetNParameters(); ++i) {
881  for (unsigned int j = 0; j < GetNParameters(); ++j) {
882  if (i >= j)
883  continue;
884  else
885  fMarginalized2D.push_back(0);
886  }
887  }
888  }
889  else if (GetNFreeParameters() == 2) {
890  // create a 2D histogram
891 
892  BCH2D* hist2d_temp = 0;
893 
894  fMarginalized2D.clear();
895  for (unsigned int i = 0; i < GetNParameters(); ++i) {
896  for (unsigned int j = 0; j < GetNParameters(); ++j) {
897  if (i >= j)
898  continue;
899  if (!fParameters[i]->Fixed() && !fParameters[j]->Fixed()) {
900  // calculate slice
901  hist2d_temp = GetSlice(GetParameter(i), GetParameter(j), fixpoint, 0);
902  fMarginalized2D.push_back(hist2d_temp);
903 
904  // remember best fit before it is normalized and the value is wrong
905  int index1, index2, useless_index;
906  hist2d_temp->GetHistogram()->GetMaximumBin(index1, index2, useless_index);
907  probmax = hist2d_temp->GetHistogram()->GetBinContent(index1, index2, useless_index);
908  bestfit_parameters.at(i) = hist2d_temp->GetHistogram()->GetXaxis()->GetBinCenter(index1);
909  bestfit_parameters.at(j) = hist2d_temp->GetHistogram()->GetYaxis()->GetBinCenter(index2);
910 
911  // normalize to unity
912  hist2d_temp->GetHistogram()->Scale(1./hist2d_temp->GetHistogram()->Integral());
913  }
914  else
915  fMarginalized2D.push_back(0);
916  }
917  }
918 
919  // marginalize by projecting
920  fMarginalized1D.clear();
921  for (unsigned int i = 0; i < GetNParameters(); ++i)
922  fMarginalized1D.push_back(0);
923  for (unsigned int i = 0; i < GetNParameters(); ++i) {
924  for (unsigned int j = 0; j < GetNParameters(); ++j) {
925  if (i >= j)
926  continue;
927  if (!fParameters[i]->Fixed() && !fParameters[j]->Fixed()) {
928  BCH1D* hist_x = new BCH1D( hist2d_temp->GetHistogram()->ProjectionX() );
929  hist_x->GetHistogram()->UseCurrentStyle(); // reset style because histogram is created by a projection
930  hist_x->GetHistogram()->SetStats(kFALSE);
931  fMarginalized1D[i] = hist_x;
932  BCH1D* hist_y = new BCH1D( hist2d_temp->GetHistogram()->ProjectionY() );
933  hist_y->GetHistogram()->UseCurrentStyle(); // reset style because histogram is created by a projection
934  hist_y->GetHistogram()->SetStats(kFALSE);
935  fMarginalized1D[j] = hist_y;
936  }
937  }
938  }
939  }
940  else {
941  BCLog::OutWarning("BCIntegrate::MarginalizeAll : Option works for 1D and 2D problems.");
942  return 0;
943  }
944 
945  // save if improved the log posterior
946 
947  if (fBestFitParameters.empty() || probmax > fMCMCLogMaximum) {
948  fLogMaximum = probmax;
949  fBestFitParameters = bestfit_parameters;
950  fBestFitParameterErrors.assign(fBestFitParameters.size(), std::numeric_limits<double>::infinity());
951  // todo can't set this one yet
952  // fOptimizationMethodUsed =
953  }
954 
955  BCLog::OutDetail(" --> Global mode from Grid:");
956  BCLog::OutDebug(Form(" --> Posterior value: %g", probmax));
957  int ndigits = (int) log10(fParameters.Size());
958  for (unsigned i = 0; i < fParameters.Size(); ++i)
959  BCLog::OutDetail(TString::Format(" --> parameter %*i: %.4g", ndigits+1, i, bestfit_parameters[i]));
960 
961  // start postprocess
962  MarginalizePostprocess();
963 
964  // set used marginalization method
965  fMarginalizationMethodUsed = BCIntegrate::kMargGrid;
966 
967  break;
968  }
969 
970  // default
971  case BCIntegrate::kMargDefault:
972  {
973  if ( GetNFreeParameters() <= 2 ) {
974  SetMarginalizationMethod(BCIntegrate::kMargGrid);
975  }
976  else {
977  SetMarginalizationMethod(BCIntegrate::kMargMetropolis);
978  }
979 
980  // call again
981  return MarginalizeAll();
982 
983  break;
984  }
985 
986  default:
987  BCLog::OutError(TString::Format("BCIntegrate::MarginalizeAll : Invalid marginalization method: %d", GetMarginalizationMethod()));
988  return 0;
989  break;
990  }
991 
992  // set flag
993  fFlagMarginalized = true;
994 
995  return 1;
996 }
997 
998 // ---------------------------------------------------------
999 int BCIntegrate::MarginalizeAll(BCIntegrate::BCMarginalizationMethod margmethod)
1000 {
1001  // remember original method
1002  BCMarginalizationMethod method_temp = fMarginalizationMethodCurrent;
1003 
1004  // set method
1005  SetMarginalizationMethod(margmethod);
1006 
1007  // run algorithm
1008  int result = MarginalizeAll();
1009 
1010  // re-set original method
1011  SetMarginalizationMethod(method_temp);
1012 
1013  // return result
1014  return result;
1015 }
1016 
1017 // ---------------------------------------------------------
1018 BCH1D * BCIntegrate::GetSlice(const BCParameter* parameter, const std::vector<double> parameters, int nbins, bool flag_norm)
1019 {
1020  // check if parameter exists
1021  if (!parameter) {
1022  BCLog::OutError("BCIntegrate::GetSlice : Parameter does not exist.");
1023  return 0;
1024  }
1025 
1026  // check if parameter is fixed
1027  if (parameter->Fixed())
1028  return 0;
1029 
1030  // create local copy of parameter set
1031  std::vector<double> parameters_temp;
1032  parameters_temp = parameters;
1033 
1034  // check if parameter set if defined
1035  if (parameters_temp.empty() && GetNParameters() == 1) {
1036  parameters_temp.push_back(0);
1037  }
1038  else if (parameters_temp.empty() && GetNParameters() != 1) {
1039  BCLog::OutError("BCIntegrate::GetSlice : No parameters defined.");
1040  return 0;
1041  }
1042 
1043  // calculate number of bins
1044  if (nbins <= 0)
1045  nbins = parameter->GetNbins();
1046 
1047  // create histogram
1048  TH1D * hist = new TH1D("", "", nbins, parameter->GetLowerLimit(), parameter->GetUpperLimit());
1049  hist->UseCurrentStyle();
1050 
1051  // set axis labels
1052  hist->SetXTitle(parameter->GetLatexName().data());
1053  if (GetNParameters() == 1)
1054  hist->SetYTitle(Form("p(%s|data)", parameter->GetLatexName().data()));
1055  else
1056  hist->SetYTitle(Form("p(%s|data, all other parameters fixed)", parameter->GetLatexName().data()));
1057  hist->SetStats(kFALSE);
1058 
1059  // fill histogram
1060  for (int i = 1; i <= nbins; ++i) {
1061  double par_temp = hist->GetBinCenter(i);
1062  parameters_temp[fParameters.Index(parameter->GetName())] = par_temp;
1063  double prob = Eval(parameters_temp);
1064  hist->SetBinContent(i, prob);
1065  }
1066 
1067  // normalize
1068  if (flag_norm)
1069  hist->Scale(1.0/hist->Integral());
1070 
1071  // set histogram
1072  BCH1D * hprob = new BCH1D();
1073  hprob->SetHistogram(hist);
1074 
1075  return hprob;
1076 }
1077 
1078 // ---------------------------------------------------------
1079 BCH2D* BCIntegrate::GetSlice(const BCParameter* parameter1, const BCParameter* parameter2, const std::vector<double> parameters, int nbins, bool flag_norm)
1080 {
1081  return GetSlice(parameter1->GetName().c_str(), parameter2->GetName().c_str(), parameters, nbins, flag_norm);
1082 }
1083 
1084 // ---------------------------------------------------------
1085 BCH2D* BCIntegrate::GetSlice(const char* name1, const char* name2, const std::vector<double> parameters, int nbins, bool flag_norm)
1086 {
1087  return GetSlice(fParameters.Index(name1), fParameters.Index(name2), parameters, nbins, flag_norm);
1088 }
1089 
1090 // ---------------------------------------------------------
1091 BCH2D* BCIntegrate::GetSlice(unsigned index1, unsigned index2, const std::vector<double> parameters, int nbins, bool flag_norm)
1092 {
1093  // check if parameters exists
1094  if (!fParameters.ValidIndex(index1) || !fParameters.ValidIndex(index2)) {
1095  BCLog::OutError("BCIntegrate::GetSlice : Parameter does not exist.");
1096  return 0;
1097  }
1098 
1099  // check if parameters are fixed
1100  if (fParameters[index1]->Fixed() || fParameters[index2]->Fixed())
1101  return 0;
1102 
1103  // create local copy of parameter set
1104  std::vector<double> parameters_temp;
1105  parameters_temp = parameters;
1106 
1107  // check number of dimensions
1108  if (GetNParameters() < 2) {
1109  BCLog::OutError("BCIntegrate::GetSlice : Number of parameters need to be at least 2.");
1110  }
1111 
1112  // check if parameter set if defined
1113  if (parameters_temp.size()==0 && GetNParameters()==2) {
1114  parameters_temp.push_back(0);
1115  parameters_temp.push_back(0);
1116  }
1117  else if (parameters_temp.size()==0 && GetNParameters()>2) {
1118  BCLog::OutError("BCIntegrate::GetSlice : No parameters defined.");
1119  return 0;
1120  }
1121 
1122  // calculate number of bins
1123  const BCParameter * p1 = fParameters.Get(index1);
1124  const BCParameter * p2 = fParameters.Get(index2);
1125  unsigned nbins1, nbins2;
1126  if (nbins <= 0) {
1127  nbins1 = p1->GetNbins();
1128  nbins2 = p2->GetNbins();
1129  } else {
1130  nbins1 = nbins2 = nbins;
1131  }
1132 
1133  // create histogram
1134  TH2D * hist = new TH2D("", "", nbins1, p1->GetLowerLimit(), p1->GetUpperLimit(),
1135  nbins2, p2->GetLowerLimit(), p2->GetUpperLimit());
1136  hist->UseCurrentStyle();
1137 
1138  // set axis labels
1139  hist->SetXTitle(Form("%s", p1->GetLatexName().data()));
1140  hist->SetYTitle(Form("%s", p2->GetLatexName().data()));
1141  hist->SetStats(kFALSE);
1142 
1143  // fill histogram
1144  for (unsigned int ix = 1; ix <= nbins1; ++ix) {
1145  for (unsigned int iy = 1; iy <= nbins2; ++iy) {
1146  double par_temp1 = hist->GetXaxis()->GetBinCenter(ix);
1147  double par_temp2 = hist->GetYaxis()->GetBinCenter(iy);
1148 
1149  parameters_temp[index1] = par_temp1;
1150  parameters_temp[index2] = par_temp2;
1151 
1152  double prob = Eval(parameters_temp);
1153  hist->SetBinContent(ix, iy, prob);
1154  }
1155  }
1156 
1157  // calculate normalization
1158  double norm = hist->Integral("width");
1159 
1160  // normalize
1161  if (flag_norm)
1162  hist->Scale(1.0/norm);
1163 
1164  // set histogram
1165  BCH2D * hprob = new BCH2D();
1166  hprob->SetHistogram(hist);
1167 
1168  // renormalize
1169  hist->Scale(norm / hist->Integral("width"));
1170 
1171  return hprob;
1172 }
1173 // ---------------------------------------------------------
1174 double BCIntegrate::GetRandomPoint(std::vector<double> &x)
1175 {
1176  GetRandomVectorInParameterSpace(x);
1177  return Eval(x);
1178 }
1179 
1180 // ---------------------------------------------------------
1181 void BCIntegrate::GetRandomVectorUnitHypercube(std::vector<double> &x) const
1182 {
1183  fRandom->RndmArray(x.size(), &x.front());
1184 }
1185 
1186 // ---------------------------------------------------------
1187 void BCIntegrate::GetRandomVectorInParameterSpace(std::vector<double> &x) const
1188 {
1189  GetRandomVectorUnitHypercube(x);
1190 
1191  for (unsigned i = 0; i < fParameters.Size(); i++){
1192  if (fParameters[i]->Fixed())
1193  x[i] = fParameters[i]->GetFixedValue();
1194  else
1195  x[i] = fParameters[i]->GetLowerLimit() + x[i] * fParameters[i]->GetRangeWidth();
1196  }
1197 }
1198 
1199 // ---------------------------------------------------------
1200 BCH1D * BCIntegrate::GetMarginalized(const BCParameter * parameter)
1201 {
1202  if ( !parameter)
1203  return 0;
1204  return GetMarginalized(fParameters.Index(parameter->GetName()));
1205 }
1206 
1207 // ---------------------------------------------------------
1208 BCH1D * BCIntegrate::GetMarginalized(unsigned index)
1209 {
1210  // check if marginalized histogram exists
1211  if (fMarginalized1D.size() <= index)
1212  return 0;
1213 
1214  // get histogram
1215  BCH1D * htemp = fMarginalized1D.at(index);
1216 
1217  // check if histogram exists
1218  if (!htemp)
1219  return 0;
1220 
1221  // set global mode
1222  if (fBestFitParameters.size() == GetNParameters())
1223  htemp->SetGlobalMode(fBestFitParameters.at(index));
1224 
1225  // set axis labels
1226  htemp->GetHistogram()->SetName(Form("hist_%i_%s", fID, fParameters[index]->GetName().data()));
1227  htemp->GetHistogram()->SetYTitle(Form("p(%s|data)", fParameters[index]->GetLatexName().data()));
1228 
1229  // return histogram
1230  return htemp;
1231 }
1232 
1233  // ---------------------------------------------------------
1234 int BCIntegrate::ReadMarginalizedFromFile(const char * file)
1235 {
1236  TFile * froot = TFile::Open(file);
1237  if (!froot->IsOpen()) {
1238  BCLog::OutError(Form("BCIntegrate::ReadMarginalizedFromFile : Couldn't open file %s.", file));
1239  return 0;
1240  }
1241 
1242  // We reset the MCMCEngine here for the moment.
1243  // In the future maybe we only want to do this if the engine
1244  // wans't initialized at all or when there were some changes
1245  // in the model.
1246  // But maybe we want reset everything since we're overwriting
1247  // the marginalized distributions anyway.
1248  MCMCInitialize();
1249 
1250  int k = 0;
1251  int n = GetNParameters();
1252  for (int i = 0; i < n; i++) {
1253  const BCParameter * a = GetParameter(i);
1254  TKey * key = froot->GetKey(TString::Format("hist_%i_%s", fID, a->GetName().data()));
1255  if (key) {
1256  TH1D * h1 = (TH1D*) key->ReadObjectAny(TH1D::Class());
1257  h1->SetDirectory(0);
1258  if (SetMarginalized(i, h1))
1259  k++;
1260  }
1261  else
1262  BCLog::OutWarning(
1263  Form("BCIntegrate::ReadMarginalizedFromFile : Couldn't read histogram \"hist_%i_%s\" from file %s.",
1264  fID, a->GetName().data(), file));
1265  }
1266 
1267  for (int i = 0; i < n - 1; i++) {
1268  for (int j = i + 1; j < n; j++) {
1269  const BCParameter * a = GetParameter(i);
1270  const BCParameter * b = GetParameter(j);
1271  TKey * key = froot->GetKey(
1272  TString::Format("hist_%i_%s_%s",fID, a->GetName().data(),b->GetName().data()));
1273  if (key) {
1274  TH2D * h2 = (TH2D*) key->ReadObjectAny(TH2D::Class());
1275  h2->SetDirectory(0);
1276  if (SetMarginalized(i, j, h2))
1277  k++;
1278  }
1279  else
1280  BCLog::OutWarning(
1281  Form("BCIntegrate::ReadMarginalizedFromFile : Couldn't read histogram \"hist_%i_%s_%s\" from file %s.",
1282  fID, a->GetName().data(), b->GetName().data(), file));
1283  }
1284  }
1285 
1286  froot->Close();
1287 
1288  return k;
1289 }
1290 
1291 
1292 // ---------------------------------------------------------
1293 int BCIntegrate::PrintAllMarginalized1D(const char * filebase)
1294 {
1295  if (fMCMCH1Marginalized.size() == 0) {
1296  BCLog::OutError("BCIntegrate::PrintAllMarginalized : Marginalized distributions not available.");
1297  return 0;
1298  }
1299 
1300  int n = GetNParameters();
1301  for (int i = 0; i < n; i++) {
1302  const BCParameter * a = GetParameter(i);
1303  if (GetMarginalized(a))
1304  GetMarginalized(a)->Print(Form("%s_1D_%s.pdf", filebase, a->GetName().data()));
1305  }
1306 
1307  return n;
1308 }
1309 
1310 // ---------------------------------------------------------
1311 int BCIntegrate::PrintAllMarginalized2D(const char * filebase)
1312 {
1313  if (fMCMCH2Marginalized.size() == 0) {
1314  BCLog::OutError("BCIntegrate::PrintAllMarginalized : Marginalized distributions not available.");
1315  return 0;
1316  }
1317 
1318  int k = 0;
1319  int n = GetNParameters();
1320  for (int i = 0; i < n - 1; i++) {
1321  for (int j = i + 1; j < n; j++) {
1322  const BCParameter * a = GetParameter(i);
1323  const BCParameter * b = GetParameter(j);
1324 
1325  double meana = (a->GetLowerLimit() + a->GetUpperLimit()) / 2.;
1326  double deltaa = (a->GetUpperLimit() - a->GetLowerLimit());
1327  if (deltaa <= 1e-7 * meana)
1328  continue;
1329 
1330  double meanb = (b->GetLowerLimit() + b->GetUpperLimit()) / 2.;
1331  double deltab = (b->GetUpperLimit() - b->GetLowerLimit());
1332  if (deltab <= 1e-7 * meanb)
1333  continue;
1334 
1335  if (GetMarginalized(a, b))
1336  GetMarginalized(a, b)->Print(
1337  Form("%s_2D_%s_%s.pdf",filebase, a->GetName().data(), b->GetName().data()));
1338  k++;
1339  }
1340  }
1341 
1342  return k;
1343 }
1344 
1345 // ---------------------------------------------------------
1346 int BCIntegrate::PrintAllMarginalized(const char * file, std::string options1d, std::string options2d, unsigned int hdiv, unsigned int vdiv)
1347 {
1348  if (fMarginalized1D.size() == 0 and fMarginalized2D.size() == 0) {
1349  BCLog::OutError("BCIntegrate::PrintAllMarginalized : Marginalized distributions not available.");
1350  return 0;
1351  }
1352 
1353  // count all valid (non NULL) histograms
1354  int nvalid1D = 0;
1355  int nvalid2D = 0;
1356 
1357  for (unsigned i = 0 ; i < fMarginalized1D.size() ; ++i) {
1358  if (BCH1D * h = fMarginalized1D[i])
1359  if (h->GetHistogram())
1360  nvalid1D++;
1361  }
1362 
1363  for (unsigned i = 0 ; i < fMarginalized2D.size() ; ++i) {
1364  if (BCH2D * h = fMarginalized2D[i])
1365  if (h->GetHistogram())
1366  nvalid2D++;
1367  }
1368 
1369  std::string filename(file);
1370 
1371  // check if file extension does not exist or is not pdf or ps
1372  if ( (filename.find_last_of(".") == std::string::npos) or
1373  ((filename.substr(filename.find_last_of(".")+1) != "pdf") and
1374  (filename.substr(filename.find_last_of(".")+1) != "ps"))) {
1375  // make it a PDF file
1376  filename += ".pdf";
1377  }
1378 
1379  int c_width = gStyle->GetCanvasDefW(); // default canvas width
1380  int c_height = gStyle->GetCanvasDefH(); // default canvas height
1381 
1382  if (hdiv > vdiv) {
1383  if (hdiv > 3) {
1384  c_width = 1000;
1385  c_height = 700;
1386  }
1387  else {
1388  c_width = 800;
1389  c_height = 600;
1390  }
1391  }
1392  else if (hdiv < vdiv) {
1393  if (hdiv > 3) {
1394  c_height = 1000;
1395  c_width = 700;
1396  }
1397  else {
1398  c_height = 800;
1399  c_width = 600;
1400  }
1401  }
1402 
1403  const unsigned nplots = nvalid1D + nvalid2D;
1404 
1405  // give out warning if too many plots
1406  BCLog::OutSummary(Form("Printing all marginalized distributions (%d x 1D + %d x 2D = %d) into file %s",
1407  nvalid1D, nvalid2D, nplots, filename.c_str()));
1408  if (nplots > 100)
1409  BCLog::OutDetail("This can take a while...");
1410 
1411  // setup the canvas and file
1412  TCanvas c("c", "canvas", c_width, c_height);
1413  c.Divide(hdiv, vdiv);
1414 
1415  // for clean up later
1416  std::vector<BCH1D *> h1;
1417 
1418  // count plots
1419  unsigned n = 0;
1420 
1421  // open file for printing
1422  c.Print(std::string( filename + "[").c_str());
1423 
1424  for (unsigned i = 0; i < fParameters.Size(); ++i) {
1425  BCH1D * h = GetMarginalized(i);
1426  h1.push_back(h);
1427 
1428  // check if histogram exists
1429  if ( !h)
1430  continue;
1431 
1432  // if current page is full, switch to new page
1433  if (n != 0 && n % (hdiv * vdiv) == 0) {
1434  c.Print(filename.c_str());
1435  c.Clear("D");
1436  }
1437 
1438  // go to next pad
1439  c.cd(n % (hdiv * vdiv) + 1);
1440 
1441  h->Draw(options1d);
1442 
1443  if (++n % 100 == 0)
1444  BCLog::OutDetail(Form(" --> %d plots done", n));
1445  }
1446 
1447  // print page if any were plots were drawn
1448  if (n>0) {
1449  c.Print(filename.c_str());
1450  c.Clear("D");
1451  }
1452 
1453  // for clean up later
1454  std::vector<BCH2D *> h2;
1455 
1456  // check how many 2D plots are actually drawn, despite no histogram filling or delta prior
1457  unsigned k = 0;
1458  for (unsigned i = 0; i < fParameters.Size() - 1; ++i) {
1459  for (unsigned j = i + 1; j < fParameters.Size(); ++j) {
1460  // check if histogram exists, or skip if one par has a delta prior
1461  h2.push_back(GetMarginalized(i, j));
1462  if ( !h2.back())
1463  continue;
1464 
1465  // get corresponding parameters
1466  BCParameter * a = GetParameter(i);
1467  BCParameter * b = GetParameter(j);
1468 
1469  // if current page is full, switch to new page, but only if there is data to plot
1470  if ((k != 0 && k % (hdiv * vdiv) == 0)) {
1471  c.Print(filename.c_str());
1472  c.Clear("D");
1473  }
1474 
1475  // go to next pad
1476  c.cd(k % (hdiv * vdiv) + 1);
1477 
1478  const double meana = (a->GetLowerLimit() + a->GetUpperLimit()) / 2.;
1479  if (a->GetRangeWidth() <= 1e-7 * meana)
1480  continue;
1481 
1482  const double meanb = (b->GetLowerLimit() + b->GetUpperLimit()) / 2.;
1483  if (b->GetRangeWidth() <= 1e-7 * meanb)
1484  continue;
1485 
1486  h2.back()->Draw(options2d);
1487  ++k;
1488 
1489  if ((n + k) % 100 == 0)
1490  BCLog::OutDetail(Form(" --> %d plots done", n + k));
1491  }
1492  }
1493 
1494  if (k>0) {
1495  c.Print(filename.c_str());
1496  }
1497 
1498  if ((n + k) > 100 && (n + k) % 100 != 0)
1499  BCLog::OutDetail(Form(" --> %d plots done", n + k));
1500 
1501  c.Print(std::string( filename + "]").c_str());
1502 
1503  // return total number of drawn histograms
1504  return n + k;
1505 }
1506 
1507 // ---------------------------------------------------------
1508 BCH2D * BCIntegrate::GetMarginalized(const BCParameter * par1, const BCParameter * par2)
1509 {
1510  if ( !par1 or !par2 or (par1 == par2) )
1511  return 0;
1512 
1513  return GetMarginalized(fParameters.Index(par1->GetName()), fParameters.Index(par2->GetName()));
1514 }
1515 
1516 // ---------------------------------------------------------
1517 BCH2D * BCIntegrate::GetMarginalized(unsigned index1, unsigned index2)
1518 {
1519  // swap indices if necessary
1520  if (index1 > index2) {
1521  unsigned indexTemp = index1;
1522  index1 = index2;
1523  index2 = indexTemp;
1524  }
1525 
1526  // check if marginalized histogram exists
1527  if (fMarginalized2D.size() <= GetNParameters() * index1 - (index1 * index1 + 3 * index1) / 2 + index2 - 1)
1528  return 0;
1529 
1530  // get histogram
1531  BCH2D * htemp = fMarginalized2D.at(GetNParameters() * index1 - (index1 * index1 + 3 * index1) / 2 + index2 - 1);
1532 
1533  // check if histogram exists
1534  if ( !htemp)
1535  return 0;
1536 
1537  // set global mode
1538  if (fBestFitParameters.size() == GetNParameters()) {
1539  double gmode[] = { fBestFitParameters.at(index1), fBestFitParameters.at(index2) };
1540  htemp->SetGlobalMode(gmode);
1541  }
1542 
1543  // set name
1544  htemp->GetHistogram()->SetName(Form("hist_%i_%s_%s", fID,
1545  fParameters[index1]->GetName().data(),
1546  fParameters[index2]->GetName().data()));
1547 
1548  // return histogram
1549  return htemp;
1550 }
1551 
1552 // ---------------------------------------------------------
1553 std::vector<double> BCIntegrate::FindMode(std::vector<double> start)
1554 {
1555  if (fParameters.Size() < 1) {
1556  BCLog::OutError("FindMode : No parameters defined. Aborting.");
1557  return std::vector<double>();
1558  }
1559 
1560  if (start.empty() && fBestFitParameters.size() == fParameters.Size())
1561  start = fBestFitParameters;
1562 
1563  std::vector<double> mode_temp(GetNParameters());
1564  std::vector<double> errors_temp(GetNParameters());
1565  BCIntegrate::BCOptimizationMethod method_temp = fOptimizationMethodCurrent;
1566 
1567  // output
1568  if (!(fOptimizationMethodCurrent == BCIntegrate::kOptDefault) && !(fOptimizationMethodCurrent == BCIntegrate::kOptEmpty))
1569  BCLog::OutSummary(Form("Finding mode using %s", DumpCurrentOptimizationMethod().c_str()));
1570 
1571  switch (fOptimizationMethodCurrent)
1572  {
1573  case BCIntegrate::kOptEmpty:
1574  {
1575  BCLog::OutWarning("BCIntegrate::FindMode : No optimization method chosen.");
1576  return std::vector<double>();
1577  }
1578  case BCIntegrate::kOptSimAnn:
1579  {
1580  FindModeSA(mode_temp, errors_temp, start);
1581 
1582  break;
1583  }
1584 
1585  case BCIntegrate::kOptMinuit:
1586  {
1587  int printlevel = -1;
1588  if (BCLog::GetLogLevelScreen() <= BCLog::detail)
1589  printlevel = 0;
1590  if (BCLog::GetLogLevelScreen() <= BCLog::debug)
1591  printlevel = 1;
1592 
1593  BCIntegrate::FindModeMinuit(mode_temp, errors_temp, start, printlevel);
1594 
1595  break;
1596  }
1597 
1598  case BCIntegrate::kOptMetropolis:
1599  {
1600  FindModeMCMC(mode_temp, errors_temp);
1601 
1602  break;
1603  }
1604  case BCIntegrate::kOptDefault:
1605  {
1606  SetOptimizationMethod(BCIntegrate::kOptMinuit);
1607 
1608  return FindMode(start);
1609  }
1610 
1611  default:
1612  BCLog::OutError(Form("BCIntegrate::FindMode : Invalid mode finding method: %d", GetOptimizationMethod()));
1613  return std::vector<double>();
1614  }
1615 
1616  // calculate function at new mode
1617  double fcnatmode_temp = Eval(mode_temp);
1618 
1619  // check if the mode found mode is better than the previous estimate
1620  if ( (!fFlagIgnorePrevOptimization) && (fcnatmode_temp < fLogMaximum) ) {
1621  // set best fit parameters
1622  if (mode_temp.size() == fBestFitParameters.size())
1623  mode_temp = fBestFitParameters;
1624  else
1625  BCLog::OutError("BCIntegrate::FindMode : previous mode has a different number of parameters than current.");
1626 
1627  if (errors_temp.size() == fBestFitParameterErrors.size())
1628  errors_temp = fBestFitParameterErrors;
1629  else
1630  BCLog::OutError("BCIntegrate::FindMode : previous error estimate has a different number of parameters than current.");
1631 
1632  fcnatmode_temp = fLogMaximum;
1633  method_temp = fOptimizationMethodUsed;
1634  }
1635 
1636  // set the best-fit parameters
1637  fBestFitParameters = mode_temp;
1638  fBestFitParameterErrors = errors_temp;
1639  fLogMaximum = fcnatmode_temp;
1640 
1641  // set used optimization method
1642  fOptimizationMethodUsed = method_temp;
1643 
1644  // return the new mode
1645  return mode_temp;
1646 
1647 }
1648 
1649 // ---------------------------------------------------------
1650 std::vector<double> BCIntegrate::FindMode(BCIntegrate::BCOptimizationMethod optmethod, std::vector<double> start)
1651 {
1652  // remember original method
1653  BCOptimizationMethod method_temp = fOptimizationMethodCurrent;
1654 
1655  // set method
1656  SetOptimizationMethod(optmethod);
1657 
1658  // run algorithm
1659  std::vector<double> mode = FindMode(start);
1660 
1661  // re-set original method
1662  SetOptimizationMethod(method_temp);
1663 
1664  // return mode
1665  return mode;
1666 }
1667 
1668 // ---------------------------------------------------------
1669 TMinuit * BCIntegrate::GetMinuit()
1670 {
1671  if (!fMinuit)
1672  fMinuit = new TMinuit();
1673 
1674  return fMinuit;
1675 }
1676 
1677 // ---------------------------------------------------------
1678 std::vector<double> BCIntegrate::FindModeMinuit(std::vector<double> &mode, std::vector<double> &errors, std::vector<double> start, int printlevel)
1679 {
1680  if (fParameters.Size() < 1) {
1681  BCLog::OutError("BCIntegrate::FindModeMinuit : No parameters defined. Aborting.");
1682  return std::vector<double>();
1683  }
1684 
1685  bool have_start = true;
1686 
1687  // check start values
1688  if (start.size() == 0)
1689  have_start = false;
1690  else if (start.size() != fParameters.Size()) {
1691  have_start = false;
1692  BCLog::OutWarning("BCIntegrate::FindModeMinuit : Start point not valid (mismatch of dimensions), set to center.");
1693  }
1694 
1695  // check if point is allowed
1696  if (have_start) {
1697  for (unsigned int i = 0; i <fParameters.Size(); ++i) {
1698  if (!fParameters[i]->IsValid(start[i]))
1699  have_start = false;
1700  if (fParameters[i]->Fixed() && start[i] != fParameters[i]->GetFixedValue())
1701  have_start = false;
1702  }
1703  if (!have_start)
1704  BCLog::OutWarning("BCIntegrate::FindModeMinuit : Start point not valid (parameter not inside valid range), set to center.");
1705  }
1706 
1707  // set global this
1708  ::BCIntegrateHolder::instance(this);
1709 
1710  // define minuit
1711  if (fMinuit)
1712  delete fMinuit;
1713  fMinuit = new TMinuit(fParameters.Size());
1714 
1715  // set print level
1716  fMinuit->SetPrintLevel(printlevel);
1717 
1718  // set function
1719  fMinuit->SetFCN(&BCIntegrate::FCNLikelihood);
1720 
1721  // set UP for likelihood
1722  fMinuit->SetErrorDef(0.5);
1723 
1724  // set parameters
1725  int flag;
1726  for (unsigned i = 0; i < fParameters.Size(); i++) {
1727  double starting_point = (fParameters[i]->GetUpperLimit() + fParameters[i]->GetLowerLimit()) / 2.;
1728  if(have_start)
1729  starting_point = start[i];
1730  if (fParameters[i]->Fixed())
1731  starting_point = fParameters[i]->GetFixedValue();
1732  fMinuit->mnparm(i,
1733  fParameters[i]->GetName().data(),
1734  starting_point,
1735  fParameters[i]->GetRangeWidth() / 100.,
1736  fParameters[i]->GetLowerLimit(),
1737  fParameters[i]->GetUpperLimit(),
1738  flag);
1739  }
1740 
1741  for (unsigned i = 0; i < fParameters.Size(); i++)
1742  if (fParameters[i]->Fixed())
1743  fMinuit->FixParameter(i);
1744 
1745  // do mcmc minimization
1746  // fMinuit->mnseek();
1747 
1748  // do minimization
1749  fMinuit->mnexcm("MIGRAD", fMinuitArglist, 2, flag);
1750 
1751  // improve search for local minimum
1752  // fMinuit->mnimpr();
1753 
1754  // copy flag and result
1755  fMinuitErrorFlag = flag;
1756  // std::vector<double> localMode(fParameters.Size(), 0);
1757  // std::vector<double> errors(fParameters.Size(), 0);
1758  for (unsigned i = 0; i < fParameters.Size(); i++) {
1759  fMinuit->GetParameter(i, mode[i], errors[i]);
1760  }
1761 
1762  // delete minuit
1763  delete fMinuit;
1764  fMinuit = 0;
1765 
1766  return mode;
1767 }
1768 
1769 // ---------------------------------------------------------
1770 void BCIntegrate::InitializeSATree()
1771 {
1772  if (fTreeSA)
1773  delete fTreeSA;
1774  fTreeSA = new TTree("SATree", "SATree");
1775 
1776  fTreeSA->Branch("Iteration", &fSANIterations, "iteration/I");
1777  // todo make consistent with examples and test
1778  // remove because would require fixed number of parameters, and just superfluous info
1779 // fTreeSA->Branch("NParameters", &fNvar, "parameters/I");
1780  fTreeSA->Branch("Temperature", &fSATemperature, "temperature/D");
1781  fTreeSA->Branch("LogProbability", &fSALogProb, "log(probability)/D");
1782 
1783  for (unsigned i = 0; i < fParameters.Size(); ++i)
1784  fTreeSA->Branch(TString::Format("Parameter%i", i), &fSAx[i], TString::Format("parameter %i/D", i));
1785 }
1786 
1787 // ---------------------------------------------------------
1788 std::vector<double> BCIntegrate::FindModeSA(std::vector<double> &mode, std::vector<double> &errors, std::vector<double> start)
1789 {
1790  // note: if f(x) is the function to be minimized, then
1791  // f(x) := - LogEval(parameters)
1792 
1793  bool have_start = true;
1794  std::vector<double> x, y; // vectors for current state, new proposed state and best fit up to now
1795  double fval_x, fval_y, fval_mode; // function values at points x, y and mode (we save them rather than to re-calculate them every time)
1796  int t = 1; // time iterator
1797 
1798  // check start values
1799  if (start.size() == 0)
1800  have_start = false;
1801  else if (start.size() != fParameters.Size()) {
1802  have_start = false;
1803  BCLog::OutWarning("BCIntegrate::FindModeSA : Start point not valid (mismatch of dimensions), set to center.");
1804  }
1805 
1806  // check if point is allowed
1807  if (have_start) {
1808  for (unsigned int i = 0; i <fParameters.Size(); ++i) {
1809  if (!fParameters[i]->IsValid(start[i]))
1810  have_start = false;
1811  if (fParameters[i]->Fixed() && start[i] != fParameters[i]->GetFixedValue())
1812  have_start = false;
1813  }
1814  if (!have_start)
1815  BCLog::OutWarning("BCIntegrate::FindModeSA : Start point not valid (parameter not inside valid range), set to center.");
1816  }
1817 
1818  // if no starting point is given, set to center of parameter space
1819  if ( !have_start ) {
1820  start.clear();
1821  for (unsigned i=0; i<fParameters.Size(); i++)
1822  if (fParameters[i]->Fixed())
1823  start.push_back(fParameters[i]->GetFixedValue());
1824  else
1825  start.push_back((fParameters[i]->GetLowerLimit() + fParameters[i]->GetUpperLimit()) / 2.);
1826  }
1827 
1828  // set current state and best fit to starting point
1829  x = start;
1830  mode = start;
1831 
1832  // calculate function value at starting point
1833  fval_x = fval_mode = LogEval(x);
1834 
1835  // run while still "hot enough"
1836  while ( SATemperature(t) > fSATmin ) {
1837  // generate new state
1838  y = GetProposalPointSA(x, t);
1839 
1840  // check if the proposed point is inside the phase space
1841  // if not, reject it
1842  bool in_range = true;
1843 
1844  for (unsigned i = 0; i < fParameters.Size(); i++)
1845  if ( !fParameters[i]->IsValid(y[i]))
1846  in_range = false;
1847 
1848  if ( in_range ){
1849  // calculate function value at new point
1850  fval_y = LogEval(y);
1851 
1852  // is it better than the last one?
1853  // if so, update state and chef if it is the new best fit...
1854  if (fval_y >= fval_x) {
1855  x = y;
1856 
1857  fval_x = fval_y;
1858 
1859  if (fval_y > fval_mode) {
1860  mode = y;
1861  fval_mode = fval_y;
1862  }
1863  }
1864  // ...else, only accept new state w/ certain probability
1865  else {
1866  if (fRandom->Rndm() <= exp( (fval_y - fval_x) / SATemperature(t) )) {
1867  x = y;
1868  fval_x = fval_y;
1869  }
1870  }
1871  }
1872 
1873  // update tree variables
1874  fSANIterations = t;
1875  fSATemperature = SATemperature(t);
1876  fSALogProb = fval_x;
1877  fSAx = x;
1878 
1879  // fill tree
1880  if (fFlagWriteSAToFile && fTreeSA)
1881  fTreeSA->Fill();
1882 
1883  // increate t
1884  t++;
1885  }
1886 
1887  // calculate uncertainty
1888  errors.assign(fParameters.Size(),-1);
1889 
1890  return mode;
1891 }
1892 
1893 // ---------------------------------------------------------
1894 double BCIntegrate::SATemperature(double t)
1895 {
1896  // do we have Cauchy (default), Boltzmann or custom annealing schedule?
1897  if (fSASchedule == BCIntegrate::kSABoltzmann)
1898  return SATemperatureBoltzmann(t);
1899  else if (fSASchedule == BCIntegrate::kSACauchy)
1900  return SATemperatureCauchy(t);
1901  else
1902  return SATemperatureCustom(t);
1903 }
1904 
1905 // ---------------------------------------------------------
1906 double BCIntegrate::SATemperatureBoltzmann(double t)
1907 {
1908  return fSAT0 / log((double)(t + 1));
1909 }
1910 
1911 // ---------------------------------------------------------
1912 double BCIntegrate::SATemperatureCauchy(double t)
1913 {
1914  return fSAT0 / (double)t;
1915 }
1916 
1917 // ---------------------------------------------------------
1918 double BCIntegrate::SATemperatureCustom(double /*t*/)
1919 {
1920  BCLog::OutError("BCIntegrate::SATemperatureCustom : No custom temperature schedule defined");
1921  return 0.;
1922 }
1923 
1924 // ---------------------------------------------------------
1925 std::vector<double> BCIntegrate::GetProposalPointSA(const std::vector<double> &x, int t)
1926 {
1927  // do we have Cauchy (default), Boltzmann or custom annealing schedule?
1928  if (fSASchedule == BCIntegrate::kSABoltzmann)
1929  return GetProposalPointSABoltzmann(x, t);
1930  else if (fSASchedule == BCIntegrate::kSACauchy)
1931  return GetProposalPointSACauchy(x, t);
1932  else
1933  return GetProposalPointSACustom(x, t);
1934 }
1935 
1936 // ---------------------------------------------------------
1937 std::vector<double> BCIntegrate::GetProposalPointSABoltzmann(const std::vector<double> &x, int t)
1938 {
1939  std::vector<double> y;
1940  y.clear();
1941  double new_val, norm;
1942 
1943  for (unsigned i = 0; i < fParameters.Size(); i++) {
1944  if (fParameters[i]->Fixed()) {
1945  y.push_back(fParameters[i]->GetFixedValue());
1946  }
1947  else {
1948  norm = fParameters[i]->GetRangeWidth() * SATemperature(t) / 2.;
1949  new_val = x[i] + norm * fRandom->Gaus();
1950  y.push_back(new_val);
1951  }
1952  }
1953 
1954  return y;
1955 }
1956 
1957 // ---------------------------------------------------------
1958 std::vector<double> BCIntegrate::GetProposalPointSACauchy(const std::vector<double> &x, int t)
1959 {
1960  std::vector<double> y;
1961  y.clear();
1962 
1963  if (fParameters.Size() == 1) {
1964  double cauchy, new_val, norm;
1965 
1966  if (fParameters[0]->Fixed()) {
1967  y.push_back(fParameters[0]->GetFixedValue());
1968  }
1969  else {
1970  norm = fParameters[0]->GetRangeWidth() * SATemperature(t) / 2.;
1971  cauchy = tan(3.14159 * (fRandom->Rndm() - 0.5));
1972  new_val = x[0] + norm * cauchy;
1973  y.push_back(new_val);
1974  }
1975  }
1976  else {
1977  // use sampling to get radial n-dim Cauchy distribution
1978 
1979  // first generate a random point uniformly distributed on a
1980  // fNvar-dimensional hypersphere
1981  y = SAHelperGetRandomPointOnHypersphere();
1982 
1983  // scale the vector by a random factor determined by the radial
1984  // part of the fNvar-dimensional Cauchy distribution
1985  double radial = SATemperature(t) * SAHelperGetRadialCauchy();
1986 
1987  // scale y by radial part and the size of dimension i in phase space
1988  // afterwards, move by x
1989  for (unsigned i = 0; i < fParameters.Size(); i++) {
1990  if (fParameters[i]->Fixed()) {
1991  y[i] = fParameters[i]->GetFixedValue(); }
1992  else {
1993  y[i] = fParameters[i]->GetRangeWidth() * y[i] * radial / 2. + x[i];
1994  }
1995  }
1996  }
1997 
1998  return y;
1999 }
2000 
2001 // ---------------------------------------------------------
2002 std::vector<double> BCIntegrate::GetProposalPointSACustom(const std::vector<double> & /*x*/, int /*t*/)
2003 {
2004  BCLog::OutError("BCIntegrate::GetProposalPointSACustom : No custom proposal function defined");
2005  return std::vector<double>(fParameters.Size());
2006 }
2007 
2008 // ---------------------------------------------------------
2009 std::vector<double> BCIntegrate::SAHelperGetRandomPointOnHypersphere()
2010 {
2011  std::vector<double> rand_point(fParameters.Size());
2012 
2013  // This method can only be called with fNvar >= 2 since the 1-dim case
2014  // is already hard wired into the Cauchy annealing proposal function.
2015  // To speed things up, hard-code fast method for 2 and dimensions.
2016  // The algorithm for 2D can be found at
2017  // http://mathworld.wolfram.com/CirclePointPicking.html
2018  // For 3D just using ROOT's algorithm.
2019  if (fParameters.Size() == 2) {
2020  double x1, x2, s;
2021  do {
2022  x1 = fRandom->Rndm() * 2. - 1.;
2023  x2 = fRandom->Rndm() * 2. - 1.;
2024  s = x1*x1 + x2*x2;
2025  }
2026  while (s >= 1);
2027 
2028  rand_point[0] = (x1*x1 - x2*x2) / s;
2029  rand_point[1] = (2.*x1*x2) / s;
2030  }
2031  else if (fParameters.Size() == 3) {
2032  fRandom->Sphere(rand_point[0], rand_point[1], rand_point[2], 1.0);
2033  }
2034  else {
2035  double s = 0.,
2036  gauss_num;
2037 
2038  for (unsigned i = 0; i < fParameters.Size(); i++) {
2039  gauss_num = fRandom->Gaus();
2040  rand_point[i] = gauss_num;
2041  s += gauss_num * gauss_num;
2042  }
2043  s = sqrt(s);
2044 
2045  for (unsigned i = 0; i < fParameters.Size(); i++)
2046  rand_point[i] = rand_point[i] / s;
2047  }
2048 
2049  return rand_point;
2050 }
2051 
2052 // ---------------------------------------------------------
2053 double BCIntegrate::SAHelperGetRadialCauchy()
2054 {
2055  // theta is sampled from a rather complicated distribution,
2056  // so first we create a lookup table with 10000 random numbers
2057  // once and then, each time we need a new random number,
2058  // we just look it up in the table.
2059  double theta;
2060 
2061  // static vectors for theta-sampling-map
2062  static double map_u[10001];
2063  static double map_theta[10001];
2064  static bool initialized = false;
2065  static unsigned map_dimension = 0;
2066 
2067  // is the lookup-table already initialized? if not, do it!
2068  if (!initialized or map_dimension != fParameters.Size()) {
2069  double init_theta;
2070  double beta = SAHelperSinusToNIntegral(fParameters.Size() - 1, 1.57079632679);
2071 
2072  for (int i = 0; i <= 10000; i++) {
2073  init_theta = 3.14159265 * (double)i / 5000.;
2074  map_theta[i] = init_theta;
2075 
2076  map_u[i] = SAHelperSinusToNIntegral(fParameters.Size() - 1, init_theta) / beta;
2077  }
2078 
2079  map_dimension = fParameters.Size();
2080  initialized = true;
2081  } // initializing is done.
2082 
2083  // generate uniform random number for sampling
2084  double u = fRandom->Rndm();
2085 
2086  // Find the two elements just greater than and less than u
2087  // using a binary search (O(log(N))).
2088  int lo = 0;
2089  int up = 10000;
2090  int mid;
2091 
2092  while (up != lo) {
2093  mid = ((up - lo + 1) / 2) + lo;
2094 
2095  if (u >= map_u[mid])
2096  lo = mid;
2097  else
2098  up = mid - 1;
2099  }
2100  up++;
2101 
2102  // perform linear interpolation:
2103  theta = map_theta[lo] + (u - map_u[lo]) / (map_u[up] - map_u[lo]) * (map_theta[up] - map_theta[lo]);
2104 
2105  return tan(theta);
2106 }
2107 
2108 // ---------------------------------------------------------
2109 double BCIntegrate::SAHelperSinusToNIntegral(int dim, double theta)
2110 {
2111  if (dim < 1)
2112  return theta;
2113  else if (dim == 1)
2114  return (1. - cos(theta));
2115  else if (dim == 2)
2116  return 0.5 * (theta - sin(theta) * cos(theta));
2117  else if (dim == 3)
2118  return (2. - sin(theta) * sin(theta) * cos(theta) - 2. * cos(theta)) / 3.;
2119  else
2120  return - pow(sin(theta), (double)(dim - 1)) * cos(theta) / (double)dim
2121  + (double)(dim - 1) / (double)dim
2122  * SAHelperSinusToNIntegral(dim - 2, theta);
2123 }
2124 
2125 // ---------------------------------------------------------
2126 void BCIntegrate::FCNLikelihood(int & /*npar*/, double * /*grad*/, double &fval, double * par, int /*flag*/)
2127 {
2128  // copy parameters
2129  static std::vector<double> parameters;
2130 
2131  // calculate number of active + fixed parameters
2132  // remember: npar is just the number of _active_ parameters while
2133  // par is a vector of _all_ parameters
2134  int nparameters = ::BCIntegrateHolder::instance()->GetNParameters();
2135 
2136  // adjust size if needed
2137  parameters.resize(nparameters, 0.0);
2138 
2139  // copy values
2140  std::copy(par, par + nparameters, parameters.begin());
2141 
2142  // evaluate, for efficiency don't check if npar matches
2143  fval = - ::BCIntegrateHolder::instance()->LogEval(parameters);
2144 }
2145 
2146 // ---------------------------------------------------------
2147 std::vector<double> BCIntegrate::FindModeMCMC(std::vector<double> &mode, std::vector<double> &errors)
2148 {
2149  // call PreRun
2150  MCMCMetropolisPreRun();
2151 
2152  // loop over all chains and find the maximum point
2153  double logProb = -std::numeric_limits<double>::max();
2154  unsigned index = 0;
2155  for (unsigned i = 0; i < fMCMCNChains; ++i) {
2156  if (MCMCGetMaximumLogProb().at(i) > logProb){
2157  index = i;
2158  logProb = MCMCGetMaximumLogProb().at(i);
2159  }
2160  }
2161 
2162  mode = MCMCGetMaximumPoint(index);
2163  errors.assign(fParameters.Size(),-1.);
2164 
2165  return mode;
2166 }
2167 
2168 // ---------------------------------------------------------
2169 void BCIntegrate::SetIntegrationMethod(BCIntegrate::BCIntegrationMethod method)
2170 {
2171  if (method >= BCIntegrate::NIntMethods) {
2172  BCLog::OutError(Form("BCIntegrate::SetIntegrationMethod: Invalid method '%d' ", method));
2173  return;
2174  }
2175  if (method == BCIntegrate::kIntCuba) {
2176 #ifndef HAVE_CUBA_H
2177  BCLog::OutError("BCIntegrate::SetIntegrationMethod: Cuba not enabled during configure");
2178 #endif
2179  }
2180  fIntegrationMethodCurrent = method;
2181 }
2182 
2183 // ---------------------------------------------------------
2184 void BCIntegrate::SetCubaIntegrationMethod(BCIntegrate::BCCubaMethod type)
2185 {
2186 #ifdef HAVE_CUBA_H
2187  switch(type) {
2188  case BCIntegrate::kCubaVegas:
2189  case BCIntegrate::kCubaSuave:
2190  case BCIntegrate::kCubaDivonne:
2191  case BCIntegrate::kCubaCuhre:
2192  fCubaIntegrationMethod = type;
2193  return;
2194  default:
2195  BCLog::OutError(TString::Format("Integration method of type %d is not defined for Cuba",type));
2196  return;
2197  }
2198 #else
2199  (void) type; // suppress compiler warning about unused parameters
2200  BCLog::OutError("SetCubaIntegrationMethod: Cuba not enabled during configure");
2201 #endif
2202 }
2203 
2204 // ---------------------------------------------------------
2205 int BCIntegrate::CubaIntegrand(const int * ndim, const double xx[],
2206  const int * /*ncomp*/, double ff[], void * userdata)
2207 {
2208  BCIntegrate * local_this = static_cast<BCIntegrate *>(userdata);
2209 
2210  // scale variables
2211  double jacobian = 1.0;
2212 
2213  // create local parameter vector
2214  // important for thread safety, though not super efficient
2215  std::vector<double> scaled_parameters(local_this->fParameters.Size());
2216 
2217  // stay in sync with the possible lower number of parameters
2218  // that cuba sees due to fixing in BAT
2219  unsigned cubaIndex = 0;
2220  unsigned batIndex = 0;
2221  for (batIndex = 0; batIndex < local_this->fParameters.Size(); ++batIndex) {
2222  const BCParameter * p = local_this->fParameters[batIndex];
2223 
2224  // get the scaled parameter value
2225  if (p->Fixed())
2226  scaled_parameters[batIndex] = p->GetFixedValue();
2227  else {
2228  // convert from unit hypercube to actual parameter hyperrectangle
2229  scaled_parameters[batIndex] = p->GetLowerLimit() + xx[cubaIndex] * p->GetRangeWidth();
2230 
2231  // multiply range to jacobian
2232  jacobian *= p->GetRangeWidth();
2233 
2234  // one more parameter that cuba varies
2235  ++cubaIndex;
2236  }
2237  }
2238 
2239  if (cubaIndex != unsigned(*ndim))
2240  BCLog::OutError(Form("BCIntegrate::CubaIntegrand: mismatch between variable parameters"
2241  "in BAT (%d) and Cuba(%d)", batIndex, cubaIndex));
2242 
2243  // call function to integrate
2244  ff[0] = local_this->Eval(scaled_parameters);
2245 
2246  // multiply jacobian
2247  ff[0] *= jacobian;
2248 
2249  return 0;
2250 }
2251 
2252 // ---------------------------------------------------------
2253 double BCIntegrate::IntegrateCuba(BCCubaMethod cubatype) {
2254 #if HAVE_CUBA_H
2255  LogOutputAtStartOfIntegration(kIntCuba, cubatype);
2256 
2257  // integrand has only one component
2258  static const int ncomp = 1;
2259 
2260  // don't store integration in a slot for reuse
2261  static const int gridno = -1;
2262 
2263  // we don't want dumps of internal state
2264  static const char * statefile = "";
2265 
2266  // only evaluate at one position in parameter space at a time
2267  static const int nvec = 1;
2268 
2269 #ifdef CUBAVERSION_40
2270  // we have no spinning cores
2271  int * spin = 0;
2272 #endif
2273 
2274  // cuba returns info in these variables
2275  int fail = 0;
2276  int nregions = 0;
2277  std::vector<double> integral(ncomp, -1);
2278  std::vector<double> error(ncomp, -1);
2279  std::vector<double> prob(ncomp, -1);
2280 
2281  // reset number of iterations
2282  fNIterations = 0;
2283 
2284  // Cuba needs int variable
2285  int nIntegrationVariables = GetNIntegrationVariables();
2286 
2287  switch (cubatype) {
2288 
2289  case BCIntegrate::kCubaVegas:
2290  Vegas(nIntegrationVariables, ncomp,
2291  &BCIntegrate::CubaIntegrand, static_cast<void *>(this),
2292  nvec,
2293  fRelativePrecision, fAbsolutePrecision,
2294  fCubaVegasOptions.flags, fRandom->GetSeed(),
2295  fNIterationsMin, fNIterationsMax,
2296  fCubaVegasOptions.nstart, fCubaVegasOptions.nincrease, fCubaVegasOptions.nbatch,
2297  gridno, statefile,
2298 #ifdef CUBAVERSION_40
2299  spin,
2300 #endif
2301  &fNIterations, &fail,
2302  &integral[0], &error[0], &prob[0]);
2303  break;
2304 
2305  case BCIntegrate::kCubaSuave:
2306  Suave(nIntegrationVariables, ncomp,
2307  &BCIntegrate::CubaIntegrand, static_cast<void *>(this),
2308  nvec,
2309  fRelativePrecision, fAbsolutePrecision,
2310  fCubaSuaveOptions.flags, fRandom->GetSeed(),
2311  fNIterationsMin, fNIterationsMax,
2312  fCubaSuaveOptions.nnew, fCubaSuaveOptions.flatness,
2313  statefile,
2314 #ifdef CUBAVERSION_40
2315  spin,
2316 #endif
2317  &nregions, &fNIterations, &fail,
2318  &integral[0], &error[0], &prob[0]);
2319  break;
2320 
2321  case BCIntegrate::kCubaDivonne:
2322  if (nIntegrationVariables < 2 or nIntegrationVariables > 33)
2323  BCLog::OutError("BCIntegrate::IntegrateCuba(Divonne): Divonne only works in 1 < d < 34");
2324  else {
2325  // no extra info supported
2326  static const int ngiven = 0;
2327  static const int nextra = ngiven;
2328  Divonne(nIntegrationVariables, ncomp,
2329  &BCIntegrate::CubaIntegrand, static_cast<void *>(this),
2330  nvec,
2331  fRelativePrecision, fAbsolutePrecision,
2332  fCubaDivonneOptions.flags, fRandom->GetSeed(),
2333  fNIterationsMin, fNIterationsMax,
2334  fCubaDivonneOptions.key1, fCubaDivonneOptions.key2, fCubaDivonneOptions.key3,
2335  fCubaDivonneOptions.maxpass, fCubaDivonneOptions.border,
2336  fCubaDivonneOptions.maxchisq, fCubaDivonneOptions.mindeviation,
2337  ngiven, nIntegrationVariables /*ldxgiven*/, NULL, nextra, NULL,
2338  statefile,
2339 #ifdef CUBAVERSION_40
2340  spin,
2341 #endif
2342  &nregions, &fNIterations, &fail,
2343  &integral[0], &error[0], &prob[0]);
2344  }
2345  break;
2346 
2347  case BCIntegrate::kCubaCuhre:
2348  if (nIntegrationVariables < 2)
2349  BCLog::OutError("BCIntegrate::IntegrateCuba(Cuhre): Cuhre(cubature) only works in d > 1");
2350 
2351  Cuhre(nIntegrationVariables, ncomp,
2352  &BCIntegrate::CubaIntegrand, static_cast<void *>(this),
2353  nvec,
2354  fRelativePrecision, fAbsolutePrecision,
2355  fCubaCuhreOptions.flags, fNIterationsMin, fNIterationsMax,
2356  fCubaCuhreOptions.key,
2357  statefile,
2358 #ifdef CUBAVERSION_40
2359  spin,
2360 #endif
2361  &nregions, &fNIterations, &fail,
2362  &integral[0], &error[0], &prob[0]);
2363  break;
2364 
2365  case BCIntegrate::NCubaMethods:
2366  default:
2367  BCLog::OutError("Cuba integration method not set.");
2368  error[0] = -1;
2369  integral[0] = -1;
2370  break;
2371  }
2372 
2373  fError = error[0];
2374  double result = integral[0];
2375 
2376  if (fail != 0) {
2377  BCLog::OutWarning(" Warning, integral did not converge with the given set of parameters. ");
2378  BCLog::OutWarning(TString::Format(" neval = %d", fNIterations));
2379  BCLog::OutWarning(TString::Format(" fail = %d", fail));
2380  BCLog::OutWarning(TString::Format(" integral = %e", result));
2381  BCLog::OutWarning(TString::Format(" error = %e", fError));
2382  BCLog::OutWarning(TString::Format(" prob = %e", prob[0]));
2383 
2384  // handle cases in which cuba does not alter integral
2385  if (fNIterations == 0)
2386  {
2387  fError = -1;
2388  result = -1;
2389  }
2390 
2391  } else
2392  LogOutputAtEndOfIntegration(result,fError,fError/result,fNIterations);
2393 
2394  return result;
2395 #else
2396  (void) cubatype; // suppress compiler warning about unused parameters
2397  BCLog::OutError("IntegrateCuba: Cuba not enabled during configure");
2398  return -1;
2399 #endif
2400 }
2401 
2402 // ---------------------------------------------------------
2403 double BCIntegrate::IntegrateSlice()
2404 {
2405  // print to log
2406  LogOutputAtStartOfIntegration(fIntegrationMethodCurrent, NCubaMethods);
2407 
2408  double integral = -1;
2409  double absprecision = -1;
2410  double relprecision = -1;
2411  fError = -1;
2412 
2413  // calculate values are which the function should be evaluated
2414  std::vector<double> fixpoint(GetNParameters());
2415  for (unsigned int i = 0; i < GetNParameters(); ++i) {
2416  if (fParameters[i]->Fixed())
2417  fixpoint[i] = fParameters[i]->GetFixedValue();
2418  else
2419  fixpoint[i] = 0;
2420  }
2421 
2422  if (GetNFreeParameters() == 1) {
2423  for (unsigned int i = 0; i < GetNParameters(); ++i) {
2424  if (!fParameters[i]->Fixed()) {
2425  // calculate slice
2426  BCH1D* hist_temp = GetSlice(fParameters[i], fixpoint, 0, false);
2427 
2428  // calculate integral
2429  integral = hist_temp->GetHistogram()->Integral("width");
2430 
2431  // free memory
2432  delete hist_temp;
2433  }
2434  }
2435  }
2436  else if (GetNFreeParameters() == 2) {
2437  for (unsigned int i = 0; i < GetNParameters(); ++i) {
2438  for (unsigned int j = 0; j < GetNParameters(); ++j) {
2439  if (i >= j)
2440  continue;
2441  if (!fParameters[i]->Fixed() && !fParameters[j]->Fixed()) {
2442  // calculate slice
2443  BCH2D* hist_temp = GetSlice(GetParameter(i), GetParameter(j), fixpoint, 0, false);
2444 
2445  // calculate integral
2446  integral = hist_temp->GetHistogram()->Integral("width");
2447 
2448  // free memory
2449  delete hist_temp;
2450  }
2451  }
2452  }
2453  }
2454  else {
2455  BCLog::OutWarning("BCIntegrate::IntegrateSlice: Method only implemented for 1D and 2D problems. Return -1.");
2456 
2457  integral = -1;
2458  }
2459 
2460  // print to log
2461  LogOutputAtEndOfIntegration(integral, absprecision, relprecision, -1);
2462 
2463  return integral;
2464 }
2465 
2466 // ---------------------------------------------------------
2467 void BCIntegrate::SAInitialize()
2468 {
2469  fSAx.clear();
2470  fSAx.assign(fParameters.Size(), 0.0);
2471 }
2472 
2473 // ---------------------------------------------------------
2474 std::string BCIntegrate::DumpIntegrationMethod(BCIntegrate::BCIntegrationMethod type)
2475 {
2476  switch(type) {
2477  case BCIntegrate::kIntEmpty:
2478  return "Empty";
2479  case BCIntegrate::kIntMonteCarlo:
2480  return "Sample Mean Monte Carlo";
2481  case BCIntegrate::kIntCuba:
2482  return "Cuba";
2483  case BCIntegrate::kIntGrid:
2484  return "Grid";
2485  default:
2486  return "Undefined";
2487  }
2488 }
2489 
2490 // ---------------------------------------------------------
2491 std::string BCIntegrate::DumpMarginalizationMethod(BCIntegrate::BCMarginalizationMethod type)
2492 {
2493  switch(type) {
2494  case BCIntegrate::kMargEmpty:
2495  return "Empty";
2496  case BCIntegrate::kMargMonteCarlo:
2497  return "Sample Mean Monte Carlo";
2498  case BCIntegrate::kMargMetropolis:
2499  return "Metropolis";
2500  case BCIntegrate::kMargGrid:
2501  return "Grid";
2502  case BCIntegrate::kMargDefault:
2503  return "Default";
2504  default:
2505  return "Undefined";
2506  }
2507 }
2508 
2509 // ---------------------------------------------------------
2510 std::string BCIntegrate::DumpOptimizationMethod(BCIntegrate::BCOptimizationMethod type)
2511 {
2512  switch(type) {
2513  case BCIntegrate::kOptEmpty:
2514  return "Empty";
2515  case BCIntegrate::kOptSimAnn:
2516  return "Simulated Annealing";
2517  case BCIntegrate::kOptMetropolis:
2518  return "Metropolis MCMC";
2519  case BCIntegrate::kOptMinuit:
2520  return "Minuit";
2521  case BCIntegrate::kOptDefault:
2522  return "Default";
2523  default:
2524  return "Undefined";
2525  }
2526 }
2527 
2528 // ---------------------------------------------------------
2529 std::string BCIntegrate::DumpCubaIntegrationMethod(BCIntegrate::BCCubaMethod type)
2530 {
2531  switch(type) {
2532  case BCIntegrate::kCubaVegas:
2533  return "Vegas";
2534  case BCIntegrate::kCubaSuave:
2535  return "Suave";
2536  case BCIntegrate::kCubaDivonne:
2537  return "Divonne";
2538  case BCIntegrate::kCubaCuhre:
2539  return "Cuhre";
2540  default:
2541  return "Undefined";
2542  }
2543 }
2544 
2545 namespace BCCubaOptions
2546 {
2547 General::General() :
2548  ncomp(1),
2549  flags(0),
2550  nregions(0),
2551  neval(0),
2552  fail(0),
2553  error(0),
2554  prob(0)
2555 {}
2556 
2557 General::~General()
2558 {}
2559 
2560 /*
2561  * copy values from demo-c.c shipping with cuba 3.2
2562  * for three-dimensional examples.
2563  */
2564 
2565 Vegas::Vegas() :
2566  General(),
2567  nstart(1000),
2568  nincrease(500),
2569  nbatch(1000),
2570  gridno(0)
2571 {}
2572 
2573 Suave::Suave() :
2574  General(),
2575  nnew(1000),
2576  flatness(25)
2577 {}
2578 
2579 Divonne::Divonne() :
2580  General(),
2581  key1(47),
2582  key2(1),
2583  key3(1),
2584  maxpass(5),
2585  border(0),
2586  maxchisq(10),
2587  mindeviation(0.25)
2588 {}
2589 
2590 Cuhre::Cuhre() :
2591  General(),
2592  key(0) // let cuba choose default cubature rule
2593 {}
2594 }
virtual void ResetResults()
double GetLowerLimit() const
Definition: BCParameter.h:65
A class for handling numerical operations for models.
double GetRangeWidth() const
Definition: BCParameter.h:77
A class for handling 2D distributions.
Definition: BCH2D.h:37
void SetGlobalMode(double mode[2])
Definition: BCH2D.h:92
LogLevel
Definition: BCLog.h:45
TH2D * GetHistogram()
Definition: BCH2D.h:60
void SetHistogram(TH2D *hist)
Definition: BCH2D.cxx:99
void Copy(const BCEngineMCMC &enginemcmc)
void SetHistogram(TH1D *hist)
Definition: BCH1D.h:149
A class representing a parameter of a model.
Definition: BCParameter.h:28
An engine class for Markov Chain Monte Carlo.
Definition: BCEngineMCMC.h:41
TH1D * GetHistogram()
Definition: BCH1D.h:53
static void Out(BCLog::LogLevel loglevelfile, BCLog::LogLevel loglevelscreen, const char *message)
Definition: BCLog.cxx:100
const std::string & GetLatexName() const
Definition: BCParameter.h:60
double GetUpperLimit() const
Definition: BCParameter.h:70
A class for handling 1D distributions.
Definition: BCH1D.h:31
void SetGlobalMode(double mode)
Definition: BCH1D.h:159
const std::string & GetName() const
Definition: BCParameter.h:54
static BCLog::LogLevel GetLogLevelScreen()
Definition: BCLog.h:71
void Draw(std::string options="BTsiB3CS1D0Lmeanmode", std::vector< double > intervals=std::vector< double >(0))
Definition: BCH1D.cxx:231
A class for managing log messages.
Definition: BCLog.h:29