Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
MnPrint.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
10#include "Minuit2/MnPrint.h"
18#include "Minuit2/MinosError.h"
20#include "Minuit2/MnPlot.h"
21
22#include <iomanip>
23#include <utility>
24#include <cstring>
25#include <vector>
26#include <algorithm>
27
28constexpr int PRECISION = 10;
29constexpr int WIDTH = PRECISION + 7;
30
31namespace ROOT {
32namespace Minuit2 {
33
34// we don't use a std::vector or std::array here, because we want a mix of the two;
35// a stack-allocated container with fixed capacity but dynamic size, i.e. the equivalent
36// of static_vector from the Boost Container library
37template <class T>
39public:
40 using const_pointer = const T *;
41 using const_reference = const T &;
42
43 void Push(T prefix)
44 {
45 if (fSize < fMaxSize)
46 fData[fSize] = prefix;
47 else {
48 // crop the stack when it becomes too deep as a last resort, but this should not
49 // happen, fMaxSize should be increased instead if this occurs
50 fData[fMaxSize - 1] = prefix;
51 fData[fMaxSize - 2] = "...";
52 }
53 ++fSize;
54 }
55
56 void Pop()
57 {
58 assert(fSize > 0);
59 --fSize;
60 }
61
62 const_pointer begin() const { return fData; }
63 const_pointer end() const { return fData + (fSize < fMaxSize ? fSize : fMaxSize); }
64 const_reference back() const { return *(end() - 1); }
65
66private:
67 static constexpr unsigned fMaxSize = 10; // increase as needed
69 unsigned fSize = 0;
70};
71
72// gShowPrefixStack determines how messages are printed, it acts on all threads;
73// race conditions when writing to this do not cause failures
74bool gShowPrefixStack = false;
75
76// writing to gPrefixFilter is not thread-safe, should be done only from main thread
77std::vector<std::string> gPrefixFilter;
78
79// gPrintLevel must be thread-local, because it may be manipulated by a thread to
80// temporarily turn logging on or off; Minuit2Minimizer does this, for example
81thread_local int gPrintLevel = 0;
82
83// gPrefixStack must be thread-local
85
86MnPrint::MnPrint(const char *prefix, int level) : fLevel{level}
87{
88 gPrefixStack.Push(prefix);
89}
90
92{
93 gPrefixStack.Pop();
94}
95
100
101void MnPrint::AddFilter(const char *filter)
102{
103 gPrefixFilter.emplace_back(filter);
104}
105
107{
108 gPrefixFilter.clear();
109}
110
112{
113 // should use std::exchange or boost::exchange
114 std::swap(gPrintLevel, level);
115 return level;
116}
117
119{
120 return gPrintLevel;
121}
122
123int MnPrint::SetLevel(int level)
124{
125 // should use std::exchange or boost::exchange
126 std::swap(fLevel, level);
127 return level;
128}
129
130int MnPrint::Level() const
131{
132 return fLevel;
133}
134
135void StreamFullPrefix(std::ostringstream &os)
136{
137 const char *prev = "";
138 for (const auto cs : gPrefixStack) {
139 // skip repeated prefixes; repetition happens when class method calls another
140 // method of the same class and both set up a MnPrint instance
141 if (std::strcmp(cs, prev) != 0)
142 os << cs << ":";
143 prev = cs;
144 }
145}
146
147void MnPrint::StreamPrefix(std::ostringstream &os)
148{
149 if (gShowPrefixStack) {
150 // show full prefix stack, useful to set sharp filters and to see what calls what
152 } else {
153 // show only the top of the prefix stack (the prefix of the innermost scope)
154 os << gPrefixStack.back();
155 }
156}
157
159{
160 // Filtering is not implemented a very efficient way to keep it simple, but the
161 // implementation ensures that the performance drop is opt-in. Only when filters are
162 // used there is a performance loss.
163
164 // The intended use case of filtering is for debugging, when highest performance
165 // does not matter. Filtering is only every attempted if the message passes the
166 // threshold level.
167
168 // Filtering is very fast when the filter is empty.
169 if (gPrefixFilter.empty())
170 return false;
171
172 std::ostringstream os;
173 os << "^";
175 std::string prefix = os.str();
176 // Filtering works like grep, the message is shown if any of the filter strings match.
177 // To only match the beginning of the prefix, use "^". For example "^MnHesse" only
178 // matches direct execution of MnHesse, but not MnHesse called by MnMigrad.
179 for (const auto &s : gPrefixFilter) {
180 if (prefix.find(s) != std::string::npos)
181 return false;
182 }
183 return true;
184}
185
186MnPrint::Oneline::Oneline(double fcn, double edm, int ncalls, int iter)
187 : fFcn(fcn), fEdm(edm), fNcalls(ncalls), fIter(iter)
188{
189}
190
192 : MnPrint::Oneline(state.Fval(), state.Edm(), state.NFcn(), iter)
193{
194}
195
196MnPrint::Oneline::Oneline(const FunctionMinimum &fmin, int iter) : MnPrint::Oneline(fmin.State(), iter) {}
197
198std::ostream &operator<<(std::ostream &os, const MnPrint::Oneline &x)
199{
200 // print iteration, function value, edm and ncalls in one single line
201 if (x.fIter >= 0)
202 os << std::setw(4) << x.fIter << " - ";
203 const int pr = os.precision(PRECISION);
204 os << "FCN = " << std::setw(WIDTH) << x.fFcn << " Edm = " << std::setw(WIDTH) << x.fEdm
205 << " NCalls = " << std::setw(6) << x.fNcalls;
206 os.precision(pr);
207 return os;
208}
209
210std::ostream &operator<<(std::ostream &os, const MnUserParameters &par)
211{
212 // print the MnUserParameter object
213 os << "\n Pos | Name | type | Value | Error +/-";
214
215 int pr = os.precision();
216
217 const double eps2 = par.Precision().Eps2();
218 for (auto &&p : par.Parameters()) {
219 os << "\n" << std::setw(5) << p.Number() << " | " << std::setw(10) << p.Name() << " |";
220 if (p.IsConst())
221 os << " const |";
222 else if (p.IsFixed())
223 os << " fixed |";
224 else if (p.HasLimits())
225 os << " limited |";
226 else
227 os << " free |";
228 os.precision(PRECISION);
229 os.width(WIDTH);
230 os << p.Value() << " | " << std::setw(12);
231 if (p.Error() > 0) {
232 os << p.Error();
233 if (p.HasLimits()) {
234 if (std::fabs(p.Value() - p.LowerLimit()) < eps2) {
235 os << " (at lower limit)";
236 } else if (std::fabs(p.Value() - p.UpperLimit()) < eps2) {
237 os << " (at upper limit)";
238 }
239 }
240 }
241 }
242 os.precision(pr);
243
244 return os;
245}
246
247std::ostream &operator<<(std::ostream &os, const MnUserCovariance &matrix)
248{
249 // print the MnUserCovariance
250 const int pr = os.precision(6);
251
252 unsigned int n = matrix.Nrow();
253 for (unsigned int i = 0; i < n; i++) {
254 os << '\n';
255 for (unsigned int j = 0; j < n; j++) {
256 os.width(13);
257 os << matrix(i, j);
258 }
259 os << " | ";
260 double di = matrix(i, i);
261 for (unsigned int j = 0; j < n; j++) {
262 double dj = matrix(j, j);
263 os.width(13);
264 os << matrix(i, j) / std::sqrt(std::fabs(di * dj));
265 }
266 }
267 os.precision(pr);
268 return os;
269}
270
271std::ostream &operator<<(std::ostream &os, const MnGlobalCorrelationCoeff &coeff)
272{
273 // print the global correlation coefficient
274 const int pr = os.precision(6);
275 for (auto &&x : coeff.GlobalCC()) {
276 os << '\n';
277 os.width(6 + 7);
278 os << x;
279 }
280 os.precision(pr);
281 return os;
282}
283
284std::ostream &operator<<(std::ostream &os, const MnUserParameterState &state)
285{
286 // print the MnUserParameterState
287 const int pr = os.precision(PRECISION);
288 os << "\n Valid : " << (state.IsValid() ? "yes" : "NO") << "\n Function calls: " << state.NFcn()
289 << "\n Minimum value : " << state.Fval() << "\n Edm : " << state.Edm()
290 << "\n Parameters : " << state.Parameters() << "\n CovarianceStatus: " << state.CovarianceStatus()
291 << "\n Covariance and correlation matrix: ";
292 if (state.HasCovariance())
293 os << state.Covariance();
294 else
295 os << "matrix is not present or not valid";
296 if (state.HasGlobalCC())
297 os << "\n Global correlation coefficients: " << state.GlobalCC();
298
299 os.precision(pr);
300 return os;
301}
302
303std::ostream &operator<<(std::ostream &os, const FunctionMinimum &min)
304{
305 // print the FunctionMinimum
306 const int pr = os.precision(PRECISION);
307 os << "\n Valid : " << (min.IsValid() ? "yes" : "NO") << "\n Function calls: " << min.NFcn()
308 << "\n Minimum value : " << min.Fval() << "\n Edm : " << min.Edm()
309 << "\n Internal parameters: " << min.Parameters().Vec();
310 if (min.HasValidCovariance())
311 os << "\n Internal covariance matrix: " << min.Error().Matrix();
312 os << "\n External parameters: " << min.UserParameters();
313 // os << min.UserCovariance() << '\n';
314 // os << min.UserState().GlobalCC() << '\n';
315
316 if (!min.IsValid()) {
317 os << "\n FunctionMinimum is invalid:";
318 if (!min.State().IsValid())
319 os << "\n State is invalid";
320 if (min.IsAboveMaxEdm())
321 os << "\n Edm is above max";
322 if (min.HasReachedCallLimit())
323 os << "\n Reached call limit";
324 }
325
326 os.precision(pr);
327
328 return os;
329}
330
331std::ostream &operator<<(std::ostream &os, const MinimumState &min)
332{
333 const int pr = os.precision(PRECISION);
334 os << "\n Minimum value : " << min.Fval() << "\n Edm : " << min.Edm()
335 << "\n Internal parameters:" << min.Vec() << "\n Internal gradient :" << min.Gradient().Vec();
336 if (min.HasCovariance())
337 os << "\n Internal covariance matrix:" << min.Error().Matrix();
338 os.precision(pr);
339 return os;
340}
341
342std::ostream &operator<<(std::ostream &os, const MnMachinePrecision &prec)
343{
344 // print the Precision
345 int pr = os.precision(PRECISION);
346 os << "MnMachinePrecision " << prec.Eps() << '\n';
347 os.precision(pr);
348
349 return os;
350}
351
352std::ostream &operator<<(std::ostream &os, const MinosError &me)
353{
354 // print the Minos Error
355 os << "Minos # of function calls: " << me.NFcn() << '\n';
356
357 if (!me.IsValid())
358 os << "Minos Error is not valid." << '\n';
359 if (!me.LowerValid())
360 os << "lower Minos Error is not valid." << '\n';
361 if (!me.UpperValid())
362 os << "upper Minos Error is not valid." << '\n';
363 if (me.AtLowerLimit())
364 os << "Minos Error is Lower limit of Parameter " << me.Parameter() << "." << '\n';
365 if (me.AtUpperLimit())
366 os << "Minos Error is Upper limit of Parameter " << me.Parameter() << "." << '\n';
367 if (me.AtLowerMaxFcn())
368 os << "Minos number of function calls for Lower Error exhausted." << '\n';
369 if (me.AtUpperMaxFcn())
370 os << "Minos number of function calls for Upper Error exhausted." << '\n';
371 if (me.LowerNewMin()) {
372 os << "Minos found a new Minimum in negative direction." << '\n';
373 os << me.LowerState() << '\n';
374 }
375 if (me.UpperNewMin()) {
376 os << "Minos found a new Minimum in positive direction." << '\n';
377 os << me.UpperState() << '\n';
378 }
379
380 int pr = os.precision();
381
382 os << "No |"
383 << "| Name |"
384 << "| Value@min |"
385 << "| negative |"
386 << "| positive " << '\n';
387 os << std::setw(4) << me.Parameter() << std::setw(5) << "||";
388 os << std::setw(10) << me.LowerState().Name(me.Parameter()) << std::setw(3) << "||";
389 os << std::setprecision(PRECISION) << std::setw(WIDTH) << me.Min() << " ||" << std::setprecision(PRECISION)
390 << std::setw(WIDTH) << me.Lower() << " ||" << std::setw(WIDTH) << me.Upper() << '\n';
391
392 os << '\n';
393 os.precision(pr);
394
395 return os;
396}
397
398std::ostream &operator<<(std::ostream &os, const ContoursError &ce)
399{
400 // print the ContoursError
401 os << "Contours # of function calls: " << ce.NFcn() << '\n';
402 os << "MinosError in x: " << '\n';
403 os << ce.XMinosError() << '\n';
404 os << "MinosError in y: " << '\n';
405 os << ce.YMinosError() << '\n';
406 MnPlot plot;
407 plot(ce.XMin(), ce.YMin(), ce());
408 for (auto ipar = ce().begin(); ipar != ce().end(); ++ipar) {
409 os << ipar - ce().begin() << " " << (*ipar).first << " " << (*ipar).second << '\n';
410 }
411 os << '\n';
412
413 return os;
414}
415
416std::ostream &operator<<(std::ostream &os, const std::pair<double, double> &point)
417{
418 os << "\t x = " << point.first << " y = " << point.second << std::endl;
419 return os;
420}
421
422} // namespace Minuit2
423} // namespace ROOT
constexpr int WIDTH
Definition MnMatrix.cxx:16
constexpr int WIDTH
Definition MnPrint.cxx:29
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
winID h TVirtualViewer3D TVirtualGLPainter char TVirtualGLPainter plot
class holding the full result of the minimization; both internal and external (MnUserParameterState) ...
MinimumState keeps the information (position, Gradient, 2nd deriv, etc) after one minimization step (...
Class holding the result of Minos (lower and upper values) for a specific parameter.
Definition MinosError.h:25
unsigned int NFcn() const
Definition MinosError.h:97
unsigned int Parameter() const
Definition MinosError.h:85
const MnUserParameterState & UpperState() const
Definition MinosError.h:87
bool AtUpperLimit() const
Definition MinosError.h:92
bool AtLowerMaxFcn() const
Definition MinosError.h:93
const MnUserParameterState & LowerState() const
Definition MinosError.h:86
bool AtUpperMaxFcn() const
Definition MinosError.h:94
bool AtLowerLimit() const
Definition MinosError.h:91
class for global correlation coefficient
Sets the relative floating point (double) arithmetic precision.
MnPlot produces a text-screen graphical output of (x,y) points, e.g.
Definition MnPlot.h:28
Oneline(double fcn, double edm, int ncalls, int iter=-1)
Definition MnPrint.cxx:186
static void ClearFilter()
Definition MnPrint.cxx:106
static void AddFilter(const char *prefix)
Definition MnPrint.cxx:101
static bool Hidden()
Definition MnPrint.cxx:158
static int GlobalLevel()
Definition MnPrint.cxx:118
static void ShowPrefixStack(bool yes)
Definition MnPrint.cxx:96
static int SetGlobalLevel(int level)
Definition MnPrint.cxx:111
MnPrint(const char *prefix, int level=MnPrint::GlobalLevel())
Definition MnPrint.cxx:86
static void StreamPrefix(std::ostringstream &os)
Definition MnPrint.cxx:147
int SetLevel(int level)
Definition MnPrint.cxx:123
Class containing the covariance matrix data represented as a vector of size n*(n+1)/2 Used to hide in...
class which holds the external user and/or internal Minuit representation of the parameters and error...
const MnUserParameters & Parameters() const
const MnGlobalCorrelationCoeff & GlobalCC() const
const MnUserCovariance & Covariance() const
API class for the user interaction with the parameters; serves as input to the minimizer as well as o...
const MnMachinePrecision & Precision() const
const std::vector< ROOT::Minuit2::MinuitParameter > & Parameters() const
access to parameters (row-wise)
const_reference back() const
Definition MnPrint.cxx:64
const_pointer end() const
Definition MnPrint.cxx:63
static constexpr unsigned fMaxSize
Definition MnPrint.cxx:67
const_pointer begin() const
Definition MnPrint.cxx:62
Double_t x[n]
Definition legend1.C:17
const Int_t n
Definition legend1.C:16
std::vector< std::string > gPrefixFilter
Definition MnPrint.cxx:77
std::ostream & operator<<(std::ostream &, const LAVector &)
Definition MnMatrix.cxx:602
thread_local PrefixStack< const char * > gPrefixStack
Definition MnPrint.cxx:84
thread_local int gPrintLevel
Definition MnPrint.cxx:81
bool gShowPrefixStack
Definition MnPrint.cxx:74
void StreamFullPrefix(std::ostringstream &os)
Definition MnPrint.cxx:135
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...