SimpleFits.h
Go to the documentation of this file.
1 /**
2  * @file SimpleFits.h
3  * @brief Classes performing simple fits
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date March 31st, 2015
6  *
7  * Currently includes:
8  * - LinearFit
9  * -
10  *
11  */
12 
13 #ifndef SIMPLEFITS_H
14 #define SIMPLEFITS_H 1
15 
16 // C/C++ standard libraries
17 #include <cmath> // std::sqrt()
18 #include <tuple>
19 #include <array>
20 #include <iterator> // std::begin(), std::end()
21 #include <algorithm> // std::for_each()
22 #include <type_traits> // std::enable_if<>, std::is_const<>
23 #include <stdexcept> // std::range_error
24 #include <ostream> // std::endl
25 
26 
27 #include "lardataalg/Utilities/StatCollector.h" // lar::util::identity
28 #include "lardata/Utilities/FastMatrixMathHelper.h" // lar::util::details::FastMatrixOperations
29 
30 namespace lar {
31  namespace util {
32 
33  namespace details {
34 
35  /// Class providing data collection for the simple polynomial fitters
36  template <typename T, unsigned int D>
38 
39  /**
40  * @details
41  * The "extractor" is just a C++ trick to replace a statement like:
42  *
43  * (N == 0)? weight.Weights(): sums.template SumN<N>()
44  *
45  * where N is a constexpr number. The problem is that SumN<0> is not
46  * valid (in our case, it raises a static assertion). The analysis of
47  * the full statement shows that it would not be a problem, since the
48  * compiler could remove the ternary operator since it always knows
49  * whether N is 0 or not. Matter of fact, the compiler can also choose
50  * to be dumb and compile the whole thing, including a SumN<0>.
51  *
52  * The trick is in the form of a class that gets specialized for N = 0.
53  * A long list of limitations in C++ (up to 2014 at least) forces the
54  * implementation in a struct.
55  */
56  template <unsigned int Power, unsigned int N>
57  struct SumExtractor {
58  static T Sum
60  { return sums.template SumN<N>(); }
61  }; // SumExtractor
62 
63  // specialization
64  template <unsigned int Power>
65  struct SumExtractor<Power, 0U> {
66  static T Sum
68  { return weight.Weights(); }
69  }; // SumExtractor<>
70 
71  public:
72  /// Degree of the fit
73  static constexpr unsigned int Degree = D;
74  static constexpr unsigned int NParams = Degree + 1;
75 
76  using Data_t = T; ///< type of the data
77 
78  /// type of measurement without uncertainty
79  using Measurement_t = std::tuple<Data_t, Data_t>;
80 
81  /// type of measurement with uncertainty
82  using MeasurementAndUncertainty_t = std::tuple<Data_t, Data_t, Data_t>;
83 
84  // default constructor, destructor and all the rest
85 
86  /// @{
87  /// @name Add elements
88 
89  /**
90  * @brief Adds one entry with specified x, y and uncertainty
91  * @param x value of x
92  * @param y value of y
93  * @param sy value of uncertainty on y (1 by default)
94  * @return whether the point was added
95  *
96  * If the uncertainty is exactly 0, the entry is ignored and not added.
97  */
98  bool add(Data_t x, Data_t y, Data_t sy = Data_t(1.0));
99 
100  /**
101  * @brief Adds one entry with specified x, y and uncertainty
102  * @param value the ( x ; y ) pair
103  * @param sy value of uncertainty on y (1 by default)
104  * @return whether the point was added
105  *
106  * If the uncertainty is exactly 0, the entry is ignored and not added.
107  */
109  { return add(std::get<0>(value), std::get<1>(value), sy); }
110 
111  /**
112  * @brief Adds one entry with specified x, y and uncertainty
113  * @param value ( x ; y ; sy ), sy being the uncertainty on y
114  * @return whether the point was added
115  *
116  * If the uncertainty is exactly 0, the entry is ignored and not added.
117  */
119  {
120  return
121  add(std::get<0>(value), std::get<1>(value), std::get<2>(value));
122  }
123 
124 
125  /**
126  * @brief Adds measurements from a sequence, with no uncertainty
127  * @tparam Iter forward iterator to the pairs to be added
128  * @param begin iterator pointing to the first element to be added
129  * @param end iterator pointing after the last element to be added
130  *
131  * The value pointed by the iterator must be a tuple with types compatible
132  * with Measurement_t.
133  */
134  template <typename Iter>
136  { add_without_uncertainty(begin, end, identity()); }
137 
138  /**
139  * @brief Adds measurements from a sequence with no uncertainty
140  * @tparam Iter forward iterator to the elements to be added
141  * @tparam Pred a predicate to extract the element from iterator value
142  * @param begin iterator pointing to the first element to be added
143  * @param end iterator pointing after the last element to be added
144  * @param extractor the predicate extracting the value to be inserted
145  *
146  * The predicate is required to react to a call like with:
147  *
148  * Measurement_t Pred::operator() (typename Iter::value_type);
149  *
150  */
151  template <typename Iter, typename Pred>
152  void add_without_uncertainty(Iter begin, Iter end, Pred extractor);
153 
154  /**
155  * @brief Adds all measurements from a container, with no uncertainty
156  * @tparam Cont type of container of the elements to be added
157  * @tparam Pred a predicate to extract the element from iterator value
158  * @param cont container of the elements to be added
159  * @param extractor the predicate extracting the value to be inserted
160  *
161  * The predicate is required to react to a call like with:
162  *
163  * Measurement_t Pred::operator() (typename Cont::value_type);
164  *
165  * The container must support the range-based for loop syntax, that is
166  * is must have std::begin<Cont>() and std::end<Cont>() defined.
167  */
168  template <typename Cont, typename Pred>
169  void add_without_uncertainty(Cont cont, Pred extractor)
170  { add_without_uncertainty(std::begin(cont), std::end(cont), extractor); }
171 
172  /**
173  * @brief Adds all measurements from a container, with no uncertainty
174  * @tparam Cont type of container of the elements to be added
175  * @param cont container of the elements to be added
176  *
177  * The container must support the range-based for loop syntax, that is
178  * is must have std::begin<Cont>() and std::end<Cont>() defined.
179  * The value in the container must be convertible to the Measurement_t
180  * type.
181  */
182  template <typename Cont>
183  void add_without_uncertainty(Cont cont)
184  { add_without_uncertainty(std::begin(cont), std::end(cont)); }
185 
186 
187  /**
188  * @brief Adds measurements with uncertainties from a sequence
189  * @tparam VIter forward iterator to the elements to be added
190  * @tparam UIter forward iterator to the uncertainties
191  * @tparam VPred predicate to extract the measurement from iterator value
192  * @tparam UPred predicate to extract the uncertainty from iterator value
193  * @param begin_value iterator to the first measurement to be added
194  * @param end_value iterator after the last measurement to be added
195  * @param begin_uncertainty iterator to the uncertainty of first measurement
196  * @param value_extractor predicate extracting the measurement to be inserted
197  * @param uncertainty_extractor predicate extracting the uncertainty
198  * @return number of points added
199  *
200  * Each element is added with the uncertainty pointed by the matching
201  * element in the list pointed by begin_weight: the @f$ y @f$ measurement
202  * of `*(begin_value)` will have uncertainty `*(begin_uncertainty)`, the
203  * next measurement `*(begin_value + 1)` will have uncertainty
204  * `*(begin_uncertainty + 1)`, etc.
205  *
206  * The predicates are required to react to a call like with:
207  *
208  * Measurement_t VPred::operator() (typename VIter::value_type);
209  * Data_t UPred::operator() (typename UIter::value_type);
210  *
211  * Points with zero or infinite uncertainty are ignored and not added.
212  */
213  template <
214  typename VIter, typename UIter,
215  typename VPred, typename UPred = identity
216  >
217  unsigned int add_with_uncertainty(
218  VIter begin_value, VIter end_value,
219  UIter begin_uncertainty,
220  VPred value_extractor,
221  UPred uncertainty_extractor = UPred()
222  );
223 
224 
225  /**
226  * @brief Adds measurements with uncertainties from a sequence
227  * @tparam Iter forward iterator to MeasurementAndUncertainty_t to be added
228  * @param begin iterator pointing to the first measurement to be added
229  * @param end iterator pointing after the last measurement to be added
230  * @return number of points added
231  *
232  * The value pointed by the iterator must be a MeasurementAndUncertainty_t
233  * or something with elements convertible to its own (Data_t triplet).
234  * For more complicate structures, use the version with two predicates
235  * (using the uncertainty iterator the same as the measurement iterator).
236  *
237  * Points with zero or infinite uncertainty are ignored and not added.
238  */
239  template <typename Iter>
240  unsigned int add_with_uncertainty(Iter begin, Iter end);
241 
242  /**
243  * @brief Adds measurements with uncertainties from a container
244  * @tparam Cont type of container of MeasurementAndUncertainty_t elements
245  * @param cont container of MeasurementAndUncertainty_t to be added
246  * @return number of points added
247  *
248  * The values in the container must be tuples with each element
249  * convertible to Data_t.
250  *
251  * Points with zero or infinite uncertainty are ignored and not added.
252  */
253  template <typename Cont>
254  unsigned int add_with_uncertainty(Cont cont)
255  { return add_with_uncertainty(std::begin(cont), std::end(cont)); }
256 
257  ///@}
258 
259  /// Clears all the statistics
260  void clear();
261 
262  /// @{
263  /// @name Statistic retrieval
264 
265  /// Returns the number of entries added
266  int N() const { return s2.N(); }
267 
268  /**
269  * @brief Returns an average of the uncertainties
270  * @return the uncertainty average
271  * @throws std::range_error if no entry was added
272  *
273  * The average is the square root of the harmonic average of the variances
274  * (that is, the errors squared):
275  * @f$ \bar{s}^{-2} = \frac{1}{N} \sum_{i=1}^{N} s_{y}^{-2} @f$
276  */
278  { return WeightToUncertainty(s2.AverageWeight()); }
279 
280 
281  /// Returns the square of the specified value
282  template <typename V>
283  static constexpr V sqr(V const& v) { return v*v; }
284 
285 
286  /// Returns the weighted sum of x^n
287  Data_t XN(unsigned int n) const
288  { return (n == 0)? s2.Weights(): x.Sum(n); }
289 
290  /// Returns the weighted sum of x^n y
291  Data_t XNY(unsigned int n) const
292  { return (n == 0)? y.Weights(): xy.Sum(n); }
293 
294 
295  /// Returns the weighted sum of x^N
296  template <unsigned int N>
297  Data_t XN() const
299 
300  /// Returns the weighted sum of x^N y
301  template <unsigned int N>
302  Data_t XNY() const
304 
305 
306  /// Returns the weighted sum of y^2
307  Data_t Y2() const { return y2.template SumN<1>(); }
308 
309 
310  /// @}
311 
312  /// Prints the statistics into a stream
313  template <typename Stream>
314  void Print(Stream& out) const;
315 
316  /// Transforms an uncertainty into a weight (@f$ s^{-2} @f$)
318  { return Data_t(1.)/sqr(s); }
319 
320  /// Transforms a weight back to an uncertainty (@f$ s^{-1/2} @f$)
322  { return Data_t(1.)/std::sqrt(w); }
323 
324 
325  protected:
326 
327  WeightTracker<Data_t> s2; ///< accumulator for uncertainty
328  DataTracker<Degree*2, Data_t> x; ///< accumulator for variable x^k
329  WeightTracker<Data_t> y; ///< accumulator for y
330  DataTracker<1, Data_t> y2; ///< accumulator for y2
331  DataTracker<Degree, Data_t> xy; ///< accumulator for variable xy
332 
333  }; // class FitDataCollector<>
334 
335 
336  template <typename T, unsigned int D>
337  inline std::ostream& operator<<
338  (std::ostream& out, FitDataCollector<T, D> const& stats)
339  { stats.Print(out); return out; }
340 
341 
342  /// Base class providing data collection for the simple polynomial fitters
343  template <typename T, unsigned int D>
345  using Collector_t = FitDataCollector<T, D>; ///< class storing input
346 
347  public:
348  /// Degree of the fit
349  static constexpr unsigned int Degree = Collector_t::Degree;
350 
351  using Data_t = typename Collector_t::Data_t; ///< type of the data
352 
353  /// type of measurement without uncertainty
355 
356  /// type of measurement with uncertainty
359 
360  // default constructor, destructor and all the rest
361 
362  /// @{
363  /// @name Add elements
364  /// @see FitDataCollector
365 
366  bool add(Data_t x, Data_t y, Data_t sy = Data_t(1.0))
367  { return stats.add(x, y, sy); }
368 
370  { return stats.add(value, sy); }
371 
373  { return stats.add(value); }
374 
375 
376  template <typename Iter>
378  { stats.add_without_uncertainty(begin, end); }
379 
380  template <typename Iter, typename Pred>
381  void add_without_uncertainty(Iter begin, Iter end, Pred extractor)
382  { stats.add_without_uncertainty(begin, end, extractor); }
383 
384  template <typename Cont, typename Pred>
385  void add_without_uncertainty(Cont cont, Pred extractor)
386  { stats.add_without_uncertainty(cont, extractor); }
387 
388  template <typename Cont>
389  void add_without_uncertainty(Cont cont)
390  { stats.add_without_uncertainty(cont); }
391 
392 
393  template <
394  typename VIter, typename UIter,
395  typename VPred, typename UPred = identity
396  >
397  unsigned int add_with_uncertainty(
398  VIter begin_value, VIter end_value,
399  UIter begin_uncertainty,
400  VPred value_extractor,
401  UPred uncertainty_extractor = UPred()
402  )
403  {
404  return stats.add_with_uncertainty(
405  begin_value, end_value, begin_uncertainty,
406  value_extractor, uncertainty_extractor);
407  }
408 
409 
410  template <typename Iter>
411  unsigned int add_with_uncertainty(Iter begin, Iter end)
412  { return stats.add_with_uncertainty(begin, end); }
413 
414  template <typename Cont>
415  unsigned int add_with_uncertainty(Cont cont)
416  { return stats.add_with_uncertainty(cont); }
417 
418  ///@}
419 
420  /// Clears all the statistics
421  void clear() { stats.clear(); }
422 
423  /// @{
424  /// @name Statistic retrieval
425  /// @see FitDataCollector
426 
427  int N() const { return stats.N(); }
428 
429  Data_t AverageUncertainty() const { return stats.AverageUncertainty(); }
430 
431  /// @}
432 
433 
434  /// Prints the collected statistics into a stream
435  template <typename Stream>
436  void PrintStats(Stream& out) const { stats.Print(out); }
437 
438 
439  /// Returns the square of the specified value
440  template <typename V>
441  static constexpr V sqr(V const& v) { return Collector_t::sqr(v); }
442 
443  protected:
444  Collector_t stats; ///< statistics collected from fit data input
445 
446  /// Returns the weighted sum of x^n
447  Data_t XN(unsigned int n) const { return stats.XN(n); }
448 
449  /// Returns the weighted sum of x^n y
450  Data_t XNY(unsigned int n) const { return stats.XNY(n); }
451 
452  }; // class SimplePolyFitterDataBase<>
453 
454 
455 
456  /// Simple fitter abstract interface
457  template <typename T, unsigned int N>
459  public:
460 
461  /// Number of parameters in the fit
462  static constexpr unsigned int NParams = N;
463 
464  using Data_t = T; ///< type of the data
465 
467 
468  /// type of set of fit parameters
469  using FitParameters_t = std::array<Data_t, NParams>;
470 
471  /// type of matrix for covariance (a std::array)
473 
474 
475  /// Virtual destructor: compiler's default
476  virtual ~SimpleFitterInterface() = default;
477 
478 
479  /**
480  * @brief Returns if the fit has valid results
481  * @return if the fit has valid results
482  *
483  * The fit has no valid results if:
484  * 1. insufficient data has been add()ed (no more than the fit Degree)
485  * 2. if input points are vertically aligned
486  *
487  * Note that checking point 2 is expensive in terms of time.
488  */
489  virtual bool isValid() const = 0;
490 
491  /// @{
492  /// @name Fitting
493 
494  /**
495  * @brief Computes and returns all the parameters of the fit result
496  * @return the full set of parameters of the fit
497  * @throws std::runtime_error if there is no unique solution
498  */
499  virtual FitParameters_t FitParameters() const = 0;
500 
501  /**
502  * @brief Computes and returns all the parameter errors of the fit result
503  * @return the full set of parameter errors of the fit
504  * @throws std::runtime_error if there is no unique solution
505  */
506  virtual FitParameters_t FitParameterErrors() const = 0;
507 
508  /**
509  * @brief Computes and returns all the covariance matrix of the fit result
510  * @return the the covariance matrix of the fit
511  * @throws std::runtime_error if there is no unique solution
512  *
513  * The matrix is symmetric, and stored in a linear way (say, first row,
514  * then second row).
515  */
516  virtual FitMatrix_t FitParameterCovariance() const = 0;
517 
518  /**
519  * @brief Returns the parameter n of the fit result
520  * @param n degree of the parameter; must be no larger than Degree
521  * @return the parameter of the fit, in y/x^n units
522  * @throws std::runtime_error if there is no unique solution
523  */
524  virtual Data_t FitParameter(unsigned int n) const
525  { return FitParameters()[n]; }
526 
527  /**
528  * @brief Returns the error on parameter n of the fit result
529  * @param n degree of the parameter; must be no larger than Degree
530  * @return the error on the parameter of the fit, in y/x^n units
531  * @throws std::runtime_error if there is no unique solution
532  */
533  virtual Data_t FitParameterError(unsigned int n) const
534  { return std::sqrt(FitParameterCovariance()[n * (NParams + 1)]); }
535 
536 
537  /**
538  * @brief Returns the @f$ \chi^{2} @f$ of the fit
539  * @return the @f$ \chi^{2} @f$ of the fit (not divided by NDF())
540  */
541  virtual Data_t ChiSquare() const = 0;
542 
543  /**
544  * @brief Returns the degrees of freedom in the determination of the fit
545  * @return the degrees of freedom in the determination of the fit
546  *
547  * The return value may be 0 or negative if insufficient points have been
548  * added.
549  */
550  virtual int NDF() const = 0;
551 
552  /// @}
553 
554 
555  /**
556  * @brief Fills the specified parameters
557  * @param params the fitted values of the parameters
558  * @param Xmat the matrix of the x^n/s^2 sums
559  * @param Smat the covariance matrix
560  * @param det the determinant of Xmat
561  * @return true if the fit is valid (i.e. if a unique solution exists)
562  */
563  virtual bool FillResults(
565  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
566  ) const = 0;
567 
568  /**
569  * @brief Fills the specified parameters
570  * @param params the fitted values of the parameters
571  * @param paramerrors the uncertainty on the fitted parameters
572  * @param Xmat the matrix of the x^n/s^2 sums
573  * @param Smat the covariance matrix
574  * @param det the determinant of Xmat
575  * @return true if the fit is valid (i.e. if a unique solution exists)
576  */
577  virtual bool FillResults(
578  FitParameters_t& params, FitParameters_t& paramerrors,
579  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
580  ) const = 0;
581 
582  /**
583  * @brief Fills the specified parameters
584  * @param params the fitted values of the parameters
585  * @param paramerrors the uncertainty on the fitted parameters
586  * @return true if the fit is valid (i.e. if a unique solution exists)
587  */
588  virtual bool FillResults
589  (FitParameters_t& params, FitParameters_t& paramerrors) const = 0;
590 
591 
592  /**
593  * @brief Evaluates the fitted function at the specified point
594  * @param x the point where to evaluate the fit function
595  * @return the value of the fit function
596  *
597  * No check is performed whether the fit is valid.
598  */
599  virtual Data_t Evaluate(Data_t x) const = 0;
600 
601 
602  /// Evaluates the fitted function; alias of Evaluate()
603  Data_t operator() (Data_t x) const { return Evaluate(x); }
604 
605 
606  /// Returns the square of the specified data value
607  static constexpr Data_t sqr(Data_t v) { return v*v; }
608 
609  /// Returns the cube of the specified data value
610  static constexpr Data_t cube(Data_t v) { return v*v*v; }
611 
612  protected:
613 
614  /// Computes the determinant of a matrix
615  virtual Data_t Determinant(FitMatrix_t const& mat) const
616  { return MatrixOps::Determinant(mat); }
617 
618  /// Computes the inverse of a matrix (using provided determinant)
619  virtual FitMatrix_t InvertMatrix
620  (FitMatrix_t const& mat, Data_t det) const
621  { return MatrixOps::InvertSymmetricMatrix(mat, det); }
622 
623  /// Computes the inverse of a matrix
624  virtual FitMatrix_t InvertMatrix(FitMatrix_t const& mat) const
625  { return MatrixOps::InvertSymmetricMatrix(mat); }
626 
627  /// Computes the product of a FitMatrix_t and a FitParameters_t
628  virtual FitParameters_t MatrixProduct
629  (FitMatrix_t const& mat, FitParameters_t const& vec) const
630  { return MatrixOps::MatrixVectorProduct(mat, vec); }
631 
632  }; // class SimpleFitterInterface<>
633 
634 
635  /// Base class providing virtual fitting interface for polynomial fitters
636  template <typename T, unsigned int D>
638  public SimpleFitterInterface<T, D + 1>,
639  public SimplePolyFitterDataBase<T, D>
640  {
642  using Base_t = SimplePolyFitterDataBase<T, D>; ///< class storing input
643 
644  public:
645  using Base_t::sqr;
646 
647  /// Degree of the fit
648  static constexpr unsigned int Degree = Base_t::Degree;
649 
650  /// Number of parameters in the fit
651  static constexpr unsigned int NParams = Interface_t::NParams;
652 
653  using Data_t = typename Base_t::Data_t; ///< type of the data
654 
655  /// type of set of fit parameters
657 
658  /// type of matrix for covariance (a std::array)
660 
661 
662  /**
663  * @brief Returns if the fit has valid results
664  * @return if the fit has valid results
665  *
666  * The fit has no valid results if:
667  * 1. insufficient data has been add()ed (no more than the fit Degree)
668  * 2. if input points are vertically aligned
669  *
670  * Note that checking point 2 is expensive in terms of time.
671  */
672  virtual bool isValid() const override;
673 
674  /// @{
675  /// @name Fitting
676 
677  /**
678  * @brief Computes and returns all the parameters of the fit result
679  * @return the full set of parameters of the fit
680  * @throws std::range_error if there is no unique solution
681  */
682  virtual FitParameters_t FitParameters() const override;
683 
684  /**
685  * @brief Computes and returns all the parameter errors of the fit result
686  * @return the full set of parameter errors of the fit
687  * @throws std::range_error if there is no unique solution
688  */
689  virtual FitParameters_t FitParameterErrors() const override;
690 
691  /**
692  * @brief Computes and returns all the covariance matrix of the fit result
693  * @return the the covariance matrix of the fit
694  * @throws std::range_error if there is no unique solution
695  *
696  * The matrix is symmetric, and stored in a linear way (say, first row,
697  * then second row).
698  */
699  virtual FitMatrix_t FitParameterCovariance() const override;
700 
701  /**
702  * @brief Returns the parameter n of the fit result
703  * @param n degree of the parameter; must be no larger than Degree
704  * @return the parameter of the fit, in y/x^n units
705  * @throws std::range_error if there is no unique solution
706  */
707  virtual Data_t FitParameter(unsigned int n) const override;
708 
709  /**
710  * @brief Returns the error on parameter n of the fit result
711  * @param n degree of the parameter; must be no larger than Degree
712  * @return the error on the parameter of the fit, in y/x^n units
713  * @throws std::range_error if there is no unique solution
714  */
715  virtual Data_t FitParameterError(unsigned int n) const override;
716 
717 
718  /**
719  * @brief Returns the @f$ \chi^{2} @f$ of the fit
720  * @return the @f$ \chi^{2} @f$ of the fit (not divided by NDF())
721  */
722  virtual Data_t ChiSquare() const override;
723 
724  /**
725  * @brief Returns the degrees of freedom in the determination of the fit
726  * @return the degrees of freedom in the determination of the fit
727  *
728  * The return value may be 0 or negative if insufficient points have been
729  * added.
730  */
731  virtual int NDF() const override { return Base_t::N() - NParams; }
732 
733  /// @}
734 
735 
736  /**
737  * @brief Fills the specified parameters
738  * @param params the fitted values of the parameters
739  * @param Xmat the matrix of the x^n/s^2 sums
740  * @param Smat the covariance matrix
741  * @param det the determinant of Xmat
742  * @return true if the fit is valid (i.e. if a unique solution exists)
743  */
744  bool FillResults(
745  FitParameters_t& params,
746  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
747  ) const override;
748 
749  /**
750  * @brief Fills the specified parameters
751  * @param params the fitted values of the parameters
752  * @param paramerrors the uncertainty on the fitted parameters
753  * @param Xmat the matrix of the x^n/s^2 sums
754  * @param Smat the covariance matrix
755  * @param det the determinant of Xmat
756  * @return true if the fit is valid (i.e. if a unique solution exists)
757  */
758  bool FillResults(
759  FitParameters_t& params, FitParameters_t& paramerrors,
760  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
761  ) const override;
762 
763  /**
764  * @brief Fills the specified parameters
765  * @param params the fitted values of the parameters
766  * @param paramerrors the uncertainty on the fitted parameters
767  * @return true if the fit is valid (i.e. if a unique solution exists)
768  */
769  bool FillResults
770  (FitParameters_t& params, FitParameters_t& paramerrors)
771  const override;
772 
773 
774  /**
775  * @brief Evaluates the fitted function at the specified point
776  * @param x the point where to evaluate the fit function
777  * @return the value of the fit function
778  *
779  * No check is performed whether the fit is valid.
780  */
781  virtual Data_t Evaluate(Data_t x) const override;
782 
783 
784  /// Extracts parameter errors from diagonal of the covarriance matrix
785  static FitParameters_t ExtractParameterErrors(FitMatrix_t const& Smat);
786 
787 
788  protected:
789 
790  /// Fills and returns the matrix of x^n sum coefficients ( { x^(i+j) } )
791  virtual FitMatrix_t MakeMatrixX() const;
792 
793  /// Fills and returns the matrix (vector) of x^n y sum coefficients
794  virtual FitParameters_t MakeMatrixY() const;
795 
796  /// Computes and returns all the parameter errors of the fit result
797  virtual FitParameters_t FitParameterErrors
798  (FitMatrix_t const& Smat) const
799  { return ExtractParameterErrors(Smat); }
800 
801  //@{
802  /// Returns the fitted parameters using the provided information
803  virtual FitParameters_t FitParameters(FitMatrix_t const& Xmat) const;
804 
805  virtual FitParameters_t FitParameters
806  (FitMatrix_t const& Smat, Data_t /* det */) const;
807  //@}
808 
809  //@{
810  /// Computes a single fit parameter using the given information
811  virtual Data_t Param
812  (unsigned int n, FitMatrix_t const& Xmat) const;
813  virtual Data_t Param
814  (unsigned int n, FitMatrix_t const& Xmat, Data_t detXmat) const;
815  //@}
816 
817  // import the declaration from the interface
818  using Interface_t::Determinant;
819  using Interface_t::InvertMatrix;
820  using Interface_t::MatrixProduct;
821 
822  }; // class SimplePolyFitterBase<>
823 
824 
825  } // namespace details
826 
827 
828  /** ************************************************************************
829  * @brief Performs a linear regression of data
830  * @tparam T type of the quantities
831  * @tparam W type of the weight (as T by default)
832  *
833  * The linear regression connects measurements
834  * @f$ ( y_{i} \pm \sigma_{y,i} ) @f$ with a parameter @f$ ( x_{i} ) @f$
835  * not affected by uncertainty.
836  * The returned parameters describe a straight line @f$ y = a x + b @f$
837  * obtained by minimization of
838  * @f$ \chi^{2} = \sum_{i} \frac{ \left(y_{i} - a x_{i} - b \right)^{2} }{ \sigma^{2}_{y,i} }@f$
839  *
840  * This saves having to link to ROOT for the simplest cases.
841  *
842  * This simple linear fitter does not store any result: each time a result
843  * is requested, it is computed anew.
844  * In particular that is true also for ChiSquare(), that requires the full
845  * parameters set and therefore reruns the full fit (FitParameters())
846  * and for the covariance matrix of the parameters.
847  */
848  template <typename T>
851 
852  public:
853  using Base_t::Degree;
854  using Base_t::NParams;
855  using typename Base_t::Data_t;
856 
857  /// type of measurement without uncertainty
858  using typename Base_t::Measurement_t;
859 
860  /// type of measurement with uncertainty
862 
863  using Base_t::sqr;
864 
865  /// type of set of fit parameters
866  using FitParameters_t = std::array<Data_t, NParams>;
867  using FitMatrix_t = std::array<Data_t, sqr(NParams)>;
868 
869 
870  // default constructor, destructor and all the rest
871 
872  /**
873  * @brief Returns the intercept of the fit
874  * @return the intercept of the fit, in y units
875  * @throws std::range_error if there is no unique solution
876  */
877  Data_t Intercept() const { return this->FitParameter(0); }
878 
879  /**
880  * @brief Returns the slope of the fit
881  * @return the slope of the fit, in y/x units
882  * @throws std::range_error if there is no unique solution
883  */
884  Data_t Slope() const { return this->FitParameter(1); }
885 
886  /**
887  * @brief Returns the error on intercept of the fit
888  * @return the error on intercept of the fit, in y units
889  * @throws std::range_error if there is no unique solution
890  */
891  Data_t InterceptError() const { return this->FitParameterError(0); }
892 
893  /**
894  * @brief Returns the error in slope of the fit
895  * @return the error on slope of the fit, in y/x units
896  * @throws std::range_error if there is no unique solution
897  */
898  Data_t SlopeError() const { return this->FitParameterError(1); }
899 
900  /**
901  * @brief Returns the covariance between intercept and slope of the fit
902  * @return the covariance between intercept and slope of the fit, in y^2 units
903  * @throws std::range_error if there is no unique solution
904  */
906  { return this->FitParameterCovariance()[0 * NParams + 1]; }
907 
908 
909  /**
910  * @brief Returns the @f$ \chi^{2} @f$ of the fit
911  * @return the @f$ \chi^{2} @f$ of the fit (not divided by NDF())
912  */
913  virtual Data_t ChiSquare() const override;
914 
915 
916  protected:
917 
918  //@{
919  /// Aliases
920  Data_t I() const { return Base_t::stats.template XN<0>(); }
921  Data_t X() const { return Base_t::stats.template XN<1>(); }
922  Data_t X2() const { return Base_t::stats.template XN<2>(); }
923  Data_t Y() const { return Base_t::stats.template XNY<0>(); }
924  Data_t XY() const { return Base_t::stats.template XNY<1>(); }
925  Data_t Y2() const { return Base_t::stats.Y2(); }
926  //@}
927 
928  }; // class LinearFit<>
929 
930 
931 
932  /** ************************************************************************
933  * @brief Performs a second-degree fit of data
934  * @tparam T type of the quantities
935  * @tparam W type of the weight (as T by default)
936  *
937  * The quadratic fit connects measurements
938  * @f$ ( y_{i} \pm \sigma_{y,i} ) @f$ with a parameter @f$ ( x_{i} ) @f$
939  * not affected by uncertainty.
940  * The returned parameters describe a quadratic curve
941  * @f$ f(x) = a_{0} + a_{1} x + a_{2} x^{2} @f$ obtained by minimization of
942  * @f$ \chi^{2} = \sum_{i} \frac{ \left(y_{i} - f(x_{i}) \right)^{2} }{ \sigma^{2}_{y,i} }@f$
943  *
944  * This saves having to link to ROOT for the simplest cases.
945  *
946  * This simple quadratic fitter does not store any result: each time a
947  * result is requested, it is computed anew.
948  * In particular that is true also for ChiSquare(), that requires the full
949  * parameters set and therefore reruns the full fit (FitParameters())
950  * and for the covariance matrix of the parameters.
951  */
952  template <typename T>
955 
956  public:
957  using Base_t::Degree;
958  using Base_t::NParams;
959  using typename Base_t::Data_t;
960 
961  /// type of measurement without uncertainty
962  using typename Base_t::Measurement_t;
963 
964  /// type of measurement with uncertainty
966 
967  using Base_t::sqr;
968 
969  /// type of set of fit parameters
970  using FitParameters_t = std::array<Data_t, NParams>;
971  using FitMatrix_t = std::array<Data_t, sqr(NParams)>;
972 
973 
974  // default constructor, destructor and all the rest
975 
976  /**
977  * @brief Returns the @f$ \chi^{2} @f$ of the fit
978  * @return the @f$ \chi^{2} @f$ of the fit (not divided by NDF())
979  */
980  virtual Data_t ChiSquare() const override;
981 
982 
983  protected:
984 
985  //@{
986  /// Aliases
987  Data_t I() const { return Base_t::stats.template XN<0>(); }
988  Data_t X() const { return Base_t::stats.template XN<1>(); }
989  Data_t X2() const { return Base_t::stats.template XN<2>(); }
990  Data_t X3() const { return Base_t::stats.template XN<3>(); }
991  Data_t X4() const { return Base_t::stats.template XN<4>(); }
992  Data_t Y() const { return Base_t::stats.template XNY<0>(); }
993  Data_t XY() const { return Base_t::stats.template XNY<1>(); }
994  Data_t X2Y() const { return Base_t::stats.template XNY<2>(); }
995  Data_t Y2() const { return Base_t::stats.Y2(); }
996  //@}
997 
998  }; // class QuadraticFit<>
999 
1000 
1001 
1002  /** **********************************************************************
1003  * @brief "Fast" Gaussian fit
1004  * @tparam T data type
1005  *
1006  * This class performs a Gaussian fit on demand.
1007  * This fit translates the data to its logarithm and then internally
1008  * performs a quadratic fit.
1009  * Note that as a consequence this fitter does not accept negative values
1010  * for the y variable.
1011  * Negative values in input will be completely ignored.
1012  *
1013  * Methods that do not change functionality respect to the base class are
1014  * not documented here -- see the base class(es) documentation
1015  * (mostly SimplePolyFitterBase).
1016  */
1017  template <typename T>
1020  using Fitter_t = QuadraticFit<T>; ///< base class
1021 
1022  public:
1023  /// Number of parameters in the fit
1024  static constexpr unsigned int NParams = Base_t::NParams;
1025 
1026  using Data_t = typename Base_t::Data_t; ///< type of the data
1027 
1028  /// type of measurement without uncertainty
1030 
1031  /// type of measurement with uncertainty
1034 
1037 
1038  using Base_t::sqr;
1039  using Base_t::cube;
1040 
1041 
1042  // default constructor, destructor and all the rest
1043 
1044  /// @{
1045  /// @name Add elements
1046  /// @see FitDataCollector
1047 
1048  bool add(Data_t x, Data_t y, Data_t sy = Data_t(1.0));
1049 
1050  bool add(Measurement_t value, Data_t sy = Data_t(1.0))
1051  { return add(std::get<0>(value), std::get<1>(value), sy); }
1052 
1054  {
1055  return
1056  add(std::get<0>(value), std::get<1>(value), std::get<2>(value));
1057  }
1058 
1059 
1060  template <typename Iter>
1062  { add_without_uncertainty(begin, end, identity()); }
1063 
1064  template <typename Iter, typename Pred>
1065  void add_without_uncertainty(Iter begin, Iter end, Pred extractor);
1066 
1067  template <typename Cont, typename Pred>
1068  void add_without_uncertainty(Cont cont, Pred extractor)
1069  { add_without_uncertainty(std::begin(cont), std::end(cont), extractor); }
1070 
1071  template <typename Cont>
1072  void add_without_uncertainty(Cont cont)
1073  { add_without_uncertainty(std::begin(cont), std::end(cont)); }
1074 
1075 
1076  template <
1077  typename VIter, typename UIter,
1078  typename VPred, typename UPred = identity
1079  >
1080  unsigned int add_with_uncertainty(
1081  VIter begin_value, VIter end_value,
1082  UIter begin_uncertainty,
1083  VPred value_extractor,
1084  UPred uncertainty_extractor = UPred()
1085  );
1086 
1087 
1088  template <typename Iter>
1089  unsigned int add_with_uncertainty(Iter begin, Iter end);
1090 
1091  template <typename Cont>
1092  unsigned int add_with_uncertainty(Cont cont)
1093  { return add_with_uncertainty(std::begin(cont), std::end(cont)); }
1094 
1095 
1096  /// Clears all the input statistics
1097  void clear() { fitter.clear(); }
1098 
1099  /// Returns the number of (valid) points added
1100  int N() const { return fitter.N(); }
1101 
1102 
1103  /// Prints the collected statistics into a stream
1104  template <typename Stream>
1105  void PrintStats(Stream& out) const { fitter.PrintStats(out); }
1106 
1107  ///@}
1108 
1109 
1110  /// @{
1111  /// @name Fitting
1112  /**
1113  * @brief Returns if the fit has valid results
1114  * @return if the fit has valid results
1115  *
1116  * The fit has no valid results if:
1117  * 1. insufficient data has been add()ed (no more than the fit Degree)
1118  * 2. if input points are vertically aligned
1119  *
1120  * Note that checking point 2 is expensive in terms of time.
1121  */
1122  virtual bool isValid() const override { return fitter.isValid(); }
1123 
1124  /// @{
1125  /// @name Fitting
1126 
1127  /**
1128  * @brief Computes and returns all the parameters of the fit result
1129  * @return the full set of parameters of the fit
1130  * @throws std::runtime_error if there is no unique solution
1131  */
1132  virtual FitParameters_t FitParameters() const override;
1133 
1134  /**
1135  * @brief Computes and returns all the parameter errors of the fit result
1136  * @return the full set of parameter errors of the fit
1137  * @throws std::runtime_error if there is no unique solution
1138  */
1139  virtual FitParameters_t FitParameterErrors() const override;
1140 
1141  /**
1142  * @brief Computes and returns all the covariance matrix of the fit result
1143  * @return the the covariance matrix of the fit
1144  * @throws std::runtime_error if there is no unique solution
1145  *
1146  * Not supported.
1147  * It's fairly too complicate to fill the whole matrix.
1148  * Doable, on request.
1149  */
1150  virtual FitMatrix_t FitParameterCovariance() const override;
1151 
1152 
1153  /**
1154  * @brief Returns the @f$ \chi^{2} @f$ of the original fit
1155  * @return the @f$ \chi^{2} @f$ of the original fit (not divided by NDF())
1156  *
1157  * This is not defined in the space of the Gaussian, but in the space of
1158  * the internal quadratic fit. Where one is minimum, the other also is,
1159  * but the actual value is different.
1160  */
1161  virtual Data_t ChiSquare() const override { return fitter.ChiSquare(); }
1162 
1163  /**
1164  * @brief Returns the degrees of freedom in the determination of the fit
1165  * @return the degrees of freedom in the determination of the fit
1166  *
1167  * The return value may be 0 or negative if insufficient points have been
1168  * added.
1169  */
1170  virtual int NDF() const override { return fitter.NDF(); }
1171 
1172  /// @}
1173 
1174 
1175  /**
1176  * @brief Fills the specified parameters
1177  * @param params the fitted values of the parameters
1178  * @param Xmat the matrix of the x^n/s^2 sums
1179  * @param Smat the covariance matrix
1180  * @param det the determinant of Xmat
1181  * @return true if the fit is valid (i.e. if a unique solution exists)
1182  *
1183  * Unsupported.
1184  */
1185 
1186  virtual bool FillResults(
1187  FitParameters_t& params,
1188  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
1189  ) const override;
1190  /**
1191  * @brief Fills the specified parameters
1192  * @param params the fitted values of the parameters
1193  * @param paramerrors the uncertainty on the fitted parameters
1194  * @param Xmat the matrix of the x^n/s^2 sums
1195  * @param Smat the covariance matrix
1196  * @param det the determinant of Xmat
1197  * @return true if the fit is valid (i.e. if a unique solution exists)
1198  *
1199  * Unsupported.
1200  */
1201  virtual bool FillResults(
1202  FitParameters_t& params, FitParameters_t& paramerrors,
1203  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
1204  ) const override;
1205 
1206  /**
1207  * @brief Fills the specified parameters
1208  * @param params the fitted values of the parameters
1209  * @param paramerrors the uncertainty on the fitted parameters
1210  * @return true if the fit is valid (i.e. if a unique solution exists)
1211  *
1212  * Only the version returning the parameters and errors is supported.
1213  */
1214  virtual bool FillResults
1215  (FitParameters_t& params, FitParameters_t& paramerrors) const override;
1216 
1217 
1218  /**
1219  * @brief Evaluates the fitted function at the specified point
1220  * @param x the point where to evaluate the fit function
1221  * @return the value of the fit function
1222  *
1223  * No check is performed whether the fit is valid.
1224  */
1225  virtual Data_t Evaluate(Data_t x) const override
1226  { return Evaluate(x, FitParameters().data()); }
1227 
1228 
1229  /// Returns the internal fitter (mostly for debugging)
1230  virtual Fitter_t const& Fitter() const { return fitter; }
1231 
1232 
1233  /**
1234  * @brief Evaluates a Gaussian with given parameters at one point
1235  * @param x the point where to evaluate the fit function
1236  * @param params Gaussian parameters: amplitude, mean, sigma
1237  * @return the Gaussian function evaluated at x
1238  */
1239  static Data_t Evaluate(Data_t x, Data_t const* params);
1240 
1241  protected:
1242  Fitter_t fitter; ///< the actual fitter and data holder
1243 
1244  /// @{
1245  /// @name Mumbo-jumbo to convert the values for a quadratic fit
1246 
1247  ///< type of value and error
1248  struct Value_t: public std::tuple<Data_t, Data_t> {
1249  using Base_t = std::tuple<Data_t, Data_t>;
1250 
1251  Value_t(Data_t v, Data_t e): Base_t(v, e) {}
1253  Base_t(std::get<1>(meas), std::get<2>(meas)) {}
1254 
1255  constexpr Data_t value() const { return std::get<0>(*this); }
1256  constexpr Data_t error() const { return std::get<1>(*this); }
1257 
1258  Data_t& value() { return std::get<0>(*this); }
1259  Data_t& error() { return std::get<1>(*this); }
1260 
1261  }; // Value_t
1262 
1263  /// Converts a value into a proper input for the quadratic fit;
1264  /// does not accept 0 or negative values!
1265  static Data_t EncodeValue(Data_t value) { return std::log(value); }
1266 
1267  /// Converts a value from the quadratic fit into a proper value
1268  static Data_t DecodeValue(Data_t value) { return std::exp(value); }
1269 
1270 
1271  /// Converts a value and error into a proper input for the quadratic fit
1273  { return { std::log(value), error / std::abs(value) }; }
1274 
1275 
1276  /// Converts a value and error into a proper input for the quadratic fit
1277  static Value_t EncodeValue(Value_t const& value)
1278  { return EncodeValue(value.value(), value.error()); }
1279 
1280 
1281  /// Converts a value from the quadratic fit into a proper value
1282  static Value_t DecodeValue(Value_t const& value)
1283  {
1284  const Data_t v = std::exp(value.value());
1285  return { v, v * value.error() };
1286  } // DecodeValue()
1287 
1288  /// Converts a value and error into a proper input for the quadratic fit
1290  {
1291  return
1292  Measurement_t(std::get<0>(meas), EncodeValue(std::get<1>(meas)));
1293  }
1294 
1295  /// Converts a value and error into a proper input for the quadratic fit
1296  static MeasurementAndUncertainty_t EncodeValue
1298  {
1299  Value_t value = EncodeValue(Value_t(meas));
1300  return { std::get<0>(meas), value.value(), value.error() };
1301  } // EncodeValue(MeasurementAndUncertainty_t)
1302 
1303  /// Converts a value and error into a proper input for the quadratic fit
1304  static MeasurementAndUncertainty_t EncodeValue
1305  (Measurement_t const& meas, Data_t error)
1306  {
1307  Value_t value = EncodeValue(Value_t(std::get<1>(meas), error));
1308  return { std::get<0>(meas), value.value(), value.error() };
1309  } // EncodeValue(Measurement_t, Data_t)
1310 
1311 
1312  /// Wrapper to encode a MeasurementAndUncertainty_t from a value
1313  /// and a error extractor
1314  template <typename VPred, typename UPred = void>
1316  EncodeExtractor(VPred& vpred, UPred& upred):
1317  value_extractor(vpred), error_extractor(upred) {}
1318 
1319  // extractor takes whatever dereferencing Iter gives and returns
1320  // Measurement_t or MeasurementAndUncertainty_t,
1321  // the one the extractor returns
1322  template <typename Elem>
1323  auto operator() (Elem elem)
1324  {
1325  // use explicit casts to make sure we know what we are doing
1326  return EncodeValue(
1327  static_cast<Measurement_t&&>(value_extractor(elem)),
1328  static_cast<Data_t&&>(error_extractor(elem))
1329  );
1330  } // operator()
1331 
1332  VPred& value_extractor; ///< value extractor
1333  UPred& error_extractor; ///< uncertainty extractor
1334  }; // struct EncodeExtractor
1335 
1336  /// Wrapper to encode a Measurement_t or MeasurementAndUncertainty_t
1337  /// from a extractor
1338  template <typename Pred>
1339  struct EncodeExtractor<Pred, void> {
1340  EncodeExtractor(Pred& pred): extractor(pred) {}
1341 
1342  // extractor takes whatever dereferencing Iter gives and returns
1343  // Measurement_t or MeasurementAndUncertainty_t,
1344  // the one the extractor returns;
1345  // as usual with enable_if, I am not sure it makes sense
1346  template <
1347  typename Elem,
1349  >
1350  auto operator() (Elem elem) const
1351  { return EncodeValue(extractor(elem)); }
1352 
1353  template <
1354  typename Elem,
1356  >
1357  auto operator() (Elem elem)
1358  { return EncodeValue(extractor(elem)); }
1359 
1360  Pred& extractor;
1361  }; // struct EncodeExtractor<Pred>
1362 
1363  template <typename Pred>
1364  static EncodeExtractor<Pred> Encoder(Pred& pred) { return { pred }; }
1365 
1366  template <typename VPred, typename UPred>
1367  static EncodeExtractor<VPred, UPred> Encoder(VPred& vpred, UPred& upred)
1368  { return { vpred, upred }; }
1369 
1370  /// @}
1371 
1372  /**
1373  * @brief Converts the specified quadratic fit parameters into Gaussian
1374  * @param qpars the quadratic fit parameters
1375  * @return Gaussian function parameters
1376  */
1377  static FitParameters_t ConvertParameters(FitParameters_t const& qpars);
1378 
1379  /**
1380  * @brief Converts the specified quadratic fit parameters and errors
1381  * @param qpars the quadratic fit parameters
1382  * @param qparerrmat the quadratic fit parameter error matrix
1383  * @param params the Gaussian fit parameters
1384  * @param paramerrors the Gaussian fit parameter errors
1385  */
1386  static void ConvertParametersAndErrors(
1387  FitParameters_t const& qpars, FitMatrix_t const& qparerrmat,
1388  FitParameters_t& params, FitParameters_t& paramerrors
1389  );
1390 
1391  /**
1392  * @brief Converts the specified quadratic fit parameters and errors
1393  * @param qpars the quadratic fit parameters
1394  * @param qparerrmat the quadratic fit parameter error matrix
1395  * @param params the Gaussian fit parameters
1396  * @param paramvariances the Gaussian fit parameter variance
1397  */
1398  static void ConvertParametersAndVariances(
1399  FitParameters_t const& qpars, FitMatrix_t const& qparerrmat,
1400  FitParameters_t& params, FitParameters_t& paramvariances
1401  );
1402 
1403  /**
1404  * @brief Converts the specified quadratic fit parameters and errors
1405  * @param qpars the quadratic fit parameters
1406  * @param qparerrmat the quadratic fit parameter error matrix
1407  * @param params the Gaussian fit parameters
1408  * @param Smat the covariance matrix of the Gaussian fit parameters
1409  */
1410  static void ConvertParametersAndErrorMatrix(
1411  FitParameters_t const& qpars, FitMatrix_t const& qparerrmat,
1412  FitParameters_t& params, FitMatrix_t& Smat
1413  );
1414 
1415  /**
1416  * @brief Returns whether the specified parameters represent a valid fit
1417  * @param params Gaussian parameters
1418  * @param qpars quadratic fit parameters
1419  * @return whether specified parameters represent a valid Gaussian fit
1420  */
1421  static bool isValid
1422  (FitParameters_t const& params, FitParameters_t const& qpars);
1423 
1424 
1425  static void ThrowNotImplemented [[noreturn]] (std::string method)
1426  { throw std::logic_error("Method " + method + "() not implemented"); }
1427 
1428  }; // class GaussianFit<>
1429 
1430 
1431  } // namespace util
1432 } // namespace lar
1433 
1434 
1435 //==============================================================================
1436 //=== template implementation
1437 //==============================================================================
1438 
1439 
1440 //******************************************************************************
1441 //*** FitDataCollector<>
1442 //***
1443 
1444 template <typename T, unsigned int D>
1446  (Data_t x_value, Data_t y_value, Data_t sy /* = Data_t(1.0) */)
1447 {
1449  if (!std::isnormal(w)) return false;
1450  // the x section has a 1/s^2 weight; we track that weight separately
1451  s2.add(w);
1452  x.add(x_value, w);
1453  // we treat the y section as if it were a x section with a y/s^2 weight;
1454  // we track that weight separately
1455  Data_t yw = y_value * w;
1456  y.add(yw);
1457  y2.add(sqr(y_value), w); // used only for chi^2
1458  xy.add(x_value, yw);
1459 
1460  return true; // we did add the value
1461 } // FitDataCollector<>::add()
1462 
1463 
1464 template <typename T, unsigned int D>
1465 template <typename Iter, typename Pred>
1467  (Iter begin, Iter end, Pred extractor)
1468 {
1469  std::for_each
1470  (begin, end, [this, extractor](auto item) { this->add(extractor(item)); });
1471 } // FitDataCollector<>::add_without_uncertainty(Iter, Pred)
1472 
1473 
1474 template <typename T, unsigned int D>
1475 template <typename VIter, typename UIter, typename VPred, typename UPred>
1476 unsigned int
1478  VIter begin_value, VIter end_value,
1479  UIter begin_uncertainty,
1480  VPred value_extractor,
1481  UPred uncertainty_extractor /* = UPred() */
1482 ) {
1483  unsigned int n = 0;
1484  while (begin_value != end_value) {
1485  if (add
1486  (value_extractor(*begin_value), uncertainty_extractor(*begin_uncertainty))
1487  )
1488  ++n;
1489  ++begin_value;
1490  ++begin_uncertainty;
1491  } // while
1492  return n;
1493 } // FitDataCollector<>::add_with_uncertainty(VIter, VIter, UIter, VPred, UPred)
1494 
1495 
1496 template <typename T, unsigned int D>
1497 template <typename Iter>
1499  (Iter begin, Iter end)
1500 {
1501  unsigned int old_n = N();
1502  std::for_each(begin, end, [this](auto p) { this->add(p); });
1503  return N() - old_n;
1504 } // FitDataCollector<>::add_with_uncertainty(Iter, Iter)
1505 
1506 
1507 
1508 template <typename T, unsigned int D>
1510  s2.clear();
1511  x.clear();
1512  y.clear();
1513  y2.clear();
1514  xy.clear();
1515 } // FitDataCollector<>::clear()
1516 
1517 
1518 template <typename T, unsigned int D> template <typename Stream>
1520 
1521  out << "Sums 1/s^2=" << s2.Weights()
1522  << "\n x/s^2=" << x.template SumN<1>();
1523  for (unsigned int degree = 2; degree <= x.Power; ++degree)
1524  out << "\n x^" << degree << "/s^2=" << x.Sum(degree);
1525  out
1526  << "\n y/s^2=" << y.Weights()
1527  << "\n y^2/s^2=" << y2.Sum();
1528  if (xy.Power >= 1)
1529  out << "\n xy/s^2=" << xy.template SumN<1>();
1530  for (unsigned int degree = 2; degree <= xy.Power; ++degree)
1531  out << "\n x^" << degree << "y/s^2=" << xy.Sum(degree);
1532  out << std::endl;
1533 } // FitDataCollector<>::Print()
1534 
1535 
1536 //******************************************************************************
1537 //*** SimplePolyFitterBase<>
1538 //***
1539 template <typename T, unsigned int D>
1541  return (Base_t::N() > (int) Degree)
1542  && std::isnormal(Determinant(MakeMatrixX()));
1543 } // SimplePolyFitterBase<>::isValid()
1544 
1545 
1546 template <typename T, unsigned int D>
1548  (unsigned int n) const -> Data_t
1549 {
1550  return Param(n, MakeMatrixX());
1551 } // SimplePolyFitterBase<>::FitParameter(unsigned int)
1552 
1553 
1554 template <typename T, unsigned int D>
1556  (unsigned int n) const -> Data_t
1557 {
1558  if (n > Degree) return Data_t(0); // no parameter, no error
1559  return std::sqrt(FitParameterCovariance()[n * (NParams + 1)]);
1560 } // SimplePolyFitterBase<>::FitParameterError()
1561 
1562 
1563 template <typename T, unsigned int D>
1565  -> FitParameters_t
1566 {
1567  FitMatrix_t Xmat = MakeMatrixX();
1568  FitParameters_t fit_params;
1569  for (unsigned int iParam = 0; iParam < NParams; ++iParam)
1570  fit_params[iParam] = Param(iParam, Xmat);
1571  return fit_params;
1572 } // SimplePolyFitterBase<>::FitParameters()
1573 
1574 
1575 template <typename T, unsigned int D>
1577  -> FitParameters_t
1578 {
1579  return FitParameterErrors(FitParameterCovariance());
1580 } // SimplePolyFitterBase<>::FitParameterErrors()
1581 
1582 
1583 template <typename T, unsigned int D>
1585  () const -> FitMatrix_t
1586 {
1587  FitMatrix_t Xmat = MakeMatrixX();
1588  Data_t det = Determinant(Xmat);
1589  if (!std::isnormal(det)) {
1590  throw std::range_error
1591  ("SimplePolyFitterBase::FitParameterCovariance(): determinant 0 while fitting");
1592  }
1593  return InvertMatrix(Xmat, det);
1594 } // SimplePolyFitterBase<>::FitParameterCovariance()
1595 
1596 
1597 template <typename T, unsigned int D>
1599  FitParameters_t& params,
1600  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
1601 ) const {
1602 
1603  Xmat = MakeMatrixX();
1604  det = Determinant(Xmat);
1605  if (!std::isnormal(det)) {
1606  Smat.fill(Data_t(0));
1607  params.fill(Data_t(0));
1608  return false;
1609  }
1610  Smat = InvertMatrix(Xmat, det);
1611  params = FitParameters(Smat, det);
1612  return true;
1613 } // SimplePolyFitterBase<>::FillResults(params, matrices, determinant)
1614 
1615 
1616 template <typename T, unsigned int D>
1618  FitParameters_t& params, FitParameters_t& paramerrors,
1619  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
1620 ) const {
1621 
1622  if (!this->FillResults(params, Xmat, det, Smat)) return false;
1623  paramerrors = ExtractParameterErrors(Smat);
1624  return true;
1625 } // SimplePolyFitterBase<>::FillResults(params, errors, matrices, determinant)
1626 
1627 
1628 template <typename T, unsigned int D>
1630  FitParameters_t& params, FitParameters_t& paramerrors
1631 ) const {
1632  // to compute the parameters, we need all the stuff;
1633  // we just keep it local and discard it in the end. Such a waste.
1634  FitMatrix_t Xmat, Smat;
1635  Data_t det;
1636  return FillResults(params, paramerrors, Xmat, det, Smat);
1637 } // SimplePolyFitterBase<>::FillResults(params, errors)
1638 
1639 
1640 template <typename T, unsigned int D>
1642  -> Data_t
1643 {
1644  FitParameters_t params = FitParameters();
1645  unsigned int iParam = NParams - 1; // point to last parameter (highest degree)
1646  Data_t v = params[iParam];
1647  while (iParam > 0) v = v * x + params[--iParam];
1648  return v;
1649 } // SimplePolyFitterBase<>::Evaluate()
1650 
1651 
1652 // --- protected methods follow ---
1653 template <typename T, unsigned int D>
1655  -> FitMatrix_t
1656 {
1657  FitMatrix_t Xmat;
1658  for (unsigned int i = 0; i < NParams; ++i) { // row
1659  for (unsigned int j = i; j < NParams; ++j) { // column
1660  Xmat[j * NParams + i] = Xmat[i * NParams + j] = Base_t::XN(i+j);
1661  } // for j
1662  } // for i
1663  return Xmat;
1664 } // SimplePolyFitterBase<>::MakeMatrixX()
1665 
1666 
1667 template <typename T, unsigned int D>
1669  -> FitParameters_t
1670 {
1671  FitParameters_t Ymat;
1672  for (unsigned int i = 0; i < NParams; ++i) Ymat[i] = Base_t::XNY(i);
1673  return Ymat;
1674 } // SimplePolyFitterBase<>::MakeMatrixY()
1675 
1676 
1677 template <typename T, unsigned int D>
1679  (FitMatrix_t const& Xmat) const
1680  -> FitParameters_t
1681 {
1682  FitParameters_t fit_params;
1683  for (unsigned int iParam = 0; iParam < NParams; ++iParam)
1684  fit_params[iParam] = Param(iParam, Xmat);
1685  return fit_params;
1686 } // SimplePolyFitterBase<>::FitParameters(FitMatrix_t)
1687 
1688 
1689 template <typename T, unsigned int D>
1691  (FitMatrix_t const& Smat, Data_t /* det */) const
1692  -> FitParameters_t
1693 {
1694  return MatrixProduct(Smat, MakeMatrixY());
1695 } // SimplePolyFitterBase<>::FitParameters(FitMatrix_t)
1696 
1697 
1698 template <typename T, unsigned int D>
1700  (unsigned int n, FitMatrix_t const& Xmat) const -> Data_t
1701 {
1702  if (n > Degree) return Data_t(0); // no such a degree, its coefficient is 0
1703 
1704  Data_t detXmat = Determinant(Xmat);
1705  if (!std::isnormal(detXmat)) {
1706  throw std::range_error
1707  ("SimplePolyFitterBase::Param(): Determinant 0 while fitting");
1708  }
1709  return Param(n, Xmat, detXmat);
1710 } // SimplePolyFitterBase<>::Param(unsigned int, FitMatrix_t)
1711 
1712 
1713 template <typename T, unsigned int D>
1715  (FitMatrix_t const& Smat)
1716  -> FitParameters_t
1717 {
1718  FitParameters_t fit_errors;
1719  for (unsigned int iParam = 0; iParam <= Degree; ++iParam)
1720  fit_errors[iParam] = std::sqrt(Smat[iParam * (NParams + 1)]);
1721  return fit_errors;
1722 } // SimplePolyFitterBase<>::FitParameterErrors(FitMatrix_t)
1723 
1724 
1725 template <typename T, unsigned int D>
1727  (unsigned int n, FitMatrix_t const& Xmat, Data_t detXmat) const -> Data_t
1728 {
1729  if (n > Degree) return Data_t(0); // no such a degree, its coefficient is 0
1730  // XYmat is as Xmat...
1731  FitMatrix_t XYmat(Xmat);
1732  // ... except that the N-th column is replaced with { sum x^i y }
1733  for (unsigned int i = 0; i < NParams; ++i)
1734  XYmat[i * NParams + n] = Base_t::XNY(i);
1735 
1736  return Determinant(XYmat) / detXmat;
1737 } // SimplePolyFitterBase<>::Param(unsigned int, FitMatrix_t, Data_t)
1738 
1739 
1740 template <typename T, unsigned int D>
1742 {
1743  // the generic implementation of ChiSquare from sums is complex enough that
1744  // I freaked out
1745  throw std::logic_error
1746  ("SimplePolyFitterBase::ChiSquare() not implemented for generic fit");
1747 } // SimplePolyFitterBase<>::ChiSquare()
1748 
1749 
1750 
1751 //******************************************************************************
1752 //*** LinearFit<>
1753 //***
1754 
1755 template <typename T>
1757 {
1758  FitParameters_t fit_params = this->FitParameters();
1759  const Data_t b = fit_params[0];
1760  const Data_t a = fit_params[1];
1761  return Y2() + sqr(a) * X2() + sqr(b) * I()
1762  + Data_t(2) * (a * b * X2() - a * XY() - b * Y());
1763 } // LinearFit<T>::ChiSquare()
1764 
1765 
1766 //******************************************************************************
1767 //*** QuadraticFit<>
1768 //***
1769 
1770 template <typename T>
1772 {
1773  FitParameters_t a = this->FitParameters();
1774  return Y2() - Data_t(2) * (a[0]*Y() + a[1]*XY() + a[2]*X2Y())
1775  + sqr(a[0])*I() + Data_t(2) * a[0] * ( a[1]*X() + a[2]*X2() )
1776  + sqr(a[1])*X2() + Data_t(2) * a[1] * ( a[2]*X3() )
1777  + sqr(a[2])*X4();
1778 } // QuadraticFit<T>::ChiSquare()
1779 
1780 
1781 //******************************************************************************
1782 //*** GaussianFit<>
1783 //***
1784 
1785 //
1786 // data interface
1787 //
1788 template <typename T>
1790  (Data_t x, Data_t y, Data_t sy /* = Data_t(1.0) */)
1791 {
1792  if (y <= Data_t(0)) return false; // ignore the non-positive values
1793  Value_t value = EncodeValue(Value_t(y, sy));
1794  return fitter.add(x, value.value(), value.error());
1795 } // GaussianFit<T>::add(Data_t, Data_t, Data_t)
1796 
1797 
1798 template <typename T>
1799 template <typename Iter, typename Pred>
1801  (Iter begin, Iter end, Pred extractor)
1802 {
1803  return fitter.add_without_uncertainty(begin, end, Encoder(extractor));
1804 } // GaussianFit<>::add_without_uncertainty(Iter, Iter, Pred)
1805 
1806 
1807 template <typename T>
1808 template <
1809  typename VIter, typename UIter,
1810  typename VPred, typename UPred
1811  >
1813  VIter begin_value, VIter end_value,
1814  UIter begin_uncertainty,
1815  VPred value_extractor,
1816  UPred uncertainty_extractor /* = UPred() */
1817  )
1818 {
1819  return add_with_uncertainty(
1820  begin_value, end_value, begin_uncertainty,
1821  Encoder(value_extractor, uncertainty_extractor)
1822  );
1823 } // GaussianFit<T>::add_with_uncertainty()
1824 
1825 
1826 template <typename T>
1827 template <typename Iter>
1829  (Iter begin, Iter end)
1830 {
1831  unsigned int old_n = N();
1832  std::for_each(begin, end, [this](auto p) { this->add(p); });
1833  return N() - old_n;
1834 } // GaussianFit<T>::add_with_uncertainty()
1835 
1836 
1837 //
1838 // fitting interface
1839 //
1840 template <typename T>
1842  return ConvertParameters(fitter.FitParameters());
1843 } // GaussianFit<>::FitParameters()
1844 
1845 
1846 template <typename T>
1848  FitParameters_t qpars, qparerrors;
1849  if (!FillResults(qpars, qparerrors)) {
1850  throw std::runtime_error
1851  ("GaussianFit::FitParameterErrors() yielded invalid results");
1852  }
1853  return qparerrors;
1854 } // GaussianFit<>::FitParameterErrors()
1855 
1856 
1857 template <typename T>
1859 {
1860  // we need to go through the whole chain to get the error matrix
1861  FitParameters_t params;
1862  FitMatrix_t Xmat;
1863  Data_t det;
1864  FitMatrix_t Smat;
1865  if (!FillResults(params, Xmat, det, Smat)) {
1866  throw std::runtime_error
1867  ("GaussianFit::FitParameterCovariance() yielded invalid results");
1868  }
1869  return Smat;
1870 } // SimplePolyFitterBase<>::FitParameterCovariance()
1871 
1872 
1873 template <typename T>
1875  (FitParameters_t& params, FitParameters_t& paramerrors) const
1876 {
1877  FitParameters_t qpars;
1878  FitMatrix_t qparerrmat;
1879  FitMatrix_t Xmat; // not used
1880  Data_t det; // not used
1881  if (!fitter.FillResults(qpars, Xmat, det, qparerrmat)) return false;
1882  ConvertParametersAndErrors(qpars, qparerrmat, params, paramerrors);
1883  return isValid(params, qpars);
1884 } // GaussianFit<>::FillResults()
1885 
1886 
1887 template <typename T>
1889  FitParameters_t& params, FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
1890 ) const {
1891  FitParameters_t qpars;
1892  FitMatrix_t qparerrmat;
1893  if (!fitter.FillResults(qpars, Xmat, det, qparerrmat)) return false;
1894  ConvertParametersAndErrorMatrix(qpars, qparerrmat, params, Smat);
1895  return isValid(params, qpars);
1896 } // GaussianFit::FillResults()
1897 
1898 
1899 template <typename T>
1901  FitParameters_t& params, FitParameters_t& paramerrors,
1902  FitMatrix_t& Xmat, Data_t& det, FitMatrix_t& Smat
1903 ) const {
1904  if (!FillResults(params, Xmat, det, Smat)) return false;
1905  paramerrors = fitter.ExtractParameterErrors(Smat);
1906  return true;
1907 } // GaussianFit::FillResults()
1908 
1909 
1910 template <typename T>
1912  -> Data_t
1913 {
1914  Data_t z = (x - params[1]) / params[2];
1915  return params[0] * std::exp(-0.5*sqr(z));
1916 } // GaussianFit<>::Evaluate()
1917 
1918 
1919 template <typename T>
1921  -> FitParameters_t
1922 {
1923  FitParameters_t params;
1924 
1925 
1926  Data_t sigma2 = -0.5 / qpars[2]; // sigma^2 = -1 / (2 a2)
1927  params[2] = std::sqrt(sigma2); // sigma
1928 
1929  params[1] = sigma2 * qpars[1]; // mean = sigma2 a1
1930 
1931  params[0] = std::exp(qpars[0] - 0.25 * sqr(qpars[1])/qpars[2]);
1932 
1933  return params;
1934 } // GaussianFit<>::ConvertParameters()
1935 
1936 
1937 template <typename T>
1939  FitParameters_t const& qpars, FitMatrix_t const& qparerrmat,
1940  FitParameters_t& params, FitParameters_t& paramvariances
1941  )
1942 {
1943  params = ConvertParameters(qpars);
1944 
1945  FitParameters_t const& a = qpars;
1946  Data_t const& A = params[0];
1947  Data_t const& mu = params[1];
1948  Data_t const& sigma = params[2];
1949 
1950  // error on sigma
1951  paramvariances[2] = qparerrmat[3 * 2 + 2] / sqr(cube(sigma));
1952 
1953  // error on mu
1954  paramvariances[1] = sqr(mu * (
1955  + qparerrmat[3 * 1 + 1] / sqr(a[1])
1956  - 2.*qparerrmat[3 * 2 + 1] / (a[1]*a[2])
1957  + qparerrmat[3 * 2 + 2] / sqr(a[2])
1958  ));
1959 
1960  // error on A
1961  paramvariances[0] = sqr(A * (
1962  + qparerrmat[3 * 0 + 0]
1963  + 2.*qparerrmat[3 * 0 + 1] * mu
1964  +( qparerrmat[3 * 1 + 1]
1965  + 2.*qparerrmat[3 * 0 + 2]) * sqr(mu)
1966  + 2.*qparerrmat[3 * 1 + 2] * cube(mu)
1967  + qparerrmat[3 * 2 + 2] * sqr(sqr(mu))
1968  ));
1969 
1970 } // GaussianFit<>::ConvertParametersAndVariances()
1971 
1972 
1973 template <typename T>
1975  FitParameters_t const& qpars, FitMatrix_t const& qparerrmat,
1976  FitParameters_t& params, FitParameters_t& paramerrors
1977  )
1978 {
1979  ConvertParametersAndVariances(qpars, qparerrmat, params, paramerrors);
1980  // paramerrors actually stores the square of the error; fix it:
1981  for (Data_t& paramerror: paramerrors) paramerror = std::sqrt(paramerror);
1982 } // GaussianFit<>::ConvertParametersAndErrors()
1983 
1984 
1985 template <typename T>
1987  FitParameters_t const& qpars, FitMatrix_t const& qparerrmat,
1988  FitParameters_t& params, FitMatrix_t& Smat
1989  )
1990 {
1991  FitParameters_t paramvariances;
1992  ConvertParametersAndVariances(qpars, qparerrmat, params, paramvariances);
1993 
1994  // let's call things with their names
1995  FitParameters_t const& a = qpars;
1996  Data_t const& A = params[0];
1997  Data_t const& mu = params[1];
1998  Data_t const& sigma = params[2];
1999 
2000  // variance on sigma
2001  Smat[3 * 2 + 2] = paramvariances[2];
2002 
2003  // variance on mu
2004  Smat[3 * 1 + 1] = paramvariances[1];
2005 
2006  // variance on A
2007  Smat[3 * 0 + 0] = paramvariances[0];
2008 
2009  // covariance on sigma and mu
2010  Smat[3 * 1 + 2] = Smat[3 * 2 + 1]
2011  = (qparerrmat[3 * 1 + 2] + 2 * mu * qparerrmat[3 * 2 + 2]) / sigma;
2012 
2013  // this is the sum of the derivatives of A vs. all a parameters, each one
2014  // multiplied by the covariance of that parameter with a2
2015  const Data_t dA_dak_cov_aka2 = A * (
2016  qparerrmat[3 * 0 + 2]
2017  + qparerrmat[3 * 1 + 2] * mu
2018  + qparerrmat[3 * 2 + 2] * sqr(mu)
2019  );
2020  // covariance on A and sigma
2021  Smat[3 * 0 + 2] = Smat[3 * 2 + 0]
2022  = dA_dak_cov_aka2 / cube(sigma);
2023 
2024  // this other is the same as dA_dak_cov_aka2, but for a1
2025  const Data_t dA_dak_cov_aka1 = A * (
2026  qparerrmat[3 * 0 + 1]
2027  + qparerrmat[3 * 1 + 1] * mu
2028  + qparerrmat[3 * 2 + 1] * sqr(mu)
2029  );
2030 
2031  // covariance on A and mu
2032  Smat[3 * 0 + 1] = Smat[3 * 1 + 0] = mu *
2033  (dA_dak_cov_aka1 / a[1] - dA_dak_cov_aka2 / a[2]);
2034 
2035 } // GaussianFit<>::ConvertParametersAndErrors()
2036 
2037 
2038 template <typename T>
2040  (FitParameters_t const& params, FitParameters_t const& qpars)
2041 {
2042  return (qpars[2] < Data_t(0)) && (params[0] >= Data_t(0));
2043 } // GaussianFit<>::isValid(FitParameters_t)
2044 
2045 
2046 //******************************************************************************
2047 
2048 
2049 #endif // SIMPLEFITS_H
static constexpr Data_t cube(Data_t v)
Returns the cube of the specified data value.
Definition: SimpleFits.h:610
Weight_t Weights() const
Returns the sum of the weights.
Definition: StatCollector.h:62
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
void add(Data_t v, Weight_t w)
Adds the specified weight to the statistics.
void add_without_uncertainty(Iter begin, Iter end)
Adds measurements from a sequence, with no uncertainty.
Definition: SimpleFits.h:135
static constexpr unsigned int NParams
Definition: SimpleFits.h:74
virtual Data_t Evaluate(Data_t x) const override
Evaluates the fitted function at the specified point.
Definition: SimpleFits.h:1641
Data_t X4() const
Definition: SimpleFits.h:991
bool add(MeasurementAndUncertainty_t value)
Definition: SimpleFits.h:372
int N() const
Returns the number of entries added.
Definition: StatCollector.h:59
Data_t InterceptError() const
Returns the error on intercept of the fit.
Definition: SimpleFits.h:891
Namespace for general, non-LArSoft-specific utilities.
unsigned int add_with_uncertainty(Iter begin, Iter end)
Definition: SimpleFits.h:411
unsigned int add_with_uncertainty(VIter begin_value, VIter end_value, UIter begin_uncertainty, VPred value_extractor, UPred uncertainty_extractor=UPred())
Adds measurements with uncertainties from a sequence.
Definition: SimpleFits.h:1477
void add_without_uncertainty(Iter begin, Iter end)
Definition: SimpleFits.h:377
bool add(Data_t x, Data_t y, Data_t sy=Data_t(1.0))
Definition: SimpleFits.h:1790
typename Base_t::Data_t Data_t
type of the data
Definition: SimpleFits.h:1026
unsigned int add_with_uncertainty(VIter begin_value, VIter end_value, UIter begin_uncertainty, VPred value_extractor, UPred uncertainty_extractor=UPred())
Definition: SimpleFits.h:397
Data_t XN(unsigned int n) const
Returns the weighted sum of x^n.
Definition: SimpleFits.h:447
constexpr Data_t error() const
Definition: SimpleFits.h:1256
virtual Data_t FitParameterError(unsigned int n) const
Returns the error on parameter n of the fit result.
Definition: SimpleFits.h:533
std::string string
Definition: nybbler.cc:12
Data_t XN(unsigned int n) const
Returns the weighted sum of x^n.
Definition: SimpleFits.h:287
virtual FitParameters_t FitParameterErrors() const override
Computes and returns all the parameter errors of the fit result.
Definition: SimpleFits.h:1847
Data_t XN() const
Returns the weighted sum of x^N.
Definition: SimpleFits.h:297
typename Collector_t::Data_t Data_t
type of the data
Definition: SimpleFits.h:351
Weight_t AverageWeight() const
Returns the arithmetic average of the weights.
unsigned int add_with_uncertainty(Cont cont)
Definition: SimpleFits.h:1092
std::array< Data_t, sqr(NParams)> FitMatrix_t
Definition: SimpleFits.h:971
virtual int NDF() const override
Returns the degrees of freedom in the determination of the fit.
Definition: SimpleFits.h:731
unsigned int add_with_uncertainty(VIter begin_value, VIter end_value, UIter begin_uncertainty, VPred value_extractor, UPred uncertainty_extractor=UPred())
Definition: SimpleFits.h:1812
EncodeExtractor(VPred &vpred, UPred &upred)
Definition: SimpleFits.h:1316
static Data_t UncertaintyToWeight(Data_t s)
Transforms an uncertainty into a weight ( )
Definition: SimpleFits.h:317
< type of value and error
Definition: SimpleFits.h:1248
error
Definition: include.cc:26
static constexpr Data_t sqr(Data_t v)
Returns the square of the specified data value.
Definition: SimpleFits.h:607
STL namespace.
WeightTracker< Data_t > y
accumulator for y
Definition: SimpleFits.h:329
static void ConvertParametersAndVariances(FitParameters_t const &qpars, FitMatrix_t const &qparerrmat, FitParameters_t &params, FitParameters_t &paramvariances)
Converts the specified quadratic fit parameters and errors.
Definition: SimpleFits.h:1938
Data_t Y2() const
Definition: SimpleFits.h:995
virtual Data_t Param(unsigned int n, FitMatrix_t const &Xmat) const
Computes a single fit parameter using the given information.
Definition: SimpleFits.h:1700
virtual Data_t Evaluate(Data_t x) const override
Evaluates the fitted function at the specified point.
Definition: SimpleFits.h:1225
bool add(Measurement_t value, Data_t sy=Data_t(1.0))
Definition: SimpleFits.h:1050
#define D
Debug message.
Definition: tclscanner.cpp:775
static Value_t EncodeValue(Data_t value, Data_t error)
Converts a value and error into a proper input for the quadratic fit.
Definition: SimpleFits.h:1272
Class providing data collection for the simple polynomial fitters.
Definition: SimpleFits.h:37
typename Fitter_t::FitMatrix_t FitMatrix_t
Definition: SimpleFits.h:1036
static constexpr V sqr(V const &v)
Returns the square of the specified value.
Definition: SimpleFits.h:283
virtual Data_t ChiSquare() const override
Returns the of the fit.
Definition: SimpleFits.h:1771
void add(Weight_t weight)
Adds the specified weight to the statistics.
Definition: StatCollector.h:53
std::tuple< Data_t, Data_t > Base_t
Definition: SimpleFits.h:1249
Classes gathering simple statistics.
std::array< Data_t, sqr(NParams)> FitMatrix_t
Definition: SimpleFits.h:867
DataTracker< 1, Data_t > y2
accumulator for y2
Definition: SimpleFits.h:330
weight
Definition: test.py:257
virtual FitParameters_t FitParameters() const override
Computes and returns all the parameters of the fit result.
Definition: SimpleFits.h:1841
int N() const
Returns the number of (valid) points added.
Definition: SimpleFits.h:1100
Value_t(Data_t v, Data_t e)
Definition: SimpleFits.h:1251
bool add(MeasurementAndUncertainty_t value)
Adds one entry with specified x, y and uncertainty.
Definition: SimpleFits.h:118
Performs a linear regression of data.
Definition: SimpleFits.h:849
Data_t I() const
Aliases.
Definition: SimpleFits.h:920
static Measurement_t EncodeValue(Measurement_t const &meas)
Converts a value and error into a proper input for the quadratic fit.
Definition: SimpleFits.h:1289
Weight_t Sum(unsigned int n) const
Returns the sum of the values to the power n (1 <= n <= 2, no check)
Data_t XNY(unsigned int n) const
Returns the weighted sum of x^n y.
Definition: SimpleFits.h:450
T sqr(T v)
virtual FitMatrix_t MakeMatrixX() const
Fills and returns the matrix of x^n sum coefficients ( { x^(i+j) } )
Definition: SimpleFits.h:1654
virtual FitMatrix_t FitParameterCovariance() const override
Computes and returns all the covariance matrix of the fit result.
Definition: SimpleFits.h:1858
typename Collector_t::MeasurementAndUncertainty_t MeasurementAndUncertainty_t
type of measurement with uncertainty
Definition: SimpleFits.h:358
UPred & error_extractor
uncertainty extractor
Definition: SimpleFits.h:1333
Data_t XNY() const
Returns the weighted sum of x^N y.
Definition: SimpleFits.h:302
virtual FitParameters_t FitParameterErrors() const override
Computes and returns all the parameter errors of the fit result.
Definition: SimpleFits.h:1576
void clear()
Resets the count.
Definition: StatCollector.h:56
typename Base_t::Data_t Data_t
type of the data
Definition: SimpleFits.h:653
Classes with hard-coded (hence "fast") matrix math.
Data_t Slope() const
Returns the slope of the fit.
Definition: SimpleFits.h:884
void add_without_uncertainty(Cont cont)
Definition: SimpleFits.h:1072
static Value_t DecodeValue(Value_t const &value)
Converts a value from the quadratic fit into a proper value.
Definition: SimpleFits.h:1282
virtual bool FillResults(FitParameters_t &params, FitMatrix_t &Xmat, Data_t &det, FitMatrix_t &Smat) const override
Fills the specified parameters.
Definition: SimpleFits.h:1888
virtual Data_t ChiSquare() const override
Returns the of the fit.
Definition: SimpleFits.h:1756
T abs(T value)
virtual FitMatrix_t InvertMatrix(FitMatrix_t const &mat) const
Computes the inverse of a matrix.
Definition: SimpleFits.h:624
unsigned int add_with_uncertainty(Cont cont)
Adds measurements with uncertainties from a container.
Definition: SimpleFits.h:254
static FitParameters_t ConvertParameters(FitParameters_t const &qpars)
Converts the specified quadratic fit parameters into Gaussian.
Definition: SimpleFits.h:1920
const double e
Provides "fast" matrix operations.
constexpr Data_t value() const
Definition: SimpleFits.h:1255
WeightTracker< Data_t > s2
accumulator for uncertainty
Definition: SimpleFits.h:327
Data_t InterceptSlopeCovariance() const
Returns the covariance between intercept and slope of the fit.
Definition: SimpleFits.h:905
Data_t Intercept() const
Returns the intercept of the fit.
Definition: SimpleFits.h:877
std::void_t< T > n
Data_t X2() const
Definition: SimpleFits.h:922
const double a
virtual FitMatrix_t FitParameterCovariance() const override
Computes and returns all the covariance matrix of the fit result.
Definition: SimpleFits.h:1585
DataTracker< Degree *2, Data_t > x
accumulator for variable x^k
Definition: SimpleFits.h:328
static T Sum(WeightTracker< T > const &, DataTracker< Power, T > const &sums)
Definition: SimpleFits.h:59
A unary functor returning its own argument (any type)
Definition: StatCollector.h:33
std::array< Data_t, NParams > FitParameters_t
type of set of fit parameters
Definition: SimpleFits.h:970
void add_without_uncertainty(Cont cont, Pred extractor)
Definition: SimpleFits.h:385
void add_without_uncertainty(Cont cont, Pred extractor)
Definition: SimpleFits.h:1068
p
Definition: test.py:223
bool FillResults(FitParameters_t &params, FitMatrix_t &Xmat, Data_t &det, FitMatrix_t &Smat) const override
Fills the specified parameters.
Definition: SimpleFits.h:1598
static void ConvertParametersAndErrors(FitParameters_t const &qpars, FitMatrix_t const &qparerrmat, FitParameters_t &params, FitParameters_t &paramerrors)
Converts the specified quadratic fit parameters and errors.
Definition: SimpleFits.h:1974
typename Interface_t::FitParameters_t FitParameters_t
type of set of fit parameters
Definition: SimpleFits.h:656
static Data_t WeightToUncertainty(Data_t w)
Transforms a weight back to an uncertainty ( )
Definition: SimpleFits.h:321
int N() const
Returns the number of entries added.
Definition: SimpleFits.h:266
void add_without_uncertainty(Cont cont, Pred extractor)
Adds all measurements from a container, with no uncertainty.
Definition: SimpleFits.h:169
void PrintStats(Stream &out) const
Prints the collected statistics into a stream.
Definition: SimpleFits.h:436
void clear()
Clears all the statistics.
Definition: SimpleFits.h:421
Data_t X() const
Definition: SimpleFits.h:921
void add_without_uncertainty(Iter begin, Iter end)
Definition: SimpleFits.h:1061
"Fast" Gaussian fit
Definition: SimpleFits.h:1018
Class tracking sums of variables up to a specified power.
Definition: StatCollector.h:93
virtual int NDF() const override
Returns the degrees of freedom in the determination of the fit.
Definition: SimpleFits.h:1170
VPred & value_extractor
value extractor
Definition: SimpleFits.h:1332
Data_t SlopeError() const
Returns the error in slope of the fit.
Definition: SimpleFits.h:898
virtual Data_t FitParameterError(unsigned int n) const override
Returns the error on parameter n of the fit result.
Definition: SimpleFits.h:1556
bool add(Measurement_t value, Data_t sy=Data_t(1.0))
Definition: SimpleFits.h:369
std::array< Data_t, NParams > FitParameters_t
type of set of fit parameters
Definition: SimpleFits.h:866
Value_t(MeasurementAndUncertainty_t meas)
Definition: SimpleFits.h:1252
Data_t AverageUncertainty() const
Returns an average of the uncertainties.
Definition: SimpleFits.h:277
static Value_t EncodeValue(Value_t const &value)
Converts a value and error into a proper input for the quadratic fit.
Definition: SimpleFits.h:1277
Data_t XNY(unsigned int n) const
Returns the weighted sum of x^n y.
Definition: SimpleFits.h:291
Performs a second-degree fit of data.
Definition: SimpleFits.h:953
typename Interface_t::FitMatrix_t FitMatrix_t
type of matrix for covariance (a std::array)
Definition: SimpleFits.h:659
void clear()
Resets the count.
typename MatrixOps::Matrix_t FitMatrix_t
type of matrix for covariance (a std::array)
Definition: SimpleFits.h:472
Data_t Y() const
Definition: SimpleFits.h:992
void Print(Stream &out) const
Prints the statistics into a stream.
Definition: SimpleFits.h:1519
static constexpr unsigned int Power
Definition: StatCollector.h:95
Fitter_t fitter
the actual fitter and data holder
Definition: SimpleFits.h:1242
virtual FitParameters_t FitParameters() const override
Computes and returns all the parameters of the fit result.
Definition: SimpleFits.h:1564
static constexpr V sqr(V const &v)
Returns the square of the specified value.
Definition: SimpleFits.h:441
std::tuple< Data_t, Data_t > Measurement_t
type of measurement without uncertainty
Definition: SimpleFits.h:79
static FitParameters_t ExtractParameterErrors(FitMatrix_t const &Smat)
Extracts parameter errors from diagonal of the covarriance matrix.
Definition: SimpleFits.h:1715
Data_t X2Y() const
Definition: SimpleFits.h:994
virtual Fitter_t const & Fitter() const
Returns the internal fitter (mostly for debugging)
Definition: SimpleFits.h:1230
DataTracker< Degree, Data_t > xy
accumulator for variable xy
Definition: SimpleFits.h:331
Data_t I() const
Aliases.
Definition: SimpleFits.h:987
Base class providing virtual fitting interface for polynomial fitters.
Definition: SimpleFits.h:637
bool add(MeasurementAndUncertainty_t value)
Definition: SimpleFits.h:1053
LArSoft-specific namespace.
Base class providing data collection for the simple polynomial fitters.
Definition: SimpleFits.h:344
typename Fitter_t::Measurement_t Measurement_t
type of measurement without uncertainty
Definition: SimpleFits.h:1029
Data_t XY() const
Definition: SimpleFits.h:924
Simple fitter abstract interface.
Definition: SimpleFits.h:458
typename Fitter_t::MeasurementAndUncertainty_t MeasurementAndUncertainty_t
type of measurement with uncertainty
Definition: SimpleFits.h:1033
bool add(Measurement_t value, Data_t sy=Data_t(1.0))
Adds one entry with specified x, y and uncertainty.
Definition: SimpleFits.h:108
virtual FitParameters_t MakeMatrixY() const
Fills and returns the matrix (vector) of x^n y sum coefficients.
Definition: SimpleFits.h:1668
void clear()
Clears all the statistics.
Definition: SimpleFits.h:1509
static EncodeExtractor< VPred, UPred > Encoder(VPred &vpred, UPred &upred)
Definition: SimpleFits.h:1367
static constexpr unsigned int Degree
Degree of the fit.
Definition: SimpleFits.h:73
virtual Data_t Determinant(FitMatrix_t const &mat) const
Computes the determinant of a matrix.
Definition: SimpleFits.h:615
void add_without_uncertainty(Cont cont)
Adds all measurements from a container, with no uncertainty.
Definition: SimpleFits.h:183
void clear()
Clears all the input statistics.
Definition: SimpleFits.h:1097
static bool * b
Definition: config.cpp:1043
virtual Data_t ChiSquare() const override
Returns the of the fit.
Definition: SimpleFits.h:1741
unsigned int add_with_uncertainty(Cont cont)
Definition: SimpleFits.h:415
Data_t XY() const
Definition: SimpleFits.h:993
virtual bool isValid() const override
Returns if the fit has valid results.
Definition: SimpleFits.h:1540
void add_without_uncertainty(Iter begin, Iter end, Pred extractor)
Definition: SimpleFits.h:381
static void ConvertParametersAndErrorMatrix(FitParameters_t const &qpars, FitMatrix_t const &qparerrmat, FitParameters_t &params, FitMatrix_t &Smat)
Converts the specified quadratic fit parameters and errors.
Definition: SimpleFits.h:1986
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
Data_t X() const
Definition: SimpleFits.h:988
typename Collector_t::Measurement_t Measurement_t
type of measurement without uncertainty
Definition: SimpleFits.h:354
static constexpr double degree
Definition: Units.h:161
virtual Data_t ChiSquare() const override
Returns the of the original fit.
Definition: SimpleFits.h:1161
std::array< Data_t, NParams > FitParameters_t
type of set of fit parameters
Definition: SimpleFits.h:469
typename Fitter_t::FitParameters_t FitParameters_t
Definition: SimpleFits.h:1035
Data_t Y() const
Definition: SimpleFits.h:923
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
static Data_t DecodeValue(Data_t value)
Converts a value from the quadratic fit into a proper value.
Definition: SimpleFits.h:1268
static Data_t EncodeValue(Data_t value)
Definition: SimpleFits.h:1265
virtual Data_t FitParameter(unsigned int n) const
Returns the parameter n of the fit result.
Definition: SimpleFits.h:524
Data_t X2() const
Definition: SimpleFits.h:989
bool add(Data_t x, Data_t y, Data_t sy=Data_t(1.0))
Definition: SimpleFits.h:366
static QCString * s
Definition: config.cpp:1042
static EncodeExtractor< Pred > Encoder(Pred &pred)
Definition: SimpleFits.h:1364
Data_t X3() const
Definition: SimpleFits.h:990
Collector_t stats
statistics collected from fit data input
Definition: SimpleFits.h:444
bool add(Data_t x, Data_t y, Data_t sy=Data_t(1.0))
Adds one entry with specified x, y and uncertainty.
Definition: SimpleFits.h:1446
virtual Data_t FitParameter(unsigned int n) const override
Returns the parameter n of the fit result.
Definition: SimpleFits.h:1548
void PrintStats(Stream &out) const
Prints the collected statistics into a stream.
Definition: SimpleFits.h:1105
Data_t Y2() const
Definition: SimpleFits.h:925
QTextStream & endl(QTextStream &s)
Data_t Y2() const
Returns the weighted sum of y^2.
Definition: SimpleFits.h:307
std::tuple< Data_t, Data_t, Data_t > MeasurementAndUncertainty_t
type of measurement with uncertainty
Definition: SimpleFits.h:82
T cube(T side)
virtual bool isValid() const override
Returns if the fit has valid results.
Definition: SimpleFits.h:1122