All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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
67  (WeightTracker<T> const& weight, DataTracker<Power, T> const&)
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 
369  bool add(Measurement_t value, Data_t sy = Data_t(1.0))
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  {
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 
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(
564  FitParameters_t& params,
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
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
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
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 
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
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
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
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 {
1448  Data_t w = UncertaintyToWeight(sy);
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
void add_without_uncertainty(Iter begin, Iter end)
Adds measurements from a sequence, with no uncertainty.
Definition: SimpleFits.h:135
see a below echo or echo I(indirect symbol).'echo" If the symbol is local (non-external)
process_name opflash particleana ie ie ie z
static constexpr unsigned int NParams
Number of parameters in the fit.
Definition: SimpleFits.h:651
static constexpr unsigned int NParams
Definition: SimpleFits.h:74
Data_t X4() const
Definition: SimpleFits.h:991
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
bool add(MeasurementAndUncertainty_t value)
Definition: SimpleFits.h:372
virtual Data_t ChiSquare() const override
Returns the of the fit.
Definition: SimpleFits.h:1741
static constexpr unsigned int Degree
Degree of the fit.
Definition: SimpleFits.h:349
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
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
virtual FitParameters_t FitParameterErrors() const =0
Computes and returns all the parameter errors of the fit result.
virtual FitMatrix_t InvertMatrix(FitMatrix_t const &mat, Data_t det) const
Computes the inverse of a matrix (using provided determinant)
Definition: SimpleFits.h:620
virtual Data_t FitParameterError(unsigned int n) const override
Returns the error on parameter n of the fit result.
Definition: SimpleFits.h:1556
Data_t XN(unsigned int n) const
Returns the weighted sum of x^n.
Definition: SimpleFits.h:447
virtual FitMatrix_t FitParameterCovariance() const =0
Computes and returns all the covariance matrix of the fit result.
static Data_t Determinant(Matrix_t const &mat)
Computes the determinant of a matrix.
constexpr Data_t error() const
Definition: SimpleFits.h:1256
Data_t operator()(Data_t x) const
Evaluates the fitted function; alias of Evaluate()
Definition: SimpleFits.h:603
virtual Data_t FitParameterError(unsigned int n) const
Returns the error on parameter n of the fit result.
Definition: SimpleFits.h:533
static void ThrowNotImplemented(std::string method)
Definition: SimpleFits.h:1425
Data_t XN(unsigned int n) const
Returns the weighted sum of x^n.
Definition: SimpleFits.h:287
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 constexpr unsigned int NParams
Number of parameters in the fit.
Definition: SimpleFits.h:1024
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.
pdgs p
Definition: selectors.fcl:22
unsigned int add_with_uncertainty(Cont cont)
Definition: SimpleFits.h:1092
std::array< Data_t, sqr(NParams)> FitMatrix_t
Definition: SimpleFits.h:971
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
&lt; type of value and error
Definition: SimpleFits.h:1248
virtual FitParameters_t FitParameters() const =0
Computes and returns all the parameters of the fit result.
static constexpr Data_t sqr(Data_t v)
Returns the square of the specified data value.
Definition: SimpleFits.h:607
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 ChiSquare() const override
Returns the of the original fit.
Definition: SimpleFits.h:1161
virtual Data_t FitParameter(unsigned int n) const override
Returns the parameter n of the fit result.
Definition: SimpleFits.h:1548
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
bool add(Measurement_t value, Data_t sy=Data_t(1.0))
Definition: SimpleFits.h:1050
virtual FitParameters_t FitParameterErrors() const override
Computes and returns all the parameter errors of the fit result.
Definition: SimpleFits.h:1576
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
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
static constexpr V sqr(V const &v)
Returns the square of the specified value.
Definition: SimpleFits.h:283
pdgs mu
Definition: selectors.fcl:22
virtual FitParameters_t FitParameterErrors() const override
Computes and returns all the parameter errors of the fit result.
Definition: SimpleFits.h:1847
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
static Matrix_t InvertSymmetricMatrix(Matrix_t const &mat, Data_t det)
DataTracker< 1, Data_t > y2
accumulator for y2
Definition: SimpleFits.h:330
int N() const
Returns the number of (valid) points added.
Definition: SimpleFits.h:1100
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
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 &lt;= n &lt;= 2, no check)
Data_t XNY(unsigned int n) const
Returns the weighted sum of x^n y.
Definition: SimpleFits.h:450
process_name gaushit a
virtual FitMatrix_t MakeMatrixX() const
Fills and returns the matrix of x^n sum coefficients ( { x^(i+j) } )
Definition: SimpleFits.h:1654
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
typename Base_t::Data_t Data_t
type of the data
Definition: SimpleFits.h:653
Classes with hard-coded (hence &quot;fast&quot;) 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
T abs(T value)
virtual FitMatrix_t InvertMatrix(FitMatrix_t const &mat) const
Computes the inverse of a matrix.
Definition: SimpleFits.h:624
BEGIN_PROLOG V
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
Provides &quot;fast&quot; 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
Data_t X2() const
Definition: SimpleFits.h:922
DataTracker< Degree *2, Data_t > x
accumulator for variable x^k
Definition: SimpleFits.h:328
constexpr T sqr(T v)
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
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
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
&quot;Fast&quot; Gaussian fit
Definition: SimpleFits.h:1018
virtual FitParameters_t MatrixProduct(FitMatrix_t const &mat, FitParameters_t const &vec) const
Computes the product of a FitMatrix_t and a FitParameters_t.
Definition: SimpleFits.h:629
Class tracking sums of variables up to a specified power.
Definition: StatCollector.h:93
virtual ~SimpleFitterInterface()=default
Virtual destructor: compiler&#39;s default.
j template void())
Definition: json.hpp:3108
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
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
typename MatrixOps::Matrix_t FitMatrix_t
type of matrix for covariance (a std::array)
Definition: SimpleFits.h:472
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
Data_t Y() const
Definition: SimpleFits.h:992
void Print(Stream &out) const
Prints the statistics into a stream.
Definition: SimpleFits.h:1519
static Vector_t MatrixVectorProduct(Matrix_t const &mat, Vector_t const &vec)
Returns the product of a square matrix times a column vector.
virtual bool isValid() const override
Returns if the fit has valid results.
Definition: SimpleFits.h:1122
Fitter_t fitter
the actual fitter and data holder
Definition: SimpleFits.h:1242
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 Data_t Evaluate(Data_t x) const override
Evaluates the fitted function at the specified point.
Definition: SimpleFits.h:1641
BEGIN_PROLOG method
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
virtual int NDF() const override
Returns the degrees of freedom in the determination of the fit.
Definition: SimpleFits.h:1170
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
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
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
Simple fitter abstract interface.
Definition: SimpleFits.h:458
virtual FitMatrix_t FitParameterCovariance() const override
Computes and returns all the covariance matrix of the fit result.
Definition: SimpleFits.h:1585
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 bool isValid() const =0
Returns if the fit has valid results.
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
process_name largeant stream1 can override from command line with o or output physics producers generator N
static EncodeExtractor< VPred, UPred > Encoder(VPred &vpred, UPred &upred)
Definition: SimpleFits.h:1367
virtual Data_t ChiSquare() const override
Returns the of the fit.
Definition: SimpleFits.h:1771
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
do i e
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
virtual FitParameters_t FitParameters() const override
Computes and returns all the parameters of the fit result.
Definition: SimpleFits.h:1564
virtual Data_t ChiSquare() const =0
Returns the of the fit.
static constexpr unsigned int Degree
Degree of the fit.
Definition: SimpleFits.h:648
unsigned int add_with_uncertainty(Cont cont)
Definition: SimpleFits.h:415
Data_t XY() const
Definition: SimpleFits.h:993
virtual Data_t Evaluate(Data_t x) const override
Evaluates the fitted function at the specified point.
Definition: SimpleFits.h:1225
static constexpr unsigned int NParams
Number of parameters in the fit.
Definition: SimpleFits.h:462
virtual FitMatrix_t FitParameterCovariance() const override
Computes and returns all the covariance matrix of the fit result.
Definition: SimpleFits.h:1858
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
virtual bool FillResults(FitParameters_t &params, FitMatrix_t &Xmat, Data_t &det, FitMatrix_t &Smat) const =0
Fills the specified parameters.
temporary value
Data_t X() const
Definition: SimpleFits.h:988
virtual int NDF() const =0
Returns the degrees of freedom in the determination of the fit.
typename Collector_t::Measurement_t Measurement_t
type of measurement without uncertainty
Definition: SimpleFits.h:354
virtual bool isValid() const override
Returns if the fit has valid results.
Definition: SimpleFits.h:1540
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
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
float A
Definition: dedx.py:137
virtual int NDF() const override
Returns the degrees of freedom in the determination of the fit.
Definition: SimpleFits.h:731
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
do Param
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 Evaluate(Data_t x) const =0
Evaluates the fitted function at the specified point.
bnb BNB Stream
void PrintStats(Stream &out) const
Prints the collected statistics into a stream.
Definition: SimpleFits.h:1105
Data_t Y2() const
Definition: SimpleFits.h:925
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 FitParameters_t FitParameters() const override
Computes and returns all the parameters of the fit result.
Definition: SimpleFits.h:1841
virtual Data_t ChiSquare() const override
Returns the of the fit.
Definition: SimpleFits.h:1756