/***************************************************************************** * Project: RooFit * * Package: RooFitCore * * @(#)root/roofitcore:$Id$ * Authors: * * WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu * * DK, David Kirkby, UC Irvine, dkirkby@uci.edu * * AL, Alfio Lazzaro, INFN Milan, alfio.lazzaro@mi.infn.it * * * * Redistribution and use in source and binary forms, * * with or without modification, are permitted according to the terms * * listed in LICENSE (http://roofit.sourceforge.net/license.txt) * *****************************************************************************/ ////////////////////////////////////////////////////////////////////////////// // // BEGIN_HTML // RooMinimizer is a wrapper class around ROOT::Fit:Fitter that // provides a seamless interface between the minimizer functionality // and the native RooFit interface. //

// By default the Minimizer is MINUIT. //

// RooMinimizer can minimize any RooAbsReal function with respect to // its parameters. Usual choices for minimization are RooNLLVar // and RooChi2Var //

// RooMinimizer has methods corresponding to MINUIT functions like // hesse(), migrad(), minos() etc. In each of these function calls // the state of the MINUIT engine is synchronized with the state // of the RooFit variables: any change in variables, change // in the constant status etc is forwarded to MINUIT prior to // execution of the MINUIT call. Afterwards the RooFit objects // are resynchronized with the output state of MINUIT: changes // parameter values, errors are propagated. //

// Various methods are available to control verbosity, profiling, // automatic PDF optimization. // END_HTML // #ifndef __ROOFIT_NOROOMINIMIZER #include "RooFit.h" #include "Riostream.h" #include "TClass.h" #include #include #include "TH1.h" #include "TH2.h" #include "TMarker.h" #include "TGraph.h" #include "TStopwatch.h" #include "TDirectory.h" #include "TMatrixDSym.h" #include "RooArgSet.h" #include "RooArgList.h" #include "RooAbsReal.h" #include "RooAbsRealLValue.h" #include "RooRealVar.h" #include "RooAbsPdf.h" #include "RooSentinel.h" #include "RooMsgService.h" #include "RooPlot.h" #include "RooMinimizer.h" #include "RooFitResult.h" #include "Math/Minimizer.h" #if (__GNUC__==3&&__GNUC_MINOR__==2&&__GNUC_PATCHLEVEL__==3) char* operator+( streampos&, char* ); #endif using namespace std; ClassImp(RooMinimizer) ; ROOT::Fit::Fitter *RooMinimizer::_theFitter = 0 ; //////////////////////////////////////////////////////////////////////////////// /// Cleanup method called by atexit handler installed by RooSentinel /// to delete all global heap objects when the program is terminated void RooMinimizer::cleanup() { if (_theFitter) { delete _theFitter ; _theFitter =0 ; } } //////////////////////////////////////////////////////////////////////////////// /// Construct MINUIT interface to given function. Function can be anything, /// but is typically a -log(likelihood) implemented by RooNLLVar or a chi^2 /// (implemented by RooChi2Var). Other frequent use cases are a RooAddition /// of a RooNLLVar plus a penalty or constraint term. This class propagates /// all RooFit information (floating parameters, their values and errors) /// to MINUIT before each MINUIT call and propagates all MINUIT information /// back to the RooFit object at the end of each call (updated parameter /// values, their (asymmetric errors) etc. The default MINUIT error level /// for HESSE and MINOS error analysis is taken from the defaultErrorLevel() /// value of the input function. RooMinimizer::RooMinimizer(RooAbsReal& function) { RooSentinel::activate() ; // Store function reference _extV = 0 ; _func = &function ; _optConst = kFALSE ; _verbose = kFALSE ; _profile = kFALSE ; _profileStart = kFALSE ; _printLevel = 1 ; _minimizerType = "Minuit"; // default minimizer if (_theFitter) delete _theFitter ; _theFitter = new ROOT::Fit::Fitter; _fcn = new RooMinimizerFcn(_func,this,_verbose); _theFitter->Config().SetMinimizer(_minimizerType.c_str()); setEps(1.0); // default tolerance // default max number of calls _theFitter->Config().MinimizerOptions().SetMaxIterations(500*_fcn->NDim()); _theFitter->Config().MinimizerOptions().SetMaxFunctionCalls(500*_fcn->NDim()); // Shut up for now setPrintLevel(-1) ; // Use +0.5 for 1-sigma errors setErrorLevel(_func->defaultErrorLevel()) ; // Declare our parameters to MINUIT _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; // Now set default verbosity if (RooMsgService::instance().silentMode()) { setPrintLevel(-1) ; } else { setPrintLevel(1) ; } } //////////////////////////////////////////////////////////////////////////////// /// Destructor RooMinimizer::~RooMinimizer() { if (_extV) { delete _extV ; } if (_fcn) { delete _fcn; } } //////////////////////////////////////////////////////////////////////////////// /// Change MINUIT strategy to istrat. Accepted codes /// are 0,1,2 and represent MINUIT strategies for dealing /// most efficiently with fast FCNs (0), expensive FCNs (2) /// and 'intermediate' FCNs (1) void RooMinimizer::setStrategy(Int_t istrat) { _theFitter->Config().MinimizerOptions().SetStrategy(istrat); } //////////////////////////////////////////////////////////////////////////////// /// Change maximum number of MINUIT iterations /// (RooMinimizer default 500 * #parameters) void RooMinimizer::setMaxIterations(Int_t n) { _theFitter->Config().MinimizerOptions().SetMaxIterations(n); } //////////////////////////////////////////////////////////////////////////////// /// Change maximum number of likelihood function calss from MINUIT /// (RooMinimizer default 500 * #parameters) void RooMinimizer::setMaxFunctionCalls(Int_t n) { _theFitter->Config().MinimizerOptions().SetMaxFunctionCalls(n); } //////////////////////////////////////////////////////////////////////////////// /// Set the level for MINUIT error analysis to the given /// value. This function overrides the default value /// that is taken in the RooMinimizer constructor from /// the defaultErrorLevel() method of the input function void RooMinimizer::setErrorLevel(Double_t level) { _theFitter->Config().MinimizerOptions().SetErrorDef(level); } //////////////////////////////////////////////////////////////////////////////// /// Change MINUIT epsilon void RooMinimizer::setEps(Double_t eps) { _theFitter->Config().MinimizerOptions().SetTolerance(eps); } //////////////////////////////////////////////////////////////////////////////// /// Enable internal likelihood offsetting for enhanced numeric precision void RooMinimizer::setOffsetting(Bool_t flag) { _func->enableOffsetting(flag) ; } //////////////////////////////////////////////////////////////////////////////// /// Choose the minimzer algorithm. void RooMinimizer::setMinimizerType(const char* type) { _minimizerType = type; } //////////////////////////////////////////////////////////////////////////////// /// Return underlying ROOT fitter object ROOT::Fit::Fitter* RooMinimizer::fitter() { return _theFitter ; } //////////////////////////////////////////////////////////////////////////////// /// Return underlying ROOT fitter object const ROOT::Fit::Fitter* RooMinimizer::fitter() const { return _theFitter ; } //////////////////////////////////////////////////////////////////////////////// /// Parse traditional RooAbsPdf::fitTo driver options /// /// m - Run Migrad only /// h - Run Hesse to estimate errors /// v - Verbose mode /// l - Log parameters after each Minuit steps to file /// t - Activate profile timer /// r - Save fit result /// 0 - Run Migrad with strategy 0 RooFitResult* RooMinimizer::fit(const char* options) { TString opts(options) ; opts.ToLower() ; // Initial configuration if (opts.Contains("v")) setVerbose(1) ; if (opts.Contains("t")) setProfile(1) ; if (opts.Contains("l")) setLogFile(Form("%s.log",_func->GetName())) ; if (opts.Contains("c")) optimizeConst(1) ; // Fitting steps if (opts.Contains("0")) setStrategy(0) ; migrad() ; if (opts.Contains("0")) setStrategy(1) ; if (opts.Contains("h")||!opts.Contains("m")) hesse() ; if (!opts.Contains("m")) minos() ; return (opts.Contains("r")) ? save() : 0 ; } //////////////////////////////////////////////////////////////////////////////// Int_t RooMinimizer::minimize(const char* type, const char* alg) { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; _theFitter->Config().SetMinimizer(type,alg); profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; bool ret = _theFitter->FitFCN(*_fcn); _status = ((ret) ? _theFitter->Result().Status() : -1); RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("MINIMIZE",_status) ; return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Execute MIGRAD. Changes in parameter values /// and calculated errors are automatically /// propagated back the RooRealVars representing /// the floating parameters in the MINUIT operation Int_t RooMinimizer::migrad() { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; _theFitter->Config().SetMinimizer(_minimizerType.c_str(),"migrad"); bool ret = _theFitter->FitFCN(*_fcn); _status = ((ret) ? _theFitter->Result().Status() : -1); RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("MIGRAD",_status) ; return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Execute HESSE. Changes in parameter values /// and calculated errors are automatically /// propagated back the RooRealVars representing /// the floating parameters in the MINUIT operation Int_t RooMinimizer::hesse() { if (_theFitter->GetMinimizer()==0) { coutW(Minimization) << "RooMinimizer::hesse: Error, run Migrad before Hesse!" << endl ; _status = -1; } else { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; _theFitter->Config().SetMinimizer(_minimizerType.c_str()); bool ret = _theFitter->CalculateHessErrors(); _status = ((ret) ? _theFitter->Result().Status() : -1); RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("HESSE",_status) ; } return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Execute MINOS. Changes in parameter values /// and calculated errors are automatically /// propagated back the RooRealVars representing /// the floating parameters in the MINUIT operation Int_t RooMinimizer::minos() { if (_theFitter->GetMinimizer()==0) { coutW(Minimization) << "RooMinimizer::minos: Error, run Migrad before Minos!" << endl ; _status = -1; } else { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; _theFitter->Config().SetMinimizer(_minimizerType.c_str()); bool ret = _theFitter->CalculateMinosErrors(); _status = ((ret) ? _theFitter->Result().Status() : -1); RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("MINOS",_status) ; } return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Execute MINOS for given list of parameters. Changes in parameter values /// and calculated errors are automatically /// propagated back the RooRealVars representing /// the floating parameters in the MINUIT operation Int_t RooMinimizer::minos(const RooArgSet& minosParamList) { if (_theFitter->GetMinimizer()==0) { coutW(Minimization) << "RooMinimizer::minos: Error, run Migrad before Minos!" << endl ; _status = -1; } else if (minosParamList.getSize()>0) { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; // get list of parameters for Minos TIterator* aIter = minosParamList.createIterator() ; RooAbsArg* arg ; std::vector paramInd; while((arg=(RooAbsArg*)aIter->Next())) { RooAbsArg* par = _fcn->GetFloatParamList()->find(arg->GetName()); if (par && !par->isConstant()) { Int_t index = _fcn->GetFloatParamList()->index(par); paramInd.push_back(index); } } delete aIter ; if (paramInd.size()) { // set the parameter indeces _theFitter->Config().SetMinosErrors(paramInd); _theFitter->Config().SetMinimizer(_minimizerType.c_str()); bool ret = _theFitter->CalculateMinosErrors(); _status = ((ret) ? _theFitter->Result().Status() : -1); // to avoid that following minimization computes automatically the Minos errors _theFitter->Config().SetMinosErrors(kFALSE); } RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("MINOS",_status) ; } return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Execute SEEK. Changes in parameter values /// and calculated errors are automatically /// propagated back the RooRealVars representing /// the floating parameters in the MINUIT operation Int_t RooMinimizer::seek() { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; _theFitter->Config().SetMinimizer(_minimizerType.c_str(),"seek"); bool ret = _theFitter->FitFCN(*_fcn); _status = ((ret) ? _theFitter->Result().Status() : -1); RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("SEEK",_status) ; return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Execute SIMPLEX. Changes in parameter values /// and calculated errors are automatically /// propagated back the RooRealVars representing /// the floating parameters in the MINUIT operation Int_t RooMinimizer::simplex() { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; _theFitter->Config().SetMinimizer(_minimizerType.c_str(),"simplex"); bool ret = _theFitter->FitFCN(*_fcn); _status = ((ret) ? _theFitter->Result().Status() : -1); RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("SEEK",_status) ; return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Execute IMPROVE. Changes in parameter values /// and calculated errors are automatically /// propagated back the RooRealVars representing /// the floating parameters in the MINUIT operation Int_t RooMinimizer::improve() { _fcn->Synchronize(_theFitter->Config().ParamsSettings(), _optConst,_verbose) ; profileStart() ; RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; RooAbsReal::clearEvalErrorLog() ; _theFitter->Config().SetMinimizer(_minimizerType.c_str(),"migradimproved"); bool ret = _theFitter->FitFCN(*_fcn); _status = ((ret) ? _theFitter->Result().Status() : -1); RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; profileStop() ; _fcn->BackProp(_theFitter->Result()); saveStatus("IMPROVE",_status) ; return _status ; } //////////////////////////////////////////////////////////////////////////////// /// Change the MINUIT internal printing level Int_t RooMinimizer::setPrintLevel(Int_t newLevel) { Int_t ret = _printLevel ; _theFitter->Config().MinimizerOptions().SetPrintLevel(newLevel+1); _printLevel = newLevel+1 ; return ret ; } //////////////////////////////////////////////////////////////////////////////// /// If flag is true, perform constant term optimization on /// function being minimized. void RooMinimizer::optimizeConst(Int_t flag) { RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ; if (_optConst && !flag){ if (_printLevel>-1) coutI(Minimization) << "RooMinimizer::optimizeConst: deactivating const optimization" << endl ; _func->constOptimizeTestStatistic(RooAbsArg::DeActivate) ; _optConst = flag ; } else if (!_optConst && flag) { if (_printLevel>-1) coutI(Minimization) << "RooMinimizer::optimizeConst: activating const optimization" << endl ; _func->constOptimizeTestStatistic(RooAbsArg::Activate,flag>1) ; _optConst = flag ; } else if (_optConst && flag) { if (_printLevel>-1) coutI(Minimization) << "RooMinimizer::optimizeConst: const optimization already active" << endl ; } else { if (_printLevel>-1) coutI(Minimization) << "RooMinimizer::optimizeConst: const optimization wasn't active" << endl ; } RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ; } //////////////////////////////////////////////////////////////////////////////// /// Save and return a RooFitResult snaphot of current minimizer status. /// This snapshot contains the values of all constant parameters, /// the value of all floating parameters at RooMinimizer construction and /// after the last MINUIT operation, the MINUIT status, variance quality, /// EDM setting, number of calls with evaluation problems, the minimized /// function value and the full correlation matrix RooFitResult* RooMinimizer::save(const char* userName, const char* userTitle) { if (_theFitter->GetMinimizer()==0) { coutW(Minimization) << "RooMinimizer::save: Error, run minimization before!" << endl ; return 0; } TString name,title ; name = userName ? userName : Form("%s", _func->GetName()) ; title = userTitle ? userTitle : Form("%s", _func->GetTitle()) ; RooFitResult* fitRes = new RooFitResult(name,title) ; // Move eventual fixed parameters in floatList to constList Int_t i ; RooArgList saveConstList(*(_fcn->GetConstParamList())) ; RooArgList saveFloatInitList(*(_fcn->GetInitFloatParamList())) ; RooArgList saveFloatFinalList(*(_fcn->GetFloatParamList())) ; for (i=0 ; i<_fcn->GetFloatParamList()->getSize() ; i++) { RooAbsArg* par = _fcn->GetFloatParamList()->at(i) ; if (par->isConstant()) { saveFloatInitList.remove(*saveFloatInitList.find(par->GetName()),kTRUE) ; saveFloatFinalList.remove(*par) ; saveConstList.add(*par) ; } } saveConstList.sort() ; fitRes->setConstParList(saveConstList) ; fitRes->setInitParList(saveFloatInitList) ; fitRes->setStatus(_status) ; fitRes->setCovQual(_theFitter->GetMinimizer()->CovMatrixStatus()) ; fitRes->setMinNLL(_theFitter->Result().MinFcnValue()) ; fitRes->setNumInvalidNLL(_fcn->GetNumInvalidNLL()) ; fitRes->setEDM(_theFitter->Result().Edm()) ; fitRes->setFinalParList(saveFloatFinalList) ; if (!_extV) { std::vector globalCC; TMatrixDSym corrs(_theFitter->Result().Parameters().size()) ; TMatrixDSym covs(_theFitter->Result().Parameters().size()) ; for (UInt_t ic=0; ic<_theFitter->Result().Parameters().size(); ic++) { globalCC.push_back(_theFitter->Result().GlobalCC(ic)); for (UInt_t ii=0; ii<_theFitter->Result().Parameters().size(); ii++) { corrs(ic,ii) = _theFitter->Result().Correlation(ic,ii); covs(ic,ii) = _theFitter->Result().CovMatrix(ic,ii); } } fitRes->fillCorrMatrix(globalCC,corrs,covs) ; } else { fitRes->setCovarianceMatrix(*_extV) ; } fitRes->setStatusHistory(_statusHistory) ; return fitRes ; } //////////////////////////////////////////////////////////////////////////////// /// Create and draw a TH2 with the error contours in parameters var1 and v2 at up to 6 'sigma' settings /// where 'sigma' is calculated as n*n*errorLevel RooPlot* RooMinimizer::contour(RooRealVar& var1, RooRealVar& var2, Double_t n1, Double_t n2, Double_t n3, Double_t n4, Double_t n5, Double_t n6) { RooArgList* params = _fcn->GetFloatParamList() ; RooArgList* paramSave = (RooArgList*) params->snapshot() ; // Verify that both variables are floating parameters of PDF Int_t index1= _fcn->GetFloatParamList()->index(&var1); if(index1 < 0) { coutE(Minimization) << "RooMinimizer::contour(" << GetName() << ") ERROR: " << var1.GetName() << " is not a floating parameter of " << _func->GetName() << endl ; return 0; } Int_t index2= _fcn->GetFloatParamList()->index(&var2); if(index2 < 0) { coutE(Minimization) << "RooMinimizer::contour(" << GetName() << ") ERROR: " << var2.GetName() << " is not a floating parameter of PDF " << _func->GetName() << endl ; return 0; } // create and draw a frame RooPlot* frame = new RooPlot(var1,var2) ; // draw a point at the current parameter values TMarker *point= new TMarker(var1.getVal(), var2.getVal(), 8); frame->addObject(point) ; // check first if a inimizer is available. If not means // the minimization is not done , so do it if (_theFitter->GetMinimizer()==0) { coutW(Minimization) << "RooMinimizer::contour: Error, run Migrad before contours!" << endl ; return frame; } // remember our original value of ERRDEF Double_t errdef= _theFitter->GetMinimizer()->ErrorDef(); Double_t n[6] ; n[0] = n1 ; n[1] = n2 ; n[2] = n3 ; n[3] = n4 ; n[4] = n5 ; n[5] = n6 ; unsigned int npoints(50); for (Int_t ic = 0 ; ic<6 ; ic++) { if(n[ic] > 0) { // set the value corresponding to an n1-sigma contour _theFitter->GetMinimizer()->SetErrorDef(n[ic]*n[ic]*errdef); // calculate and draw the contour Double_t *xcoor = new Double_t[npoints+1]; Double_t *ycoor = new Double_t[npoints+1]; bool ret = _theFitter->GetMinimizer()->Contour(index1,index2,npoints,xcoor,ycoor); if (!ret) { coutE(Minimization) << "RooMinimizer::contour(" << GetName() << ") ERROR: MINUIT did not return a contour graph for n=" << n[ic] << endl ; } else { xcoor[npoints] = xcoor[0]; ycoor[npoints] = ycoor[0]; TGraph* graph = new TGraph(npoints+1,xcoor,ycoor); graph->SetName(Form("contour_%s_n%f",_func->GetName(),n[ic])) ; graph->SetLineStyle(ic+1) ; graph->SetLineWidth(2) ; graph->SetLineColor(kBlue) ; frame->addObject(graph,"L") ; } delete [] xcoor; delete [] ycoor; } } // restore the original ERRDEF _theFitter->Config().MinimizerOptions().SetErrorDef(errdef); // restore parameter values *params = *paramSave ; delete paramSave ; return frame ; } //////////////////////////////////////////////////////////////////////////////// /// Start profiling timer void RooMinimizer::profileStart() { if (_profile) { _timer.Start() ; _cumulTimer.Start(_profileStart?kFALSE:kTRUE) ; _profileStart = kTRUE ; } } //////////////////////////////////////////////////////////////////////////////// /// Stop profiling timer and report results of last session void RooMinimizer::profileStop() { if (_profile) { _timer.Stop() ; _cumulTimer.Stop() ; coutI(Minimization) << "Command timer: " ; _timer.Print() ; coutI(Minimization) << "Session timer: " ; _cumulTimer.Print() ; } } //////////////////////////////////////////////////////////////////////////////// /// Apply results of given external covariance matrix. i.e. propagate its errors /// to all RRV parameter representations and give this matrix instead of the /// HESSE matrix at the next save() call void RooMinimizer::applyCovarianceMatrix(TMatrixDSym& V) { _extV = (TMatrixDSym*) V.Clone() ; _fcn->ApplyCovarianceMatrix(*_extV); } RooFitResult* RooMinimizer::lastMinuitFit(const RooArgList& varList) { // Import the results of the last fit performed, interpreting // the fit parameters as the given varList of parameters. if (_theFitter==0 || _theFitter->GetMinimizer()==0) { oocoutE((TObject*)0,InputArguments) << "RooMinimizer::save: Error, run minimization before!" << endl ; return 0; } // Verify length of supplied varList if (varList.getSize()>0 && varList.getSize()!=Int_t(_theFitter->Result().NTotalParameters())) { oocoutE((TObject*)0,InputArguments) << "RooMinimizer::lastMinuitFit: ERROR: supplied variable list must be either empty " << endl << " or match the number of variables of the last fit (" << _theFitter->Result().NTotalParameters() << ")" << endl ; return 0 ; } // Verify that all members of varList are of type RooRealVar TIterator* iter = varList.createIterator() ; RooAbsArg* arg ; while((arg=(RooAbsArg*)iter->Next())) { if (!dynamic_cast(arg)) { oocoutE((TObject*)0,InputArguments) << "RooMinimizer::lastMinuitFit: ERROR: variable '" << arg->GetName() << "' is not of type RooRealVar" << endl ; return 0 ; } } delete iter ; RooFitResult* res = new RooFitResult("lastMinuitFit","Last MINUIT fit") ; // Extract names of fit parameters // and construct corresponding RooRealVars RooArgList constPars("constPars") ; RooArgList floatPars("floatPars") ; UInt_t i ; for (i = 0; i < _theFitter->Result().NTotalParameters(); ++i) { TString varName(_theFitter->Result().GetParameterName(i)); Bool_t isConst(_theFitter->Result().IsParameterFixed(i)) ; Double_t xlo = _theFitter->Config().ParSettings(i).LowerLimit(); Double_t xhi = _theFitter->Config().ParSettings(i).UpperLimit(); Double_t xerr = _theFitter->Result().Error(i); Double_t xval = _theFitter->Result().Value(i); RooRealVar* var ; if (varList.getSize()==0) { if ((xlosetConstant(isConst) ; } else { var = (RooRealVar*) varList.at(i)->Clone() ; var->setConstant(isConst) ; var->setVal(xval) ; if (xlosetRange(xlo,xhi) ; } if (varName.CompareTo(var->GetName())) { oocoutI((TObject*)0,Eval) << "RooMinimizer::lastMinuitFit: fit parameter '" << varName << "' stored in variable '" << var->GetName() << "'" << endl ; } } if (isConst) { constPars.addOwned(*var) ; } else { var->setError(xerr) ; floatPars.addOwned(*var) ; } } res->setConstParList(constPars) ; res->setInitParList(floatPars) ; res->setFinalParList(floatPars) ; res->setMinNLL(_theFitter->Result().MinFcnValue()) ; res->setEDM(_theFitter->Result().Edm()) ; res->setCovQual(_theFitter->GetMinimizer()->CovMatrixStatus()) ; res->setStatus(_theFitter->Result().Status()) ; std::vector globalCC; TMatrixDSym corrs(_theFitter->Result().Parameters().size()) ; TMatrixDSym covs(_theFitter->Result().Parameters().size()) ; for (UInt_t ic=0; ic<_theFitter->Result().Parameters().size(); ic++) { globalCC.push_back(_theFitter->Result().GlobalCC(ic)); for (UInt_t ii=0; ii<_theFitter->Result().Parameters().size(); ii++) { corrs(ic,ii) = _theFitter->Result().Correlation(ic,ii); covs(ic,ii) = _theFitter->Result().CovMatrix(ic,ii); } } res->fillCorrMatrix(globalCC,corrs,covs) ; return res; } #endif