Belle II Software  release-05-01-25
CalcMeanCov.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2010 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Martin Ritter *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #pragma once
12 
13 #include <cmath>
14 
15 namespace Belle2 {
36  template<int N = 1, class RealType = double>
37  class CalcMeanCov {
38  static_assert(N > 0, "Number of parameters, N, must be positive");
39  public:
41  CalcMeanCov() { clear(); }
42 
44  typedef RealType value_type;
45 
47  void clear()
48  {
49  m_entries = 0;
50  for (int i = 0; i < N; i++)
51  m_mean[i] = 0;
52  for (int i = 0; i < N * (N + 1) / 2; i++)
53  m_covariance[i] = 0;
54  }
55 
61  template<class... T> void addWeighted(value_type weight, T... values)
62  {
63  static_assert(sizeof...(values) == N,
64  "Number of arguments must be equal N");
65  m_entries += weight;
66  addValue<0>(weight, values...);
67  }
68 
73  template<class... T> void add(T... values)
74  {
75  addWeighted(1.0, values...);
76  }
77 
79  void add(const CalcMeanCov<N, RealType>& other)
80  {
81  const value_type n = m_entries + other.m_entries;
82  if (n == 0)
83  return;
84  for (int i = 0; i < N; ++i) {
85  const value_type delta = (other.m_mean[i] - m_mean[i]);
86  //Update covariance matrix
87  for (int j = i; j < N; ++j) {
88  const value_type delta2 = (other.m_mean[j] - m_mean[j]);
89  m_covariance[getIndex(i, j)] += other.m_covariance[getIndex(i, j)] + m_entries * other.m_entries
90  / n * delta * delta2;
91  }
92  //Update mean value
93  m_mean[i] += other.m_entries * delta / n;
94  }
95  m_entries = n;
96  }
97 
102  void addWeightedArray(value_type weight, value_type* values)
103  {
104  m_entries += weight;
105  addArrayValues(weight, values);
106  }
107 
111  void addArray(value_type* values)
112  {
113  addWeightedArray(1.0, values);
114  }
115 
122  value_type getEntries() const { return m_entries; }
124  value_type getMean(int i) const { return m_mean[i]; }
126  value_type getCovariance(int i, int j) const
127  {
128  if (m_entries == 0.0) return 0.0;
129  return m_covariance[getIndex(i, j)] / m_entries;
130  }
132  value_type getCorrelation(int i, int j) const
133  {
134  if (i == j) return 1.0;
135  if (m_entries == 0.0) return 0.0;
136  return getCovariance(i, j) / (getStddev(i) * getStddev(j));
137  }
139  value_type getVariance(int i) const { return getCovariance(i, i); }
141  value_type getStddev(int i) const { return std::sqrt(getVariance(i)); }
143  value_type getSum(int i) const { return getMean(i) * m_entries; }
144 
154  template <int i = 0> value_type getMean() const
155  {
156  static_assert(i >= 0 && i < N, "index i out of range");
157  return m_mean[i];
158  }
160  template <int i, int j> value_type getCovariance() const
161  {
162  static_assert(i >= 0 && i < N, "index i out of range");
163  static_assert(j >= 0 && j < N, "index j out of range");
164  if (m_entries == 0.0) return 0.0;
165  return m_covariance[getIndex(i, j)] / m_entries;
166  }
168  template <int i, int j> value_type getCorrelation() const
169  {
170  if (i == j) return 1.0;
171  if (m_entries == 0.0) return 0.0;
172  return getCovariance<i, j>() / (getStddev<i>() * getStddev<j>());
173  }
175  template <int i = 0> value_type getVariance() const
176  {
177  return getCovariance<i, i>();
178  }
180  template <int i = 0> value_type getStddev() const
181  {
182  return std::sqrt(getVariance<i>());
183  }
185  template <int i = 0> value_type getSum() const
186  {
187  return getMean<i>() * m_entries;
188  }
189 
192  private:
200  template<int i, class... T>
201  void addValue(value_type weight, value_type x, T... values)
202  {
203  const value_type delta = (x - m_mean[i]);
204  //Update covariance elements
205  updateCov<i, i>(weight, delta, x, values...);
206  //Update mean value
207  m_mean[i] += weight * delta / m_entries;
208  //recursively call again for remaining values
209  addValue < i + 1 > (weight, values...);
210  }
212  template<int i> void addValue(value_type) {}
213 
223  template<int i, int j, class... T>
224  void updateCov(value_type weight, value_type delta, value_type x,
225  T... values)
226  {
227  const value_type delta2 = (x - m_mean[j]);
228  m_covariance[getIndex(i, j)] += (m_entries - weight) * weight
229  / m_entries * delta * delta2;
230  updateCov < i, j + 1 > (weight, delta, values...);
231  }
232 
234  template<int i, int j> void updateCov(value_type, value_type) {}
235 
243  {
244  for (int i = 0; i < N; ++i) {
245  const value_type delta = (x[i] - m_mean[i]);
246  //Update covariance matrix
247  for (int j = i; j < N; ++j) {
248  const value_type delta2 = (x[j] - m_mean[j]);
249  m_covariance[getIndex(i, j)] += (m_entries - weight) * weight
250  / m_entries * delta * delta2;
251  }
252  //Update mean value
253  m_mean[i] += weight * delta / m_entries;
254  }
255  }
256 
262  constexpr int getIndex(unsigned int i, unsigned int j) const
263  {
264  //swap indices if i >= j
265  return (i < j) ? ((j + 1) * j / 2 + i) : ((i + 1) * i / 2 + j);
266  }
267 
271  value_type m_mean[N];
274  value_type m_covariance[N * (N + 1) / 2];
275  };
276 
278 } //Belle2 namespace
Belle2::CalcMeanCov::add
void add(T... values)
Update mean and covariance by adding a new entry.
Definition: CalcMeanCov.h:81
Belle2::CalcMeanCov::getSum
value_type getSum() const
Return the weighted sum values for parameter i.
Definition: CalcMeanCov.h:193
Belle2::CalcMeanCov::getCovariance
value_type getCovariance() const
Return the covariance between parameters i and j.
Definition: CalcMeanCov.h:168
Belle2::CalcMeanCov::getEntries
value_type getEntries() const
Return the number of entries.
Definition: CalcMeanCov.h:130
Belle2::CalcMeanCov::updateCov
void updateCov(value_type weight, value_type delta, value_type x, T... values)
Update covariance between parameters i and j.
Definition: CalcMeanCov.h:232
Belle2::CalcMeanCov::addValue
void addValue(value_type weight, value_type x, T... values)
Add a single value for parameter i and update mean and covariance.
Definition: CalcMeanCov.h:209
Belle2::CalcMeanCov::addWeighted
void addWeighted(value_type weight, T... values)
Update mean and covariance by adding a new, weighted entry.
Definition: CalcMeanCov.h:69
Belle2::CalcMeanCov::CalcMeanCov
CalcMeanCov()
default constructor.
Definition: CalcMeanCov.h:49
Belle2::CalcMeanCov::addArray
void addArray(value_type *values)
Update mean and covariance by adding a new entry.
Definition: CalcMeanCov.h:119
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::CalcMeanCov::getMean
value_type getMean() const
Return the mean for parameter i.
Definition: CalcMeanCov.h:162
Belle2::CalcMeanCov::getIndex
constexpr int getIndex(unsigned int i, unsigned int j) const
Access element in triangular matrix including diagonal elements.
Definition: CalcMeanCov.h:270
Belle2::CalcMeanCov::getVariance
value_type getVariance() const
Return the variance for paramter i.
Definition: CalcMeanCov.h:183
Belle2::CalcMeanCov::getStddev
value_type getStddev() const
Return the standard deviation for parameter i.
Definition: CalcMeanCov.h:188
Belle2::CalcMeanCov::addArrayValues
void addArrayValues(value_type weight, value_type *x)
Add a new set of values and update mean and covariance.
Definition: CalcMeanCov.h:250
Belle2::CalcMeanCov::m_entries
value_type m_entries
Store the sum of weights.
Definition: CalcMeanCov.h:277
Belle2::CalcMeanCov::getCorrelation
value_type getCorrelation() const
Return the correlation coefficient between parameters i and j.
Definition: CalcMeanCov.h:176
Belle2::CalcMeanCov::m_mean
value_type m_mean[N]
Store the mean values for all parameters.
Definition: CalcMeanCov.h:279
Belle2::CalcMeanCov::m_covariance
value_type m_covariance[N *(N+1)/2]
Store the triangular covariance matrix for all parameters in continous memory.
Definition: CalcMeanCov.h:282
Belle2::CalcMeanCov::clear
void clear()
Clear all values.
Definition: CalcMeanCov.h:55
Belle2::CalcMeanCov::value_type
RealType value_type
type of float variable to use for calculations and storage
Definition: CalcMeanCov.h:52
Belle2::CalcMeanCov::addWeightedArray
void addWeightedArray(value_type weight, value_type *values)
Update mean and covarianced by adding a new weighted entry.
Definition: CalcMeanCov.h:110