ROOT  6.06/09
Reference Guide
BinData.cxx
Go to the documentation of this file.
1 // @(#)root/mathcore:$Id$
2 // Author: L. Moneta Wed Aug 30 11:10:03 2006
3 
4 /**********************************************************************
5  * *
6  * Copyright (c) 2006 LCG ROOT Math Team, CERN/PH-SFT *
7  * *
8  * *
9  **********************************************************************/
10 
11 // Implementation file for class BinData
12 
13 #include "Fit/BinData.h"
14 #include "Math/Error.h"
15 
16 #include <cassert>
17 #include <cmath>
18 
19 
20 namespace ROOT {
21 
22  namespace Fit {
23 
24  /**
25  */
26 
27 BinData::BinData(unsigned int maxpoints , unsigned int dim , ErrorType err ) :
28 // constructor from dimension of point and max number of points (to pre-allocate vector)
29 // Give a zero value and then use Initialize later one if the size is not known
30  FitData(),
31  fDim(dim),
32  fPointSize(GetPointSize(err,dim) ),
33  fNPoints(0),
34  fSumContent(0),
35  fSumError2(0),
36  fRefVolume(1.0),
37  fDataVector(0),
38  fDataWrapper(0)
39 {
40  unsigned int n = fPointSize*maxpoints;
41  if ( n > MaxSize() )
42  MATH_ERROR_MSGVAL("BinData","Invalid data size n - no allocation done", n )
43  else if (n > 0)
44  fDataVector = new DataVector(n);
45 }
46 
47 BinData::BinData (const DataOptions & opt, unsigned int maxpoints, unsigned int dim, ErrorType err ) :
48 // constructor from option and default range
49  // DataVector( opt, (dim+2)*maxpoints ),
50  FitData(opt),
51  fDim(dim),
52  fPointSize(GetPointSize(err,dim) ),
53  fNPoints(0),
54  fSumContent(0),
55  fSumError2(0),
56  fRefVolume(1.0),
57  fDataVector(0),
58  fDataWrapper(0)
59 {
60  unsigned int n = fPointSize*maxpoints;
61  if ( n > MaxSize() )
62  MATH_ERROR_MSGVAL("BinData","Invalid data size n - no allocation done", n )
63  else if (n > 0)
64  fDataVector = new DataVector(n);
65 }
66 
67  /**
68  */
69 BinData::BinData (const DataOptions & opt, const DataRange & range, unsigned int maxpoints , unsigned int dim , ErrorType err ) :
70 // constructor from options and range
71 // default is 1D and value errors
72 
73  //DataVector( opt, range, (dim+2)*maxpoints ),
74  FitData(opt,range),
75  fDim(dim),
76  fPointSize(GetPointSize(err,dim) ),
77  fNPoints(0),
78  fSumContent(0),
79  fSumError2(0),
80  fRefVolume(1.0),
81  fDataVector(0),
82  fDataWrapper(0)
83 {
84  unsigned int n = fPointSize*maxpoints;
85  if ( n > MaxSize() )
86  MATH_ERROR_MSGVAL("BinData","Invalid data size n - no allocation done", n )
87  else if (n > 0)
88  fDataVector = new DataVector(n);
89 }
90 
91 /** constructurs using external data */
92 
93  /**
94  */
95 BinData::BinData(unsigned int n, const double * dataX, const double * val, const double * ex , const double * eval ) :
96 // constructor from external data for 1D with errors on coordinate and value
97  fDim(1),
98  fPointSize(2),
99  fNPoints(n),
100  fSumContent(0),
101  fSumError2(0),
102  fRefVolume(1.0),
103  fDataVector(0)
104 {
105  if (eval != 0) {
106  fPointSize++;
107  if (ex != 0) fPointSize++;
108  }
109  fDataWrapper = new DataWrapper(dataX, val, eval, ex);
110 }
111 
112 
113  /**
114 
115  */
116 BinData::BinData(unsigned int n, const double * dataX, const double * dataY, const double * val, const double * ex , const double * ey, const double * eval ) :
117 // constructor from external data for 2D with errors on coordinate and value
118  fDim(2),
119  fPointSize(3),
120  fNPoints(n),
121  fSumContent(0),
122  fSumError2(0),
123  fRefVolume(1.0),
124  fDataVector(0)
125 {
126  if (eval != 0) {
127  fPointSize++;
128  if (ex != 0 && ey != 0 ) fPointSize += 2;
129  }
130  fDataWrapper = new DataWrapper(dataX, dataY, val, eval, ex, ey);
131 }
132 
133  /**
134  */
135 BinData::BinData(unsigned int n, const double * dataX, const double * dataY, const double * dataZ, const double * val, const double * ex , const double * ey , const double * ez , const double * eval ) :
136 // constructor from external data for 3D with errors on coordinate and value
137  fDim(3),
138  fPointSize(4),
139  fNPoints(n),
140  fSumContent(0),
141  fSumError2(0),
142  fRefVolume(1.0),
143  fDataVector(0)
144 {
145  if (eval != 0) {
146  fPointSize++;
147  if (ex != 0 && ey != 0 && ez != 0) fPointSize += 3;
148  }
149  fDataWrapper = new DataWrapper(dataX, dataY, dataZ, val, eval, ex, ey, ez);
150 }
151 
152 
153  /// copy constructor
154 BinData::BinData(const BinData & rhs) :
155  FitData(rhs.Opt(), rhs.Range()),
156  fDim(rhs.fDim),
157  fPointSize(rhs.fPointSize),
158  fNPoints(rhs.fNPoints),
159  fSumContent(rhs.fSumContent),
160  fSumError2(rhs.fSumError2),
161  fRefVolume(rhs.fRefVolume),
162  fDataVector(0),
163  fDataWrapper(0),
164  fBinEdge(rhs.fBinEdge)
165 {
166  // copy constructor (copy data vector or just the pointer)
167  if (rhs.fDataVector != 0) fDataVector = new DataVector(*rhs.fDataVector);
168  else if (rhs.fDataWrapper != 0) fDataWrapper = new DataWrapper(*rhs.fDataWrapper);
169 }
170 
171 
172 
174  // assignment operator
175 
176  // copy options but cannot copy range since cannot be modified afterwards
177  DataOptions & opt = Opt();
178  opt = rhs.Opt();
179  //t.b.c
180  //DataRange & range = Range();
181  //range = rhs.Range();
182  //
183  // assignment operator
184  if (&rhs == this) return *this;
185  fDim = rhs.fDim;
186  fPointSize = rhs.fPointSize;
187  fNPoints = rhs.fNPoints;
188  fSumContent = rhs.fSumContent;
189  fSumError2 = rhs.fSumError2;
190  fBinEdge = rhs.fBinEdge;
191  fRefVolume = rhs.fRefVolume;
192  // delete previous pointers
193  if (fDataVector) delete fDataVector;
194  if (fDataWrapper) delete fDataWrapper;
195  if (rhs.fDataVector != 0)
196  fDataVector = new DataVector(*rhs.fDataVector);
197  else
198  fDataVector = 0;
199  if (rhs.fDataWrapper != 0)
201  else
202  fDataWrapper = 0;
203 
204  return *this;
205 }
206 
207 
208 
210  // destructor
211  if (fDataVector) delete fDataVector;
212  if (fDataWrapper) delete fDataWrapper;
213 }
214 
215 void BinData::Initialize(unsigned int maxpoints, unsigned int dim , ErrorType err ) {
216 // preallocate a data set given size and dimension
217 // need to be initialized with the right dimension before
218  if (fDataWrapper) delete fDataWrapper;
219  fDataWrapper = 0;
220  unsigned int pointSize = GetPointSize(err,dim);
221  if ( pointSize != fPointSize && fDataVector) {
222 // MATH_INFO_MSGVAL("BinData::Initialize"," Reset amd re-initialize with a new fit point size of ",
223 // pointSize);
224  delete fDataVector;
225  fDataVector = 0;
226  }
227  fPointSize = pointSize;
228  fDim = dim;
229  unsigned int n = fPointSize*maxpoints;
230  if ( n > MaxSize() ) {
231  MATH_ERROR_MSGVAL("BinData::Initialize"," Invalid data size ", n );
232  return;
233  }
234  if (fDataVector) {
235  // resize vector by adding the extra points on top of the previously existing ones
236  (fDataVector->Data()).resize( fDataVector->Size() + n);
237  }
238  else {
239  fDataVector = new DataVector(n);
240  }
241  // reserve space for bin width in case of integral options
242  if (Opt().fIntegral) fBinEdge.reserve( maxpoints * fDim);
243 }
244 
245 void BinData::Resize(unsigned int npoints) {
246  // resize vector to new points
247  if (fPointSize == 0) return;
248  if ( npoints > MaxSize() ) {
249  MATH_ERROR_MSGVAL("BinData::Resize"," Invalid data size ", npoints );
250  return;
251  }
252  int nextraPoints = npoints - DataSize()/ fPointSize;
253  if (nextraPoints == 0) return;
254  else if (nextraPoints < 0) {
255  // delete extra points
256  if (!fDataVector) return;
257  (fDataVector->Data()).resize( npoints * fPointSize);
258  }
259  else
260  Initialize(nextraPoints, fDim, GetErrorType() );
261 }
262  /**
263  */
264 void BinData::Add(double x, double y ) {
265 // add one dim data with only coordinate and values
266  int index = fNPoints*PointSize();
267  assert (fDataVector != 0);
268  assert (PointSize() == 2 );
269  assert (index + PointSize() <= DataSize() );
270 
271  double * itr = &((fDataVector->Data())[ index ]);
272  *itr++ = x;
273  *itr++ = y;
274 
275  fNPoints++;
276  fSumContent += y;
277 }
278 
279  /**
280  */
281 void BinData::Add(double x, double y, double ey) {
282 // add one dim data with no error in x
283 // in this case store the inverse of the error in y
284  int index = fNPoints*PointSize();
285 
286  assert( fDim == 1);
287  assert (fDataVector != 0);
288  assert (PointSize() == 3 );
289  assert (index + PointSize() <= DataSize() );
290 
291  double * itr = &((fDataVector->Data())[ index ]);
292  *itr++ = x;
293  *itr++ = y;
294  *itr++ = (ey!= 0) ? 1.0/ey : 0;
295 
296  fNPoints++;
297  fSumContent += y;
298  fSumError2 += ey*ey;
299 }
300 
301  /**
302  */
303 void BinData::Add(double x, double y, double ex, double ey) {
304 // add one dim data with error in x
305 // in this case store the y error and not the inverse
306  int index = fNPoints*PointSize();
307  assert (fDataVector != 0);
308  assert( fDim == 1);
309  assert (PointSize() == 4 );
310  assert (index + PointSize() <= DataSize() );
311 
312  double * itr = &((fDataVector->Data())[ index ]);
313  *itr++ = x;
314  *itr++ = y;
315  *itr++ = ex;
316  *itr++ = ey;
317 
318  fNPoints++;
319  fSumContent += y;
320  fSumError2 += ey*ey;
321 }
322 
323  /**
324  */
325 void BinData::Add(double x, double y, double ex, double eyl , double eyh) {
326 // add one dim data with error in x and asymmetric errors in y
327 // in this case store the y errors and not the inverse
328  int index = fNPoints*PointSize();
329  assert (fDataVector != 0);
330  assert( fDim == 1);
331  assert (PointSize() == 5 );
332  assert (index + PointSize() <= DataSize() );
333 
334  double * itr = &((fDataVector->Data())[ index ]);
335  *itr++ = x;
336  *itr++ = y;
337  *itr++ = ex;
338  *itr++ = eyl;
339  *itr++ = eyh;
340 
341  fNPoints++;
342  fSumContent += y;
343  fSumError2 += (eyl+eyh)*(eyl+eyh)/4;
344 }
345 
346 
347  /**
348  */
349 void BinData::Add(const double *x, double val) {
350 // add multi dim data with only value (no errors)
351  int index = fNPoints*PointSize();
352  assert (fDataVector != 0);
353  assert (PointSize() == fDim + 1 );
354 
355  if (index + PointSize() > DataSize())
356  MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
357 
358  assert (index + PointSize() <= DataSize() );
359 
360  double * itr = &((fDataVector->Data())[ index ]);
361 
362  for (unsigned int i = 0; i < fDim; ++i)
363  *itr++ = x[i];
364  *itr++ = val;
365 
366  fNPoints++;
367  fSumContent += val;
368 }
369 
370  /**
371  */
372 void BinData::Add(const double *x, double val, double eval) {
373 // add multi dim data with only error in value
374  int index = fNPoints*PointSize();
375  assert (fDataVector != 0);
376  assert (PointSize() == fDim + 2 );
377 
378  if (index + PointSize() > DataSize())
379  MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
380 
381  assert (index + PointSize() <= DataSize() );
382 
383  double * itr = &((fDataVector->Data())[ index ]);
384 
385  for (unsigned int i = 0; i < fDim; ++i)
386  *itr++ = x[i];
387  *itr++ = val;
388  *itr++ = (eval!= 0) ? 1.0/eval : 0;
389 
390  fNPoints++;
391  fSumContent += val;
392  fSumError2 += eval*eval;
393 }
394 
395 
396  /**
397  */
398 void BinData::Add(const double *x, double val, const double * ex, double eval) {
399  // add multi dim data with error in coordinates and value
400  int index = fNPoints*PointSize();
401  assert (fDataVector != 0);
402  assert (PointSize() == 2*fDim + 2 );
403 
404  if (index + PointSize() > DataSize())
405  MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
406 
407  assert (index + PointSize() <= DataSize() );
408 
409  double * itr = &((fDataVector->Data())[ index ]);
410 
411  for (unsigned int i = 0; i < fDim; ++i)
412  *itr++ = x[i];
413  *itr++ = val;
414  for (unsigned int i = 0; i < fDim; ++i)
415  *itr++ = ex[i];
416  *itr++ = eval;
417 
418  fNPoints++;
419  fSumContent += val;
420  fSumError2 += eval*eval;
421 }
422 
423  /**
424  */
425 void BinData::Add(const double *x, double val, const double * ex, double elval, double ehval) {
426  // add multi dim data with error in coordinates and asymmetric error in value
427  int index = fNPoints*PointSize();
428  assert (fDataVector != 0);
429  assert (PointSize() == 2*fDim + 3 );
430 
431  if (index + PointSize() > DataSize())
432  MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
433 
434  assert (index + PointSize() <= DataSize() );
435 
436  double * itr = &((fDataVector->Data())[ index ]);
437 
438  for (unsigned int i = 0; i < fDim; ++i)
439  *itr++ = x[i];
440  *itr++ = val;
441  for (unsigned int i = 0; i < fDim; ++i)
442  *itr++ = ex[i];
443  *itr++ = elval;
444  *itr++ = ehval;
445 
446  fNPoints++;
447  fSumContent += val;
448  fSumError2 += (elval+ehval)*(elval+ehval)/4;
449 }
450 
451 void BinData::AddBinUpEdge(const double *xup ) {
452 // add multi dim bin upper edge data (coord2)
453 
454  fBinEdge.insert( fBinEdge.end(), xup, xup + fDim);
455 
456  // check that is consistent with number of points added in the data
457  assert( fNPoints * fDim == fBinEdge.size() );
458 
459  // compute the bin volume
460  const double * xlow = Coords(fNPoints-1);
461 
462  double binVolume = 1;
463  for (unsigned int j = 0; j < fDim; ++j) {
464  binVolume *= (xup[j]-xlow[j]);
465  }
466 
467  // store the minimum bin volume found as reference for future normalizations
468  if (fNPoints == 1) {
469  fRefVolume = binVolume;
470  return;
471  }
472 
473  if (binVolume < fRefVolume)
474  fRefVolume = binVolume;
475 
476 }
477 
478 
480  // apply log transform on the bin data values
481 
482  if (fNPoints == 0) return *this;
483 
484  if (fDataVector) {
485 
487 
488  std::vector<double> & data = fDataVector->Data();
489 
490  typedef std::vector<double>::iterator DataItr;
491  unsigned int ip = 0;
492  DataItr itr = data.begin();
493 
494  if (type == kNoError ) {
495  fPointSize = fDim + 2;
496  }
497 
498  fSumContent = 0;
499  fSumError2 = 0;
500  while (ip < fNPoints ) {
501  assert( itr != data.end() );
502  DataItr valitr = itr + fDim;
503  double val = *(valitr);
504  if (val <= 0) {
505  MATH_ERROR_MSG("BinData::TransformLog","Some points have negative values - cannot apply a log transformation");
506  // return an empty data-sets
507  Resize(0);
508  return *this;
509  }
510  *(valitr) = std::log(val);
511  fSumContent += *(valitr);
512  // change also errors to 1/val * err
513  if (type == kNoError ) {
514  // insert new error value
515  DataItr errpos = data.insert(valitr+1,val);
516  // need to get new iterators for right position
517  itr = errpos - fDim -1;
518  //std::cout << " itr " << *(itr) << " itr +1 " << *(itr+1) << std::endl;
519  }
520  else if (type == kValueError) {
521  // new weight = val * old weight
522  *(valitr+1) *= val;
523  double invErr = *(valitr+1);
524  fSumError2 += 1./(invErr*invErr);
525  }
526  else {
527  // other case (error in value is stored) : new error = old_error/value
528  for (unsigned int j = 2*fDim + 1; j < fPointSize; ++j) {
529  *(itr+j) /= val;
530  }
531  double err = 0;
532  if (type != kAsymError)
533  err = *(itr+2*fDim+1);
534  else
535  err = 0.5 * ( *(itr+2*fDim+1) + *(itr+2*fDim+2) );
536  fSumError2 += err*err;
537  }
538  itr += fPointSize;
539  ip++;
540  }
541  // in case of Noerror since we added the errors we have changes the type
542  return *this;
543  }
544  // case of data wrapper - we copy the data and build a datavector
545  if (fDataWrapper == 0) return *this;
546 
547  // asym errors are not supported for data wrapper
549  std::vector<double> errx;
550  if (fDataWrapper->CoordErrors(0) != 0 ) {
551  type = kCoordError;
552  errx.resize(fDim); // allocate vector to store errors
553  }
554 
555  BinData tmpData(fNPoints, fDim, type);
556  for (unsigned int i = 0; i < fNPoints; ++i ) {
557  double val = fDataWrapper->Value(i);
558  if (val <= 0) {
559  MATH_ERROR_MSG("BinData::TransformLog","Some points have negative values - cannot apply a log transformation");
560  // return an empty data-sets
561  Resize(0);
562  return *this;
563  }
564  double err = fDataWrapper->Error(i);
565  if (err <= 0) err = 1;
566  if (type == kValueError )
567  tmpData.Add(fDataWrapper->Coords(i), std::log(val), err/val);
568  else if (type == kCoordError) {
569  const double * exold = fDataWrapper->CoordErrors(i);
570  assert(exold != 0);
571  for (unsigned int j = 0; j < fDim; ++j) {
572  std::cout << " j " << j << " val " << val << " " << errx.size() << std::endl;
573  errx[j] = exold[j]/val;
574  }
575  tmpData.Add(fDataWrapper->Coords(i), std::log(val), &errx.front(), err/val);
576  }
577  }
578  delete fDataWrapper;
579  fDataWrapper = 0; // no needed anymore
580  *this = tmpData;
581  return *this;
582 }
583 
584 
585  } // end namespace Fit
586 
587 } // end namespace ROOT
588 
ErrorType GetErrorType() const
Definition: BinData.h:75
void Initialize(unsigned int maxpoints, unsigned int dim=1, ErrorType err=kValueError)
preallocate a data set with given size , dimension and error type (to get the full point size) If the...
Definition: BinData.cxx:215
Namespace for new ROOT classes and functions.
Definition: ROOT.py:1
double Value(unsigned int ipoint) const
Definition: DataVector.h:363
#define assert(cond)
Definition: unittest.h:542
Base class for all the fit data types.
Definition: DataVector.h:67
const double * Coords(unsigned int ipoint) const
Definition: DataVector.h:332
void AddBinUpEdge(const double *xup)
add the bin width data, a pointer to an array with the bin upper edge information.
Definition: BinData.cxx:451
DataWrapper * fDataWrapper
Definition: BinData.h:528
BinData & operator=(const BinData &)
assignment operator
Definition: BinData.cxx:173
#define MATH_ERROR_MSGVAL(loc, str, x)
Definition: Error.h:69
const FData & Data() const
const access to underlying vector
Definition: DataVector.h:163
unsigned int fDim
Definition: BinData.h:520
Double_t x[n]
Definition: legend1.C:17
class holding the fit data points.
Definition: DataVector.h:134
const double * CoordErrors(unsigned int ipoint) const
Definition: DataVector.h:348
unsigned int PointSize() const
return the size of a fit point (is the coordinate dimension + 1 for the value and eventually the numb...
Definition: BinData.h:150
DataVector * fDataVector
Definition: BinData.h:527
double fSumError2
Definition: BinData.h:524
double fSumContent
Definition: BinData.h:523
unsigned int DataSize() const
return the size of internal data (number of fit points) if data are not copied in but used externally...
Definition: BinData.h:158
#define MATH_ERROR_MSG(loc, str)
Definition: Error.h:50
class maintaining a pointer to external data Using this class avoids copying the data when performing...
Definition: DataVector.h:222
DataOptions : simple structure holding the options on how the data are filled.
Definition: DataOptions.h:28
double fRefVolume
Definition: BinData.h:525
const double * Coords(unsigned int ipoint) const
return a pointer to the coordinates data for the given fit point
Definition: BinData.h:226
virtual ~BinData()
destructor
Definition: BinData.cxx:209
Class describing the binned data sets : vectors of x coordinates, y values and optionally error on y ...
Definition: BinData.h:61
void Resize(unsigned int npoints)
resize the vector to the new given npoints if vector does not exists is created using existing point ...
Definition: BinData.cxx:245
BinData(unsigned int maxpoints=0, unsigned int dim=1, ErrorType err=kValueError)
constructor from dimension of point and max number of points (to pre-allocate vector) Give a zero val...
Definition: BinData.cxx:27
class describing the range in the coordinates it supports multiple range in a coordinate.
Definition: DataRange.h:34
void Add(double x, double y)
add one dim data with only coordinate and values
Definition: BinData.cxx:264
TFitResultPtr Fit(FitObject *h1, TF1 *f1, Foption_t &option, const ROOT::Math::MinimizerOptions &moption, const char *goption, ROOT::Fit::DataRange &range)
Definition: HFitImpl.cxx:132
int type
Definition: TGX11.cxx:120
Double_t y[n]
Definition: legend1.C:17
Double_t ey[n]
Definition: legend1.C:17
BinData & LogTransform()
apply a Log transformation of the data values can be used for example when fitting an exponential or ...
Definition: BinData.cxx:479
size_t Size() const
full size of data vector (npoints * point size)
Definition: DataVector.h:197
unsigned int fPointSize
Definition: BinData.h:521
double Error(unsigned int ipoint) const
Definition: DataVector.h:367
static unsigned int MaxSize()
define a max size to avoid allocating too large arrays
Definition: DataVector.h:111
Ta Range(0, 0, 1, 1)
const DataOptions & Opt() const
access to options
Definition: DataVector.h:97
static unsigned int GetPointSize(ErrorType err, unsigned int dim)
Definition: BinData.h:67
Double_t ex[n]
Definition: legend1.C:17
const Int_t n
Definition: legend1.C:16
unsigned int fNPoints
Definition: BinData.h:522
double log(double)
std::vector< double > fBinEdge
Definition: BinData.h:530