Jpp  17.3.2
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  * Options for evaluation of quantile.
304  */
305  enum Quantile_t {
306  forward_t = +1, //!< forward
307  symmetric_t = 0, //!< symmatric
308  backward_t = -1 //!< backward
309  };
310 
311 
312  /**
313  * Get quantile.
314  *
315  * \param Q quantile
316  * \param option option
317  * \return value
318  */
319  double getQuantile(const double Q, const Quantile_t option = forward_t) const
320  {
321  if (quantiles) {
322 
323  double W = 0.0;
324 
325  for (std::map<double, double>::const_iterator i = buffer.begin(); i != buffer.end(); ++i) {
326  W += i->second;
327  }
328 
329  switch (option) {
330  case forward_t:
331  return (getQuantile(buffer. begin(), buffer. end(), Q*W));
332  case symmetric_t:
333  return (getQuantile(buffer.rbegin(), buffer.rend(), 0.5*(1.0 - Q)*W) -
334  getQuantile(buffer. begin(), buffer. end(), 0.5*(1.0 - Q)*W));
335  case backward_t:
336  return (getQuantile(buffer.rbegin(), buffer.rend(), Q*W));
337  default:
338  THROW(JNoValue, "Invalid option " << option);
339  }
340  }
341 
342  THROW(JNoValue, "Option 'quantiles' at JQuantile() incompatible with method getQuantile().");
343  }
344 
345 
346  /**
347  * Print quantile.
348  *
349  * \param out output stream
350  * \param lpr long print
351  */
352  std::ostream& print(std::ostream& out, bool lpr = true) const
353  {
354  using namespace std;
355 
356  const int nc = getTitle().size();
357 
358  if (lpr) {
359  out << setw(nc) << left << " " << ' '
360  << setw(12) << left << " mean" << ' '
361  << setw(12) << left << " STD" << ' '
362  << setw(12) << left << " deviation" << endl;
363  }
364 
365  out << setw(nc) << left << getTitle() << ' '
366  << SCIENTIFIC(12,5) << getMean() << ' '
367  << SCIENTIFIC(12,5) << getSTDev() << ' '
368  << SCIENTIFIC(12,5) << getDeviation(false) << endl;
369 
370  return out;
371  }
372 
373 
374  /**
375  * Print quantile.
376  *
377  * \param out output stream
378  * \param quantile quantile
379  * \return output stream
380  */
381  friend inline std::ostream& operator<<(std::ostream& out, const JQuantile& quantile)
382  {
383  return quantile.print(out, getLongprint(out));
384  }
385 
386  protected:
387  /**
388  * Get quantile.
389  *
390  * \param __begin begin of data
391  * \param __end end of data
392  * \param W weight
393  * \return value
394  */
395  template<class T>
396  static double getQuantile(T __begin, T __end, const double W)
397  {
398  double w = 0.0;
399 
400  for (T i = __begin; i != __end; ++i) {
401 
402  w += i->second;
403 
404  if (w >= W) {
405  return i->first;
406  }
407  }
408 
409  THROW(JNoValue, "Invalid weight " << W);
410  }
411 
412 
413  bool quantiles;
414  double mean;
415  double sigma;
416  double total;
417  long long int count;
418  double xmin;
419  double xmax;
420  double wmin;
421  double wmax;
423  };
424 }
425 
426 #endif
data_type w[N+1][M+1]
Definition: JPolint.hh:778
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:109
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:381
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:696
Quantile_t
Options for evaluation of quantile.
Definition: JQuantile.hh:305
long long int count
Definition: JQuantile.hh:417
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 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:422
std::ostream & print(std::ostream &out, bool lpr=true) const
Print quantile.
Definition: JQuantile.hh:352
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
double getQuantile(const double Q, const Quantile_t option=forward_t) const
Get quantile.
Definition: JQuantile.hh:319
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:162
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:396
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