BinData.cxx

Go to the documentation of this file.
00001 // @(#)root/mathcore:$Id: BinData.cxx 32166 2010-02-01 11:09:31Z moneta $
00002 // Author: L. Moneta Wed Aug 30 11:10:03 2006
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
00007  *                                                                    *
00008  *                                                                    *
00009  **********************************************************************/
00010 
00011 // Implementation file for class BinData
00012 
00013 #include "Fit/BinData.h"
00014 #include "Math/Error.h"
00015 
00016 #include <cassert> 
00017 #include <cmath>
00018 
00019 namespace ROOT { 
00020 
00021    namespace Fit { 
00022 
00023    /**
00024     */
00025 
00026 BinData::BinData(unsigned int maxpoints , unsigned int dim , ErrorType err ) : 
00027 //      constructor from dimension of point  and max number of points (to pre-allocate vector)
00028 //      Give a zero value and then use Initialize later one if the size is not known
00029    FitData(),
00030    fDim(dim),
00031    fPointSize(GetPointSize(err,dim) ),
00032    fNPoints(0),
00033    fRefVolume(1.0),
00034    fDataVector(0),
00035    fDataWrapper(0)
00036 { 
00037    unsigned int n = fPointSize*maxpoints; 
00038    if ( n > MaxSize() ) 
00039       MATH_ERROR_MSGVAL("BinData","Invalid data size n - no allocation done", n )
00040    else if (n > 0) 
00041       fDataVector = new DataVector(n);
00042 } 
00043 
00044 BinData::BinData (const DataOptions & opt, unsigned int maxpoints, unsigned int dim, ErrorType err ) : 
00045 //      constructor from option and default range
00046       // DataVector( opt, (dim+2)*maxpoints ), 
00047    FitData(opt),
00048    fDim(dim),
00049    fPointSize(GetPointSize(err,dim) ),
00050    fNPoints(0),
00051    fRefVolume(1.0),
00052    fDataVector(0),
00053    fDataWrapper(0)
00054 { 
00055    unsigned int n = fPointSize*maxpoints; 
00056    if ( n > MaxSize() ) 
00057       MATH_ERROR_MSGVAL("BinData","Invalid data size n - no allocation done", n )
00058    else if (n > 0) 
00059       fDataVector = new DataVector(n);
00060 } 
00061       
00062    /**
00063     */
00064 BinData::BinData (const DataOptions & opt, const DataRange & range, unsigned int maxpoints , unsigned int dim , ErrorType err  ) : 
00065 //      constructor from options and range
00066 //      default is 1D and value errors
00067 
00068       //DataVector( opt, range, (dim+2)*maxpoints ), 
00069    FitData(opt,range),
00070    fDim(dim),
00071    fPointSize(GetPointSize(err,dim) ),
00072    fNPoints(0),
00073    fRefVolume(1.0),
00074    fDataVector(0),
00075    fDataWrapper(0)
00076 { 
00077    unsigned int n = fPointSize*maxpoints; 
00078    if ( n > MaxSize() ) 
00079       MATH_ERROR_MSGVAL("BinData","Invalid data size n - no allocation done", n )
00080    else if (n > 0) 
00081       fDataVector = new DataVector(n);
00082 } 
00083       
00084 /** constructurs using external data */
00085    
00086    /**
00087     */
00088 BinData::BinData(unsigned int n, const double * dataX, const double * val, const double * ex , const double * eval ) : 
00089 //      constructor from external data for 1D with errors on  coordinate and value
00090    fDim(1), 
00091    fPointSize(2),
00092    fNPoints(n),
00093    fRefVolume(1.0),
00094    fDataVector(0)
00095 { 
00096    if (eval != 0) { 
00097       fPointSize++;
00098       if (ex != 0) fPointSize++;
00099    }
00100    fDataWrapper  = new DataWrapper(dataX, val, eval, ex);
00101 } 
00102 
00103    
00104    /**
00105 
00106     */
00107 BinData::BinData(unsigned int n, const double * dataX, const double * dataY, const double * val, const double * ex , const double * ey, const double * eval  ) : 
00108 //      constructor from external data for 2D with errors on  coordinate and value      
00109    fDim(2), 
00110    fPointSize(3),
00111    fNPoints(n),
00112    fRefVolume(1.0),
00113    fDataVector(0)
00114 { 
00115    if (eval != 0) { 
00116       fPointSize++;
00117       if (ex != 0 && ey != 0 ) fPointSize += 2;
00118    }
00119    fDataWrapper  = new DataWrapper(dataX, dataY, val, eval, ex, ey);
00120 } 
00121 
00122    /**
00123     */
00124 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   ) : 
00125 //      constructor from external data for 3D with errors on  coordinate and value
00126    fDim(3), 
00127    fPointSize(4),
00128    fNPoints(n),
00129    fRefVolume(1.0),
00130    fDataVector(0)
00131 { 
00132    if (eval != 0) { 
00133       fPointSize++;
00134       if (ex != 0 && ey != 0 && ez != 0) fPointSize += 3;
00135    }
00136    fDataWrapper  = new DataWrapper(dataX, dataY, dataZ, val, eval, ex, ey, ez);
00137 } 
00138 
00139 
00140    /// copy constructor 
00141 BinData::BinData(const BinData & rhs) : 
00142    FitData(), 
00143    fDim(rhs.fDim), 
00144    fPointSize(rhs.fPointSize), 
00145    fNPoints(rhs.fNPoints), 
00146    fRefVolume(1.0),
00147    fDataVector(0),
00148    fDataWrapper(0), 
00149    fBinEdge(rhs.fBinEdge)
00150 {
00151    // copy constructor (copy data vector or just the pointer)
00152    if (rhs.fDataVector != 0) fDataVector = new DataVector(*rhs.fDataVector);
00153    else if (rhs.fDataWrapper != 0) fDataWrapper = new DataWrapper(*rhs.fDataWrapper);
00154 }
00155 
00156 
00157 BinData & BinData::operator= (const BinData & rhs) { 
00158    // assignment operator  
00159    if (&rhs == this) return *this; 
00160    fDim = rhs.fDim;  
00161    fPointSize = rhs.fPointSize;  
00162    fNPoints = rhs.fNPoints;  
00163    fBinEdge = rhs.fBinEdge;
00164    fRefVolume = rhs.fRefVolume;
00165    // delete previous pointers 
00166    if (fDataVector) delete fDataVector; 
00167    if (fDataWrapper) delete fDataWrapper; 
00168    if (rhs.fDataVector != 0)  
00169       fDataVector = new DataVector(*rhs.fDataVector);
00170    else 
00171       fDataVector = 0; 
00172    if (rhs.fDataWrapper != 0) 
00173       fDataWrapper = new DataWrapper(*rhs.fDataWrapper);
00174    else 
00175       fDataWrapper = 0; 
00176 
00177    return *this; 
00178 } 
00179 
00180 
00181       
00182 BinData::~BinData() {
00183    // destructor 
00184    if (fDataVector) delete fDataVector; 
00185    if (fDataWrapper) delete fDataWrapper; 
00186 }
00187 
00188 void BinData::Initialize(unsigned int maxpoints, unsigned int dim , ErrorType err  ) { 
00189 //       preallocate a data set given size and dimension
00190 //       need to be initialized with the  right dimension before
00191    if (fDataWrapper) delete fDataWrapper;
00192    fDataWrapper = 0; 
00193    unsigned int pointSize = GetPointSize(err,dim);  
00194    if ( pointSize != fPointSize && fDataVector) { 
00195 //       MATH_INFO_MSGVAL("BinData::Initialize"," Reset amd re-initialize with a new fit point size of ",
00196 //                        pointSize);
00197       delete fDataVector; 
00198       fDataVector = 0; 
00199    }
00200    fPointSize = pointSize; 
00201    fDim = dim;
00202    unsigned int n = fPointSize*maxpoints; 
00203    if ( n > MaxSize() ) { 
00204       MATH_ERROR_MSGVAL("BinData::Initialize"," Invalid data size  ", n );
00205       return; 
00206    }
00207    if (fDataVector) { 
00208       // resize vector by adding the extra points on top of the previously existing ones 
00209       (fDataVector->Data()).resize( fDataVector->Size() + n);
00210    }
00211    else {
00212       fDataVector = new DataVector(n);
00213    }
00214    // reserve space for bin width in case of integral options
00215    if (Opt().fIntegral) fBinEdge.reserve( maxpoints * fDim);
00216 }
00217 
00218 void BinData::Resize(unsigned int npoints) { 
00219    // resize vector to new points 
00220    if (fPointSize == 0) return; 
00221    if ( npoints > MaxSize() ) { 
00222       MATH_ERROR_MSGVAL("BinData::Resize"," Invalid data size  ", npoints );
00223       return; 
00224    }
00225    int nextraPoints = npoints - DataSize()/ fPointSize;  
00226    if (nextraPoints == 0) return; 
00227    else if (nextraPoints < 0) {
00228       // delete extra points
00229       if (!fDataVector) return; 
00230       (fDataVector->Data()).resize( npoints * fPointSize);
00231    } 
00232    else 
00233       Initialize(nextraPoints, fDim, GetErrorType() ); 
00234 }
00235    /**
00236    */
00237 void BinData::Add(double x, double y ) { 
00238 //       add one dim data with only coordinate and values
00239    int index = fNPoints*PointSize();
00240    assert (fDataVector != 0);
00241    assert (PointSize() == 2 ); 
00242    assert (index + PointSize() <= DataSize() ); 
00243    
00244    double * itr = &((fDataVector->Data())[ index ]);
00245    *itr++ = x; 
00246    *itr++ = y; 
00247    
00248    fNPoints++;
00249 }
00250    
00251    /**
00252    */
00253 void BinData::Add(double x, double y, double ey) { 
00254 //       add one dim data with no error in x
00255 //       in this case store the inverse of the error in y
00256    int index = fNPoints*PointSize(); 
00257 
00258    assert( fDim == 1);
00259    assert (fDataVector != 0);
00260    assert (PointSize() == 3 ); 
00261    assert (index + PointSize() <= DataSize() ); 
00262    
00263    double * itr = &((fDataVector->Data())[ index ]);
00264    *itr++ = x; 
00265    *itr++ = y; 
00266    *itr++ =  (ey!= 0) ? 1.0/ey : 0; 
00267    
00268    fNPoints++;
00269 }
00270 
00271    /**
00272    */
00273 void BinData::Add(double x, double y, double ex, double ey) { 
00274 //      add one dim data with  error in x
00275 //      in this case store the y error and not the inverse 
00276    int index = fNPoints*PointSize(); 
00277    assert (fDataVector != 0);
00278    assert( fDim == 1);
00279    assert (PointSize() == 4 ); 
00280    assert (index + PointSize() <= DataSize() ); 
00281 
00282    double * itr = &((fDataVector->Data())[ index ]);
00283    *itr++ = x; 
00284    *itr++ = y; 
00285    *itr++ = ex; 
00286    *itr++ = ey; 
00287    
00288    fNPoints++;
00289 }
00290 
00291    /**
00292    */
00293 void BinData::Add(double x, double y, double ex, double eyl , double eyh) { 
00294 //      add one dim data with  error in x and asymmetric errors in y
00295 //      in this case store the y errors and not the inverse 
00296    int index = fNPoints*PointSize(); 
00297    assert (fDataVector != 0);
00298    assert( fDim == 1);
00299    assert (PointSize() == 5 ); 
00300    assert (index + PointSize() <= DataSize() ); 
00301    
00302    double * itr = &((fDataVector->Data())[ index ]);
00303    *itr++ = x; 
00304    *itr++ = y; 
00305    *itr++ = ex; 
00306    *itr++ = eyl; 
00307    *itr++ = eyh; 
00308    
00309    fNPoints++;
00310 }
00311 
00312 
00313    /**
00314    */
00315 void BinData::Add(const double *x, double val) { 
00316 //      add multi dim data with only value (no errors)
00317    int index = fNPoints*PointSize(); 
00318    assert (fDataVector != 0);
00319    assert (PointSize() == fDim + 1 ); 
00320    
00321    if (index + PointSize() > DataSize()) 
00322       MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
00323 
00324    assert (index + PointSize() <= DataSize() ); 
00325    
00326    double * itr = &((fDataVector->Data())[ index ]);
00327    
00328    for (unsigned int i = 0; i < fDim; ++i) 
00329       *itr++ = x[i]; 
00330    *itr++ = val; 
00331    
00332    fNPoints++;
00333 }
00334 
00335    /**
00336    */
00337 void BinData::Add(const double *x, double val, double  eval) { 
00338 //      add multi dim data with only error in value 
00339    int index = fNPoints*PointSize(); 
00340    assert (fDataVector != 0);
00341    assert (PointSize() == fDim + 2 ); 
00342    
00343    if (index + PointSize() > DataSize()) 
00344       MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
00345 
00346    assert (index + PointSize() <= DataSize() ); 
00347    
00348    double * itr = &((fDataVector->Data())[ index ]);
00349    
00350    for (unsigned int i = 0; i < fDim; ++i) 
00351       *itr++ = x[i]; 
00352    *itr++ = val; 
00353    *itr++ =  (eval!= 0) ? 1.0/eval : 0; 
00354    
00355    fNPoints++;
00356 }
00357 
00358 
00359    /**
00360    */
00361 void BinData::Add(const double *x, double val, const double * ex, double  eval) { 
00362    //      add multi dim data with error in coordinates and value 
00363    int index = fNPoints*PointSize(); 
00364    assert (fDataVector != 0);
00365    assert (PointSize() == 2*fDim + 2 ); 
00366    
00367    if (index + PointSize() > DataSize()) 
00368       MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
00369 
00370    assert (index + PointSize() <= DataSize() ); 
00371    
00372    double * itr = &((fDataVector->Data())[ index ]);
00373    
00374    for (unsigned int i = 0; i < fDim; ++i) 
00375       *itr++ = x[i]; 
00376    *itr++ = val; 
00377    for (unsigned int i = 0; i < fDim; ++i) 
00378       *itr++ = ex[i]; 
00379    *itr++ = eval; 
00380    
00381    fNPoints++;
00382 }
00383 
00384    /**
00385    */
00386 void BinData::Add(const double *x, double val, const double * ex, double  elval, double  ehval) { 
00387    //      add multi dim data with error in coordinates and asymmetric error in value
00388    int index = fNPoints*PointSize(); 
00389    assert (fDataVector != 0);
00390    assert (PointSize() == 2*fDim + 3 ); 
00391    
00392    if (index + PointSize() > DataSize()) 
00393       MATH_ERROR_MSGVAL("BinData::Add","add a point beyond the data size", DataSize() );
00394 
00395    assert (index + PointSize() <= DataSize() ); 
00396    
00397    double * itr = &((fDataVector->Data())[ index ]);
00398    
00399    for (unsigned int i = 0; i < fDim; ++i) 
00400       *itr++ = x[i]; 
00401    *itr++ = val; 
00402    for (unsigned int i = 0; i < fDim; ++i) 
00403       *itr++ = ex[i]; 
00404    *itr++ = elval; 
00405    *itr++ = ehval; 
00406    
00407    fNPoints++;
00408 }
00409 
00410 void BinData::AddBinUpEdge(const double *xup ) { 
00411 //      add multi dim bin upper edge data (coord2)
00412 
00413    fBinEdge.insert( fBinEdge.end(), xup, xup + fDim);
00414    
00415    // check that is consistent with number of points added in the data
00416    assert( fNPoints * fDim == fBinEdge.size() );
00417 
00418    // compute the bin volume 
00419    const double * xlow = Coords(fNPoints-1);
00420 
00421    double binVolume = 1;
00422    for (unsigned int j = 0; j < fDim; ++j) {
00423       binVolume *= (xup[j]-xlow[j]);
00424    }
00425       
00426    // store the minimum bin volume found as  reference for future normalizations
00427    if (fNPoints == 1) {
00428       fRefVolume = binVolume;
00429       return;
00430    }
00431 
00432    if (binVolume < fRefVolume) 
00433       fRefVolume = binVolume;
00434    
00435 }
00436 
00437 
00438 BinData & BinData::LogTransform() { 
00439    // apply log transform on the bin data values
00440 
00441    if (fNPoints == 0) return *this; 
00442 
00443    if (fDataVector) {       
00444 
00445       ErrorType type = GetErrorType(); 
00446 
00447       std::vector<double> & data = fDataVector->Data(); 
00448 
00449       typedef std::vector<double>::iterator DataItr; 
00450       unsigned int ip = 0;
00451       DataItr itr = data.begin();      
00452 
00453       if (type == kNoError ) { 
00454          fPointSize = fDim + 2;
00455       }
00456 
00457       while (ip <  fNPoints ) {     
00458          assert( itr != data.end() );
00459          DataItr valitr = itr + fDim; 
00460          double val = *(itr+fDim); 
00461          if (val <= 0) { 
00462             MATH_ERROR_MSG("BinData::TransformLog","Some points have negative values - cannot apply a log transformation");
00463             // return an empty data-sets
00464             Resize(0);
00465             return *this; 
00466          }
00467          *(itr+fDim) = std::log(val);
00468          // change also errors to 1/val * err
00469          if (type == kNoError ) { 
00470             // insert new error value 
00471             DataItr errpos = data.insert(itr+fDim+1,val); 
00472             // need to get new iterators for right position
00473             itr = errpos - fDim -1;
00474             //std::cout << " itr " << *(itr) << " itr +1 " << *(itr+1) << std::endl;
00475          }
00476          else if (type == kValueError) { 
00477              // new weight = val * old weight
00478             *(itr+fDim+1) *= val; 
00479          } 
00480          else {
00481             // other case (error in value is stored) : new error = old_error/value 
00482             for (unsigned int j = fDim + 1; j < fPointSize; ++j)  
00483                *(itr+j) /= val;  
00484          }
00485          itr += fPointSize; 
00486          ip++;
00487       }
00488       // in case of Noerror since we added the errors we have changes the type 
00489    return *this; 
00490    }
00491    // case of data wrapper - we copy the data and build a datavector
00492    if (fDataWrapper == 0) return *this; 
00493 
00494    // asym errors are not supported for data wrapper 
00495    ErrorType type = kValueError; 
00496    std::vector<double> errx; 
00497    if (fDataWrapper->CoordErrors(0) != 0 ) { 
00498       type = kCoordError; 
00499       errx.resize(fDim);  // allocate vector to store errors 
00500    }
00501 
00502    BinData tmpData(fNPoints, fDim, type); 
00503    for (unsigned int i = 0; i < fNPoints; ++i ) { 
00504       double val = fDataWrapper->Value(i);
00505       if (val <= 0) { 
00506          MATH_ERROR_MSG("BinData::TransformLog","Some points have negative values - cannot apply a log transformation");
00507          // return an empty data-sets
00508          Resize(0);
00509          return *this; 
00510       } 
00511       double err = fDataWrapper->Error(i); 
00512       if (err <= 0) err = 1;
00513       if (type == kValueError ) 
00514          tmpData.Add(fDataWrapper->Coords(i), std::log(val), err/val);
00515       else if (type == kCoordError) { 
00516          const double * exold = fDataWrapper->CoordErrors(i);
00517          assert(exold != 0);
00518          for (unsigned int j = 0; j < fDim; ++j) { 
00519             std::cout << " j " << j << " val " << val << " " << errx.size() <<  std::endl;
00520             errx[j] = exold[j]/val; 
00521          }
00522          tmpData.Add(fDataWrapper->Coords(i), std::log(val), &errx.front(),  err/val); 
00523       }                                            
00524    }
00525    delete fDataWrapper;
00526    fDataWrapper = 0; // no needed anymore
00527    *this = tmpData; 
00528    return *this; 
00529 }
00530 
00531    } // end namespace Fit
00532 
00533 } // end namespace ROOT
00534 

Generated on Tue Jul 5 14:33:21 2011 for ROOT_528-00b_version by  doxygen 1.5.1