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
28 bool operator()(const MinuitParameter &par) const
29 {
30 // return (strcmp(par.Name(), fName) == 0);
31 return par.GetName() == fName;
32 }
33
34private:
35 const std::string &fName;
36};
37
38MnUserTransformation::MnUserTransformation(std::span<const double> par, std::span<const double> err)
39{
40 // constructor from a vector of parameter values and a vector of errors (step sizes)
41 // class has as data member the transformation objects (all of the types),
42 // the std::vector of MinuitParameter objects and the vector with the index conversions from
43 // internal to external (fExtOfInt)
44
45 fParameters.reserve(par.size());
46 fExtOfInt.reserve(par.size());
47 fCache.reserve(par.size());
48
49 std::string parName;
50 for (unsigned int i = 0; i < par.size(); i++) {
51 std::ostringstream buf;
52 buf << "p" << i;
53 parName = buf.str();
54 Add(parName, par[i], err[i]);
55 }
56}
57
58//#ifdef MINUIT2_THREAD_SAFE
59// this if a thread-safe implementation needed if want to share transformation object between the threads
61{
62 // transform an internal Minuit vector of internal values in a std::vector of external values
63 // fixed parameters will have their fixed values
64 unsigned int n = pstates.size();
65 // need to initialize to the stored (initial values) parameter values for the fixed ones
66 std::vector<double> pcache(fCache);
67 for (unsigned int i = 0; i < n; i++) {
68 if (fParameters[fExtOfInt[i]].HasLimits()) {
69 pcache[fExtOfInt[i]] = Int2ext(i, pstates(i));
70 } else {
71 pcache[fExtOfInt[i]] = pstates(i);
72 }
73 }
74 return pcache;
75}
76
77// #else
78// const std::vector<double> & MnUserTransformation::operator()(const MnAlgebraicVector& pstates) const {
79// // transform an internal Minuit vector of internal values in a std::vector of external values
80// // std::vector<double> Cache(pstates.size() );
81// for(unsigned int i = 0; i < pstates.size(); i++) {
82// if(fParameters[fExtOfInt[i]].HasLimits()) {
83// fCache[fExtOfInt[i]] = Int2ext(i, pstates(i));
84// } else {
85// fCache[fExtOfInt[i]] = pstates(i);
86// }
87// }
88
89// return fCache;
90// }
91// #endif
92
93double MnUserTransformation::Int2ext(unsigned int i, double val) const
94{
95 // return external value from internal value for parameter i
96 if (fParameters[fExtOfInt[i]].HasLimits()) {
97 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
98 return fDoubleLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit(),
99 fParameters[fExtOfInt[i]].LowerLimit());
100 else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
101 return fUpperLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].UpperLimit());
102 else
103 return fLowerLimTrafo.Int2ext(val, fParameters[fExtOfInt[i]].LowerLimit());
104 }
105
106 return val;
107}
108
109double MnUserTransformation::Int2extError(unsigned int i, double val, double err) const
110{
111 // return external error from internal error for parameter i
112
113 // err = sigma Value == std::sqrt(cov(i,i))
114 double dx = err;
115
116 if (fParameters[fExtOfInt[i]].HasLimits()) {
117 double ui = Int2ext(i, val);
118 double du1 = Int2ext(i, val + dx) - ui;
119 double du2 = Int2ext(i, val - dx) - ui;
120 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit()) {
121 // double al = fParameters[fExtOfInt[i]].Lower();
122 // double ba = fParameters[fExtOfInt[i]].Upper() - al;
123 // double du1 = al + 0.5*(sin(val + dx) + 1.)*ba - ui;
124 // double du2 = al + 0.5*(sin(val - dx) + 1.)*ba - ui;
125 // if(dx > 1.) du1 = ba;
126 if (dx > 1.)
127 du1 = fParameters[fExtOfInt[i]].UpperLimit() - fParameters[fExtOfInt[i]].LowerLimit();
128 dx = 0.5 * (std::fabs(du1) + std::fabs(du2));
129 } else {
130 dx = 0.5 * (std::fabs(du1) + std::fabs(du2));
131 }
132 }
133
134 return dx;
135}
136
139{
140 // return the external covariance matrix from the internal error matrix and the internal parameter value
141 // the vector of internal parameter is needed for the derivatives (Jacobian of the transformation)
142 // Vext(i,j) = Vint(i,j) * dPext(i)/dPint(i) * dPext(j)/dPint(j)
143
145 for (unsigned int i = 0; i < vec.size(); i++) {
146 double dxdi = 1.;
147 if (fParameters[fExtOfInt[i]].HasLimits()) {
148 // dxdi = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() -
149 // fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
150 dxdi = DInt2Ext(i, vec(i));
151 }
152 for (unsigned int j = i; j < vec.size(); j++) {
153 double dxdj = 1.;
154 if (fParameters[fExtOfInt[j]].HasLimits()) {
155 // dxdj = 0.5*std::fabs((fParameters[fExtOfInt[j]].Upper() -
156 // fParameters[fExtOfInt[j]].Lower())*cos(vec(j)));
157 dxdj = DInt2Ext(j, vec(j));
158 }
159 result(i, j) = dxdi * cov(i, j) * dxdj;
160 }
161 // double diag = Int2extError(i, vec(i), std::sqrt(cov(i,i)));
162 // result(i,i) = diag*diag;
163 }
164
165 return result;
166}
167
170{
171 // return the internal covariance matrix from the external error matrix and the internal parameter value
172 // the vector of internal parameter is needed for the derivatives (Jacobian of the transformation)
173 // Vint(i,j) = Vext(i,j) * dPint(i)/dPext(i) * dPint(j)/dPext(j)
174
176 for (unsigned int i = 0; i < vec.size(); i++) {
177 double dxdi = 1.;
178 if (fParameters[fExtOfInt[i]].HasLimits()) {
179 dxdi = DExt2Int(i, vec(i));
180 }
181 for (unsigned int j = i; j < vec.size(); j++) {
182 double dxdj = 1.;
183 if (fParameters[fExtOfInt[j]].HasLimits()) {
184 dxdj = DExt2Int(j, vec(j));
185 }
186 result(i, j) = dxdi * cov(i, j) * dxdj;
187 }
188 }
189
190 return result;
191}
192
193double MnUserTransformation::Ext2int(unsigned int i, double val) const
194{
195 // return the internal value for parameter i with external value val
196
197 if (fParameters[i].HasLimits()) {
198 if (fParameters[i].HasUpperLimit() && fParameters[i].HasLowerLimit())
199 return fDoubleLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), fParameters[i].LowerLimit(), Precision());
200 else if (fParameters[i].HasUpperLimit() && !fParameters[i].HasLowerLimit())
201 return fUpperLimTrafo.Ext2int(val, fParameters[i].UpperLimit(), Precision());
202 else
203 return fLowerLimTrafo.Ext2int(val, fParameters[i].LowerLimit(), Precision());
204 }
205
206 return val;
207}
208
209double MnUserTransformation::DInt2Ext(unsigned int i, double val) const
210{
211 // return the derivative of the int->ext transformation: dPext(i) / dPint(i)
212 // for the parameter i with value val
213
214 double dd = 1.;
215 if (fParameters[fExtOfInt[i]].HasLimits()) {
216 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
217 // dd = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() -
218 // fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
219 dd = fDoubleLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit(),
220 fParameters[fExtOfInt[i]].LowerLimit());
221 else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
222 dd = fUpperLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].UpperLimit());
223 else
224 dd = fLowerLimTrafo.DInt2Ext(val, fParameters[fExtOfInt[i]].LowerLimit());
225 }
226
227 return dd;
228}
229
230double MnUserTransformation::D2Int2Ext(unsigned int i, double val) const
231{
232 // return the second derivative of the int->ext transformation: d^2 Pext(i) / d Pint(i)^2
233 // for the parameter i with value val
234
235 double dd = 0.;
236 if (fParameters[fExtOfInt[i]].HasLimits()) {
237 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
238 dd = fDoubleLimTrafo.D2Int2Ext(val, fParameters[fExtOfInt[i]].UpperLimit(),
239 fParameters[fExtOfInt[i]].LowerLimit());
240 else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
241 dd = fUpperLimTrafo.D2Int2Ext(val, fParameters[fExtOfInt[i]].UpperLimit());
242 else
243 dd = fLowerLimTrafo.D2Int2Ext(val, fParameters[fExtOfInt[i]].LowerLimit());
244 }
245
246 return dd;
247}
248
249double MnUserTransformation::DExt2Int(unsigned int i, double val) const
250{
251 // return the derivative of the ext->int transformation: dPint(i) / dPext(i)
252 // for the parameter i with value val
253
254 double dd = 1.;
255 if (fParameters[fExtOfInt[i]].HasLimits()) {
256 if (fParameters[fExtOfInt[i]].HasUpperLimit() && fParameters[fExtOfInt[i]].HasLowerLimit())
257 // dd = 0.5*std::fabs((fParameters[fExtOfInt[i]].Upper() -
258 // fParameters[fExtOfInt[i]].Lower())*cos(vec(i)));
259 dd = fDoubleLimTrafo.DExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit(),
260 fParameters[fExtOfInt[i]].LowerLimit());
261 else if (fParameters[fExtOfInt[i]].HasUpperLimit() && !fParameters[fExtOfInt[i]].HasLowerLimit())
262 dd = fUpperLimTrafo.DExt2Int(val, fParameters[fExtOfInt[i]].UpperLimit());
263 else
264 dd = fLowerLimTrafo.DExt2Int(val, fParameters[fExtOfInt[i]].LowerLimit());
265 }
266
267 return dd;
268}
269
270unsigned int MnUserTransformation::IntOfExt(unsigned int ext) const
271{
272 // return internal index given external one ext
273 assert(ext < fParameters.size());
274 assert(!fParameters[ext].IsFixed());
275 assert(!fParameters[ext].IsConst());
276 auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), ext);
277 assert(iind != fExtOfInt.end());
278
279 return (iind - fExtOfInt.begin());
280}
281
282std::vector<double> MnUserTransformation::Params() const
283{
284 // return std::vector of double with parameter values
285 unsigned int n = fParameters.size();
286 std::vector<double> result(n);
287 for (unsigned int i = 0; i < n; ++i)
288 result[i] = fParameters[i].Value();
289
290 return result;
291}
292
293std::vector<double> MnUserTransformation::Errors() const
294{
295 // return std::vector of double with parameter errors
296 std::vector<double> result;
297 result.reserve(fParameters.size());
298 for (auto const &ipar : Parameters()) {
299 result.push_back(ipar.Error());
300 }
301
302 return result;
303}
304
306{
307 // return the MinuitParameter object for index n (external)
308 assert(n < fParameters.size());
309 return fParameters[n];
310}
311
312// bool MnUserTransformation::Remove(const std::string & name) {
313// // remove parameter with name
314// // useful if want to re-define a parameter
315// // return false if parameter does not exist
316// auto itr = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)
317// ); if (itr == fParameters.end() ) return false; int n = itr - fParameters.begin(); if (n < 0 || n >=
318// fParameters.size() ) return false; fParameters.erase(itr); fCache.erase( fExtOfInt.begin() + n);
319// auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
320// if (iind != fExtOfInt.end()) fExtOfInt.erase(iind);
321// }
322
323bool MnUserTransformation::Add(const std::string &name, double val, double err)
324{
325 // add a new unlimited parameter giving name, value and err (step size)
326 // return false if parameter already exists
327 if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end())
328 return false;
329 fExtOfInt.push_back(fParameters.size());
330 fCache.push_back(val);
331 fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err));
332 return true;
333}
334
335bool MnUserTransformation::Add(const std::string &name, double val, double err, double low, double up)
336{
337 // add a new limited parameter giving name, value, err (step size) and lower/upper limits
338 // return false if parameter already exists
339 if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end())
340 return false;
341 fExtOfInt.push_back(fParameters.size());
342 fCache.push_back(val);
343 fParameters.push_back(MinuitParameter(fParameters.size(), name, val, err, low, up));
344 return true;
345}
346
347bool MnUserTransformation::Add(const std::string &name, double val)
348{
349 // add a new constant parameter giving name and value
350 // return false if parameter already exists
351 if (std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name)) != fParameters.end())
352 return false;
353 fCache.push_back(val);
354 // constant parameter - do not add in list of internals (fExtOfInt)
355 fParameters.push_back(MinuitParameter(fParameters.size(), name, val));
356 return true;
357}
358
359void MnUserTransformation::Fix(unsigned int n)
360{
361 // fix parameter n (external index)
362 assert(n < fParameters.size());
363 auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
364 if (iind != fExtOfInt.end())
365 fExtOfInt.erase(iind, iind + 1);
366 fParameters[n].Fix();
367}
368
370{
371 // release parameter n (external index)
372 assert(n < fParameters.size());
373 auto iind = std::find(fExtOfInt.begin(), fExtOfInt.end(), n);
374 if (iind == fExtOfInt.end()) {
375 fExtOfInt.push_back(n);
376 std::sort(fExtOfInt.begin(), fExtOfInt.end());
377 }
378 fParameters[n].Release();
379}
380
381void MnUserTransformation::SetValue(unsigned int n, double val)
382{
383 // set value for parameter n (external index)
384 assert(n < fParameters.size());
385 fParameters[n].SetValue(val);
386 fCache[n] = val;
387}
388
389void MnUserTransformation::SetError(unsigned int n, double err)
390{
391 // set error for parameter n (external index)
392 assert(n < fParameters.size());
393 fParameters[n].SetError(err);
394}
395
396void MnUserTransformation::SetLimits(unsigned int n, double low, double up)
397{
398 // set limits (lower/upper) for parameter n (external index)
399 assert(n < fParameters.size());
400 assert(low != up);
401 fParameters[n].SetLimits(low, up);
402}
403
404void MnUserTransformation::SetUpperLimit(unsigned int n, double up)
405{
406 // set upper limit for parameter n (external index)
407 assert(n < fParameters.size());
408 fParameters[n].SetUpperLimit(up);
409}
410
411void MnUserTransformation::SetLowerLimit(unsigned int n, double lo)
412{
413 // set lower limit for parameter n (external index)
414 assert(n < fParameters.size());
415 fParameters[n].SetLowerLimit(lo);
416}
417
419{
420 // remove limits for parameter n (external index)
421 assert(n < fParameters.size());
422 fParameters[n].RemoveLimits();
423}
424
425void MnUserTransformation::SetName(unsigned int n, const std::string &name)
426{
427 // set name for parameter n (external index)
428 assert(n < fParameters.size());
429 fParameters[n].SetName(name);
430}
431
432double MnUserTransformation::Value(unsigned int n) const
433{
434 // get value for parameter n (external index)
435 assert(n < fParameters.size());
436 return fParameters[n].Value();
437}
438
439double MnUserTransformation::Error(unsigned int n) const
440{
441 // get error for parameter n (external index)
442 assert(n < fParameters.size());
443 return fParameters[n].Error();
444}
445
446// interface by parameter name
447
448void MnUserTransformation::Fix(const std::string &name)
449{
450 // fix parameter
451 Fix(Index(name));
452}
453
454void MnUserTransformation::Release(const std::string &name)
455{
456 // release parameter
458}
459
460void MnUserTransformation::SetValue(const std::string &name, double val)
461{
462 // set value for parameter
463 SetValue(Index(name), val);
464}
465
466void MnUserTransformation::SetError(const std::string &name, double err)
467{
468 // set error
469 SetError(Index(name), err);
470}
471
472void MnUserTransformation::SetLimits(const std::string &name, double low, double up)
473{
474 // set lower/upper limits
475 SetLimits(Index(name), low, up);
476}
477
478void MnUserTransformation::SetUpperLimit(const std::string &name, double up)
479{
480 // set upper limit
482}
483
484void MnUserTransformation::SetLowerLimit(const std::string &name, double lo)
485{
486 // set lower limit
488}
489
491{
492 // remove limits
494}
495
496double MnUserTransformation::Value(const std::string &name) const
497{
498 // get parameter value
499 return Value(Index(name));
500}
501
502double MnUserTransformation::Error(const std::string &name) const
503{
504 // get parameter error
505 return Error(Index(name));
506}
507
508unsigned int MnUserTransformation::Index(const std::string &name) const
509{
510 // get index (external) corresponding to name
511 auto ipar = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name));
512 assert(ipar != fParameters.end());
513 // return (ipar - fParameters.begin());
514 return (*ipar).Number();
515}
516
517int MnUserTransformation::FindIndex(const std::string &name) const
518{
519 // find index (external) corresponding to name - return -1 if not found
520 auto ipar = std::find_if(fParameters.begin(), fParameters.end(), MnParStr(name));
521 if (ipar == fParameters.end())
522 return -1;
523 return (*ipar).Number();
524}
525
526const std::string &MnUserTransformation::GetName(unsigned int n) const
527{
528 // get name corresponding to index (external)
529 assert(n < fParameters.size());
530 return fParameters[n].GetName();
531}
532
533const char *MnUserTransformation::Name(unsigned int n) const
534{
535 // get name corresponding to index (external)
536 return GetName(n).c_str();
537}
538
539} // namespace Minuit2
540
541} // namespace ROOT
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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:148
Class describing a symmetric matrix of size n.
Definition MnMatrix.h:438
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
double D2Int2Ext(unsigned int, double) 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 D2Int2Ext(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 D2Int2Ext(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 D2Int2Ext(long double Value, long double Upper) 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