BCSplitGaussianPrior.cxx
1 /*
2  * Copyright (C) 2007-2018, 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 #include "BCSplitGaussianPrior.h"
10 #include "BCAux.h"
11 
12 #include <cmath>
13 
14 #include <TF1.h>
15 #include <TMath.h>
16 
17 
18 // ---------------------------------------------------------
19 BCSplitGaussianPrior::BCSplitGaussianPrior(double mode, double sigma_below, double sigma_above)
20  : BCPrior()
21  , fMode(mode)
22  , fSigmaBelow(sigma_below)
23  , fSigmaAbove(sigma_above)
24 {
25 }
26 
27 // ---------------------------------------------------------
29  : BCPrior(other)
30  , fMode(other.fMode)
31  , fSigmaBelow(other.fSigmaBelow)
32  , fSigmaAbove(other.fSigmaAbove)
33 {
34 }
35 
36 // ---------------------------------------------------------
38 {
39  if (x > fMode)
40  return -0.5 * (x - fMode) * (x - fMode) / fSigmaAbove / fSigmaAbove + 0.5 * log(2 / M_PI) - log(fSigmaAbove + fSigmaBelow);
41  return -0.5 * (x - fMode) * (x - fMode) / fSigmaBelow / fSigmaBelow + 0.5 * log(2 / M_PI) - log(fSigmaAbove + fSigmaBelow);
42 }
43 
44 // ---------------------------------------------------------
45 double BCSplitGaussianPrior::GetRawMoment(unsigned n, double xmin, double xmax)
46 {
47  if (n == 0 || n > 2)
48  return BCPrior::GetRawMoment(n, xmin, xmax);
49 
50  BCAux::BCRange r = BCAux::RangeType(xmin, xmax);
51 
52  if (r == BCAux::kReverseRange)
53  return GetRawMoment(n, xmax, xmin);
54 
55  if (r == BCAux::kEmptyRange)
56  return (n == 1) ? xmin : 0;
57 
58  // if (r == BCAux::kInfiniteRange) {
59  // if (n == 1)
60  // return fMode + sqrt(2/M_PI)*(fSigmaAbove-fSigmaBelow);
61  // // else n==2
62  // return fMode * fMode + (pow(fSigmaBelow, 3) + pow(fSigmaAbove, 3) + 2 * fMode * sqrt(2 / M_PI) * (pow(fSigmaAbove, 2) - pow(fSigmaBelow, 2))) / (fSigmaBelow + fSigmaAbove);
63  // }
64 
65  double smin = (xmin <= fMode) ? fSigmaBelow : fSigmaAbove;
66  double smax = (xmax <= fMode) ? fSigmaBelow : fSigmaAbove;
67 
68  double erf_min = (r == BCAux::kNegativeInfiniteRange) ? -1 : TMath::Erf((xmin - fMode) / smin / sqrt(2));
69  double erf_max = (r == BCAux::kPositiveInfiniteRange) ? +1 : TMath::Erf((xmax - fMode) / smax / sqrt(2));
70 
71  double phi_min = (r == BCAux::kNegativeInfiniteRange) ? 0 : exp(-0.5 * (xmin - fMode) * (xmin - fMode) / smin / smin);
72  double phi_max = (r == BCAux::kPositiveInfiniteRange) ? 0 : exp(-0.5 * (xmax - fMode) * (xmax - fMode) / smax / smax);
73 
74  double I = smax * erf_max - smin * erf_min;
75 
76  // first moment
77  double Ex = fMode + sqrt(2 / M_PI) * (smax * smax * (1 - phi_max) - smin * smin * (1 - phi_min)) / I;
78 
79  if (n == 1)
80  return Ex;
81 
82  phi_min *= (r == BCAux::kInfiniteRange or r == BCAux::kNegativeInfiniteRange) ? 0 : sqrt(2 / M_PI) * (xmin - fMode) / smin;
83  phi_max *= (r == BCAux::kInfiniteRange or r == BCAux::kPositiveInfiniteRange) ? 0 : sqrt(2 / M_PI) * (xmax - fMode) / smax;
84 
85  // second moment
86  double Ex2 = 2 * fMode * Ex - fMode * fMode + (smax * smax * smax * (erf_max - phi_max) - smin * smin * smin * (erf_min - phi_min)) / I;
87 
88  return Ex2;
89 }
90 
91 // ---------------------------------------------------------
92 double BCSplitGaussianPrior::GetIntegral(double xmin, double xmax)
93 {
94  BCAux::BCRange r = BCAux::RangeType(xmin, xmax);
95 
96  if (r == BCAux::kReverseRange)
97  return -GetIntegral(xmax, xmin);
98 
99  if (r == BCAux::kEmptyRange)
100  return 0;
101 
102  if (r == BCAux::kInfiniteRange)
103  return 1;
104 
105  double smin = (xmin <= fMode) ? fSigmaBelow : fSigmaAbove;
106  double smax = (xmax <= fMode) ? fSigmaBelow : fSigmaAbove;
107 
108  double erf_min = (r == BCAux::kNegativeInfiniteRange) ? -1 : TMath::Erf((xmin - fMode) / smin / sqrt(2));
109  double erf_max = (r == BCAux::kPositiveInfiniteRange) ? +1 : TMath::Erf((xmax - fMode) / smax / sqrt(2));
110 
111  return (smax * erf_max - smin * erf_min) / (fSigmaAbove + fSigmaBelow);
112 }
virtual double GetLogPrior(double x)
Get log of prior.
virtual double GetRawMoment(unsigned n, double xmin=-std::numeric_limits< double >::infinity(), double xmax=std::numeric_limits< double >::infinity())
Get raw moment of prior distrubion.
virtual double GetIntegral(double xmin=-std::numeric_limits< double >::infinity(), double xmax=std::numeric_limits< double >::infinity())
Get integral of prior.
double fSigmaBelow
std dev of split gaussian below mode
A class to represent the prior of a parameter.
Definition: BCPrior.h:49
double fSigmaAbove
std dev of split gaussian above mode
A class to represent a split-Gaussian prior of a parameter.
BCRange
Range types.
Definition: BCAux.h:88
BCAux::BCRange RangeType(double xmin, double xmax)
Return type of range as a BCAux::BCRange enum.
Definition: BCAux.cxx:85
lower < upper, lower limit finite, upper limit infinite
Definition: BCAux.h:91
lower > upper
Definition: BCAux.h:94
lower limit == upper limit
Definition: BCAux.h:93
lower < upper, lower limit infinite, upper limit finite
Definition: BCAux.h:90
BCSplitGaussianPrior(double mode, double sigma_below, double sigma_above)
Constructor.
lower < upper, lower and upper limits infinite
Definition: BCAux.h:92
virtual double GetRawMoment(unsigned n, double xmin=-std::numeric_limits< double >::infinity(), double xmax=std::numeric_limits< double >::infinity())
Get raw moment of prior distrubion.
Definition: BCPrior.cxx:72