ChiSquareAccumulator.h
Go to the documentation of this file.
1 /**
2  * @file lardata/Utilities/ChiSquareAccumulator.h
3  * @brief Computes a simple χ² sum from data and a expectation function.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date July 26, 2018
6  *
7  * This is a header-only library.
8  */
9 
10 #ifndef LARDATA_UTILITIES_CHISQUAREACCUMULATOR_H
11 #define LARDATA_UTILITIES_CHISQUAREACCUMULATOR_H
12 
13 
14 // C/C++ standard libraries
15 #include <utility> // std::move(), std::forward()
16 
17 
18 namespace lar {
19  namespace util {
20 
21  /**
22  * @brief Computes a &chi;&sup2; from expectation function and data points.
23  * @tparam F type of the function
24  * @tparam T type of data
25  *
26  * The formula used is the simple
27  * @f$ \chi^{2} = \sum_{i} \left(\frac{y_{i} - e(x_{i})}{\sigma_{i}}\right)^{2} @f$
28  * with each observed point being @f$ ( x_{i}, y_{i} \pm \sigma_{i} ) @f$
29  * and with @f$ e() @f$ the function describing the expectation (e.g. a fit
30  * result).
31  *
32  * The parameter `F` must be usable as a unary functor, that is it must
33  * accept a single argument convertible from type `Data_t` (that is `T`),
34  * and return a value convertible back to type `Data_t`.
35  *
36  * Example of usage:
37  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
38  * double const a = 2.0;
39  * double const b = -1.0;
40  * auto f = [a,b](double x){ return a + b * x; };
41  * lar::util::ChiSquareAccumulator<decltype(f)> chiSquare;
42  *
43  * chiSquare.add(0.0, 1.0, 0.5); // add ( 0 ; 1.0 +/- 0.5 )
44  * chiSquare.add(1.0, 1.0, 0.5); // add ( 1 ; 1.0 +/- 0.5 )
45  * chiSquare.add(2.0, 1.0, 0.5); // add ( 2 ; 1.0 +/- 0.5 )
46  *
47  * double const chi2value = chiSquare();
48  * int degreesOfFreedom = int(chiSquare.N()) - 3;
49  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
50  * will check three observations against the prediction of `2 - x`,
51  * returning a `chi2value` of `8.0` and a `degreesOfFreedom` of `0`
52  * (note that the `3` degrees are manually subtracted).
53  */
54  template <typename F, typename T = double>
56  public:
57  using Function_t = F; ///< Type of function for the expectation.
58  using Data_t = T; ///< Type of parameter and observed values.
59 
60  //@{
61  /**
62  * @brief Constructor: uses the specified expectation function.
63  * @param expected expectation function
64  *
65  * The expectation function domain must be a single dimension of type
66  * `Data_t`.
67  */
69  : fExpected(expected) {}
70  // @}
71 
72 
73  // --- BEGIN -- Access to results ----------------------------------------
74  /// @name Access to results
75  /// @{
76 
77  // @{
78  /// Returns the value of &chi;&sup2; currently accumulated.
79  Data_t chiSquare() const { return fChiSq; }
80  Data_t operator() () const { return chiSquare(); }
81  operator Data_t() const { return chiSquare(); }
82  //@}
83 
84  /// Returns the number of added points (it's not degrees of freedom yet!).
85  unsigned int N() const { return fN; }
86 
87  /// Returns the expected value for the specified parameter.
88  Data_t expected(Data_t x) const { return fExpected(x); }
89 
90  /// @}
91  // --- END -- Access to results ------------------------------------------
92 
93 
94 
95  // --- BEGIN -- Data manipulation ----------------------------------------
96  /// @name Data manipulation
97  /// @{
98 
99  /**
100  * @brief Adds a data point to the &chi;&sup2;.
101  * @param x parameter
102  * @param y observed data with the `x` parameter
103  *
104  * The &chi;&sup2; is increased by @f$ \left(y - e(x)\right)^{2} @f$
105  * where _e_ is the expectation function (`expected()`).
106  * The observed values are considered to have nominal uncertainty `1`.
107  */
108  void add(Data_t x, Data_t y)
109  { fChiSq += sqr(y - expected(x)); ++fN; }
110 
111  /**
112  * @brief Adds a data point to the &chi;&sup2;.
113  * @param x parameter
114  * @param y observed data with the `x` parameter
115  * @param s uncertainty on the observed data (default: `1.0`)
116  *
117  * The &chi;&sup2; is increased by @f$ \left(\frac{y - e(x)}{s}\right)^{2} @f$
118  * where _e_ is the expectation function (`expected()`).
119  */
121  { fChiSq += sqr(z(y, expected(x), s)); ++fN; }
122 
123  /// Resets all the counts, starting from no data.
124  void clear() { fChiSq = Data_t{0}; fN = 0U; }
125 
126  /// @}
127  // --- END -- Data manipulation ------------------------------------------
128 
129  private:
130  unsigned int fN = 0U; ///< Number of data entries.
131  Data_t fChiSq = 0.0; ///< Accumulated &chi;&sup2; value.
132 
133  Function_t fExpected; ///< Function for the expectation.
134 
135  /// Normal variable.
136  static Data_t z(Data_t x, Data_t mu, Data_t sigma)
137  { return (x - mu) / sigma; }
138 
139  /// The usual square function.
140  static Data_t sqr(Data_t v) { return v*v; }
141 
142  }; // ChiSquareAccumulator<>
143 
144 
145  //--------------------------------------------------------------------------
146  /**
147  * @brief Creates a `ChiSquareAccumulator` object with the specified function.
148  * @tparam F type of function (deduced from `e`)
149  * @param e expectation function
150  * @return a `ChiSquareAccumulator<F>` instance with specified expectation
151  *
152  * Example of usage:
153  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
154  * auto zero = [](double){ return 0.0; }; // expectation function
155  * auto chiSquare = lar::util::makeChiSquareAccumulator(zero);
156  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
157  * declare `chiSquare` in a way equivalent to:
158  * `lar::util::ChiSquareAccumulator<decltype(zero)> chiSquare(zero)`.
159  */
160  template <typename F>
162  { return lar::util::ChiSquareAccumulator<F>(std::forward<F>(e)); }
163 
164  /**
165  * @brief Creates a `ChiSquareAccumulator` object with the specified function.
166  * @tparam T type of data (default: `double`)
167  * @tparam F type of function (deduced from `e`)
168  * @param e expectation function
169  * @return a `ChiSquareAccumulator<F,T>` instance with specified expectation
170  *
171  * Example of usage:
172  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
173  * auto zero = [](float){ return 0.0F; }; // expectation function
174  * auto chiSquare = lar::util::makeChiSquareAccumulator<float>(zero);
175  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
176  * declare `chiSquare` in a way equivalent to:
177  * `lar::util::ChiSquareAccumulator<decltype(zero), float> chiSquare(zero)`.
178  */
179  template <typename T, typename F>
181  { return lar::util::ChiSquareAccumulator<F, T>(std::forward<F>(e)); }
182 
183 
184  //--------------------------------------------------------------------------
185 
186  } // namespace util
187 } // namespace lar
188 
189 
190 
191 #endif // LARDATA_UTILITIES_CHISQUAREACCUMULATOR_H
192 
auto makeChiSquareAccumulator(F &&e)
Creates a ChiSquareAccumulator object with the specified function.
void add(Data_t x, Data_t y, Data_t s)
Adds a data point to the χ².
Namespace for general, non-LArSoft-specific utilities.
void clear()
Resets all the counts, starting from no data.
Computes a χ² from expectation function and data points.
Data_t chiSquare() const
Returns the value of χ² currently accumulated.
static Data_t sqr(Data_t v)
The usual square function.
unsigned int fN
Number of data entries.
void add(Data_t x, Data_t y)
Adds a data point to the χ².
ChiSquareAccumulator(Function_t const &expected)
Constructor: uses the specified expectation function.
Function_t fExpected
Function for the expectation.
Data_t expected(Data_t x) const
Returns the expected value for the specified parameter.
const double e
F Function_t
Type of function for the expectation.
Data_t fChiSq
Accumulated χ² value.
static Data_t z(Data_t x, Data_t mu, Data_t sigma)
Normal variable.
T Data_t
Type of parameter and observed values.
LArSoft-specific namespace.
list x
Definition: train.py:276
unsigned int N() const
Returns the number of added points (it&#39;s not degrees of freedom yet!).
static QCString * s
Definition: config.cpp:1042