Jpp  15.0.5
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JQuantile.hh
Go to the documentation of this file.
1 #ifndef __JTOOLS__JQUANTILE__
2 #define __JTOOLS__JQUANTILE__
3 
4 #include <ostream>
5 #include <iomanip>
6 #include <cmath>
7 #include <limits>
8 #include <algorithm>
9 #include <map>
10 
11 #include "JLang/JException.hh"
12 #include "JLang/JTitle.hh"
13 #include "JLang/JVectorize.hh"
14 #include "JLang/JManip.hh"
15 
16 #include "JMath/JMath.hh"
17 
18 
19 /**
20  * \author mdejong
21  */
22 
23 namespace JTOOLS {}
24 namespace JPP { using namespace JTOOLS; }
25 
26 namespace JTOOLS {
27 
28  using JMATH::JMath;
29  using JLANG::JTitle;
31  using JLANG::JNoValue;
32  using JLANG::array_type;
33  using JLANG::make_array;
34 
35 
36  /**
37  * Auxiliary data structure for running average, standard deviation and quantiles.
38  *
39  * See Knuth TAOCP vol 2, 3rd edition, page 232.\n
40  * This class acts as a zero-dimensional histogram.\n
41  * Note that if a weight is used, it should strictly be positive.
42  */
43  struct JQuantile :
44  public JTitle,
45  public JMath<JQuantile>
46  {
47  /**
48  * Constructor.
49  *
50  * \param title title
51  * \param quantiles quantiles
52  */
53  JQuantile(const JTitle& title = "",
54  const bool quantiles = false) :
55  JTitle(title),
57  {
58  reset();
59  }
60 
61 
62  /**
63  * Constructor.
64  *
65  * \param title title
66  * \param buffer input data
67  * \param quantiles quantiles
68  * \param w weight
69  */
70  template<class JElement_t, class JAllocator_t>
73  const bool quantiles = false,
74  const double w = 1.0) :
75  JTitle(title),
77  {
78  reset();
79 
80  put(buffer, w);
81  }
82 
83 
84  /**
85  * Reset.
86  */
87  void reset()
88  {
89  mean = 0.0;
90  sigma = 0.0;
91  total = 0.0;
92  count = 0;
93  xmin = std::numeric_limits<double>::max();
94  xmax = std::numeric_limits<double>::lowest();
95  wmin = std::numeric_limits<double>::max();
96  wmax = std::numeric_limits<double>::lowest();
97 
98  buffer.clear();
99  }
100 
101 
102  /**
103  * Add quantile.
104  *
105  * \param Q quantile
106  * \return this quantile
107  */
109  {
110  mean += Q.mean;
111  sigma += Q.sigma;
112  total += Q.total;
113  count += Q.count;
114  xmin = std::min(xmin, Q.xmin);
115  xmax = std::max(xmax, Q.xmax);
116  wmin = std::min(wmin, Q.wmin);
117  wmax = std::max(wmax, Q.wmax);
118 
119  if (quantiles) {
120  std::copy(Q.buffer.begin(), Q.buffer.end(), std::inserter(buffer, buffer.end()));
121  }
122 
123  return *this;
124  }
125 
126 
127  /**
128  * Put value.
129  *
130  * \param x value
131  * \param w weight
132  */
133  void put(const double x, const double w = 1.0)
134  {
135  total += w;
136  count += 1;
137 
138  if (count == 1) {
139 
140  mean = x;
141  sigma = 0.0;
142 
143  } else {
144 
145  const double new_mean = mean + w * (x - mean) / total;
146  const double new_sigma = sigma + w * (x - mean) * (x - new_mean);
147 
148  // set up for next iteration
149 
150  mean = new_mean;
151  sigma = new_sigma;
152  }
153 
154  xmin = std::min(xmin, x);
155  xmax = std::max(xmax, x);
156  wmin = std::min(wmin, w);
157  wmax = std::max(wmax, w);
158 
159  if (quantiles) {
160  buffer.insert(std::make_pair(x,w));
161  }
162  }
163 
164 
165  /**
166  * Put data.
167  *
168  * \param buffer input data
169  * \param w weight
170  */
171  template<class JElement_t, class JAllocator_t>
173  const double w = 1.0)
174  {
175  for (typename array_type<JElement_t, JAllocator_t>::const_iterator i = buffer.begin(); i != buffer.end(); ++i) {
176  put(*i, w);
177  }
178  }
179 
180 
181  /**
182  * Get total count.
183  *
184  * \return count
185  */
186  long long int getCount() const
187  {
188  return count;
189  }
190 
191 
192  /**
193  * Get total weight.
194  *
195  * \return weight
196  */
197  double getTotal() const
198  {
199  return total;
200  }
201 
202 
203  /**
204  * Get minimum value.
205  *
206  * \return minimum value
207  */
208  double getXmin() const
209  {
210  return xmin;
211  }
212 
213 
214  /**
215  * Get maximum value.
216  *
217  * \return maximum value
218  */
219  double getXmax() const
220  {
221  return xmax;
222  }
223 
224 
225  /**
226  * Get minimum weight.
227  *
228  * \return minimum weight
229  */
230  double getWmin() const
231  {
232  return wmin;
233  }
234 
235 
236  /**
237  * Get maximum weight.
238  *
239  * \return maximum weight
240  */
241  double getWmax() const
242  {
243  return wmax;
244  }
245 
246 
247  /**
248  * Get mean value.
249  *
250  * \return mean value
251  */
252  double getMean() const
253  {
254  if (count != 0.0)
255  return mean;
256  else
257  THROW(JDivisionByZero, "JQuantile::getMean()");
258  }
259 
260 
261  /**
262  * Get standard deviation
263  *
264  * \return standard deviation
265  */
266  double getSTDev() const
267  {
268  if (count > 1)
269  return sqrt(count * sigma/(total * (count - 1)));
270  else
271  THROW(JDivisionByZero, "JQuantile::getSTDev()");
272  }
273 
274 
275  /**
276  * Get maximal deviation from average.
277  *
278  * \param relative if true, relative to average, else absolute
279  * \return deviation
280  */
281  double getDeviation(const bool relative = true) const
282  {
283  if (relative)
284  return std::max(getXmax() - getMean(), getMean() - getXmin());
285  else
286  return getXmax() - getXmin();
287  }
288 
289 
290  /**
291  * Test relative accuracy.
292  *
293  * \param precision relative precision
294  * \return true if reached accuracy; else false
295  */
296  bool hasAccuracy(const double precision) const
297  {
298  return getCount() > 1 && getSTDev() < precision * getMean();
299  }
300 
301 
302  /**
303  * Get quantile.
304  *
305  * \param Q quantile
306  * \param reverse reverse
307  * \return value
308  */
309  double getQuantile(const double Q, const bool reverse = false) const
310  {
311  if (quantiles) {
312 
313  double W = 0.0;
314 
315  for (std::map<double, double>::const_iterator i = buffer.begin(); i != buffer.end(); ++i) {
316  W += i->second;
317  }
318 
319  if (reverse)
320  return getQuantile(buffer.rbegin(), buffer.rend(), Q*W);
321  else
322  return getQuantile(buffer. begin(), buffer. end(), Q*W);
323  }
324 
325  THROW(JNoValue, "Option 'quantiles' at JQuantile() incompatible with method getQuantile().");
326  }
327 
328 
329  /**
330  * Print quantile.
331  *
332  * \param out output stream
333  * \param lpr long print
334  */
335  std::ostream& print(std::ostream& out, bool lpr = true) const
336  {
337  using namespace std;
338 
339  const int nc = getTitle().size();
340 
341  if (lpr) {
342  out << setw(nc) << left << " " << ' '
343  << setw(10) << left << " mean" << ' '
344  << setw(10) << left << " STD" << ' '
345  << setw(10) << left << " deviation" << endl;
346  }
347 
348  out << setw(nc) << left << getTitle() << ' '
349  << SCIENTIFIC(10,2) << getMean() << ' '
350  << SCIENTIFIC(10,2) << getSTDev() << ' '
351  << SCIENTIFIC(10,2) << getDeviation(false) << endl;
352 
353  return out;
354  }
355 
356 
357  /**
358  * Print quantile.
359  *
360  * \param out output stream
361  * \param quantile quantile
362  * \return output stream
363  */
364  friend inline std::ostream& operator<<(std::ostream& out, const JQuantile& quantile)
365  {
366  return quantile.print(out, getLongprint(out));
367  }
368 
369  protected:
370  /**
371  * Get quantile.
372  *
373  * \param __begin begin of data
374  * \param __end end of data
375  * \param W weight
376  * \return value
377  */
378  template<class T>
379  static double getQuantile(T __begin, T __end, const double W)
380  {
381  double w = 0.0;
382 
383  for (T i = __begin; i != __end; ++i) {
384 
385  w += i->second;
386 
387  if (w >= W) {
388  return i->first;
389  }
390  }
391 
392  THROW(JNoValue, "Invalid weight " << W);
393  }
394 
395 
396  bool quantiles;
397  double mean;
398  double sigma;
399  double total;
400  long long int count;
401  double xmin;
402  double xmax;
403  double wmin;
404  double wmax;
406  };
407 }
408 
409 #endif
data_type w[N+1][M+1]
Definition: JPolint.hh:741
Exceptions.
bool hasAccuracy(const double precision) const
Test relative accuracy.
Definition: JQuantile.hh:296
Q(UTCMax_s-UTCMin_s)-livetime_s
Auxiliary base class for aritmetic operations of derived class types.
Definition: JMath.hh:110
double getTotal() const
Get total weight.
Definition: JQuantile.hh:197
void reset()
Reset.
Definition: JQuantile.hh:87
double getSTDev() const
Get standard deviation.
Definition: JQuantile.hh:266
Auxiliary data structure for running average, standard deviation and quantiles.
Definition: JQuantile.hh:43
friend std::ostream & operator<<(std::ostream &out, const JQuantile &quantile)
Print quantile.
Definition: JQuantile.hh:364
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:670
long long int count
Definition: JQuantile.hh:400
const std::string & getTitle() const
Get title.
Definition: JTitle.hh:55
double getXmin() const
Get minimum value.
Definition: JQuantile.hh:208
double getWmin() const
Get minimum weight.
Definition: JQuantile.hh:230
double getMean() const
Get mean value.
Definition: JQuantile.hh:252
double getQuantile(const double Q, const bool reverse=false) const
Get quantile.
Definition: JQuantile.hh:309
double getWmax() const
Get maximum weight.
Definition: JQuantile.hh:241
Exception for missing value.
Definition: JException.hh:198
JQuantile(const JTitle &title="", const bool quantiles=false)
Constructor.
Definition: JQuantile.hh:53
std::multimap< double, double > buffer
Definition: JQuantile.hh:405
std::ostream & print(std::ostream &out, bool lpr=true) const
Print quantile.
Definition: JQuantile.hh:335
Auxiliary class for title.
Definition: JTitle.hh:19
const array_type< JValue_t > & make_array(const JValue_t(&array)[N])
Method to create array of values.
Definition: JVectorize.hh:54
do set_variable OUTPUT_DIRECTORY $WORKDIR T
bool getLongprint(std::ostream &out)
Get long print option.
Definition: JManip.hh:121
void put(const double x, const double w=1.0)
Put value.
Definition: JQuantile.hh:133
void put(const array_type< JElement_t, JAllocator_t > &buffer, const double w=1.0)
Put data.
Definition: JQuantile.hh:172
long long int getCount() const
Get total count.
Definition: JQuantile.hh:186
Auxiliary methods to convert data members or return values of member methods of a set of objects to a...
I/O manipulators.
JQuantile & add(const JQuantile &Q)
Add quantile.
Definition: JQuantile.hh:108
double getDeviation(const bool relative=true) const
Get maximal deviation from average.
Definition: JQuantile.hh:281
double getXmax() const
Get maximum value.
Definition: JQuantile.hh:219
std::string title
Definition: JTitle.hh:73
Exception for division by zero.
Definition: JException.hh:270
void copy(const Head &from, JHead &to)
Copy header from from to to.
Definition: JHead.cc:139
JQuantile(const JTitle &title, const array_type< JElement_t, JAllocator_t > &buffer, const bool quantiles=false, const double w=1.0)
Constructor.
Definition: JQuantile.hh:71
Base class for data structures with artithmetic capabilities.
static double getQuantile(T __begin, T __end, const double W)
Get quantile.
Definition: JQuantile.hh:379
Auxiliary data structure for floating point format specification.
Definition: JManip.hh:484
Auxiliary data structure for return type of make methods.
Definition: JVectorize.hh:26