Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TStatistic.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: G. Ganis 2012
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TStatistic.h"
13 
14 // clang-format off
15 /**
16 * \class TStatistic
17 * \ingroup MathCore
18 * \brief Statistical variable, defined by its mean and variance (RMS). Named, streamable, storable and mergeable.
19 */
20 // clang-format on
21 
22 templateClassImp(TStatistic);
23 
24 ////////////////////////////////////////////////////////////////////////////
25 /// \brief Constructor from a vector of values
26 /// \param[in] name The name given to the object
27 /// \param[in] n The total number of entries
28 /// \param[in] val The vector of values
29 /// \param[in] w The vector of weights for the values
30 ///
31 /// Recursively calls the TStatistic::Fill() function to fill the object.
32 TStatistic::TStatistic(const char *name, Int_t n, const Double_t *val, const Double_t *w)
33  : fName(name), fN(0), fW(0.), fW2(0.), fM(0.), fM2(0.), fMin(TMath::Limits<Double_t>::Max()), fMax(TMath::Limits<Double_t>::Min())
34 {
35  if (n > 0) {
36  for (Int_t i = 0; i < n; i++) {
37  if (w) {
38  Fill(val[i], w[i]);
39  } else {
40  Fill(val[i]);
41  }
42  }
43  }
44 }
45 
46 ////////////////////////////////////////////////////////////////////////////////
47 /// TStatistic destructor.
48 TStatistic::~TStatistic()
49 {
50  // Required since we overload TObject::Hash.
51  ROOT::CallRecursiveRemoveIfNeeded(*this);
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 /// \brief Increment the entries in the object by one value-weight pair.
56 /// \param[in] val Value to fill the Tstatistic with
57 /// \param[in] w The weight of the value
58 ///
59 /// Also updates statistics in the object. For number of entries, sum of weights,
60 /// sum of squared weights and sum of (value*weight), one extra value is added to the
61 /// statistic. For the sum of squared (value*weight) pairs, the function uses formula 1.4
62 /// in Chan-Golub, LeVeque : Algorithms for computing the Sample Variance (1983),
63 /// genralized by LM for the case of weights:
64 /// \f[
65 /// \frac{w_j}{\sum_{i=0}^{j} w_i \cdot \sum_{i=0}^{j-1} w_i} \cdot
66 /// \left(
67 /// \sum_{i=0}^{j} w_i \cdot val_i -
68 /// \sum_{i=0}^{j} \left(w_i \cdot val_i\right)
69 /// \right)
70 /// \f]
71 ///
72 /// The minimum(maximum) is computed by checking that the fill value
73 /// is either less(greater) than the current minimum(maximum)
74 void TStatistic::Fill(Double_t val, Double_t w) {
75 
76 
77  if (w == 0) return;
78  // increase data count
79  fN++;
80 
81  // update sum of weights
82  Double_t tW = fW + w;
83 
84  // update sum of (value * weight) pairs
85  fM += w * val;
86 
87  // update minimum and maximum values
88  fMin = (val < fMin) ? val : fMin;
89  fMax = (val > fMax) ? val : fMax;
90 
91 // Double_t dt = val - fM ;
92  if (tW == 0) {
93  Warning("Fill","Sum of weights is zero - ignore current data point");
94  fN--;
95  return;
96  }
97 
98  if (fW != 0) { // from the second time
99  Double_t rr = ( tW * val - fM);
100  fM2 += w * rr * rr / (tW * fW);
101  }
102  fW = tW;
103  fW2 += w*w;
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// \brief Print the content of the object
108 ///
109 /// Prints the statistics held by the object in one line. These include the mean,
110 /// mean error, RMS, the total number of values, the minimum and the maximum.
111 void TStatistic::Print(Option_t *) const {
112  TROOT::IndentLevel();
113  Printf(" OBJ: TStatistic\t %s \t Mean = %.5g +- %.4g \t RMS = %.5g \t Count = %lld \t Min = %.5g \t Max = %.5g",
114  fName.Data(), GetMean(), GetMeanErr(), GetRMS(), GetN(), GetMin(), GetMax());
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////////
118 /// \brief Merge implementation of TStatistic
119 /// \param[in] in Other TStatistic objects to be added to the current one
120 ///
121 /// The function merges the statistics of all objects together to form a new one.
122 /// Merging quantities is done via simple addition for the following class data members:
123 /// - number of entries fN
124 /// - the sum of weights fW
125 /// - the sum of squared weights fW2
126 /// - the sum of (value*weight) fM
127 ///
128 /// The sum of squared (value*weight) pairs fM2 is updated using the same formula as in
129 /// TStatistic::Fill() function.
130 ///
131 /// The minimum(maximum) is updated by checking that the minimum(maximum) of
132 /// the next TStatistic object in the queue is either less(greater) than the current minimum(maximum).
133 Int_t TStatistic::Merge(TCollection *in) {
134 
135  // Let's organise the list of objects to merge excluding the empty ones
136  std::vector<TStatistic*> statPtrs;
137  if (this->fN != 0LL) statPtrs.push_back(this);
138  TStatistic *statPtr;
139  for (auto o : *in) {
140  if ((statPtr = dynamic_cast<TStatistic *>(o)) && statPtr->fN != 0LL) {
141  statPtrs.push_back(statPtr);
142  }
143  }
144 
145  // No object included this has entries
146  const auto nStatsPtrs = statPtrs.size();
147 
148  // Early return possible in case nothing has been filled
149  if (nStatsPtrs == 0) return 0;
150 
151  // Merge the statistic quantities into local variables to then
152  // update the data members of this object
153  auto firstStatPtr = statPtrs[0];
154  auto N = firstStatPtr->fN;
155  auto M = firstStatPtr->fM;
156  auto M2 = firstStatPtr->fM2;
157  auto W = firstStatPtr->fW;
158  auto W2 = firstStatPtr->fW2;
159  auto Min = firstStatPtr->fMin;
160  auto Max = firstStatPtr->fMax;
161  for (auto i = 1U; i < nStatsPtrs; ++i) {
162  auto c = statPtrs[i];
163  double temp = (c->fW) / (W)*M - c->fM;
164  M2 += c->fM2 + W / (c->fW * (c->fW + W)) * temp * temp;
165  M += c->fM;
166  W += c->fW;
167  W2 += c->fW2;
168  N += c->fN;
169  Min = (c->fMin < Min) ? c->fMin : Min;
170  Max = (c->fMax > Max) ? c->fMax : Max;
171  }
172 
173  // Now update the data members of this object
174  fN = N;
175  fW = W;
176  fW2 = W2;
177  fM = M;
178  fM2 = M2;
179  fMin = Min;
180  fMax = Max;
181 
182  return nStatsPtrs;
183 
184 }