CMS 3D CMS Logo

GaussianSumUtilities1D.cc
Go to the documentation of this file.
3 
4 // #include "Utilities/Timing/interface/TimingReport.h"
5 // #include "Utilities/Timing/interface/TimerStack.h"
6 
7 // #include "TROOT.h"
8 // #include "TMath.h"
9 #include "Math/ProbFuncMathCore.h"
10 #include "Math/PdfFuncMathCore.h"
11 #include "Math/QuantFuncMathCore.h"
12 
13 #include <iostream>
14 #include <cmath>
15 
16 #include <map>
17 #include <functional>
18 #include <numeric>
19 #include <algorithm>
20 
21 double GaussianSumUtilities1D::pdf(unsigned int i, double x) const {
22  return weight(i) * gauss(x, mean(i), standardDeviation(i));
23 }
24 
25 double GaussianSumUtilities1D::quantile(const double q) const { return ROOT::Math::gaussian_quantile(q, 1.); }
26 
27 // double
28 // GaussianSumUtilities1D::quantile (const double q) const
29 // {
30 // //
31 // // mean and sigma of highest weight component
32 // //
33 // int iwMax(-1);
34 // float wMax(0.);
35 // for ( unsigned int i=0; i<size(); i++ ) {
36 // if ( weight(i)>wMax ) {
37 // iwMax = i;
38 // wMax = weight(i);
39 // }
40 // }
41 // //
42 // // Find start values: begin with mean and
43 // // go towards f(x)=0 until two points on
44 // // either side are found (assumes monotonously
45 // // increasing function)
46 // //
47 // double x1(mean(iwMax));
48 // double y1(cdf(x1)-q);
49 // double dx = y1>0. ? -standardDeviation(iwMax) : standardDeviation(iwMax);
50 // double x2(x1+dx);
51 // double y2(cdf(x2)-q);
52 // while ( y1*y2>0. ) {
53 // x1 = x2;
54 // y1 = y2;
55 // x2 += dx;
56 // y2 = cdf(x2) - q;
57 // }
58 // //
59 // // now use bisection to find final value
60 // //
61 // double x(0.);
62 // while ( true ) {
63 // // use linear interpolation
64 // x = -(x2*y1-x1*y2)/(y2-y1);
65 // double y = cdf(x) - q;
66 // if ( fabs(y)<1.e-6 ) break;
67 // if ( y*y1>0. ) {
68 // y1 = y;
69 // x1 = x;
70 // }
71 // else {
72 // y2 = y;
73 // x2 = x;
74 // }
75 // }
76 // return x;
77 // }
78 
81  computeMode();
82  return theModeStatus == Valid;
83 }
84 
87  computeMode();
88  return theMode;
89 }
90 
92  // TimerStack tstack;
93  // tstack.benchmark("GSU1D::benchmark",100000);
94  // FastTimerStackPush(tstack,"GaussianSumUtilities1D::computeMode");
96  //
97  // check for "degenerate" states (identical values with vanishing error)
98  //
99  if (theState.variance() < 1.e-14) {
102  return;
103  }
104  //
105  // Use means of individual components as start values.
106  // Sort by value of pdf.
107  //
108  typedef std::multimap<double, int, std::greater<double> > StartMap;
109  StartMap xStart;
110  for (unsigned int i = 0; i < size(); i++) {
111  xStart.insert(std::make_pair(pdf(mean(i)), i));
112  }
113  //
114  // Now try with each start value
115  //
116  int iRes(-1); // index of start component for current estimate
117  double xRes(mean((*xStart.begin()).second)); // current estimate of mode
118  double yRes(-1.); // pdf at current estimate of mode
119  // std::pair<double,double> result(-1.,mean((*xStart.begin()).second));
120  for (StartMap::const_iterator i = xStart.begin(); i != xStart.end(); i++) {
121  //
122  // Convergence radius for a single Gaussian = 1 sigma: don't try
123  // start values within 1 sigma of the current solution
124  //
125  if (theModeStatus == Valid && fabs(mean((*i).second) - mean(iRes)) / standardDeviation(iRes) < 1.)
126  continue;
127  //
128  // If a solution exists: drop as soon as the pdf at
129  // start value drops to < 75% of maximum (try to avoid
130  // unnecessary searches for the mode)
131  //
132  if (theModeStatus == Valid && (*i).first / (*xStart.begin()).first < 0.75)
133  break;
134  //
135  // Try to find mode
136  //
137  double x;
138  double y;
139  bool valid = findMode(x, y, mean((*i).second), standardDeviation((*i).second));
140  //
141  // consider only successful searches
142  //
143  if (valid) { //...
144  //
145  // update result only for significant changes in pdf(solution)
146  //
147  if (yRes < 0. || (y - yRes) / (y + yRes) > 1.e-10) {
148  iRes = (*i).second; // store index
149  theModeStatus = Valid; // update status
150  xRes = x; // current solution
151  yRes = y; // and its pdf value
152  // result = std::make_pair(y,x); // store solution and pdf(solution)
153  }
154  } //...
155  }
156  //
157  // check (existance of) solution
158  //
159  if (theModeStatus == Valid) {
160  //
161  // Construct single Gaussian state with
162  // mean = mode
163  // variance = local variance at mode
164  // weight such that the pdf's of the mixture and the
165  // single state are equal at the mode
166  //
167  double mode = xRes;
168  double varMode = localVariance(mode);
169  double wgtMode = pdf(mode) * sqrt(2 * M_PI * varMode);
170  theMode = SingleGaussianState1D(mode, varMode, wgtMode);
171  } else {
172  //
173  // mode finding failed: set solution to highest component
174  // (alternative would be global mean / variance ..?)
175  //
176  //two many log warnings to actually be useful - comment out
177  //edm::LogWarning("GaussianSumUtilities") << "1D mode calculation failed";
178  // double x = mean();
179  // double y = pdf(x);
180  // result = std::make_pair(y,x);
181  // theMode = SingleGaussianState1D(mean(),variance(),weight());
182  //
183  // look for component with highest value at mean
184  //
185  int icMax(0);
186  double ySqMax(0.);
187  int s = size();
188  for (int ic = 0; ic < s; ++ic) {
189  double w = weight(ic);
190  double ySq = w * w / variance(ic);
191  if (ySq > ySqMax) {
192  icMax = ic;
193  ySqMax = ySq;
194  }
195  }
197  }
198 }
199 
200 bool GaussianSumUtilities1D::findMode(double& xMode, double& yMode, const double& xStart, const double& scale) const {
201  //
202  // try with Newton on (lnPdf)'(x)
203  //
204  double x1(0.);
205  double y1(0.);
206  FinderState state(size());
207  update(state, xStart);
208 
209  double xmin(xStart - 1. * scale);
210  double xmax(xStart + 1. * scale);
211  //
212  // preset result
213  //
214  bool result(false);
215  xMode = state.x;
216  yMode = state.y;
217  //
218  // Iterate
219  //
220  int nLoop(0);
221  while (nLoop++ < 20) {
222  if (nLoop > 1 && state.yd2 < 0. &&
223  (fabs(state.yd * scale) < 1.e-10 || fabs(state.y - y1) / (state.y + y1) < 1.e-14)) {
224  result = true;
225  break;
226  }
227  if (fabs(state.yd2) < std::numeric_limits<float>::min())
229  double dx = -state.yd / state.yd2;
230  x1 = state.x;
231  y1 = state.y;
232  double x2 = x1 + dx;
233  if (state.yd2 > 0. && (x2 < xmin || x2 > xmax))
234  return false;
235  update(state, x2);
236  }
237  //
238  // result
239  //
240  if (result) {
241  xMode = state.x;
242  yMode = state.y;
243  }
244  return result;
245 }
246 
247 void GaussianSumUtilities1D::update(FinderState& state, double x) const {
248  state.x = x;
249 
250  pdfComponents(state.x, state.pdfs);
251  state.y = pdf(state.x, state.pdfs);
252  state.yd = 0;
253  if (state.y > std::numeric_limits<double>::min())
254  state.yd = d1Pdf(state.x, state.pdfs) / state.y;
255  state.yd2 = -state.yd * state.yd;
256  if (state.y > std::numeric_limits<double>::min())
257  state.yd2 += d2Pdf(state.x, state.pdfs) / state.y;
258 }
259 
260 double GaussianSumUtilities1D::pdf(double x) const {
261  double result(0.);
262  size_t s = size();
263  for (unsigned int i = 0; i < s; i++)
264  result += pdf(i, x);
265  return result;
266 }
267 
268 double GaussianSumUtilities1D::cdf(const double& x) const {
269  double result(0.);
270  size_t s = size();
271  for (unsigned int i = 0; i < s; i++)
273  return result;
274 }
275 
276 double GaussianSumUtilities1D::d1Pdf(const double& x) const { return d1Pdf(x, pdfComponents(x)); }
277 
278 double GaussianSumUtilities1D::d2Pdf(const double& x) const { return d2Pdf(x, pdfComponents(x)); }
279 
280 double GaussianSumUtilities1D::d3Pdf(const double& x) const { return d3Pdf(x, pdfComponents(x)); }
281 
282 double GaussianSumUtilities1D::lnPdf(const double& x) const { return lnPdf(x, pdfComponents(x)); }
283 
284 double GaussianSumUtilities1D::d1LnPdf(const double& x) const { return d1LnPdf(x, pdfComponents(x)); }
285 
286 double GaussianSumUtilities1D::d2LnPdf(const double& x) const { return d2LnPdf(x, pdfComponents(x)); }
287 
288 std::vector<double> GaussianSumUtilities1D::pdfComponents(const double& x) const {
289  std::vector<double> result;
290  result.reserve(size());
291  for (unsigned int i = 0; i < size(); i++)
292  result.push_back(weight(i) * gauss(x, mean(i), standardDeviation(i)));
293  return result;
294 }
295 
296 namespace {
297  struct PDF {
298  PDF(double ix) : x(ix) {}
299  double x;
300  double operator()(SingleGaussianState1D const& sg) const {
301  return sg.weight() * ROOT::Math::gaussian_pdf(x, sg.standardDeviation(), sg.mean());
302  }
303  };
304 } // namespace
305 void GaussianSumUtilities1D::pdfComponents(double x, std::vector<double>& result) const {
306  size_t s = size();
307  if (s != result.size())
308  result.resize(s);
309  std::transform(components().begin(), components().end(), result.begin(), PDF(x));
310 }
311 /*
312 void GaussianSumUtilities1D::pdfComponents (double x, std::vector<double> & result) const {
313  size_t s = size();
314  if (s!=result.size()) result.resize(s);
315  double* __restrict__ v = &result.front();
316  SingleGaussianState1D const * __restrict__ sgv = &components().front();
317  for ( unsigned int i=0; i<s; i++ )
318  v[i]= sgv[i].weight()*gauss(x,sgv[i].mean(),sgv[i].standardDeviation());
319 // result[i]=pdf(i,x);
320 }
321 */
322 
323 double GaussianSumUtilities1D::pdf(double, const std::vector<double>& pdfs) {
324  return std::accumulate(pdfs.begin(), pdfs.end(), 0.);
325 }
326 
327 double GaussianSumUtilities1D::d1Pdf(double x, const std::vector<double>& pdfs) const {
328  double result(0.);
329  size_t s = size();
330  for (unsigned int i = 0; i < s; i++) {
331  double dx = (x - mean(i)) / standardDeviation(i);
332  result += -pdfs[i] * dx / standardDeviation(i);
333  }
334  return result;
335 }
336 
337 double GaussianSumUtilities1D::d2Pdf(double x, const std::vector<double>& pdfs) const {
338  double result(0.);
339  size_t s = size();
340  for (unsigned int i = 0; i < s; i++) {
341  double dx = (x - mean(i)) / standardDeviation(i);
342  result += pdfs[i] / standardDeviation(i) / standardDeviation(i) * (dx * dx - 1);
343  }
344  return result;
345 }
346 
347 double GaussianSumUtilities1D::d3Pdf(double x, const std::vector<double>& pdfs) const {
348  double result(0.);
349  size_t s = size();
350  for (unsigned int i = 0; i < s; i++) {
351  double dx = (x - mean(i)) / standardDeviation(i);
352  result += pdfs[i] / standardDeviation(i) / standardDeviation(i) / standardDeviation(i) * (-dx * dx + 3) * dx;
353  }
354  return result;
355 }
356 
357 double GaussianSumUtilities1D::lnPdf(double x, const std::vector<double>& pdfs) {
358  double f(pdf(x, pdfs));
361  result = log(f);
362  return result;
363 }
364 
365 double GaussianSumUtilities1D::d1LnPdf(double x, const std::vector<double>& pdfs) const {
366  double f = pdf(x, pdfs);
367  double result(d1Pdf(x, pdfs));
369  result /= f;
370  else
371  result = 0.;
372  return result;
373 }
374 
375 double GaussianSumUtilities1D::d2LnPdf(double x, const std::vector<double>& pdfs) const {
376  double f = pdf(x, pdfs);
377  double df = d1LnPdf(x, pdfs);
378  double result(-df * df);
380  result += d2Pdf(x, pdfs) / f;
381  return result;
382 }
383 
384 double GaussianSumUtilities1D::gauss(double x, double mean, double sigma) {
385  // const double fNorm(1./sqrt(2*M_PI));
386  // double result(0.);
387 
388  // double d((x-mean)/sigma);
389  // if ( fabs(d)<20. ) result = exp(-d*d/2.);
390  // result *= fNorm/sigma;
391  // return result;
392  return ROOT::Math::gaussian_pdf(x, sigma, mean);
393 }
394 
395 double GaussianSumUtilities1D::gaussInt(double x, double mean, double sigma) {
396  return ROOT::Math::normal_cdf(x, sigma, mean);
397 }
398 
400  double s0(0.);
401  double s1(0.);
402  int s = size();
403  SingleGaussianState1D const* __restrict__ sgv = &components().front();
404  for (int i = 0; i < s; i++)
405  s0 += sgv[i].weight();
406  for (int i = 0; i < s; i++)
407  s1 += sgv[i].weight() * sgv[i].mean();
408  return s1 / s0;
409 }
410 
412  std::vector<double> pdfs;
413  pdfComponents(x, pdfs);
414  double result = -pdf(x, pdfs) / d2Pdf(x, pdfs);
415  // FIXME: wrong curvature seems to be non-existant but should add a proper recovery
416  if (result < 0.)
417  edm::LogWarning("GaussianSumUtilities") << "1D variance at mode < 0";
418  return result;
419 }
GaussianSumUtilities1D::localVariance
double localVariance(double x) const
Definition: GaussianSumUtilities1D.cc:411
GaussianSumUtilities1D::gaussInt
static double gaussInt(double, double, double)
Integrated value of gaussian distribution.
Definition: GaussianSumUtilities1D.cc:395
GaussianSumUtilities1D::FinderState::y
double y
Definition: GaussianSumUtilities1D.h:97
DDAxes::y
GaussianSumUtilities1D::combinedMean
double combinedMean() const
Mean value of combined state.
Definition: GaussianSumUtilities1D.cc:399
mps_fire.i
i
Definition: mps_fire.py:355
GaussianSumUtilities1D::mode
const SingleGaussianState1D & mode() const
Definition: GaussianSumUtilities1D.cc:85
MessageLogger.h
MultiGaussianState1D::weight
double weight() const
combined weight
Definition: MultiGaussianState1D.cc:5
SiStripPI::mean
Definition: SiStripPayloadInspectorHelper.h:169
f
double f[11][100]
Definition: MuScleFitUtils.cc:78
min
T min(T a, T b)
Definition: MathUtil.h:58
testProducerWithPsetDescEmpty_cfi.x2
x2
Definition: testProducerWithPsetDescEmpty_cfi.py:28
GaussianSumUtilities1D::lnPdf
double lnPdf(const double &) const
ln(pdf)
Definition: GaussianSumUtilities1D.cc:282
GaussianSumUtilities1D::FinderState::yd2
double yd2
Definition: GaussianSumUtilities1D.h:99
GaussianSumUtilities1D::standardDeviation
double standardDeviation(unsigned int i) const
standard deviation of a component
Definition: GaussianSumUtilities1D.h:36
GaussianSumUtilities1D::cdf
double cdf(const double &) const
value of the c.d.f.
Definition: GaussianSumUtilities1D.cc:268
data-class-funcs.q
q
Definition: data-class-funcs.py:169
edm::second
U second(std::pair< T, U > const &p)
Definition: ParameterSet.cc:215
GaussianSumUtilities1D::findMode
bool findMode(double &mode, double &pdfAtMode, const double &xStart, const double &scale) const
Definition: GaussianSumUtilities1D.cc:200
GaussianSumUtilities1D::size
unsigned int size() const
number of components
Definition: GaussianSumUtilities1D.h:28
GaussianSumUtilities1D::d2LnPdf
double d2LnPdf(const double &) const
second derivative of ln(pdf)
Definition: GaussianSumUtilities1D.cc:286
DDAxes::x
ExhumeParameters_cfi.PDF
PDF
Definition: ExhumeParameters_cfi.py:8
GaussianSumUtilities1D.h
dqmdumpme.first
first
Definition: dqmdumpme.py:55
SingleGaussianState1D::mean
double mean() const
parameter vector
Definition: SingleGaussianState1D.h:25
validateGeometry_cfg.valid
valid
Definition: validateGeometry_cfg.py:21
end
#define end
Definition: vmac.h:39
GaussianSumUtilities1D::d3Pdf
double d3Pdf(const double &) const
third derivative of the p.d.f.
Definition: GaussianSumUtilities1D.cc:280
GaussianSumUtilities1D::quantile
double quantile(const double) const
Quantile (i.e. x for a given value of the c.d.f.)
Definition: GaussianSumUtilities1D.cc:25
testProducerWithPsetDescEmpty_cfi.x1
x1
Definition: testProducerWithPsetDescEmpty_cfi.py:33
alignCSCRings.s
s
Definition: alignCSCRings.py:92
testProducerWithPsetDescEmpty_cfi.y1
y1
Definition: testProducerWithPsetDescEmpty_cfi.py:29
GaussianSumUtilities1D::weight
double weight() const
combined weight
Definition: GaussianSumUtilities1D.h:69
GaussianSumUtilities1D::d1LnPdf
double d1LnPdf(const double &) const
first derivative of ln(pdf)
Definition: GaussianSumUtilities1D.cc:284
GaussianSumUtilities1D::FinderState::yd
double yd
Definition: GaussianSumUtilities1D.h:98
w
const double w
Definition: UKUtility.cc:23
mathSSE::sqrt
T sqrt(T t)
Definition: SSEVec.h:19
vertices_cff.x
x
Definition: vertices_cff.py:29
GaussianSumUtilities1D::d1Pdf
double d1Pdf(const double &) const
first derivative of the p.d.f.
Definition: GaussianSumUtilities1D.cc:276
HcalDetIdTransform::transform
unsigned transform(const HcalDetId &id, unsigned transformCode)
Definition: HcalDetIdTransform.cc:7
GaussianSumUtilities1D::mean
double mean() const
combined mean
Definition: GaussianSumUtilities1D.h:71
edm::LogWarning
Definition: MessageLogger.h:141
Scenarios_cff.scale
scale
Definition: Scenarios_cff.py:2186
GaussianSumUtilities1D::components
const std::vector< SingleGaussianState1D > & components() const
components
Definition: GaussianSumUtilities1D.h:30
GaussianSumUtilities1D::NotComputed
Definition: GaussianSumUtilities1D.h:18
SingleGaussianState1D::weight
double weight() const
weight
Definition: SingleGaussianState1D.h:23
GaussianSumUtilities1D::theState
const MultiGaussianState1D & theState
Definition: GaussianSumUtilities1D.h:126
SiStripPI::max
Definition: SiStripPayloadInspectorHelper.h:169
GaussianSumUtilities1D::variance
double variance() const
combined covariance
Definition: GaussianSumUtilities1D.h:73
SingleGaussianState1D
Definition: SingleGaussianState1D.h:10
GaussianSumUtilities1D::computeMode
void computeMode() const
calculation of mode
Definition: GaussianSumUtilities1D.cc:91
GaussianSumUtilities1D::pdf
double pdf(unsigned int i, double x) const
pdf of a single component at x
Definition: GaussianSumUtilities1D.cc:21
GaussianSumUtilities1D::Valid
Definition: GaussianSumUtilities1D.h:18
M_PI
#define M_PI
Definition: BXVectorInputProducer.cc:50
GaussianSumUtilities1D::FinderState::x
double x
Definition: GaussianSumUtilities1D.h:96
MultiGaussianState1D::mean
double mean() const
combined mean
Definition: MultiGaussianState1D.cc:15
GaussianSumUtilities1D::FinderState
Definition: GaussianSumUtilities1D.h:93
GaussianSumUtilities1D::theModeStatus
ModeStatus theModeStatus
Definition: GaussianSumUtilities1D.h:129
MultiGaussianState1D::variance
double variance() const
combined variance
Definition: MultiGaussianState1D.cc:20
GaussianSumUtilities1D::gauss
static double gauss(double, double, double)
Value of gaussian distribution.
Definition: GaussianSumUtilities1D.cc:384
TrackerOfflineValidation_Dqm_cff.xmax
xmax
Definition: TrackerOfflineValidation_Dqm_cff.py:11
GaussianSumUtilities1D::theMode
SingleGaussianState1D theMode
Definition: GaussianSumUtilities1D.h:130
GaussianSumUtilities1D::FinderState::pdfs
std::vector< double > pdfs
Definition: GaussianSumUtilities1D.h:100
dqm-mbProfile.log
log
Definition: dqm-mbProfile.py:17
GaussianSumUtilities1D::d2Pdf
double d2Pdf(const double &) const
second derivative of the p.d.f.
Definition: GaussianSumUtilities1D.cc:278
GaussianSumUtilities1D::pdfComponents
std::vector< double > pdfComponents(const double &) const
pdf components
Definition: GaussianSumUtilities1D.cc:288
mps_fire.result
result
Definition: mps_fire.py:303
TrackerOfflineValidation_Dqm_cff.xmin
xmin
Definition: TrackerOfflineValidation_Dqm_cff.py:10
GaussianSumUtilities1D::NotValid
Definition: GaussianSumUtilities1D.h:18
GaussianSumUtilities1D::update
void update(FinderState &state, double x) const
Definition: GaussianSumUtilities1D.cc:247
begin
#define begin
Definition: vmac.h:32
PVValHelper::dx
Definition: PVValidationHelpers.h:48
weight
Definition: weight.py:1
GaussianSumUtilities1D::modeIsValid
bool modeIsValid() const
mode status
Definition: GaussianSumUtilities1D.cc:79
SingleGaussianState1D::standardDeviation
double standardDeviation() const
standardDeviation
Definition: SingleGaussianState1D.h:29
MillePedeFileConverter_cfg.e
e
Definition: MillePedeFileConverter_cfg.py:37