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
303void RooMinimizer::determineStatus(bool fitterReturnValue)
304{
305 // Minuit-given status:
306 _status = ((fitterReturnValue) ? _theFitter->Result().Status() : -1);
307
308 // RooFit-based additional failed state information:
309 if (evalCounter() <= _fcn->GetNumInvalidNLL()) {
310 coutE(Minimization) << "RooMinimizer: all function calls during minimization gave invalid NLL values!"
311 << std::endl;
312 }
313}
314
315////////////////////////////////////////////////////////////////////////////////
316/// Minimise the function passed in the constructor.
317/// \param[in] type Type of fitter to use, e.g. "Minuit" "Minuit2". Passing an
318/// empty string will select the default minimizer type of the
319/// RooMinimizer, as returned by
320/// ROOT::Math::MinimizerOptions::DefaultMinimizerType().
321/// \attention This overrides the default fitter of this RooMinimizer.
322/// \param[in] alg Fit algorithm to use. (Optional)
323int RooMinimizer::minimize(const char *type, const char *alg)
324{
325 if (_cfg.timingAnalysis) {
326#ifdef ROOFIT_MULTIPROCESS
328#else
329 throw std::logic_error("ProcessTimer, but ROOT was not compiled with multiprocessing enabled, "
330 "please recompile with -Droofit_multiprocess=ON for logging with the "
331 "ProcessTimer.");
332#endif
333 }
334 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
335
337 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), alg);
338
339 profileStart();
340 {
341 auto ctx = makeEvalErrorContext();
342
343 bool ret = fitFcn();
344 determineStatus(ret);
345 }
346 profileStop();
347 _fcn->BackProp(_theFitter->Result());
348
349 saveStatus("MINIMIZE", _status);
350
351 return _status;
352}
353
354////////////////////////////////////////////////////////////////////////////////
355/// Execute MIGRAD. Changes in parameter values
356/// and calculated errors are automatically
357/// propagated back the RooRealVars representing
358/// the floating parameters in the MINUIT operation.
359
361{
362 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
363 profileStart();
364 {
365 auto ctx = makeEvalErrorContext();
366
367 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "migrad");
368 bool ret = fitFcn();
369 determineStatus(ret);
370 }
371 profileStop();
372 _fcn->BackProp(_theFitter->Result());
373
374 saveStatus("MIGRAD", _status);
375
376 return _status;
377}
378
379////////////////////////////////////////////////////////////////////////////////
380/// Execute HESSE. Changes in parameter values
381/// and calculated errors are automatically
382/// propagated back the RooRealVars representing
383/// the floating parameters in the MINUIT operation.
384
386{
387 if (_theFitter->GetMinimizer() == nullptr) {
388 coutW(Minimization) << "RooMinimizer::hesse: Error, run Migrad before Hesse!" << endl;
389 _status = -1;
390 } else {
391
392 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
393 profileStart();
394 {
395 auto ctx = makeEvalErrorContext();
396
397 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str());
398 bool ret = _theFitter->CalculateHessErrors();
399 determineStatus(ret);
400 }
401 profileStop();
402 _fcn->BackProp(_theFitter->Result());
403
404 saveStatus("HESSE", _status);
405 }
406
407 return _status;
408}
409
410////////////////////////////////////////////////////////////////////////////////
411/// Execute MINOS. Changes in parameter values
412/// and calculated errors are automatically
413/// propagated back the RooRealVars representing
414/// the floating parameters in the MINUIT operation.
415
417{
418 if (_theFitter->GetMinimizer() == nullptr) {
419 coutW(Minimization) << "RooMinimizer::minos: Error, run Migrad before Minos!" << endl;
420 _status = -1;
421 } else {
422
423 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
424 profileStart();
425 {
426 auto ctx = makeEvalErrorContext();
427
428 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str());
429 bool ret = _theFitter->CalculateMinosErrors();
430 determineStatus(ret);
431 }
432
433 profileStop();
434 _fcn->BackProp(_theFitter->Result());
435
436 saveStatus("MINOS", _status);
437 }
438
439 return _status;
440}
441
442////////////////////////////////////////////////////////////////////////////////
443/// Execute MINOS for given list of parameters. Changes in parameter values
444/// and calculated errors are automatically
445/// propagated back the RooRealVars representing
446/// the floating parameters in the MINUIT operation.
447
448int RooMinimizer::minos(const RooArgSet &minosParamList)
449{
450 if (_theFitter->GetMinimizer() == nullptr) {
451 coutW(Minimization) << "RooMinimizer::minos: Error, run Migrad before Minos!" << endl;
452 _status = -1;
453 } else if (!minosParamList.empty()) {
454
455 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
456 profileStart();
457 {
458 auto ctx = makeEvalErrorContext();
459
460 // get list of parameters for Minos
461 std::vector<unsigned int> paramInd;
462 for (RooAbsArg *arg : minosParamList) {
463 RooAbsArg *par = _fcn->GetFloatParamList()->find(arg->GetName());
464 if (par && !par->isConstant()) {
465 int index = _fcn->GetFloatParamList()->index(par);
466 paramInd.push_back(index);
467 }
468 }
469
470 if (!paramInd.empty()) {
471 // set the parameter indices
472 _theFitter->Config().SetMinosErrors(paramInd);
473
474 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str());
475 bool ret = _theFitter->CalculateMinosErrors();
476 determineStatus(ret);
477 // to avoid that following minimization computes automatically the Minos errors
478 _theFitter->Config().SetMinosErrors(false);
479 }
480 }
481 profileStop();
482 _fcn->BackProp(_theFitter->Result());
483
484 saveStatus("MINOS", _status);
485 }
486
487 return _status;
488}
489
490////////////////////////////////////////////////////////////////////////////////
491/// Execute SEEK. Changes in parameter values
492/// and calculated errors are automatically
493/// propagated back the RooRealVars representing
494/// the floating parameters in the MINUIT operation.
495
497{
498 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
499 profileStart();
500 {
501 auto ctx = makeEvalErrorContext();
502
503 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "seek");
504 bool ret = fitFcn();
505 determineStatus(ret);
506 }
507 profileStop();
508 _fcn->BackProp(_theFitter->Result());
509
510 saveStatus("SEEK", _status);
511
512 return _status;
513}
514
515////////////////////////////////////////////////////////////////////////////////
516/// Execute SIMPLEX. Changes in parameter values
517/// and calculated errors are automatically
518/// propagated back the RooRealVars representing
519/// the floating parameters in the MINUIT operation.
520
522{
523 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
524 profileStart();
525 {
526 auto ctx = makeEvalErrorContext();
527
528 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "simplex");
529 bool ret = fitFcn();
530 determineStatus(ret);
531 }
532 profileStop();
533 _fcn->BackProp(_theFitter->Result());
534
535 saveStatus("SEEK", _status);
536
537 return _status;
538}
539
540////////////////////////////////////////////////////////////////////////////////
541/// Execute IMPROVE. Changes in parameter values
542/// and calculated errors are automatically
543/// propagated back the RooRealVars representing
544/// the floating parameters in the MINUIT operation.
545
547{
548 _fcn->Synchronize(_theFitter->Config().ParamsSettings());
549 profileStart();
550 {
551 auto ctx = makeEvalErrorContext();
552
553 _theFitter->Config().SetMinimizer(_cfg.minimizerType.c_str(), "migradimproved");
554 bool ret = fitFcn();
555 determineStatus(ret);
556 }
557 profileStop();
558 _fcn->BackProp(_theFitter->Result());
559
560 saveStatus("IMPROVE", _status);
561
562 return _status;
563}
564
565////////////////////////////////////////////////////////////////////////////////
566/// Change the MINUIT internal printing level
567
569{
570 _theFitter->Config().MinimizerOptions().SetPrintLevel(newLevel + 1);
571}
572
573////////////////////////////////////////////////////////////////////////////////
574/// Get the MINUIT internal printing level
575
577{
578 return _theFitter->Config().MinimizerOptions().PrintLevel() + 1;
579}
580
581////////////////////////////////////////////////////////////////////////////////
582/// If flag is true, perform constant term optimization on
583/// function being minimized.
584
586{
587 _fcn->setOptimizeConst(flag);
588}
589
590////////////////////////////////////////////////////////////////////////////////
591/// Save and return a RooFitResult snapshot of current minimizer status.
592/// This snapshot contains the values of all constant parameters,
593/// the value of all floating parameters at RooMinimizer construction and
594/// after the last MINUIT operation, the MINUIT status, variance quality,
595/// EDM setting, number of calls with evaluation problems, the minimized
596/// function value and the full correlation matrix.
597
598RooFit::OwningPtr<RooFitResult> RooMinimizer::save(const char *userName, const char *userTitle)
599{
600 if (_theFitter->GetMinimizer() == nullptr) {
601 coutW(Minimization) << "RooMinimizer::save: Error, run minimization before!" << endl;
602 return nullptr;
603 }
604
606 TString title;
607 name = userName ? userName : Form("%s", _fcn->getFunctionName().c_str());
608 title = userTitle ? userTitle : Form("%s", _fcn->getFunctionTitle().c_str());
609 auto fitRes = std::make_unique<RooFitResult>(name, title);
610
611 // Move eventual fixed parameters in floatList to constList
612 RooArgList saveConstList(*(_fcn->GetConstParamList()));
613 RooArgList saveFloatInitList(*(_fcn->GetInitFloatParamList()));
614 RooArgList saveFloatFinalList(*(_fcn->GetFloatParamList()));
615 for (std::size_t i = 0; i < _fcn->GetFloatParamList()->size(); i++) {
616 RooAbsArg *par = _fcn->GetFloatParamList()->at(i);
617 if (par->isConstant()) {
618 saveFloatInitList.remove(*saveFloatInitList.find(par->GetName()), true);
619 saveFloatFinalList.remove(*par);
620 saveConstList.add(*par);
621 }
622 }
623 saveConstList.sort();
624
625 fitRes->setConstParList(saveConstList);
626 fitRes->setInitParList(saveFloatInitList);
627
628 double removeOffset = 0.;
629 fitRes->setNumInvalidNLL(_fcn->GetNumInvalidNLL());
630 removeOffset = -_fcn->getOffset();
631
632 fitRes->setStatus(_status);
633 fitRes->setCovQual(_theFitter->GetMinimizer()->CovMatrixStatus());
634 fitRes->setMinNLL(_theFitter->Result().MinFcnValue() + removeOffset);
635 fitRes->setEDM(_theFitter->Result().Edm());
636 fitRes->setFinalParList(saveFloatFinalList);
637 if (!_extV) {
638 std::vector<double> globalCC;
639 TMatrixDSym corrs(_theFitter->Result().Parameters().size());
640 TMatrixDSym covs(_theFitter->Result().Parameters().size());
641 for (std::size_t ic = 0; ic < _theFitter->Result().Parameters().size(); ic++) {
642 globalCC.push_back(_theFitter->Result().GlobalCC(ic));
643 for (std::size_t ii = 0; ii < _theFitter->Result().Parameters().size(); ii++) {
644 corrs(ic, ii) = _theFitter->Result().Correlation(ic, ii);
645 covs(ic, ii) = _theFitter->Result().CovMatrix(ic, ii);
646 }
647 }
648 fitRes->fillCorrMatrix(globalCC, corrs, covs);
649 } else {
650 fitRes->setCovarianceMatrix(*_extV);
651 }
652
653 fitRes->setStatusHistory(_statusHistory);
654
655 return RooFit::makeOwningPtr(std::move(fitRes));
656}
657
658////////////////////////////////////////////////////////////////////////////////
659/// Create and draw a TH2 with the error contours in the parameters `var1` and `var2`.
660/// \param[in] var1 The first parameter (x axis).
661/// \param[in] var2 The second parameter (y axis).
662/// \param[in] n1 First contour.
663/// \param[in] n2 Optional contour. 0 means don't draw.
664/// \param[in] n3 Optional contour. 0 means don't draw.
665/// \param[in] n4 Optional contour. 0 means don't draw.
666/// \param[in] n5 Optional contour. 0 means don't draw.
667/// \param[in] n6 Optional contour. 0 means don't draw.
668/// \param[in] npoints Number of points for evaluating the contour.
669///
670/// Up to six contours can be drawn using the arguments `n1` to `n6` to request the desired
671/// coverage in units of \f$ \sigma = n^2 \cdot \mathrm{ErrorDef} \f$.
672/// See ROOT::Math::Minimizer::ErrorDef().
673
674RooPlot *RooMinimizer::contour(RooRealVar &var1, RooRealVar &var2, double n1, double n2, double n3, double n4,
675 double n5, double n6, unsigned int npoints)
676{
677 RooArgList *params = _fcn->GetFloatParamList();
678 RooArgList paramSave;
679 params->snapshot(paramSave);
680
681 // Verify that both variables are floating parameters of PDF
682 int index1 = _fcn->GetFloatParamList()->index(&var1);
683 if (index1 < 0) {
684 coutE(Minimization) << "RooMinimizer::contour(" << GetName() << ") ERROR: " << var1.GetName()
685 << " is not a floating parameter of " << _fcn->getFunctionName() << endl;
686 return nullptr;
687 }
688
689 int index2 = _fcn->GetFloatParamList()->index(&var2);
690 if (index2 < 0) {
691 coutE(Minimization) << "RooMinimizer::contour(" << GetName() << ") ERROR: " << var2.GetName()
692 << " is not a floating parameter of PDF " << _fcn->getFunctionName() << endl;
693 return nullptr;
694 }
695
696 // create and draw a frame
697 RooPlot *frame = new RooPlot(var1, var2);
698
699 // draw a point at the current parameter values
700 TMarker *point = new TMarker(var1.getVal(), var2.getVal(), 8);
701 frame->addObject(point);
702
703 // check first if a inimizer is available. If not means
704 // the minimization is not done , so do it
705 if (_theFitter->GetMinimizer() == nullptr) {
706 coutW(Minimization) << "RooMinimizer::contour: Error, run Migrad before contours!" << endl;
707 return frame;
708 }
709
710 // remember our original value of ERRDEF
711 double errdef = _theFitter->GetMinimizer()->ErrorDef();
712
713 double n[6];
714 n[0] = n1;
715 n[1] = n2;
716 n[2] = n3;
717 n[3] = n4;
718 n[4] = n5;
719 n[5] = n6;
720
721 for (int ic = 0; ic < 6; ic++) {
722 if (n[ic] > 0) {
723
724 // set the value corresponding to an n1-sigma contour
725 _theFitter->GetMinimizer()->SetErrorDef(n[ic] * n[ic] * errdef);
726
727 // calculate and draw the contour
728 std::vector<double> xcoor(npoints + 1);
729 std::vector<double> ycoor(npoints + 1);
730 bool ret = _theFitter->GetMinimizer()->Contour(index1, index2, npoints, xcoor.data(), ycoor.data());
731
732 if (!ret) {
733 coutE(Minimization) << "RooMinimizer::contour(" << GetName()
734 << ") ERROR: MINUIT did not return a contour graph for n=" << n[ic] << endl;
735 } else {
736 xcoor[npoints] = xcoor[0];
737 ycoor[npoints] = ycoor[0];
738 TGraph *graph = new TGraph(npoints + 1, xcoor.data(), ycoor.data());
739
740 graph->SetName(Form("contour_%s_n%f", _fcn->getFunctionName().c_str(), n[ic]));
741 graph->SetLineStyle(ic + 1);
742 graph->SetLineWidth(2);
743 graph->SetLineColor(kBlue);
744 frame->addObject(graph, "L");
745 }
746 }
747 }
748
749 // restore the original ERRDEF
750 _theFitter->GetMinimizer()->SetErrorDef(errdef);
751
752 // restore parameter values
753 params->assign(paramSave);
754
755 return frame;
756}
757
758////////////////////////////////////////////////////////////////////////////////
759/// Add parameters in metadata field to process timer
760
762{
763#ifdef ROOFIT_MULTIPROCESS
764 // parameter indices for use in timing heat matrix
765 std::vector<std::string> parameter_names;
766 for (auto &&parameter : *_fcn->GetFloatParamList()) {
767 parameter_names.push_back(parameter->GetName());
768 if (_cfg.verbose) {
769 coutI(Minimization) << "parameter name: " << parameter_names.back() << std::endl;
770 }
771 }
773#else
774 coutI(Minimization) << "Not adding parameters to processtimer because multiprocessing is not enabled." << std::endl;
775#endif
776}
777
778////////////////////////////////////////////////////////////////////////////////
779/// Start profiling timer
780
782{
783 if (_cfg.profile) {
784 _timer.Start();
785 _cumulTimer.Start(_profileStart ? false : true);
786 _profileStart = true;
787 }
788}
789
790////////////////////////////////////////////////////////////////////////////////
791/// Stop profiling timer and report results of last session
792
794{
795 if (_cfg.profile) {
796 _timer.Stop();
798 coutI(Minimization) << "Command timer: ";
799 _timer.Print();
800 coutI(Minimization) << "Session timer: ";
802 }
803}
804
806{
807 auto *fitterFcn = fitter()->GetFCN();
808 return fitterFcn ? fitterFcn : _fcn->getMultiGenFcn();
809}
810
811////////////////////////////////////////////////////////////////////////////////
812/// Apply results of given external covariance matrix. i.e. propagate its errors
813/// to all RRV parameter representations and give this matrix instead of the
814/// HESSE matrix at the next save() call
815
817{
818 _extV.reset(static_cast<TMatrixDSym *>(V.Clone()));
819 _fcn->ApplyCovarianceMatrix(*_extV);
820}
821
823{
825}
826
828{
829 // Import the results of the last fit performed, interpreting
830 // the fit parameters as the given varList of parameters.
831
832 if (_theFitter == nullptr || _theFitter->GetMinimizer() == nullptr) {
833 oocoutE(nullptr, InputArguments) << "RooMinimizer::save: Error, run minimization before!" << endl;
834 return nullptr;
835 }
836
837 // Verify length of supplied varList
838 if (!varList.empty() && varList.size() != _theFitter->Result().NTotalParameters()) {
839 oocoutE(nullptr, InputArguments)
840 << "RooMinimizer::lastMinuitFit: ERROR: supplied variable list must be either empty " << endl
841 << " or match the number of variables of the last fit ("
842 << _theFitter->Result().NTotalParameters() << ")" << endl;
843 return nullptr;
844 }
845
846 // Verify that all members of varList are of type RooRealVar
847 for (RooAbsArg *arg : varList) {
848 if (!dynamic_cast<RooRealVar *>(arg)) {
849 oocoutE(nullptr, InputArguments) << "RooMinimizer::lastMinuitFit: ERROR: variable '" << arg->GetName()
850 << "' is not of type RooRealVar" << endl;
851 return nullptr;
852 }
853 }
854
855 auto res = std::make_unique<RooFitResult>("lastMinuitFit", "Last MINUIT fit");
856
857 // Extract names of fit parameters
858 // and construct corresponding RooRealVars
859 RooArgList constPars("constPars");
860 RooArgList floatPars("floatPars");
861
862 unsigned int i;
863 for (i = 0; i < _theFitter->Result().NTotalParameters(); ++i) {
864
865 TString varName(_theFitter->Result().GetParameterName(i));
866 bool isConst(_theFitter->Result().IsParameterFixed(i));
867
868 double xlo = _theFitter->Config().ParSettings(i).LowerLimit();
869 double xhi = _theFitter->Config().ParSettings(i).UpperLimit();
870 double xerr = _theFitter->Result().Error(i);
871 double xval = _theFitter->Result().Value(i);
872
873 std::unique_ptr<RooRealVar> var;
874 if (varList.empty()) {
875
876 if ((xlo < xhi) && !isConst) {
877 var = std::make_unique<RooRealVar>(varName, varName, xval, xlo, xhi);
878 } else {
879 var = std::make_unique<RooRealVar>(varName, varName, xval);
880 }
881 var->setConstant(isConst);
882 } else {
883
884 var.reset(static_cast<RooRealVar *>(varList.at(i)->Clone()));
885 var->setConstant(isConst);
886 var->setVal(xval);
887 if (xlo < xhi) {
888 var->setRange(xlo, xhi);
889 }
890
891 if (varName.CompareTo(var->GetName())) {
892 oocoutI(nullptr, Eval) << "RooMinimizer::lastMinuitFit: fit parameter '" << varName
893 << "' stored in variable '" << var->GetName() << "'" << endl;
894 }
895 }
896
897 if (isConst) {
898 constPars.addOwned(std::move(var));
899 } else {
900 var->setError(xerr);
901 floatPars.addOwned(std::move(var));
902 }
903 }
904
905 res->setConstParList(constPars);
906 res->setInitParList(floatPars);
907 res->setFinalParList(floatPars);
908 res->setMinNLL(_theFitter->Result().MinFcnValue());
909 res->setEDM(_theFitter->Result().Edm());
910 res->setCovQual(_theFitter->GetMinimizer()->CovMatrixStatus());
911 res->setStatus(_theFitter->Result().Status());
912 std::vector<double> globalCC;
913 TMatrixDSym corrs(_theFitter->Result().Parameters().size());
914 TMatrixDSym covs(_theFitter->Result().Parameters().size());
915 for (unsigned int ic = 0; ic < _theFitter->Result().Parameters().size(); ic++) {
916 globalCC.push_back(_theFitter->Result().GlobalCC(ic));
917 for (unsigned int ii = 0; ii < _theFitter->Result().Parameters().size(); ii++) {
918 corrs(ic, ii) = _theFitter->Result().Correlation(ic, ii);
919 covs(ic, ii) = _theFitter->Result().CovMatrix(ic, ii);
920 }
921 }
922 res->fillCorrMatrix(globalCC, corrs, covs);
923
924 return RooFit::makeOwningPtr(std::move(res));
925}
926
927/// Try to recover from invalid function values. When invalid function values
928/// are encountered, a penalty term is returned to the minimiser to make it
929/// back off. This sets the strength of this penalty. \note A strength of zero
930/// is equivalent to a constant penalty (= the gradient vanishes, ROOT < 6.24).
931/// Positive values lead to a gradient pointing away from the undefined
932/// regions. Use ~10 to force the minimiser away from invalid function values.
934{
935 _cfg.recoverFromNaN = strength;
936}
937
938bool RooMinimizer::setLogFile(const char *logf)
939{
940 _cfg.logf = logf;
941 if (_cfg.logf) {
942 return _fcn->SetLogFile(_cfg.logf);
943 } else {
944 return false;
945 }
946}
947
949{
950 return _fcn->evalCounter();
951}
953{
954 _fcn->zeroEvalCount();
955}
956
958{
959 return _fcn->getNDim();
960}
961
962std::ofstream *RooMinimizer::logfile()
963{
964 return _fcn->GetLogFile();
965}
967{
968 return _fcn->GetMaxFCN();
969}
971{
972 return _fcn->getOffset();
973}
974
976{
977#ifdef ROOFIT_MULTIPROCESS
979#else
980 return 0;
981#endif
982}
983
984std::unique_ptr<RooAbsReal::EvalErrorContext> RooMinimizer::makeEvalErrorContext() const
985{
987 // If evaluation error printing is disabled, we don't need to collect the
988 // errors and only need to count them. This significantly reduces the
989 // performance overhead when having evaluation errors.
991 return std::make_unique<RooAbsReal::EvalErrorContext>(m);
992}
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.
double & fcnOffset() const
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
void determineStatus(bool fitterReturnValue)
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:45
void addObject(TObject *obj, Option_t *drawOptions="", bool invisible=false)
Add a generic object to this plot.
Definition RooPlot.cxx:366
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:438
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