00001
00002
00003
00004
00005
00006
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
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
00043
00044
00045
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
00061
00062 std::vector<double> MnUserTransformation::operator()(const MnAlgebraicVector& pstates ) const {
00063
00064
00065 unsigned int n = pstates.size();
00066
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
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 double MnUserTransformation::Int2ext(unsigned int i, double val) const {
00095
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
00110
00111
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
00120
00121
00122
00123
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
00136
00137
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
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
00150 dxdj = DInt2Ext(j, vec(j));
00151 }
00152 result(i,j) = dxdi*cov(i,j)*dxdj;
00153 }
00154
00155
00156 }
00157
00158 return result;
00159 }
00160
00161 double MnUserTransformation::Ext2int(unsigned int i, double val) const {
00162
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
00178
00179
00180 double dd = 1.;
00181 if(fParameters[fExtOfInt[i]].HasLimits()) {
00182 if(fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
00183
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
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 unsigned int MnUserTransformation::IntOfExt(unsigned int ext) const {
00213
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
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
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
00245 assert(n < fParameters.size());
00246 return fParameters[n];
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263 bool MnUserTransformation::Add(const std::string & name, double val, double err) {
00264
00265
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
00276
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
00287
00288 if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end() )
00289 return false;
00290 fCache.push_back(val);
00291
00292 fParameters.push_back(MinuitParameter(fParameters.size(), name, val));
00293 return true;
00294 }
00295
00296 void MnUserTransformation::Fix(unsigned int n) {
00297
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
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
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
00325 assert(n < fParameters.size());
00326 fParameters[n].SetError(err);
00327 }
00328
00329 void MnUserTransformation::SetLimits(unsigned int n, double low, double up) {
00330
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
00338 assert(n < fParameters.size());
00339 fParameters[n].SetUpperLimit(up);
00340 }
00341
00342 void MnUserTransformation::SetLowerLimit(unsigned int n, double lo) {
00343
00344 assert(n < fParameters.size());
00345 fParameters[n].SetLowerLimit(lo);
00346 }
00347
00348 void MnUserTransformation::RemoveLimits(unsigned int n) {
00349
00350 assert(n < fParameters.size());
00351 fParameters[n].RemoveLimits();
00352 }
00353
00354 double MnUserTransformation::Value(unsigned int n) const {
00355
00356 assert(n < fParameters.size());
00357 return fParameters[n].Value();
00358 }
00359
00360 double MnUserTransformation::Error(unsigned int n) const {
00361
00362 assert(n < fParameters.size());
00363 return fParameters[n].Error();
00364 }
00365
00366
00367
00368 void MnUserTransformation::Fix(const std::string & name) {
00369
00370 Fix(Index(name));
00371 }
00372
00373 void MnUserTransformation::Release(const std::string & name) {
00374
00375 Release(Index(name));
00376 }
00377
00378 void MnUserTransformation::SetValue(const std::string & name, double val) {
00379
00380 SetValue(Index(name), val);
00381 }
00382
00383 void MnUserTransformation::SetError(const std::string & name, double err) {
00384
00385 SetError(Index(name), err);
00386 }
00387
00388 void MnUserTransformation::SetLimits(const std::string & name, double low, double up) {
00389
00390 SetLimits(Index(name), low, up);
00391 }
00392
00393 void MnUserTransformation::SetUpperLimit(const std::string & name, double up) {
00394
00395 SetUpperLimit(Index(name), up);
00396 }
00397
00398 void MnUserTransformation::SetLowerLimit(const std::string & name, double lo) {
00399
00400 SetLowerLimit(Index(name), lo);
00401 }
00402
00403 void MnUserTransformation::RemoveLimits(const std::string & name) {
00404
00405 RemoveLimits(Index(name));
00406 }
00407
00408 double MnUserTransformation::Value(const std::string & name) const {
00409
00410 return Value(Index(name));
00411 }
00412
00413 double MnUserTransformation::Error(const std::string & name) const {
00414
00415 return Error(Index(name));
00416 }
00417
00418 unsigned int MnUserTransformation::Index(const std::string & name) const {
00419
00420 std::vector<MinuitParameter>::const_iterator ipar =
00421 std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name));
00422 assert(ipar != fParameters.end());
00423
00424 return (*ipar).Number();
00425 }
00426
00427 int MnUserTransformation::FindIndex(const std::string & name) const {
00428
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
00438 assert(n < fParameters.size());
00439 return fParameters[n].GetName();
00440 }
00441
00442 const char* MnUserTransformation::Name(unsigned int n) const {
00443
00444 return GetName(n).c_str();
00445 }
00446
00447
00448 }
00449
00450 }