Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RooMinimizer.cxx
Go to the documentation of this file.
1/*****************************************************************************
2 * Project: RooFit *
3 * Package: RooFitCore *
4 * @(#)root/roofitcore:$Id$
5 * Authors: *
6 * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu *
7 * DK, David Kirkby, UC Irvine, dkirkby@uci.edu *
8 * AL, Alfio Lazzaro, INFN Milan, alfio.lazzaro@mi.infn.it *
9 * PB, Patrick Bos, NL eScience Center, p.bos@esciencecenter.nl *
10 * *
11 * Redistribution and use in source and binary forms, *
12 * with or without modification, are permitted according to the terms *
13 * listed in LICENSE (http://roofit.sourceforge.net/license.txt) *
14 *****************************************************************************/
15
16/**
17\file RooMinimizer.cxx
18\class RooMinimizer
19\ingroup Roofitcore
20
21Wrapper class around ROOT::Fit:Fitter that
22provides a seamless interface between the minimizer functionality
23and the native RooFit interface.
24By default the Minimizer is MINUIT for classic mode and MINUIT2
25for parallelized mode (activated with the `RooFit::ModularL(true)`
26parameter or by passing a RooRealL function as the minimization
27target).
28RooMinimizer can minimize any RooAbsReal function with respect to
29its parameters. Usual choices for minimization are RooNLLVar
30and RooChi2Var
31RooMinimizer has methods corresponding to MINUIT functions like
32hesse(), migrad(), minos() etc. In each of these function calls
33the state of the MINUIT engine is synchronized with the state
34of the RooFit variables: any change in variables, change
35in the constant status etc is forwarded to MINUIT prior to
36execution of the MINUIT call. Afterwards the RooFit objects
37are resynchronized with the output state of MINUIT: changes
38parameter values, errors are propagated.
39Various methods are available to control verbosity, profiling,
40automatic PDF optimization.
41**/
42
43#include "RooMinimizer.h"
44
45#include "RooAbsMinimizerFcn.h"
46#include "RooArgSet.h"
47#include "RooArgList.h"
48#include "RooAbsReal.h"
49#include "RooDataSet.h"
50#include "RooRealVar.h"
51#include "RooSentinel.h"
52#include "RooMsgService.h"
53#include "RooPlot.h"
54#include "RooMinimizerFcn.h"
55#include "RooFitResult.h"
59#ifdef ROOFIT_MULTIPROCESS
62#endif
63
64#include "TClass.h"
65#include "Math/Minimizer.h"
66#include "TMarker.h"
67#include "TGraph.h"
68#include "Fit/FitConfig.h"
69
70#include <fstream>
71#include <iostream>
72#include <stdexcept> // logic_error
73
74using std::endl;
75
77
78std::unique_ptr<ROOT::Fit::Fitter> RooMinimizer::_theFitter = {};
79
80////////////////////////////////////////////////////////////////////////////////
81/// Cleanup method called by atexit handler installed by RooSentinel
82/// to delete all global heap objects when the program is terminated
83
85{
86 _theFitter.reset();
87}
88
89////////////////////////////////////////////////////////////////////////////////
90/// Construct MINUIT interface to given function. Function can be anything,
91/// but is typically a -log(likelihood) implemented by RooNLLVar or a chi^2
92/// (implemented by RooChi2Var). Other frequent use cases are a RooAddition
93/// of a RooNLLVar plus a penalty or constraint term. This class propagates
94/// all RooFit information (floating parameters, their values and errors)
95/// to MINUIT before each MINUIT call and propagates all MINUIT information
96/// back to the RooFit object at the end of each call (updated parameter
97/// values, their (asymmetric errors) etc. The default MINUIT error level
98/// for HESSE and MINOS error analysis is taken from the defaultErrorLevel()
99/// value of the input function.
100
101/// Constructor that accepts all configuration in struct with RooAbsReal likelihood
103{
105 auto nll_real = dynamic_cast<RooFit::TestStatistics::RooRealL *>(&function);
106 if (nll_real != nullptr) {
107 if (_cfg.parallelize != 0) { // new test statistic with multiprocessing library with
108 // parallel likelihood or parallel gradient
109#ifdef ROOFIT_MULTIPROCESS
111 // Note that this is necessary because there is currently no serial-mode LikelihoodGradientWrapper.
112 // We intend to repurpose RooGradMinimizerFcn to build such a LikelihoodGradientSerial class.
113 coutI(InputArguments) << "Modular likelihood detected and likelihood parallelization requested, "
114 << "also setting parallel gradient calculation mode." << std::endl;
116 }
117 // If _cfg.parallelize is larger than zero set the number of workers to that value. Otherwise do not do
118 // anything and let RooFit::MultiProcess handle the number of workers
119 if (_cfg.parallelize > 0)
122
123 _fcn = std::make_unique<RooFit::TestStatistics::MinuitFcnGrad>(
124 nll_real->getRooAbsL(), this, _theFitter->Config().ParamsSettings(),
126 static_cast<RooFit::TestStatistics::LikelihoodMode>(int(_cfg.enableParallelDescent))},
128#else
129 throw std::logic_error(
130 "Parallel minimization requested, but ROOT was not compiled with multiprocessing enabled, "
131 "please recompile with -Droofit_multiprocess=ON for parallel evaluation");
132#endif
133 } else { // modular test statistic non parallel
134 coutW(InputArguments)
135 << "Requested modular likelihood without gradient parallelization, some features such as offsetting "
136 << "may not work yet. Non-modular likelihoods are more reliable without parallelization." << std::endl;
137 // The RooRealL that is used in the case where the modular likelihood is being passed to a RooMinimizerFcn does
138 // not have offsetting implemented. Therefore, offsetting will not work in this case. Other features might also
139 // not work since the RooRealL was not intended for minimization. Further development is required to make the
140 // MinuitFcnGrad also handle serial gradient minimization. The MinuitFcnGrad accepts a RooAbsL and has
141 // offsetting implemented, thus omitting the need for RooRealL minimization altogether.
142 _fcn = std::make_unique<RooMinimizerFcn>(&function, this);
143 }
144 } else {
145 if (_cfg.parallelize != 0) { // Old test statistic with parallel likelihood or gradient
146 throw std::logic_error("In RooMinimizer constructor: Selected likelihood evaluation but a "
147 "non-modular likelihood was given. Please supply ModularL(true) as an "
148 "argument to createNLL for modular likelihoods to use likelihood "
149 "or gradient parallelization.");
150 }
151 _fcn = std::make_unique<RooMinimizerFcn>(&function, this);
152 }
154};
155
156/// Initialize the part of the minimizer that is independent of the function to be minimized
158{
159 RooSentinel::activate();
161
162 _theFitter = std::make_unique<ROOT::Fit::Fitter>();
163 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str());
164 setEps(1.0); // default tolerance
165}
166
167/// Initialize the part of the minimizer that is dependent on the function to be minimized
169{
170 // default max number of calls
171 _theFitter->Config().MinimizerOptions().SetMaxIterations(500 * _fcn->getNDim());
172 _theFitter->Config().MinimizerOptions().SetMaxFunctionCalls(500 * _fcn->getNDim());
173
174 // Shut up for now
175 setPrintLevel(-1);
176
177 // Use +0.5 for 1-sigma errors
179
180 // Declare our parameters to MINUIT
181 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
182
183 // Now set default verbosity
184 if (RooMsgService::instance().silentMode()) {
185 setPrintLevel(-1);
186 } else {
187 setPrintLevel(1);
188 }
189
190 // Set user defined and default _fcn config
192
193 // Likelihood holds information on offsetting in old style, so do not set here unless explicitly set by user
194 if (_cfg.offsetting != -1) {
196 }
197}
198
199////////////////////////////////////////////////////////////////////////////////
200/// Destructor
201
203
204////////////////////////////////////////////////////////////////////////////////
205/// Change MINUIT strategy to istrat. Accepted codes
206/// are 0,1,2 and represent MINUIT strategies for dealing
207/// most efficiently with fast FCNs (0), expensive FCNs (2)
208/// and 'intermediate' FCNs (1)
209
211{
212 _theFitter->Config().MinimizerOptions().SetStrategy(istrat);
213}
214
215////////////////////////////////////////////////////////////////////////////////
216/// Change maximum number of MINUIT iterations
217/// (RooMinimizer default 500 * #%parameters)
218
220{
221 _theFitter->Config().MinimizerOptions().SetMaxIterations(n);
222}
223
224////////////////////////////////////////////////////////////////////////////////
225/// Change maximum number of likelihood function class from MINUIT
226/// (RooMinimizer default 500 * #%parameters)
227
229{
230 _theFitter->Config().MinimizerOptions().SetMaxFunctionCalls(n);
231}
232
233////////////////////////////////////////////////////////////////////////////////
234/// Set the level for MINUIT error analysis to the given
235/// value. This function overrides the default value
236/// that is taken in the RooMinimizer constructor from
237/// the defaultErrorLevel() method of the input function
238
240{
241 _theFitter->Config().MinimizerOptions().SetErrorDef(level);
242}
243
244////////////////////////////////////////////////////////////////////////////////
245/// Change MINUIT epsilon
246
247void RooMinimizer::setEps(double eps)
248{
249 _theFitter->Config().MinimizerOptions().SetTolerance(eps);
250}
251
252////////////////////////////////////////////////////////////////////////////////
253/// Enable internal likelihood offsetting for enhanced numeric precision
254
256{
257 _cfg.offsetting = flag;
258 _fcn->setOffsetting(_cfg.offsetting);
259}
260
261////////////////////////////////////////////////////////////////////////////////
262/// Choose the minimizer algorithm.
263///
264/// Passing an empty string selects the default minimizer type returned by
265/// ROOT::Math::MinimizerOptions::DefaultMinimizerType().
266
267void RooMinimizer::setMinimizerType(std::string const &type)
268{
270
271 if ((_cfg.parallelize != 0) && _cfg.minimizerType != "Minuit2") {
272 std::stringstream ss;
273 ss << "In RooMinimizer::setMinimizerType: only Minuit2 is supported when not using classic function mode!";
274 if (type.empty()) {
275 ss << "\nPlease set it as your default minimizer via "
276 "ROOT::Math::MinimizerOptions::SetDefaultMinimizer(\"Minuit2\").";
277 }
278 throw std::invalid_argument(ss.str());
279 }
280}
281
282////////////////////////////////////////////////////////////////////////////////
283/// Return underlying ROOT fitter object
284
286{
287 return _theFitter.get();
288}
289
290////////////////////////////////////////////////////////////////////////////////
291/// Return underlying ROOT fitter object
292
294{
295 return _theFitter.get();
296}
297
299{
300 return _theFitter->FitFCN(*_fcn->getMultiGenFcn());
301}
302
303////////////////////////////////////////////////////////////////////////////////
304/// Minimise the function passed in the constructor.
305/// \param[in] type Type of fitter to use, e.g. "Minuit" "Minuit2". Passing an
306/// empty string will select the default minimizer type of the
307/// RooMinimizer, as returned by
308/// ROOT::Math::MinimizerOptions::DefaultMinimizerType().
309/// \attention This overrides the default fitter of this RooMinimizer.
310/// \param[in] alg Fit algorithm to use. (Optional)
311int RooMinimizer::minimize(const char *type, const char *alg)
312{
313 if (_cfg.timingAnalysis) {
314#ifdef ROOFIT_MULTIPROCESS
316#else
317 throw std::logic_error("ProcessTimer, but ROOT was not compiled with multiprocessing enabled, "
318 "please recompile with -Droofit_multiprocess=ON for logging with the "
319 "ProcessTimer.");
320#endif
321 }
322 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
323
325 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), alg);
326
327 profileStart();
328 {
329 auto ctx = makeEvalErrorContext();
330
331 bool ret = fitFcn();
332 _status = ((ret) ? _theFitter->Result().Status() : -1);
333 }
334 profileStop();
335 _fcn->BackProp(_theFitter->Result());
336
337 saveStatus("MINIMIZE", _status);
338
339 return _status;
340}
341
342////////////////////////////////////////////////////////////////////////////////
343/// Execute MIGRAD. Changes in parameter values
344/// and calculated errors are automatically
345/// propagated back the RooRealVars representing
346/// the floating parameters in the MINUIT operation.
347
349{
350 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
351 profileStart();
352 {
353 auto ctx = makeEvalErrorContext();
354
355 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "migrad");
356 bool ret = fitFcn();
357 _status = ((ret) ? _theFitter->Result().Status() : -1);
358 }
359 profileStop();
360 _fcn->BackProp(_theFitter->Result());
361
362 saveStatus("MIGRAD", _status);
363
364 return _status;
365}
366
367////////////////////////////////////////////////////////////////////////////////
368/// Execute HESSE. Changes in parameter values
369/// and calculated errors are automatically
370/// propagated back the RooRealVars representing
371/// the floating parameters in the MINUIT operation.
372
374{
375 if (_theFitter->GetMinimizer() == nullptr) {
376 coutW(Minimization) << "RooMinimizer::hesse: Error, run Migrad before Hesse!" << endl;
377 _status = -1;
378 } else {
379
380 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
381 profileStart();
382 {
383 auto ctx = makeEvalErrorContext();
384
385 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str());
386 bool ret = _theFitter->CalculateHessErrors();
387 _status = ((ret) ? _theFitter->Result().Status() : -1);
388 }
389 profileStop();
390 _fcn->BackProp(_theFitter->Result());
391
392 saveStatus("HESSE", _status);
393 }
394
395 return _status;
396}
397
398////////////////////////////////////////////////////////////////////////////////
399/// Execute MINOS. Changes in parameter values
400/// and calculated errors are automatically
401/// propagated back the RooRealVars representing
402/// the floating parameters in the MINUIT operation.
403
405{
406 if (_theFitter->GetMinimizer() == nullptr) {
407 coutW(Minimization) << "RooMinimizer::minos: Error, run Migrad before Minos!" << endl;
408 _status = -1;
409 } else {
410
411 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
412 profileStart();
413 {
414 auto ctx = makeEvalErrorContext();
415
416 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str());
417 bool ret = _theFitter->CalculateMinosErrors();
418 _status = ((ret) ? _theFitter->Result().Status() : -1);
419 }
420
421 profileStop();
422 _fcn->BackProp(_theFitter->Result());
423
424 saveStatus("MINOS", _status);
425 }
426
427 return _status;
428}
429
430////////////////////////////////////////////////////////////////////////////////
431/// Execute MINOS for given list of parameters. Changes in parameter values
432/// and calculated errors are automatically
433/// propagated back the RooRealVars representing
434/// the floating parameters in the MINUIT operation.
435
436int RooMinimizer::minos(const RooArgSet &minosParamList)
437{
438 if (_theFitter->GetMinimizer() == nullptr) {
439 coutW(Minimization) << "RooMinimizer::minos: Error, run Migrad before Minos!" << endl;
440 _status = -1;
441 } else if (!minosParamList.empty()) {
442
443 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
444 profileStart();
445 {
446 auto ctx = makeEvalErrorContext();
447
448 // get list of parameters for Minos
449 std::vector<unsigned int> paramInd;
450 for (RooAbsArg *arg : minosParamList) {
451 RooAbsArg *par = _fcn->GetFloatParamList()->find(arg->GetName());
452 if (par && !par->isConstant()) {
453 int index = _fcn->GetFloatParamList()->index(par);
454 paramInd.push_back(index);
455 }
456 }
457
458 if (!paramInd.empty()) {
459 // set the parameter indices
460 _theFitter->Config().SetMinosErrors(paramInd);
461
462 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str());
463 bool ret = _theFitter->CalculateMinosErrors();
464 _status = ((ret) ? _theFitter->Result().Status() : -1);
465 // to avoid that following minimization computes automatically the Minos errors
466 _theFitter->Config().SetMinosErrors(false);
467 }
468 }
469 profileStop();
470 _fcn->BackProp(_theFitter->Result());
471
472 saveStatus("MINOS", _status);
473 }
474
475 return _status;
476}
477
478////////////////////////////////////////////////////////////////////////////////
479/// Execute SEEK. Changes in parameter values
480/// and calculated errors are automatically
481/// propagated back the RooRealVars representing
482/// the floating parameters in the MINUIT operation.
483
485{
486 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
487 profileStart();
488 {
489 auto ctx = makeEvalErrorContext();
490
491 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "seek");
492 bool ret = fitFcn();
493 _status = ((ret) ? _theFitter->Result().Status() : -1);
494 }
495 profileStop();
496 _fcn->BackProp(_theFitter->Result());
497
498 saveStatus("SEEK", _status);
499
500 return _status;
501}
502
503////////////////////////////////////////////////////////////////////////////////
504/// Execute SIMPLEX. Changes in parameter values
505/// and calculated errors are automatically
506/// propagated back the RooRealVars representing
507/// the floating parameters in the MINUIT operation.
508
510{
511 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
512 profileStart();
513 {
514 auto ctx = makeEvalErrorContext();
515
516 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "simplex");
517 bool ret = fitFcn();
518 _status = ((ret) ? _theFitter->Result().Status() : -1);
519 }
520 profileStop();
521 _fcn->BackProp(_theFitter->Result());
522
523 saveStatus("SEEK", _status);
524
525 return _status;
526}
527
528////////////////////////////////////////////////////////////////////////////////
529/// Execute IMPROVE. Changes in parameter values
530/// and calculated errors are automatically
531/// propagated back the RooRealVars representing
532/// the floating parameters in the MINUIT operation.
533
535{
536 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
537 profileStart();
538 {
539 auto ctx = makeEvalErrorContext();
540
541 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "migradimproved");
542 bool ret = fitFcn();
543 _status = ((ret) ? _theFitter->Result().Status() : -1);
544 }
545 profileStop();
546 _fcn->BackProp(_theFitter->Result());
547
548 saveStatus("IMPROVE", _status);
549
550 return _status;
551}
552
553////////////////////////////////////////////////////////////////////////////////
554/// Change the MINUIT internal printing level
555
557{
558 _theFitter->Config().MinimizerOptions().SetPrintLevel(newLevel + 1);
559}
560
561////////////////////////////////////////////////////////////////////////////////
562/// Get the MINUIT internal printing level
563
565{
566 return _theFitter->Config().MinimizerOptions().PrintLevel() + 1;
567}
568
569////////////////////////////////////////////////////////////////////////////////
570/// If flag is true, perform constant term optimization on
571/// function being minimized.
572
574{
575 _fcn->setOptimizeConst(flag);
576}
577
578////////////////////////////////////////////////////////////////////////////////
579/// Save and return a RooFitResult snapshot of current minimizer status.
580/// This snapshot contains the values of all constant parameters,
581/// the value of all floating parameters at RooMinimizer construction and
582/// after the last MINUIT operation, the MINUIT status, variance quality,
583/// EDM setting, number of calls with evaluation problems, the minimized
584/// function value and the full correlation matrix.
585
586RooFit::OwningPtr<RooFitResult> RooMinimizer::save(const char *userName, const char *userTitle)
587{
588 if (_theFitter->GetMinimizer() == nullptr) {
589 coutW(Minimization) << "RooMinimizer::save: Error, run minimization before!" << endl;
590 return nullptr;
591 }
592
594 TString title;
595 name = userName ? userName : Form("%s", _fcn->getFunctionName().c_str());
596 title = userTitle ? userTitle : Form("%s", _fcn->getFunctionTitle().c_str());
597 auto fitRes = std::make_unique<RooFitResult>(name, title);
598
599 // Move eventual fixed parameters in floatList to constList
600 RooArgList saveConstList(*(_fcn->GetConstParamList()));
601 RooArgList saveFloatInitList(*(_fcn->GetInitFloatParamList()));
602 RooArgList saveFloatFinalList(*(_fcn->GetFloatParamList()));
603 for (std::size_t i = 0; i < _fcn->GetFloatParamList()->size(); i++) {
604 RooAbsArg *par = _fcn->GetFloatParamList()->at(i);
605 if (par->isConstant()) {
606 saveFloatInitList.remove(*saveFloatInitList.find(par->GetName()), true);
607 saveFloatFinalList.remove(*par);
608 saveConstList.add(*par);
609 }
610 }
611 saveConstList.sort();
612
613 fitRes->setConstParList(saveConstList);
614 fitRes->setInitParList(saveFloatInitList);
615
616 double removeOffset = 0.;
617 fitRes->setNumInvalidNLL(_fcn->GetNumInvalidNLL());
618 removeOffset = -_fcn->getOffset();
619
620 fitRes->setStatus(_status);
621 fitRes->setCovQual(_theFitter->GetMinimizer()->CovMatrixStatus());
622 fitRes->setMinNLL(_theFitter->Result().MinFcnValue() + removeOffset);
623 fitRes->setEDM(_theFitter->Result().Edm());
624 fitRes->setFinalParList(saveFloatFinalList);
625 if (!_extV) {
626 std::vector<double> globalCC;
627 TMatrixDSym corrs(_theFitter->Result().Parameters().size());
628 TMatrixDSym covs(_theFitter->Result().Parameters().size());
629 for (std::size_t ic = 0; ic < _theFitter->Result().Parameters().size(); ic++) {
630 globalCC.push_back(_theFitter->Result().GlobalCC(ic));
631 for (std::size_t ii = 0; ii < _theFitter->Result().Parameters().size(); ii++) {
632 corrs(ic, ii) = _theFitter->Result().Correlation(ic, ii);
633 covs(ic, ii) = _theFitter->Result().CovMatrix(ic, ii);
634 }
635 }
636 fitRes->fillCorrMatrix(globalCC, corrs, covs);
637 } else {
638 fitRes->setCovarianceMatrix(*_extV);
639 }
640
641 fitRes->setStatusHistory(_statusHistory);
642
643 return RooFit::makeOwningPtr(std::move(fitRes));
644}
645
646////////////////////////////////////////////////////////////////////////////////
647/// Create and draw a TH2 with the error contours in the parameters `var1` and `var2`.
648/// \param[in] var1 The first parameter (x axis).
649/// \param[in] var2 The second parameter (y axis).
650/// \param[in] n1 First contour.
651/// \param[in] n2 Optional contour. 0 means don't draw.
652/// \param[in] n3 Optional contour. 0 means don't draw.
653/// \param[in] n4 Optional contour. 0 means don't draw.
654/// \param[in] n5 Optional contour. 0 means don't draw.
655/// \param[in] n6 Optional contour. 0 means don't draw.
656/// \param[in] npoints Number of points for evaluating the contour.
657///
658/// Up to six contours can be drawn using the arguments `n1` to `n6` to request the desired
659/// coverage in units of \f$ \sigma = n^2 \cdot \mathrm{ErrorDef} \f$.
660/// See ROOT::Math::Minimizer::ErrorDef().
661
662RooPlot *RooMinimizer::contour(RooRealVar &var1, RooRealVar &var2, double n1, double n2, double n3, double n4,
663 double n5, double n6, unsigned int npoints)
664{
665 RooArgList *params = _fcn->GetFloatParamList();
666 RooArgList paramSave;
667 params->snapshot(paramSave);
668
669 // Verify that both variables are floating parameters of PDF
670 int index1 = _fcn->GetFloatParamList()->index(&var1);
671 if (index1 < 0) {
672 coutE(Minimization) << "RooMinimizer::contour(" << GetName() << ") ERROR: " << var1.GetName()
673 << " is not a floating parameter of " << _fcn->getFunctionName() << endl;
674 return nullptr;
675 }
676
677 int index2 = _fcn->GetFloatParamList()->index(&var2);
678 if (index2 < 0) {
679 coutE(Minimization) << "RooMinimizer::contour(" << GetName() << ") ERROR: " << var2.GetName()
680 << " is not a floating parameter of PDF " << _fcn->getFunctionName() << endl;
681 return nullptr;
682 }
683
684 // create and draw a frame
685 RooPlot *frame = new RooPlot(var1, var2);
686
687 // draw a point at the current parameter values
688 TMarker *point = new TMarker(var1.getVal(), var2.getVal(), 8);
689 frame->addObject(point);
690
691 // check first if a inimizer is available. If not means
692 // the minimization is not done , so do it
693 if (_theFitter->GetMinimizer() == nullptr) {
694 coutW(Minimization) << "RooMinimizer::contour: Error, run Migrad before contours!" << endl;
695 return frame;
696 }
697
698 // remember our original value of ERRDEF
699 double errdef = _theFitter->GetMinimizer()->ErrorDef();
700
701 double n[6];
702 n[0] = n1;
703 n[1] = n2;
704 n[2] = n3;
705 n[3] = n4;
706 n[4] = n5;
707 n[5] = n6;
708
709 for (int ic = 0; ic < 6; ic++) {
710 if (n[ic] > 0) {
711
712 // set the value corresponding to an n1-sigma contour
713 _theFitter->GetMinimizer()->SetErrorDef(n[ic] * n[ic] * errdef);
714
715 // calculate and draw the contour
716 std::vector<double> xcoor(npoints + 1);
717 std::vector<double> ycoor(npoints + 1);
718 bool ret = _theFitter->GetMinimizer()->Contour(index1, index2, npoints, xcoor.data(), ycoor.data());
719
720 if (!ret) {
721 coutE(Minimization) << "RooMinimizer::contour(" << GetName()
722 << ") ERROR: MINUIT did not return a contour graph for n=" << n[ic] << endl;
723 } else {
724 xcoor[npoints] = xcoor[0];
725 ycoor[npoints] = ycoor[0];
726 TGraph *graph = new TGraph(npoints + 1, xcoor.data(), ycoor.data());
727
728 graph->SetName(Form("contour_%s_n%f", _fcn->getFunctionName().c_str(), n[ic]));
729 graph->SetLineStyle(ic + 1);
730 graph->SetLineWidth(2);
731 graph->SetLineColor(kBlue);
732 frame->addObject(graph, "L");
733 }
734 }
735 }
736
737 // restore the original ERRDEF
738 _theFitter->GetMinimizer()->SetErrorDef(errdef);
739
740 // restore parameter values
741 params->assign(paramSave);
742
743 return frame;
744}
745
746////////////////////////////////////////////////////////////////////////////////
747/// Add parameters in metadata field to process timer
748
750{
751#ifdef ROOFIT_MULTIPROCESS
752 // parameter indices for use in timing heat matrix
753 std::vector<std::string> parameter_names;
754 for (auto &&parameter : *_fcn->GetFloatParamList()) {
755 parameter_names.push_back(parameter->GetName());
756 if (_cfg.verbose) {
757 coutI(Minimization) << "parameter name: " << parameter_names.back() << std::endl;
758 }
759 }
761#else
762 coutI(Minimization) << "Not adding parameters to processtimer because multiprocessing "
763 << "is not enabled." << std::endl;
764#endif
765}
766
767////////////////////////////////////////////////////////////////////////////////
768/// Start profiling timer
769
771{
772 if (_cfg.profile) {
773 _timer.Start();
774 _cumulTimer.Start(_profileStart ? false : true);
775 _profileStart = true;
776 }
777}
778
779////////////////////////////////////////////////////////////////////////////////
780/// Stop profiling timer and report results of last session
781
783{
784 if (_cfg.profile) {
785 _timer.Stop();
787 coutI(Minimization) << "Command timer: ";
788 _timer.Print();
789 coutI(Minimization) << "Session timer: ";
791 }
792}
793
795{
796 auto *fitterFcn = fitter()->GetFCN();
797 return fitterFcn ? fitterFcn : _fcn->getMultiGenFcn();
798}
799
800////////////////////////////////////////////////////////////////////////////////
801/// Apply results of given external covariance matrix. i.e. propagate its errors
802/// to all RRV parameter representations and give this matrix instead of the
803/// HESSE matrix at the next save() call
804
806{
807 _extV.reset(static_cast<TMatrixDSym *>(V.Clone()));
808 _fcn->ApplyCovarianceMatrix(*_extV);
809}
810
812{
814}
815
817{
818 // Import the results of the last fit performed, interpreting
819 // the fit parameters as the given varList of parameters.
820
821 if (_theFitter == nullptr || _theFitter->GetMinimizer() == nullptr) {
822 oocoutE(nullptr, InputArguments) << "RooMinimizer::save: Error, run minimization before!" << endl;
823 return nullptr;
824 }
825
826 // Verify length of supplied varList
827 if (!varList.empty() && varList.size() != _theFitter->Result().NTotalParameters()) {
828 oocoutE(nullptr, InputArguments)
829 << "RooMinimizer::lastMinuitFit: ERROR: supplied variable list must be either empty " << endl
830 << " or match the number of variables of the last fit ("
831 << _theFitter->Result().NTotalParameters() << ")" << endl;
832 return nullptr;
833 }
834
835 // Verify that all members of varList are of type RooRealVar
836 for (RooAbsArg *arg : varList) {
837 if (!dynamic_cast<RooRealVar *>(arg)) {
838 oocoutE(nullptr, InputArguments) << "RooMinimizer::lastMinuitFit: ERROR: variable '" << arg->GetName()
839 << "' is not of type RooRealVar" << endl;
840 return nullptr;
841 }
842 }
843
844 auto res = std::make_unique<RooFitResult>("lastMinuitFit", "Last MINUIT fit");
845
846 // Extract names of fit parameters
847 // and construct corresponding RooRealVars
848 RooArgList constPars("constPars");
849 RooArgList floatPars("floatPars");
850
851 unsigned int i;
852 for (i = 0; i < _theFitter->Result().NTotalParameters(); ++i) {
853
854 TString varName(_theFitter->Result().GetParameterName(i));
855 bool isConst(_theFitter->Result().IsParameterFixed(i));
856
857 double xlo = _theFitter->Config().ParSettings(i).LowerLimit();
858 double xhi = _theFitter->Config().ParSettings(i).UpperLimit();
859 double xerr = _theFitter->Result().Error(i);
860 double xval = _theFitter->Result().Value(i);
861
862 std::unique_ptr<RooRealVar> var;
863 if (varList.empty()) {
864
865 if ((xlo < xhi) && !isConst) {
866 var = std::make_unique<RooRealVar>(varName, varName, xval, xlo, xhi);
867 } else {
868 var = std::make_unique<RooRealVar>(varName, varName, xval);
869 }
870 var->setConstant(isConst);
871 } else {
872
873 var.reset(static_cast<RooRealVar *>(varList.at(i)->Clone()));
874 var->setConstant(isConst);
875 var->setVal(xval);
876 if (xlo < xhi) {
877 var->setRange(xlo, xhi);
878 }
879
880 if (varName.CompareTo(var->GetName())) {
881 oocoutI(nullptr, Eval) << "RooMinimizer::lastMinuitFit: fit parameter '" << varName
882 << "' stored in variable '" << var->GetName() << "'" << endl;
883 }
884 }
885
886 if (isConst) {
887 constPars.addOwned(std::move(var));
888 } else {
889 var->setError(xerr);
890 floatPars.addOwned(std::move(var));
891 }
892 }
893
894 res->setConstParList(constPars);
895 res->setInitParList(floatPars);
896 res->setFinalParList(floatPars);
897 res->setMinNLL(_theFitter->Result().MinFcnValue());
898 res->setEDM(_theFitter->Result().Edm());
899 res->setCovQual(_theFitter->GetMinimizer()->CovMatrixStatus());
900 res->setStatus(_theFitter->Result().Status());
901 std::vector<double> globalCC;
902 TMatrixDSym corrs(_theFitter->Result().Parameters().size());
903 TMatrixDSym covs(_theFitter->Result().Parameters().size());
904 for (unsigned int ic = 0; ic < _theFitter->Result().Parameters().size(); ic++) {
905 globalCC.push_back(_theFitter->Result().GlobalCC(ic));
906 for (unsigned int ii = 0; ii < _theFitter->Result().Parameters().size(); ii++) {
907 corrs(ic, ii) = _theFitter->Result().Correlation(ic, ii);
908 covs(ic, ii) = _theFitter->Result().CovMatrix(ic, ii);
909 }
910 }
911 res->fillCorrMatrix(globalCC, corrs, covs);
912
913 return RooFit::makeOwningPtr(std::move(res));
914}
915
916/// Try to recover from invalid function values. When invalid function values
917/// are encountered, a penalty term is returned to the minimiser to make it
918/// back off. This sets the strength of this penalty. \note A strength of zero
919/// is equivalent to a constant penalty (= the gradient vanishes, ROOT < 6.24).
920/// Positive values lead to a gradient pointing away from the undefined
921/// regions. Use ~10 to force the minimiser away from invalid function values.
923{
924 _cfg.recoverFromNaN = strength;
925}
926
927bool RooMinimizer::setLogFile(const char *logf)
928{
929 _cfg.logf = logf;
930 if (_cfg.logf) {
931 return _fcn->SetLogFile(_cfg.logf);
932 } else {
933 return false;
934 }
935}
936
938{
939 return _fcn->evalCounter();
940}
942{
943 _fcn->zeroEvalCount();
944}
945
947{
948 return _fcn->getNDim();
949}
950
951std::ofstream *RooMinimizer::logfile()
952{
953 return _fcn->GetLogFile();
954}
956{
957 return _fcn->GetMaxFCN();
958}
959
961{
962#ifdef ROOFIT_MULTIPROCESS
964#else
965 return 0;
966#endif
967}
968
969std::unique_ptr<RooAbsReal::EvalErrorContext> RooMinimizer::makeEvalErrorContext() const
970{
972 // If evaluation error printing is disabled, we don't need to collect the
973 // errors and only need to count them. This significantly reduces the
974 // performance overhead when having evaluation errors.
976 return std::make_unique<RooAbsReal::EvalErrorContext>(m);
977}
RooAbsReal & function()
double defaultErrorLevel() const override
Definition RooChi2Var.h:17
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define coutI(a)
#define coutW(a)
#define oocoutE(o, a)
#define oocoutI(o, a)
#define coutE(a)
#define ClassImp(name)
Definition Rtypes.h:377
@ kBlue
Definition Rtypes.h:66
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
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 winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
Definition TGX11.cxx:110
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2489
Fitter class, entry point for performing all type of fits.
Definition Fitter.h:77
ROOT::Math::IMultiGenFunction * GetFCN() const
return pointer to last used objective function (is NULL in case fit is not yet done) This pointer wil...
Definition Fitter.h:455
Documentation for the abstract class IBaseFunctionMultiDim.
Definition IFunction.h:61
static const std::string & DefaultMinimizerType()
Common abstract base class for objects that represent a value and a "shape" in RooFit.
Definition RooAbsArg.h:77
bool isConstant() const
Check if the "Constant" attribute is set.
Definition RooAbsArg.h:361
TObject * Clone(const char *newname=nullptr) const override
Make a clone of an object using the Streamer facility.
Definition RooAbsArg.h:89
virtual bool remove(const RooAbsArg &var, bool silent=false, bool matchByNameOnly=false)
Remove the specified argument from our list.
RooAbsCollection * snapshot(bool deepCopy=true) const
Take a snap shot of current collection contents.
virtual bool add(const RooAbsArg &var, bool silent=false)
Add the specified argument to list.
Int_t index(const RooAbsArg *arg) const
Returns index of given arg, or -1 if arg is not in the collection.
void assign(const RooAbsCollection &other) const
Sets the value, cache and constant attribute of any argument in our set that also appears in the othe...
Storage_t::size_type size() const
virtual bool addOwned(RooAbsArg &var, bool silent=false)
Add an argument and transfer the ownership to the collection.
void sort(bool reverse=false)
Sort collection using std::sort and name comparison.
RooAbsArg * find(const char *name) const
Find object with given name in list.
Abstract base class for objects that represent a real value and implements functionality common to al...
Definition RooAbsReal.h:59
double getVal(const RooArgSet *normalisationSet=nullptr) const
Evaluate object.
Definition RooAbsReal.h:103
virtual double defaultErrorLevel() const
Definition RooAbsReal.h:248
static void clearEvalErrorLog()
Clear the stack of evaluation error messages.
RooArgList is a container object that can hold multiple RooAbsArg objects.
Definition RooArgList.h:22
RooAbsArg * at(Int_t idx) const
Return object at given index, or nullptr if index is out of range.
Definition RooArgList.h:110
RooArgSet is a container object that can hold multiple RooAbsArg objects.
Definition RooArgSet.h:55
static void setDefaultNWorkers(unsigned int N_workers)
Definition Config.cxx:67
static unsigned int getDefaultNWorkers()
Definition Config.cxx:92
static void setTimingAnalysis(bool timingAnalysis)
Definition Config.cxx:78
static void add_metadata(json data)
RooAbsReal that wraps RooAbsL likelihoods for use in RooFit outside of the RooMinimizer context.
Definition RooRealL.h:28
Wrapper class around ROOT::Fit:Fitter that provides a seamless interface between the minimizer functi...
void setRecoverFromNaNStrength(double strength)
Try to recover from invalid function values.
static int getPrintLevel()
Get the MINUIT internal printing level.
void optimizeConst(int flag)
If flag is true, perform constant term optimization on function being minimized.
void initMinimizerFirstPart()
Initialize the part of the minimizer that is independent of the function to be minimized.
std::ofstream * logfile()
int simplex()
Execute SIMPLEX.
std::unique_ptr< TMatrixDSym > _extV
void setMinimizerType(std::string const &type)
Choose the minimizer algorithm.
RooFit::OwningPtr< RooFitResult > save(const char *name=nullptr, const char *title=nullptr)
Save and return a RooFitResult snapshot of current minimizer status.
std::vector< std::pair< std::string, int > > _statusHistory
void profileStart()
Start profiling timer.
RooPlot * contour(RooRealVar &var1, RooRealVar &var2, double n1=1.0, double n2=2.0, double n3=0.0, double n4=0.0, double n5=0.0, double n6=0.0, unsigned int npoints=50)
Create and draw a TH2 with the error contours in the parameters var1 and var2.
bool setLogFile(const char *logf=nullptr)
void initMinimizerFcnDependentPart(double defaultErrorLevel)
Initialize the part of the minimizer that is dependent on the function to be minimized.
void profileStop()
Stop profiling timer and report results of last session.
int minos()
Execute MINOS.
double & maxFCN()
int hesse()
Execute HESSE.
void setErrorLevel(double level)
Set the level for MINUIT error analysis to the given value.
static std::unique_ptr< ROOT::Fit::Fitter > _theFitter
int migrad()
Execute MIGRAD.
int seek()
Execute SEEK.
void setEps(double eps)
Change MINUIT epsilon.
void setPrintLevel(int newLevel)
Change the MINUIT internal printing level.
int improve()
Execute IMPROVE.
static void cleanup()
Cleanup method called by atexit handler installed by RooSentinel to delete all global heap objects wh...
void setOffsetting(bool flag)
Enable internal likelihood offsetting for enhanced numeric precision.
TStopwatch _timer
RooMinimizer::Config _cfg
static RooFit::OwningPtr< RooFitResult > lastMinuitFit()
bool fitFcn() const
void saveStatus(const char *label, int status)
~RooMinimizer() override
Destructor.
int minimize(const char *type, const char *alg=nullptr)
Minimise the function passed in the constructor.
ROOT::Math::IMultiGenFunction * getMultiGenFcn() const
std::unique_ptr< RooAbsReal::EvalErrorContext > makeEvalErrorContext() const
RooMinimizer(RooAbsReal &function, Config const &cfg={})
Construct MINUIT interface to given function.
ROOT::Fit::Fitter * fitter()
Return underlying ROOT fitter object.
void setMaxFunctionCalls(int n)
Change maximum number of likelihood function class from MINUIT (RooMinimizer default 500 * #parameter...
void setStrategy(int istrat)
Change MINUIT strategy to istrat.
int evalCounter() const
TStopwatch _cumulTimer
int getNPar() const
void setMaxIterations(int n)
Change maximum number of MINUIT iterations (RooMinimizer default 500 * #parameters)
void addParamsToProcessTimer()
Add parameters in metadata field to process timer.
std::unique_ptr< RooAbsMinimizerFcn > _fcn
void applyCovarianceMatrix(TMatrixDSym const &V)
Apply results of given external covariance matrix.
static RooMsgService & instance()
Return reference to singleton instance.
Plot frame and a container for graphics objects within that frame.
Definition RooPlot.h:43
void addObject(TObject *obj, Option_t *drawOptions="", bool invisible=false)
Add a generic object to this plot.
Definition RooPlot.cxx:378
Variable that can be changed from the outside.
Definition RooRealVar.h:37
A TGraph is an object made of two arrays X and Y with npoints each.
Definition TGraph.h:41
Manages Markers.
Definition TMarker.h:22
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual TObject * Clone(const char *newname="") const
Make a clone of an object using the Streamer facility.
Definition TObject.cxx:223
void Start(Bool_t reset=kTRUE)
Start the stopwatch.
void Stop()
Stop the stopwatch.
void Print(Option_t *option="") const override
Print the real and cpu time passed between the start and stop events.
Basic string class.
Definition TString.h:139
int CompareTo(const char *cs, ECaseCompare cmp=kExact) const
Compare a string to char *cs2.
Definition TString.cxx:457
const Int_t n
Definition legend1.C:16
OwningPtr< T > makeOwningPtr(std::unique_ptr< T > &&ptr)
Internal helper to turn a std::unique_ptr<T> into an OwningPtr.
Definition Config.h:40
T * OwningPtr
An alias for raw pointers for indicating that the return type of a RooFit function is an owning point...
Definition Config.h:35
Definition graph.py:1
Config argument to RooMinimizer constructor.
std::string minimizerType
TMarker m
Definition textangle.C:8