MnUserTransformation.cxx

Go to the documentation of this file.
00001 // @(#)root/minuit2:$Id: MnUserTransformation.cxx 35508 2010-09-21 08:23:57Z moneta $
00002 // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005  
00003 
00004 /**********************************************************************
00005  *                                                                    *
00006  * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
00007  *                                                                    *
00008  **********************************************************************/
00009 
00010 #include "Minuit2/MnUserTransformation.h"
00011 #include "Minuit2/MnUserCovariance.h"
00012 
00013 #include <algorithm>
00014 #include <stdio.h>
00015 #include <string> 
00016 #include <sstream> 
00017 
00018 namespace ROOT {
00019 
00020    namespace Minuit2 {
00021 
00022 
00023 class MnParStr {
00024 
00025 public:
00026 
00027    MnParStr(const std::string & name) : fName(name) {}
00028 
00029    ~MnParStr() {}
00030   
00031    bool operator()(const MinuitParameter& par) const {
00032 //      return (strcmp(par.Name(), fName) == 0);
00033       return par.GetName() == fName;  
00034    }
00035 
00036 private:
00037    const std::string & fName;
00038 };
00039 
00040 
00041 MnUserTransformation::MnUserTransformation(const std::vector<double>& par, const std::vector<double>& err) : fPrecision(MnMachinePrecision()), fParameters(std::vector<MinuitParameter>()), fExtOfInt(std::vector<unsigned int>()), fDoubleLimTrafo(SinParameterTransformation()),fUpperLimTrafo(SqrtUpParameterTransformation()), fLowerLimTrafo(SqrtLowParameterTransformation()), fCache(std::vector<double>()) {
00042    // constructor from a vector of parameter values and a vector of errors (step  sizes) 
00043    // class has as data member the transformation objects (all of the types), 
00044    // the std::vector of MinuitParameter objects and the vector with the index conversions from 
00045    // internal to external (fExtOfInt)
00046    
00047    fParameters.reserve(par.size());
00048    fExtOfInt.reserve(par.size());
00049    fCache.reserve(par.size());
00050 
00051    std::string parName;
00052    for(unsigned int i = 0; i < par.size(); i++) {
00053       std::ostringstream buf;
00054       buf << "p" << i;
00055       buf.str(parName);
00056       Add(parName, par[i], err[i]);
00057    }
00058 }
00059 
00060 //#ifdef MINUIT2_THREAD_SAFE
00061 //  this if a thread-safe implementation needed if want to share transformation object between the threads
00062 std::vector<double> MnUserTransformation::operator()(const MnAlgebraicVector& pstates ) const {
00063    // transform an internal  Minuit vector of internal values in a std::vector of external values 
00064    // fixed parameters will have their fixed values
00065    unsigned int n = pstates.size(); 
00066    // need to initialize to the stored (initial values) parameter  values for the fixed ones
00067    std::vector<double> pcache( fCache );
00068    for(unsigned int i = 0; i < n; i++) {
00069       if(fParameters[fExtOfInt[i]].HasLimits()) {
00070          pcache[fExtOfInt[i]] = Int2ext(i, pstates(i));
00071       } else {
00072          pcache[fExtOfInt[i]] = pstates(i);
00073       }
00074    }
00075    return pcache;
00076 }
00077 
00078 // #else
00079 // const std::vector<double> & MnUserTransformation::operator()(const MnAlgebraicVector& pstates) const {
00080 //    // transform an internal  Minuit vector of internal values in a std::vector of external values 
00081 //    // std::vector<double> Cache(pstates.size() );
00082 //    for(unsigned int i = 0; i < pstates.size(); i++) {
00083 //       if(fParameters[fExtOfInt[i]].HasLimits()) {
00084 //          fCache[fExtOfInt[i]] = Int2ext(i, pstates(i));
00085 //       } else {
00086 //          fCache[fExtOfInt[i]] = pstates(i);
00087 //       }
00088 //    }
00089    
00090 //    return fCache;
00091 // }
00092 // #endif
00093 
00094 double MnUserTransformation::Int2ext(unsigned int i, double val) const {
00095    // return external value from internal value for parameter i
00096    if(fParameters[fExtOfInt[i]].HasLimits()) {
00097       if(fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
00098          return fDoubleLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit(), fParameters[fExtOfInt[i]].LowerLimit());
00099       else if(fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
00100          return fUpperLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit());
00101       else
00102          return fLowerLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].LowerLimit());
00103    }
00104    
00105    return val;
00106 }
00107 
00108 double MnUserTransformation::Int2extError(unsigned int i, double val, double err) const {
00109    // return external error from internal error for parameter i
00110 
00111    //err = sigma Value == sqrt(cov(i,i))
00112    double dx = err;
00113    
00114    if(fParameters[fExtOfInt[i]].HasLimits()) {
00115       double ui = Int2ext(i, val);
00116       double du1 = Int2ext(i, val+dx) - ui;
00117       double du2 = Int2ext(i, val-dx) - ui;
00118       if(fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit()) {
00119          //       double al = fParameters[fExtOfInt[i]].Lower();
00120          //       double ba = fParameters[fExtOfInt[i]].Upper() - al;
00121          //       double du1 = al + 0.5*(sin(val + dx) + 1.)*ba - ui;
00122          //       double du2 = al + 0.5*(sin(val - dx) + 1.)*ba - ui;
00123          //       if(dx > 1.) du1 = ba;
00124          if(dx > 1.) du1 = fParameters[fExtOfInt[i]].UpperLimit() - fParameters[fExtOfInt[i]].LowerLimit();
00125          dx = 0.5*(fabs(du1) + fabs(du2));
00126       } else {
00127          dx = 0.5*(fabs(du1) + fabs(du2));
00128       }
00129    }
00130    
00131    return dx;
00132 }
00133 
00134 MnUserCovariance MnUserTransformation::Int2extCovariance(const MnAlgebraicVector& vec, const MnAlgebraicSymMatrix& cov) const {
00135    // return the external covariance matrix from the internal error matrix and the internal parameter value
00136    // the vector of internal parameter is needed for the derivaties (Jacobian of the transformation)
00137    // Vext(i,j) = Vint(i,j) * dPext(i)/dPint(i) * dPext(j)/dPint(j) 
00138    
00139    MnUserCovariance result(cov.Nrow());
00140    for(unsigned int i = 0; i < vec.size(); i++) {
00141       double dxdi = 1.;
00142       if(fParameters[fExtOfInt[i]].HasLimits()) {
00143          //       dxdi = 0.5*fabs((fParameters[fExtOfInt[i]].Upper() - fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
00144          dxdi = DInt2Ext(i, vec(i));
00145       }
00146       for(unsigned int j = i; j < vec.size(); j++) {
00147          double dxdj = 1.;
00148          if(fParameters[fExtOfInt[j]].HasLimits()) {
00149             //  dxdj = 0.5*fabs((fParameters[fExtOfInt[j]].Upper() - fParameters[fExtOfInt[j]].Lower())*cos(vec(j)));
00150             dxdj = DInt2Ext(j, vec(j));
00151          }
00152          result(i,j) = dxdi*cov(i,j)*dxdj;
00153       }
00154       //     double diag = Int2extError(i, vec(i), sqrt(cov(i,i)));
00155       //     result(i,i) = diag*diag;
00156    }
00157    
00158    return result;
00159 }
00160 
00161 double MnUserTransformation::Ext2int(unsigned int i, double val) const {
00162    // return the external value for parameter i with value val
00163    
00164    if(fParameters[i].HasLimits()) {
00165       if(fParameters[i].HasUpperLimit() && fParameters[i].HasLowerLimit())
00166          return fDoubleLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), fParameters[i].LowerLimit(), Precision());
00167       else if(fParameters[i].HasUpperLimit() && !fParameters[i].HasLowerLimit())
00168          return fUpperLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), Precision());
00169       else 
00170          return fLowerLimTrafo.Ext2int(val, fParameters[i].LowerLimit(), Precision());
00171    }
00172    
00173    return val;
00174 }
00175 
00176 double MnUserTransformation::DInt2Ext(unsigned int i, double val) const {
00177    // return the derivative of the int->ext transformation: dPext(i) / dPint(i)
00178    // for the parameter i with value val
00179 
00180    double dd = 1.;
00181    if(fParameters[fExtOfInt[i]].HasLimits()) {
00182       if(fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())  
00183          //       dd = 0.5*fabs((fParameters[fExtOfInt[i]].Upper() - fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
00184          dd = fDoubleLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit(), fParameters[fExtOfInt[i]].LowerLimit());
00185       else if(fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
00186          dd = fUpperLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit());
00187       else 
00188          dd = fLowerLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].LowerLimit());
00189    }
00190    
00191    return dd;
00192 }
00193 
00194 /*
00195  double MnUserTransformation::dExt2Int(unsigned int, double) const {
00196     double dd = 1.;
00197     
00198     if(fParameters[fExtOfInt[i]].HasLimits()) {
00199        if(fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())  
00200           //       dd = 0.5*fabs((fParameters[fExtOfInt[i]].Upper() - fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
00201           dd = fDoubleLimTrafo.dExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit(), fParameters[fExtOfInt[i]].LowerLimit());
00202        else if(fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
00203           dd = fUpperLimTrafo.dExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit());
00204        else 
00205           dd = fLowerLimTrafo.dExtInt(val, fParameters[fExtOfInt[i]].LowerLimit());
00206     }
00207     
00208     return dd;
00209  }
00210  */
00211 
00212 unsigned int MnUserTransformation::IntOfExt(unsigned int ext) const {
00213    // return internal index given external one ext
00214    assert(ext < fParameters.size());
00215    assert(!fParameters[ext].IsFixed());
00216    assert(!fParameters[ext].IsConst());
00217    std::vector<unsigned int>::const_iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), ext);
00218    assert(iind != fExtOfInt.end());
00219    
00220    return (iind - fExtOfInt.begin());  
00221 }
00222 
00223 std::vector<double> MnUserTransformation::Params() const {
00224    // return std::vector of double with parameter values 
00225    unsigned int n = fParameters.size(); 
00226    std::vector<double> result(n);
00227    for(unsigned int i = 0; i < n; ++i) 
00228       result[i] = fParameters[i].Value(); 
00229    
00230    return result;
00231 }
00232 
00233 std::vector<double> MnUserTransformation::Errors() const {
00234    // return std::vector of double with parameter errors
00235    std::vector<double> result; result.reserve(fParameters.size());
00236    for(std::vector<MinuitParameter>::const_iterator ipar = Parameters().begin();
00237        ipar != Parameters().end(); ipar++)
00238       result.push_back((*ipar).Error());
00239    
00240    return result;
00241 }
00242 
00243 const MinuitParameter& MnUserTransformation::Parameter(unsigned int n) const {
00244    // return the MinuitParameter object for index n (external)
00245    assert(n < fParameters.size()); 
00246    return fParameters[n];
00247 }
00248 
00249 // bool MnUserTransformation::Remove(const std::string & name) { 
00250 //    // remove parameter with name 
00251 //    // useful if want to re-define a parameter
00252 //    // return false if parameter does not exist
00253 //    std::vector<MinuitParameter>::iterator itr = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name) );
00254 //    if (itr == fParameters.end() ) return false; 
00255 //    int n = itr - fParameters.begin(); 
00256 //    if (n < 0 || n >= fParameters.size() ) return false; 
00257 //    fParameters.erase(itr);
00258 //    fCache.erase( fExtOfInt.begin() + n); 
00259 //    std::vector<unsigned int>::iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
00260 //    if (iind != fExtOfInt.end()) fExtOfInt.erase(iind);
00261 // }
00262 
00263 bool MnUserTransformation::Add(const std::string & name, double val, double err) {
00264    // add a new unlimited parameter giving name, value and err (step size)
00265    // return false if parameter already exists
00266    if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end() ) 
00267       return false; 
00268    fExtOfInt.push_back(fParameters.size());
00269    fCache.push_back(val);
00270    fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err));
00271    return true;
00272 }
00273 
00274 bool MnUserTransformation::Add(const std::string & name, double val, double err, double low, double up) {
00275    // add a new limited parameter giving name, value, err (step size) and lower/upper limits
00276    // return false if parameter already exists
00277    if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end() ) 
00278       return false; 
00279    fExtOfInt.push_back(fParameters.size());
00280    fCache.push_back(val);
00281    fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err, low, up));
00282    return true;
00283 }
00284 
00285 bool MnUserTransformation::Add(const std::string & name, double val) {
00286    // add a new constant parameter giving name and value
00287    // return false if parameter already exists
00288    if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end() ) 
00289       return false; 
00290    fCache.push_back(val);
00291    // costant parameter - do not add in list of internals (fExtOfInt)
00292    fParameters.push_back(MinuitParameter(fParameters.size(), name, val));
00293    return true;
00294 }
00295 
00296 void MnUserTransformation::Fix(unsigned int n) {
00297   // fix parameter n (external index)
00298    assert(n < fParameters.size()); 
00299    std::vector<unsigned int>::iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
00300    if (iind != fExtOfInt.end())
00301       fExtOfInt.erase(iind, iind+1);
00302    fParameters[n].Fix();
00303 }
00304 
00305 void MnUserTransformation::Release(unsigned int n) {
00306    // release parameter n (external index)
00307    assert(n < fParameters.size()); 
00308    std::vector<unsigned int>::const_iterator iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
00309    if (iind == fExtOfInt.end() ) { 
00310       fExtOfInt.push_back(n);
00311       std::sort(fExtOfInt.begin(), fExtOfInt.end());
00312    }
00313    fParameters[n].Release();
00314 }
00315 
00316 void MnUserTransformation::SetValue(unsigned int n, double val) {
00317    // set value for parameter n (external index)
00318    assert(n < fParameters.size()); 
00319    fParameters[n].SetValue(val);
00320    fCache[n] = val;
00321 }
00322 
00323 void MnUserTransformation::SetError(unsigned int n, double err) {
00324    // set error for parameter n (external index)
00325    assert(n < fParameters.size()); 
00326    fParameters[n].SetError(err);
00327 }
00328 
00329 void MnUserTransformation::SetLimits(unsigned int n, double low, double up) {
00330    // set limits (lower/upper) for parameter n (external index)
00331    assert(n < fParameters.size());
00332    assert(low != up);
00333    fParameters[n].SetLimits(low, up);
00334 }
00335 
00336 void MnUserTransformation::SetUpperLimit(unsigned int n, double up) {
00337    // set upper limit for parameter n (external index)
00338    assert(n < fParameters.size()); 
00339    fParameters[n].SetUpperLimit(up);
00340 }
00341 
00342 void MnUserTransformation::SetLowerLimit(unsigned int n, double lo) {
00343    // set lower limit for parameter n (external index)
00344    assert(n < fParameters.size()); 
00345    fParameters[n].SetLowerLimit(lo);
00346 }
00347 
00348 void MnUserTransformation::RemoveLimits(unsigned int n) {
00349    // remove limits for parameter n (external index)
00350    assert(n < fParameters.size()); 
00351    fParameters[n].RemoveLimits();
00352 }
00353 
00354 double MnUserTransformation::Value(unsigned int n) const {
00355    // get value for parameter n (external index)
00356    assert(n < fParameters.size()); 
00357    return fParameters[n].Value();
00358 }
00359 
00360 double MnUserTransformation::Error(unsigned int n) const {
00361    // get error for parameter n (external index)
00362    assert(n < fParameters.size()); 
00363    return fParameters[n].Error();
00364 }
00365 
00366 // interface by parameter name
00367 
00368 void MnUserTransformation::Fix(const std::string & name) {
00369    // fix parameter 
00370    Fix(Index(name));
00371 }
00372 
00373 void MnUserTransformation::Release(const std::string & name) {
00374    // release parameter 
00375    Release(Index(name));
00376 }
00377 
00378 void MnUserTransformation::SetValue(const std::string & name, double val) {
00379    // set value for parameter 
00380    SetValue(Index(name), val);
00381 }
00382 
00383 void MnUserTransformation::SetError(const std::string & name, double err) {
00384    // set error
00385    SetError(Index(name), err);
00386 }
00387 
00388 void MnUserTransformation::SetLimits(const std::string & name, double low, double up) {
00389    // set lower/upper limits
00390    SetLimits(Index(name), low, up);
00391 }
00392 
00393 void MnUserTransformation::SetUpperLimit(const std::string & name, double up) {
00394    // set upper limit
00395    SetUpperLimit(Index(name), up);
00396 }
00397 
00398 void MnUserTransformation::SetLowerLimit(const std::string & name, double lo) {
00399    // set lower limit
00400    SetLowerLimit(Index(name), lo);
00401 }
00402 
00403 void MnUserTransformation::RemoveLimits(const std::string & name) {
00404    // remove limits
00405    RemoveLimits(Index(name));
00406 }
00407 
00408 double MnUserTransformation::Value(const std::string & name) const {
00409    // get parameter value
00410    return Value(Index(name));
00411 }
00412 
00413 double MnUserTransformation::Error(const std::string & name) const {
00414    // get parameter error
00415    return Error(Index(name));
00416 }
00417 
00418 unsigned int MnUserTransformation::Index(const std::string & name) const {
00419    // get index (external) corresponding to name
00420    std::vector<MinuitParameter>::const_iterator ipar = 
00421    std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name));
00422    assert(ipar != fParameters.end());
00423    //   return (ipar - fParameters.begin());
00424    return (*ipar).Number();
00425 }
00426 
00427 int MnUserTransformation::FindIndex(const std::string & name) const {
00428    // find index (external) corresponding to name - return -1 if not found
00429    std::vector<MinuitParameter>::const_iterator ipar = 
00430    std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name));
00431    if (ipar == fParameters.end() ) return -1; 
00432    return (*ipar).Number();
00433 }
00434 
00435 
00436 const std::string & MnUserTransformation::GetName(unsigned int n) const {
00437    // get name corresponding to index (external)
00438    assert(n < fParameters.size()); 
00439    return fParameters[n].GetName();
00440 }
00441 
00442 const char* MnUserTransformation::Name(unsigned int n) const {
00443    // get name corresponding to index (external)
00444    return GetName(n).c_str();
00445 }
00446 
00447 
00448    }  // namespace Minuit2
00449 
00450 }  // namespace ROOT

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