Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MnUserTransformation.cxx
Go to the documentation of this file.
1// @(#)root/minuit2:$Id$
2// Authors: M. Winkler, F. James, L. Moneta, A. Zsenei 2003-2005
3
4/**********************************************************************
5 * *
6 * Copyright (c) 2005 LCG ROOT Math team, CERN/PH-SFT *
7 * *
8 **********************************************************************/
9
12#include "Minuit2/MnMatrix.h"
13
14#include <algorithm>
15#include <cstdio>
16#include <string>
17#include <sstream>
18
19namespace ROOT {
20
21namespace Minuit2 {
22
23class MnParStr {
24
25public:
26 MnParStr(const std::string &name) : fName(name) {}
27
29
30 bool operator()(const MinuitParameter &par) const
31 {
32 // return (strcmp(par.Name(), fName) == 0);
33 return par.GetName() == fName;
34 }
35
36private:
37 const std::string &fName;
38};
39
40MnUserTransformation::MnUserTransformation(std::span<const double> par, std::span<const double> err)
41{
42 // constructor from a vector of parameter values and a vector of errors (step sizes)
43 // class has as data member the transformation objects (all of the types),
44 // the std::vector of MinuitParameter objects and the vector with the index conversions from
45 // internal to external (fExtOfInt)
46
47 fParameters.reserve(par.size());
48 fExtOfInt.reserve(par.size());
49 fCache.reserve(par.size());
50
51 std::string parName;
52 for (unsigned int i = 0; i < par.size(); i++) {
53 std::ostringstream buf;
54 buf << "p" << i;
55 parName = buf.str();
56 Add(parName, par[i], err[i]);
57 }
58}
59
60//#ifdef MINUIT2_THREAD_SAFE
61// this if a thread-safe implementation needed if want to share transformation object between the threads
62std::vector<double> MnUserTransformation::operator()(const MnAlgebraicVector &pstates) const
63{
64 // transform an internal Minuit vector of internal values in a std::vector of external values
65 // fixed parameters will have their fixed values
66 unsigned int n = pstates.size();
67 // need to initialize to the stored (initial values) parameter values for the fixed ones
68 std::vector<double> pcache(fCache);
69 for (unsigned int i = 0; i < n; i++) {
70 if (fParameters[fExtOfInt[i]].HasLimits()) {
71 pcache[fExtOfInt[i]] = Int2ext(i, pstates(i));
72 } else {
73 pcache[fExtOfInt[i]] = pstates(i);
74 }
75 }
76 return pcache;
77}
78
79// #else
80// const std::vector<double> & MnUserTransformation::operator()(const MnAlgebraicVector& pstates) const {
81// // transform an internal Minuit vector of internal values in a std::vector of external values
82// // std::vector<double> Cache(pstates.size() );
83// for(unsigned int i = 0; i < pstates.size(); i++) {
84// if(fParameters[fExtOfInt[i]].HasLimits()) {
85// fCache[fExtOfInt[i]] = Int2ext(i, pstates(i));
86// } else {
87// fCache[fExtOfInt[i]] = pstates(i);
88// }
89// }
90
91// return fCache;
92// }
93// #endif
94
95double MnUserTransformation::Int2ext(unsigned int i, double val) const
96{
97 // return external value from internal value for parameter i
98 if (fParameters[fExtOfInt[i]].HasLimits()) {
99 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
100 return fDoubleLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit(),
101 fParameters[fExtOfInt[i]].LowerLimit());
102 else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
103 return fUpperLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit());
104 else
105 return fLowerLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].LowerLimit());
106 }
107
108 return val;
109}
110
111double MnUserTransformation::Int2extError(unsigned int i, double val, double err) const
112{
113 // return external error from internal error for parameter i
114
115 // err = sigma Value == std::sqrt(cov(i,i))
116 double dx = err;
117
118 if (fParameters[fExtOfInt[i]].HasLimits()) {
119 double ui = Int2ext(i, val);
120 double du1 = Int2ext(i, val + dx) - ui;
121 double du2 = Int2ext(i, val - dx) - ui;
122 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit()) {
123 // double al = fParameters[fExtOfInt[i]].Lower();
124 // double ba = fParameters[fExtOfInt[i]].Upper() - al;
125 // double du1 = al + 0.5*(sin(val + dx) + 1.)*ba - ui;
126 // double du2 = al + 0.5*(sin(val - dx) + 1.)*ba - ui;
127 // if(dx > 1.) du1 = ba;
128 if (dx > 1.)
129 du1 = fParameters[fExtOfInt[i]].UpperLimit() - fParameters[fExtOfInt[i]].LowerLimit();
130 dx = 0.5 * (std::fabs(du1) + std::fabs(du2));
131 } else {
132 dx = 0.5 * (std::fabs(du1) + std::fabs(du2));
133 }
134 }
135
136 return dx;
137}
138
141{
142 // return the external covariance matrix from the internal error matrix and the internal parameter value
143 // the vector of internal parameter is needed for the derivatives (Jacobian of the transformation)
144 // Vext(i,j) = Vint(i,j) * dPext(i)/dPint(i) * dPext(j)/dPint(j)
145
147 for (unsigned int i = 0; i < vec.size(); i++) {
148 double dxdi = 1.;
149 if (fParameters[fExtOfInt[i]].HasLimits()) {
150 // dxdi = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() -
151 // fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
152 dxdi = DInt2Ext(i, vec(i));
153 }
154 for (unsigned int j = i; j < vec.size(); j++) {
155 double dxdj = 1.;
156 if (fParameters[fExtOfInt[j]].HasLimits()) {
157 // dxdj = 0.5*std::fabs((fParameters[fExtOfInt[j]].Upper() -
158 // fParameters[fExtOfInt[j]].Lower())*cos(vec(j)));
159 dxdj = DInt2Ext(j, vec(j));
160 }
161 result(i, j) = dxdi * cov(i, j) * dxdj;
162 }
163 // double diag = Int2extError(i, vec(i), std::sqrt(cov(i,i)));
164 // result(i,i) = diag*diag;
165 }
166
167 return result;
168}
169
172{
173 // return the internal covariance matrix from the external error matrix and the internal parameter value
174 // the vector of internal parameter is needed for the derivatives (Jacobian of the transformation)
175 // Vint(i,j) = Vext(i,j) * dPint(i)/dPext(i) * dPint(j)/dPext(j)
176
178 for (unsigned int i = 0; i < vec.size(); i++) {
179 double dxdi = 1.;
180 if (fParameters[fExtOfInt[i]].HasLimits()) {
181 dxdi = DExt2Int(i, vec(i));
182 }
183 for (unsigned int j = i; j < vec.size(); j++) {
184 double dxdj = 1.;
185 if (fParameters[fExtOfInt[j]].HasLimits()) {
186 dxdj = DExt2Int(j, vec(j));
187 }
188 result(i, j) = dxdi * cov(i, j) * dxdj;
189 }
190 }
191
192 return result;
193}
194
195double MnUserTransformation::Ext2int(unsigned int i, double val) const
196{
197 // return the internal value for parameter i with external value val
198
199 if (fParameters[i].HasLimits()) {
200 if (fParameters[i].HasUpperLimit() && fParameters[i].HasLowerLimit())
201 return fDoubleLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), fParameters[i].LowerLimit(), Precision());
202 else if (fParameters[i].HasUpperLimit() && !fParameters[i].HasLowerLimit())
203 return fUpperLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), Precision());
204 else
205 return fLowerLimTrafo.Ext2int(val, fParameters[i].LowerLimit(), Precision());
206 }
207
208 return val;
209}
210
211double MnUserTransformation::DInt2Ext(unsigned int i, double val) const
212{
213 // return the derivative of the int->ext transformation: dPext(i) / dPint(i)
214 // for the parameter i with value val
215
216 double dd = 1.;
217 if (fParameters[fExtOfInt[i]].HasLimits()) {
218 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
219 // dd = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() -
220 // fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
221 dd = fDoubleLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit(),
222 fParameters[fExtOfInt[i]].LowerLimit());
223 else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
224 dd = fUpperLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit());
225 else
226 dd = fLowerLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].LowerLimit());
227 }
228
229 return dd;
230}
231
232double MnUserTransformation::DExt2Int(unsigned int i, double val) const
233{
234 // return the derivative of the ext->int transformation: dPint(i) / dPext(i)
235 // for the parameter i with value val
236
237 double dd = 1.;
238 if (fParameters[fExtOfInt[i]].HasLimits()) {
239 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
240 // dd = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() -
241 // fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
242 dd = fDoubleLimTrafo.DExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit(),
243 fParameters[fExtOfInt[i]].LowerLimit());
244 else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
245 dd = fUpperLimTrafo.DExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit());
246 else
247 dd = fLowerLimTrafo.DExt2Int(val, fParameters[fExtOfInt[i]].LowerLimit());
248 }
249
250 return dd;
251}
252
253unsigned int MnUserTransformation::IntOfExt(unsigned int ext) const
254{
255 // return internal index given external one ext
256 assert(ext < fParameters.size());
257 assert(!fParameters[ext].IsFixed());
258 assert(!fParameters[ext].IsConst());
259 auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), ext);
260 assert(iind != fExtOfInt.end());
261
262 return (iind - fExtOfInt.begin());
263}
264
265std::vector<double> MnUserTransformation::Params() const
266{
267 // return std::vector of double with parameter values
268 unsigned int n = fParameters.size();
269 std::vector<double> result(n);
270 for (unsigned int i = 0; i < n; ++i)
271 result[i] = fParameters[i].Value();
272
273 return result;
274}
275
276std::vector<double> MnUserTransformation::Errors() const
277{
278 // return std::vector of double with parameter errors
279 std::vector<double> result;
280 result.reserve(fParameters.size());
281 for (auto const &ipar : Parameters()) {
282 result.push_back(ipar.Error());
283 }
284
285 return result;
286}
287
289{
290 // return the MinuitParameter object for index n (external)
291 assert(n < fParameters.size());
292 return fParameters[n];
293}
294
295// bool MnUserTransformation::Remove(const std::string & name) {
296// // remove parameter with name
297// // useful if want to re-define a parameter
298// // return false if parameter does not exist
299// auto itr = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)
300// ); if (itr == fParameters.end() ) return false; int n = itr - fParameters.begin(); if (n < 0 || n >=
301// fParameters.size() ) return false; fParameters.erase(itr); fCache.erase( fExtOfInt.begin() + n);
302// auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
303// if (iind != fExtOfInt.end()) fExtOfInt.erase(iind);
304// }
305
306bool MnUserTransformation::Add(const std::string &name, double val, double err)
307{
308 // add a new unlimited parameter giving name, value and err (step size)
309 // return false if parameter already exists
310 if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end())
311 return false;
312 fExtOfInt.push_back(fParameters.size());
313 fCache.push_back(val);
314 fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err));
315 return true;
316}
317
318bool MnUserTransformation::Add(const std::string &name, double val, double err, double low, double up)
319{
320 // add a new limited parameter giving name, value, err (step size) and lower/upper limits
321 // return false if parameter already exists
322 if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end())
323 return false;
324 fExtOfInt.push_back(fParameters.size());
325 fCache.push_back(val);
326 fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err, low, up));
327 return true;
328}
329
330bool MnUserTransformation::Add(const std::string &name, double val)
331{
332 // add a new constant parameter giving name and value
333 // return false if parameter already exists
334 if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end())
335 return false;
336 fCache.push_back(val);
337 // constant parameter - do not add in list of internals (fExtOfInt)
338 fParameters.push_back(MinuitParameter(fParameters.size(), name, val));
339 return true;
340}
341
342void MnUserTransformation::Fix(unsigned int n)
343{
344 // fix parameter n (external index)
345 assert(n < fParameters.size());
346 auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
347 if (iind != fExtOfInt.end())
348 fExtOfInt.erase(iind, iind + 1);
349 fParameters[n].Fix();
350}
351
353{
354 // release parameter n (external index)
355 assert(n < fParameters.size());
356 auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
357 if (iind == fExtOfInt.end()) {
358 fExtOfInt.push_back(n);
359 std::sort(fExtOfInt.begin(), fExtOfInt.end());
360 }
361 fParameters[n].Release();
362}
363
364void MnUserTransformation::SetValue(unsigned int n, double val)
365{
366 // set value for parameter n (external index)
367 assert(n < fParameters.size());
368 fParameters[n].SetValue(val);
369 fCache[n] = val;
370}
371
372void MnUserTransformation::SetError(unsigned int n, double err)
373{
374 // set error for parameter n (external index)
375 assert(n < fParameters.size());
376 fParameters[n].SetError(err);
377}
378
379void MnUserTransformation::SetLimits(unsigned int n, double low, double up)
380{
381 // set limits (lower/upper) for parameter n (external index)
382 assert(n < fParameters.size());
383 assert(low != up);
384 fParameters[n].SetLimits(low, up);
385}
386
387void MnUserTransformation::SetUpperLimit(unsigned int n, double up)
388{
389 // set upper limit for parameter n (external index)
390 assert(n < fParameters.size());
391 fParameters[n].SetUpperLimit(up);
392}
393
394void MnUserTransformation::SetLowerLimit(unsigned int n, double lo)
395{
396 // set lower limit for parameter n (external index)
397 assert(n < fParameters.size());
398 fParameters[n].SetLowerLimit(lo);
399}
400
402{
403 // remove limits for parameter n (external index)
404 assert(n < fParameters.size());
405 fParameters[n].RemoveLimits();
406}
407
408void MnUserTransformation::SetName(unsigned int n, const std::string &name)
409{
410 // set name for parameter n (external index)
411 assert(n < fParameters.size());
412 fParameters[n].SetName(name);
413}
414
415double MnUserTransformation::Value(unsigned int n) const
416{
417 // get value for parameter n (external index)
418 assert(n < fParameters.size());
419 return fParameters[n].Value();
420}
421
422double MnUserTransformation::Error(unsigned int n) const
423{
424 // get error for parameter n (external index)
425 assert(n < fParameters.size());
426 return fParameters[n].Error();
427}
428
429// interface by parameter name
430
431void MnUserTransformation::Fix(const std::string &name)
432{
433 // fix parameter
434 Fix(Index(name));
435}
436
437void MnUserTransformation::Release(const std::string &name)
438{
439 // release parameter
441}
442
443void MnUserTransformation::SetValue(const std::string &name, double val)
444{
445 // set value for parameter
446 SetValue(Index(name), val);
447}
448
449void MnUserTransformation::SetError(const std::string &name, double err)
450{
451 // set error
452 SetError(Index(name), err);
453}
454
455void MnUserTransformation::SetLimits(const std::string &name, double low, double up)
456{
457 // set lower/upper limits
458 SetLimits(Index(name), low, up);
459}
460
461void MnUserTransformation::SetUpperLimit(const std::string &name, double up)
462{
463 // set upper limit
465}
466
467void MnUserTransformation::SetLowerLimit(const std::string &name, double lo)
468{
469 // set lower limit
471}
472
474{
475 // remove limits
477}
478
479double MnUserTransformation::Value(const std::string &name) const
480{
481 // get parameter value
482 return Value(Index(name));
483}
484
485double MnUserTransformation::Error(const std::string &name) const
486{
487 // get parameter error
488 return Error(Index(name));
489}
490
491unsigned int MnUserTransformation::Index(const std::string &name) const
492{
493 // get index (external) corresponding to name
494 auto ipar = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name));
495 assert(ipar != fParameters.end());
496 // return (ipar - fParameters.begin());
497 return (*ipar).Number();
498}
499
500int MnUserTransformation::FindIndex(const std::string &name) const
501{
502 // find index (external) corresponding to name - return -1 if not found
503 auto ipar = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name));
504 if (ipar == fParameters.end())
505 return -1;
506 return (*ipar).Number();
507}
508
509const std::string &MnUserTransformation::GetName(unsigned int n) const
510{
511 // get name corresponding to index (external)
512 assert(n < fParameters.size());
513 return fParameters[n].GetName();
514}
515
516const char *MnUserTransformation::Name(unsigned int n) const
517{
518 // get name corresponding to index (external)
519 return GetName(n).c_str();
520}
521
522} // namespace Minuit2
523
524} // namespace ROOT
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
char name[80]
Definition TGX11.cxx:110
Class describing a symmetric matrix of size n.
Definition LASymMatrix.h:45
unsigned int Nrow() const
unsigned int size() const
Definition LAVector.h:231
class for the individual Minuit Parameter with Name and number; contains the input numbers for the mi...
const std::string & GetName() const
MnParStr(const std::string &name)
bool operator()(const MinuitParameter &par) const
Class containing the covariance matrix data represented as a vector of size n*(n+1)/2 Used to hide in...
double Ext2int(unsigned int, double) const
MnUserCovariance Int2extCovariance(const MnAlgebraicVector &, const MnAlgebraicSymMatrix &) const
double DExt2Int(unsigned int, double) const
bool Add(const std::string &, double, double)
double DInt2Ext(unsigned int, double) const
void SetName(unsigned int, const std::string &)
std::vector< MinuitParameter > fParameters
std::vector< double > operator()(const MnAlgebraicVector &) const
const std::vector< MinuitParameter > & Parameters() const
unsigned int IntOfExt(unsigned int) const
MnUserCovariance Ext2intCovariance(const MnAlgebraicVector &, const MnAlgebraicSymMatrix &) const
const char * Name(unsigned int) const
std::vector< unsigned int > fExtOfInt
std::vector< double > Params() const
access to parameters and errors in column-wise representation
SqrtLowParameterTransformation fLowerLimTrafo
int FindIndex(const std::string &) const
double Int2ext(unsigned int, double) const
unsigned int Index(const std::string &) const
SinParameterTransformation fDoubleLimTrafo
const std::string & GetName(unsigned int) const
void SetLimits(unsigned int, double, double)
double Int2extError(unsigned int, double, double) const
const MnMachinePrecision & Precision() const
forwarded interface
SqrtUpParameterTransformation fUpperLimTrafo
const MinuitParameter & Parameter(unsigned int) const
long double DInt2Ext(long double Value, long double Upper, long double Lower) const
long double DExt2Int(long double Value, long double Upper, long double Lower) const
long double Int2ext(long double Value, long double Upper, long double Lower) const
long double Ext2int(long double Value, long double Upper, long double Lower, const MnMachinePrecision &) const
long double DExt2Int(long double Value, long double Lower) const
long double Ext2int(long double Value, long double Lower, const MnMachinePrecision &) const
long double DInt2Ext(long double Value, long double Lower) const
long double Int2ext(long double Value, long double Lower) const
long double DExt2Int(long double Value, long double Upper) const
long double Int2ext(long double Value, long double Upper) const
long double DInt2Ext(long double Value, long double Upper) const
long double Ext2int(long double Value, long double Upper, const MnMachinePrecision &) const
const Int_t n
Definition legend1.C:16
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...