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