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