RooMinuit.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooMinuit.cxx 36222 2010-10-09 18:27:06Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // BEGIN_HTML
00020 // RooMinuit is a wrapper class around TFitter/TMinuit that
00021 // provides a seamless interface between the MINUIT functionality
00022 // and the native RooFit interface.
00023 // <p>
00024 // RooMinuit can minimize any RooAbsReal function with respect to
00025 // its parameters. Usual choices for minimization are RooNLLVar
00026 // and RooChi2Var
00027 // <p>
00028 // RooMinuit has methods corresponding to MINUIT functions like
00029 // hesse(), migrad(), minos() etc. In each of these function calls
00030 // the state of the MINUIT engine is synchronized with the state
00031 // of the RooFit variables: any change in variables, change
00032 // in the constant status etc is forwarded to MINUIT prior to
00033 // execution of the MINUIT call. Afterwards the RooFit objects
00034 // are resynchronized with the output state of MINUIT: changes
00035 // parameter values, errors are propagated.
00036 // <p>
00037 // Various methods are available to control verbosity, profiling,
00038 // automatic PDF optimization.
00039 // END_HTML
00040 //
00041 
00042 #include "RooFit.h"
00043 #include "Riostream.h"
00044 
00045 #include "TClass.h"
00046 
00047 #include <fstream>
00048 #include <iomanip>
00049 #include "TH1.h"
00050 #include "TH2.h"
00051 #include "TMarker.h"
00052 #include "TGraph.h"
00053 #include "TStopwatch.h"
00054 #include "TFitter.h"
00055 #include "TMinuit.h"
00056 #include "TDirectory.h"
00057 #include "TMatrixDSym.h"
00058 #include "RooMinuit.h"
00059 #include "RooArgSet.h"
00060 #include "RooArgList.h"
00061 #include "RooAbsReal.h"
00062 #include "RooAbsRealLValue.h"
00063 #include "RooRealVar.h"
00064 #include "RooFitResult.h"
00065 #include "RooAbsPdf.h"
00066 #include "RooSentinel.h"
00067 #include "RooMsgService.h"
00068 #include "RooPlot.h"
00069 
00070 
00071 
00072 #if (__GNUC__==3&&__GNUC_MINOR__==2&&__GNUC_PATCHLEVEL__==3)
00073 char* operator+( streampos&, char* );
00074 #endif
00075 
00076 ClassImp(RooMinuit)
00077 ;
00078 
00079 TVirtualFitter *RooMinuit::_theFitter = 0 ;
00080 
00081 
00082 
00083 //_____________________________________________________________________________
00084 void RooMinuit::cleanup()
00085 {
00086   // Cleanup method called by atexit handler installed by RooSentinel
00087   // to delete all global heap objects when the program is terminated
00088   if (_theFitter) {
00089     delete _theFitter ;
00090     _theFitter =0 ;
00091   }
00092 }
00093 
00094 
00095 
00096 //_____________________________________________________________________________
00097 RooMinuit::RooMinuit(RooAbsReal& function)
00098 {
00099   // Construct MINUIT interface to given function. Function can be anything,
00100   // but is typically a -log(likelihood) implemented by RooNLLVar or a chi^2
00101   // (implemented by RooChi2Var). Other frequent use cases are a RooAddition
00102   // of a RooNLLVar plus a penalty or constraint term. This class propagates
00103   // all RooFit information (floating parameters, their values and errors)
00104   // to MINUIT before each MINUIT call and propagates all MINUIT information
00105   // back to the RooFit object at the end of each call (updated parameter
00106   // values, their (asymmetric errors) etc. The default MINUIT error level
00107   // for HESSE and MINOS error analysis is taken from the defaultErrorLevel()
00108   // value of the input function.
00109 
00110   RooSentinel::activate() ;
00111 
00112   // Store function reference
00113   _extV = 0 ;
00114   _func = &function ;
00115   _logfile = 0 ;
00116   _optConst = kFALSE ;
00117   _verbose = kFALSE ;
00118   _profile = kFALSE ;
00119   _handleLocalErrors = kTRUE ;
00120   _printLevel = 1 ;
00121   _printEvalErrors = 10 ;
00122   _warnLevel = -999 ;
00123   _doEvalErrorWall = kTRUE ;
00124 
00125   // Examine parameter list
00126   RooArgSet* paramSet = function.getParameters(RooArgSet()) ;
00127   RooArgList paramList(*paramSet) ;
00128   delete paramSet ;
00129 
00130   _floatParamList = (RooArgList*) paramList.selectByAttrib("Constant",kFALSE) ;
00131   if (_floatParamList->getSize()>1) {
00132     _floatParamList->sort() ;
00133   }
00134   _floatParamList->setName("floatParamList") ;
00135 
00136   _constParamList = (RooArgList*) paramList.selectByAttrib("Constant",kTRUE) ;
00137   if (_constParamList->getSize()>1) {
00138     _constParamList->sort() ;
00139   }
00140   _constParamList->setName("constParamList") ;
00141 
00142   // Remove all non-RooRealVar parameters from list (MINUIT cannot handle them)
00143   TIterator* pIter = _floatParamList->createIterator() ;
00144   RooAbsArg* arg ;
00145   while((arg=(RooAbsArg*)pIter->Next())) {
00146     if (!arg->IsA()->InheritsFrom(RooAbsRealLValue::Class())) {
00147       coutW(Minimization) << "RooMinuit::RooMinuit: removing parameter " << arg->GetName()
00148                           << " from list because it is not of type RooRealVar" << endl ;
00149       _floatParamList->remove(*arg) ;
00150     }
00151   }
00152   _nPar      = _floatParamList->getSize() ;
00153   delete pIter ;
00154 
00155   // Save snapshot of initial lists
00156   _initFloatParamList = (RooArgList*) _floatParamList->snapshot(kFALSE) ;
00157   _initConstParamList = (RooArgList*) _constParamList->snapshot(kFALSE) ;
00158 
00159   // Initialize MINUIT
00160   Int_t nPar= _floatParamList->getSize();
00161   if (_theFitter) delete _theFitter ;
00162   _theFitter = new TFitter(nPar*2+1) ; //WVE Kludge, nPar*2 works around TMinuit memory allocation bug
00163   _theFitter->SetObjectFit(this) ;
00164 
00165   // Shut up for now
00166   setPrintLevel(-1) ;
00167   _theFitter->Clear();
00168 
00169   // Tell MINUIT to use our global glue function
00170   _theFitter->SetFCN(RooMinuitGlue);
00171 
00172   // Use +0.5 for 1-sigma errors
00173   setErrorLevel(function.defaultErrorLevel()) ;
00174 
00175   // Declare our parameters to MINUIT
00176   synchronize(kFALSE) ;
00177 
00178   // Reset the *largest* negative log-likelihood value we have seen so far
00179   _maxFCN= -1e30 ;
00180   _numBadNLL = 0 ;
00181 
00182   // Now set default verbosity
00183   if (RooMsgService::instance().silentMode()) {
00184     setWarnLevel(-1) ;
00185     setPrintLevel(-1) ;
00186   } else {
00187     setWarnLevel(1) ;
00188     setPrintLevel(1) ;
00189   }
00190 }
00191 
00192 
00193 
00194 //_____________________________________________________________________________
00195 RooMinuit::~RooMinuit()
00196 {
00197   // Destructor
00198 
00199   delete _floatParamList ;
00200   delete _initFloatParamList ;
00201   delete _constParamList ;
00202   delete _initConstParamList ;
00203   if (_extV) {
00204     delete _extV ;
00205   }
00206 }
00207 
00208 
00209 
00210 //_____________________________________________________________________________
00211 void RooMinuit::setStrategy(Int_t istrat)
00212 {
00213   // Change MINUIT strategy to istrat. Accepted codes
00214   // are 0,1,2 and represent MINUIT strategies for dealing
00215   // most efficiently with fast FCNs (0), expensive FCNs (2)
00216   // and 'intermediate' FCNs (1)
00217 
00218   Double_t stratArg(istrat) ;
00219   _theFitter->ExecuteCommand("SET STR",&stratArg,1) ;
00220 }
00221 
00222 
00223 
00224 //_____________________________________________________________________________
00225 void RooMinuit::setErrorLevel(Double_t level)
00226 {
00227   // Set the level for MINUIT error analysis to the given
00228   // value. This function overrides the default value
00229   // that is taken in the RooMinuit constructor from
00230   // the defaultErrorLevel() method of the input function
00231   _theFitter->ExecuteCommand("SET ERR",&level,1);
00232 }
00233 
00234 
00235 
00236 //_____________________________________________________________________________
00237 void RooMinuit::setEps(Double_t eps)
00238 {
00239   // Change MINUIT epsilon
00240   _theFitter->ExecuteCommand("SET EPS",&eps,1) ;
00241 }
00242 
00243 
00244 
00245 //_____________________________________________________________________________
00246 RooFitResult* RooMinuit::fit(const char* options)
00247 {
00248   // Parse traditional RooAbsPdf::fitTo driver options
00249   //
00250   //  s - Run Hesse first to estimate initial step size
00251   //  m - Run Migrad only
00252   //  h - Run Hesse to estimate errors
00253   //  v - Verbose mode
00254   //  l - Log parameters after each Minuit steps to file
00255   //  t - Activate profile timer
00256   //  r - Save fit result
00257   //  0 - Run Migrad with strategy 0
00258 
00259   if (_floatParamList->getSize()==0) {
00260     return 0 ;
00261   }
00262 
00263   _theFitter->SetObjectFit(this) ;
00264 
00265   TString opts(options) ;
00266   opts.ToLower() ;
00267 
00268   // Initial configuration
00269   if (opts.Contains("v")) setVerbose(1) ;
00270   if (opts.Contains("t")) setProfile(1) ;
00271   if (opts.Contains("l")) setLogFile(Form("%s.log",_func->GetName())) ;
00272   if (opts.Contains("c")) optimizeConst(1) ;
00273 
00274   // Fitting steps
00275   if (opts.Contains("s")) hesse() ;
00276   if (opts.Contains("0")) setStrategy(0) ;
00277   migrad() ;
00278   if (opts.Contains("0")) setStrategy(1) ;
00279   if (opts.Contains("h")||!opts.Contains("m")) hesse() ;
00280   if (!opts.Contains("m")) minos() ;
00281 
00282   return (opts.Contains("r")) ? save() : 0 ;
00283 }
00284 
00285 
00286 
00287 //_____________________________________________________________________________
00288 Int_t RooMinuit::migrad()
00289 {
00290   // Execute MIGRAD. Changes in parameter values
00291   // and calculated errors are automatically
00292   // propagated back the RooRealVars representing
00293   // the floating parameters in the MINUIT operation
00294 
00295   if (_floatParamList->getSize()==0) {
00296     return -1 ;
00297   }
00298 
00299   _theFitter->SetObjectFit(this) ;
00300 
00301   Double_t arglist[2];
00302   arglist[0]= 500*_nPar; // maximum iterations
00303   arglist[1]= 1.0;       // tolerance
00304 
00305   synchronize(_verbose) ;
00306   profileStart() ;
00307   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00308   RooAbsReal::clearEvalErrorLog() ;
00309   _status= _theFitter->ExecuteCommand("MIGRAD",arglist,2);
00310   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00311   profileStop() ;
00312   backProp() ;
00313   return _status ;
00314 }
00315 
00316 
00317 
00318 //_____________________________________________________________________________
00319 Int_t RooMinuit::hesse()
00320 {
00321   // Execute HESSE. Changes in parameter values
00322   // and calculated errors are automatically
00323   // propagated back the RooRealVars representing
00324   // the floating parameters in the MINUIT operation
00325 
00326   if (_floatParamList->getSize()==0) {
00327     return -1 ;
00328   }
00329 
00330   _theFitter->SetObjectFit(this) ;
00331 
00332   Double_t arglist[2];
00333   arglist[0]= 500*_nPar; // maximum iterations
00334 
00335   synchronize(_verbose) ;
00336   profileStart() ;
00337   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00338   RooAbsReal::clearEvalErrorLog() ;
00339   _status= _theFitter->ExecuteCommand("HESSE",arglist,1);
00340   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00341   profileStop() ;
00342   backProp() ;
00343   return _status ;
00344 }
00345 
00346 
00347 
00348 //_____________________________________________________________________________
00349 Int_t RooMinuit::minos()
00350 {
00351   // Execute MINOS. Changes in parameter values
00352   // and calculated errors are automatically
00353   // propagated back the RooRealVars representing
00354   // the floating parameters in the MINUIT operation
00355 
00356   if (_floatParamList->getSize()==0) {
00357     return -1 ;
00358   }
00359 
00360   _theFitter->SetObjectFit(this) ;
00361 
00362   Double_t arglist[2];
00363   arglist[0]= 500*_nPar; // maximum iterations
00364 
00365   synchronize(_verbose) ;
00366   profileStart() ;
00367   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00368   RooAbsReal::clearEvalErrorLog() ;
00369   _status= _theFitter->ExecuteCommand("MINOS",arglist,1);
00370   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00371   profileStop() ;
00372   backProp() ;
00373   return _status ;
00374 }
00375 
00376 
00377 // added FMV, 08/18/03
00378 
00379 //_____________________________________________________________________________
00380 Int_t RooMinuit::minos(const RooArgSet& minosParamList)
00381 {
00382   // Execute MINOS for given list of parameters. Changes in parameter values
00383   // and calculated errors are automatically
00384   // propagated back the RooRealVars representing
00385   // the floating parameters in the MINUIT operation
00386 
00387   if (_floatParamList->getSize()==0) {
00388     return -1 ;
00389   }
00390 
00391   _theFitter->SetObjectFit(this) ;
00392 
00393   Int_t nMinosPar(0) ;
00394   Double_t* arglist = new Double_t[_nPar+1];
00395 
00396   if (minosParamList.getSize()>0) {
00397     TIterator* aIter = minosParamList.createIterator() ;
00398     RooAbsArg* arg ;
00399     while((arg=(RooAbsArg*)aIter->Next())) {
00400       RooAbsArg* par = _floatParamList->find(arg->GetName());
00401       if (par && !par->isConstant()) {
00402         Int_t index = _floatParamList->index(par);
00403         nMinosPar++;
00404         arglist[nMinosPar]=index+1;
00405       }
00406     }
00407     delete aIter ;
00408   }
00409   arglist[0]= 500*_nPar; // maximum iterations
00410 
00411   synchronize(_verbose) ;
00412   profileStart() ;
00413   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00414   RooAbsReal::clearEvalErrorLog() ;
00415   _status= _theFitter->ExecuteCommand("MINOS",arglist,1+nMinosPar);
00416   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00417   profileStop() ;
00418   backProp() ;
00419 
00420   delete[] arglist ;
00421   return _status ;
00422 }
00423 
00424 
00425 
00426 //_____________________________________________________________________________
00427 Int_t RooMinuit::seek()
00428 {
00429   // Execute SEEK. Changes in parameter values
00430   // and calculated errors are automatically
00431   // propagated back the RooRealVars representing
00432   // the floating parameters in the MINUIT operation
00433 
00434   if (_floatParamList->getSize()==0) {
00435     return -1 ;
00436   }
00437 
00438   _theFitter->SetObjectFit(this) ;
00439 
00440   Double_t arglist[2];
00441   arglist[0]= 500*_nPar; // maximum iterations
00442 
00443   synchronize(_verbose) ;
00444   profileStart() ;
00445   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00446   RooAbsReal::clearEvalErrorLog() ;
00447   _status= _theFitter->ExecuteCommand("SEEK",arglist,1);
00448   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00449   profileStop() ;
00450   backProp() ;
00451   return _status ;
00452 }
00453 
00454 
00455 
00456 //_____________________________________________________________________________
00457 Int_t RooMinuit::simplex()
00458 {
00459   // Execute SIMPLEX. Changes in parameter values
00460   // and calculated errors are automatically
00461   // propagated back the RooRealVars representing
00462   // the floating parameters in the MINUIT operation
00463 
00464   if (_floatParamList->getSize()==0) {
00465     return -1 ;
00466   }
00467 
00468   _theFitter->SetObjectFit(this) ;
00469 
00470   Double_t arglist[2];
00471   arglist[0]= 500*_nPar; // maximum iterations
00472   arglist[1]= 1.0;       // tolerance
00473 
00474   synchronize(_verbose) ;
00475   profileStart() ;
00476   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00477   RooAbsReal::clearEvalErrorLog() ;
00478   _status= _theFitter->ExecuteCommand("SIMPLEX",arglist,2);
00479   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00480   profileStop() ;
00481   backProp() ;
00482   return _status ;
00483 }
00484 
00485 
00486 
00487 //_____________________________________________________________________________
00488 Int_t RooMinuit::improve()
00489 {
00490   // Execute IMPROVE. Changes in parameter values
00491   // and calculated errors are automatically
00492   // propagated back the RooRealVars representing
00493   // the floating parameters in the MINUIT operation
00494 
00495   if (_floatParamList->getSize()==0) {
00496     return -1 ;
00497   }
00498 
00499   _theFitter->SetObjectFit(this) ;
00500 
00501   Double_t arglist[2];
00502   arglist[0]= 500*_nPar; // maximum iterations
00503 
00504   synchronize(_verbose) ;
00505   profileStart() ;
00506   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00507   RooAbsReal::clearEvalErrorLog() ;
00508   _status= _theFitter->ExecuteCommand("IMPROVE",arglist,1);
00509   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00510   profileStop() ;
00511   backProp() ;
00512   return _status ;
00513 }
00514 
00515 
00516 
00517 //_____________________________________________________________________________
00518 Int_t RooMinuit::setPrintLevel(Int_t newLevel)
00519 {
00520   // Change the MINUIT internal printing level
00521   Int_t ret = _printLevel ;
00522   Double_t arg(newLevel) ;
00523   _theFitter->ExecuteCommand("SET PRINT",&arg,1);
00524   _printLevel = newLevel ;
00525   return ret ;
00526 }
00527 
00528 
00529 
00530 //_____________________________________________________________________________
00531 void RooMinuit::setNoWarn()
00532 {
00533   // Instruct MINUIT to suppress warnings
00534 
00535   Double_t arg(0) ;
00536   _theFitter->ExecuteCommand("SET NOWARNINGS",&arg,1);
00537   _warnLevel = -1 ;
00538 }
00539 
00540 
00541 
00542 //_____________________________________________________________________________
00543 Int_t RooMinuit::setWarnLevel(Int_t newLevel)
00544 {
00545   // Set MINUIT warning level to given level
00546 
00547   if (newLevel==_warnLevel) {
00548     return _warnLevel ;
00549   }
00550 
00551   Int_t ret = _warnLevel ;
00552   Double_t arg(newLevel) ;
00553 
00554   if (newLevel>=0) {
00555     _theFitter->ExecuteCommand("SET WARNINGS",&arg,1);
00556   } else {
00557     Double_t arg2(0) ;
00558     _theFitter->ExecuteCommand("SET NOWARNINGS",&arg2,1);
00559   }
00560   _warnLevel = newLevel ;
00561 
00562   return ret ;
00563 }
00564 
00565 
00566 
00567 //_____________________________________________________________________________
00568 Bool_t RooMinuit::synchronize(Bool_t verbose)
00569 {
00570   // Internal function to synchronize TMinuit with current
00571   // information in RooAbsReal function parameters
00572 
00573   Int_t oldPrint = setPrintLevel(-1) ;
00574   gMinuit->fNwrmes[0] = 0;  // to clear buffer
00575   Int_t oldWarn = setWarnLevel(-1) ;
00576 
00577   Bool_t constValChange(kFALSE) ;
00578   Bool_t constStatChange(kFALSE) ;
00579 
00580   Int_t index(0) ;
00581 
00582   // Handle eventual migrations from constParamList -> floatParamList
00583   for(index= 0; index < _constParamList->getSize() ; index++) {
00584     RooRealVar *par= dynamic_cast<RooRealVar*>(_constParamList->at(index)) ;
00585     if (!par) continue ;
00586 
00587     RooRealVar *oldpar= dynamic_cast<RooRealVar*>(_initConstParamList->at(index)) ;
00588     if (!oldpar) continue ;
00589 
00590     // Test if constness changed
00591     if (!par->isConstant()) {
00592 
00593       // Remove from constList, add to floatList
00594       _constParamList->remove(*par) ;
00595       _floatParamList->add(*par) ;
00596       _initFloatParamList->addClone(*oldpar) ;
00597       _initConstParamList->remove(*oldpar) ;
00598       constStatChange=kTRUE ;
00599       _nPar++ ;
00600 
00601       if (verbose) {
00602         coutI(Minimization) << "RooMinuit::synchronize: parameter " << par->GetName() << " is now floating." << endl ;
00603       }
00604     }
00605 
00606     // Test if value changed
00607     if (par->getVal()!= oldpar->getVal()) {
00608       constValChange=kTRUE ;
00609       if (verbose) {
00610         coutI(Minimization) << "RooMinuit::synchronize: value of constant parameter " << par->GetName()
00611                             << " changed from " << oldpar->getVal() << " to " << par->getVal() << endl ;
00612       }
00613     }
00614 
00615   }
00616 
00617   // Update reference list
00618   *_initConstParamList = *_constParamList ;
00619 
00620 
00621   // Synchronize MINUIT with function state
00622   for(index= 0; index < _nPar; index++) {
00623     RooRealVar *par= dynamic_cast<RooRealVar*>(_floatParamList->at(index)) ;
00624     if (!par) continue ;
00625 
00626     Double_t pstep(0) ;
00627     Double_t pmin(0) ;
00628     Double_t pmax(0) ;
00629     
00630     if(!par->isConstant()) {
00631 
00632       // Verify that floating parameter is indeed of type RooRealVar
00633       if (!par->IsA()->InheritsFrom(RooRealVar::Class())) {
00634         coutW(Minimization) << "RooMinuit::fit: Error, non-constant parameter " << par->GetName()
00635                             << " is not of type RooRealVar, skipping" << endl ;
00636         continue ;
00637       }
00638 
00639       // Set the limits, if not infinite
00640       if (par->hasMin() && par->hasMax()) {
00641         pmin = par->getMin();
00642         pmax = par->getMax();
00643       }
00644 
00645       // Calculate step size
00646       pstep= par->getError();
00647       if(pstep <= 0) {
00648         // Floating parameter without error estitimate
00649         if (par->hasMin() && par->hasMax()) {
00650           pstep= 0.1*(pmax-pmin);
00651 
00652           // Trim default choice of error if within 2 sigma of limit
00653           if (pmax - par->getVal() < 2*pstep) {
00654             pstep = (pmax - par->getVal())/2 ;
00655           } else if (par->getVal() - pmin < 2*pstep) {
00656             pstep = (par->getVal() - pmin )/2 ;
00657           }
00658 
00659           // If trimming results in zero error, restore default
00660           if (pstep==0) {
00661             pstep= 0.1*(pmax-pmin);
00662           }
00663 
00664         } else {
00665           pstep=1 ;
00666         }
00667         if(_verbose) {
00668           coutW(Minimization) << "RooMinuit::synchronize: WARNING: no initial error estimate available for "
00669                               << par->GetName() << ": using " << pstep << endl;
00670         }
00671       }
00672     } else {
00673       pmin = par->getVal() ;
00674       pmax = par->getVal() ;
00675     }
00676 
00677     // Extract previous information
00678     Double_t oldVar,oldVerr,oldVlo,oldVhi ;
00679     char oldParname[100] ;
00680     Int_t ierr = _theFitter->GetParameter(index,oldParname,oldVar,oldVerr,oldVlo,oldVhi)  ;
00681 
00682     // Determine if parameters is currently fixed in MINUIT
00683 
00684     Int_t ix ;
00685     Bool_t oldFixed(kFALSE) ;
00686     if (ierr>=0) {
00687       for (ix = 1; ix <= gMinuit->fNpfix; ++ix) {
00688         if (gMinuit->fIpfix[ix-1] == index+1) oldFixed=kTRUE ;
00689       }
00690     }
00691 
00692     if (par->isConstant() && !oldFixed) {
00693 
00694       // Parameter changes floating -> constant : update only value if necessary
00695       if (oldVar!=par->getVal()) {
00696         Double_t arglist[2] ;
00697         arglist[0] = index+1 ;
00698         arglist[1] = par->getVal() ;
00699         _theFitter->ExecuteCommand("SET PAR",arglist,2) ;
00700         if (verbose) {
00701           coutI(Minimization) << "RooMinuit::synchronize: value of parameter " << par->GetName() << " changed from " << oldVar << " to " << par->getVal() << endl ;
00702         }
00703       }
00704 
00705       _theFitter->FixParameter(index) ;
00706       constStatChange=kTRUE ;
00707       if (verbose) {
00708         coutI(Minimization) << "RooMinuit::synchronize: parameter " << par->GetName() << " is now fixed." << endl ;
00709       }
00710 
00711     } else if (par->isConstant() && oldFixed) {
00712 
00713       // Parameter changes constant -> constant : update only value if necessary
00714       if (oldVar!=par->getVal()) {
00715         Double_t arglist[2] ;
00716         arglist[0] = index+1 ;
00717         arglist[1] = par->getVal() ;
00718         _theFitter->ExecuteCommand("SET PAR",arglist,2) ;
00719         constValChange=kTRUE ;
00720 
00721         if (verbose) {
00722           coutI(Minimization) << "RooMinuit::synchronize: value of fixed parameter " << par->GetName() << " changed from " << oldVar << " to " << par->getVal() << endl ;
00723         }
00724       }
00725 
00726     } else {
00727 
00728       if (!par->isConstant() && oldFixed) {
00729         _theFitter->ReleaseParameter(index) ;
00730         constStatChange=kTRUE ;
00731 
00732         if (verbose) {
00733           coutI(Minimization) << "RooMinuit::synchronize: parameter " << par->GetName() << " is now floating." << endl ;
00734         }
00735       }
00736 
00737       // Parameter changes constant -> floating : update all if necessary
00738       if (oldVar!=par->getVal() || oldVlo!=pmin || oldVhi != pmax || oldVerr!=pstep) {
00739         _theFitter->SetParameter(index, par->GetName(), par->getVal(), pstep, pmin, pmax);
00740       }
00741 
00742       // Inform user about changes in verbose mode
00743       if (verbose && ierr>=0) {
00744         // if ierr<0, par was moved from the const list and a message was already printed
00745 
00746         if (oldVar!=par->getVal()) {
00747           coutI(Minimization) << "RooMinuit::synchronize: value of parameter " << par->GetName() << " changed from " << oldVar << " to " << par->getVal() << endl ;
00748         }
00749         if (oldVlo!=pmin || oldVhi!=pmax) {
00750           coutI(Minimization) << "RooMinuit::synchronize: limits of parameter " << par->GetName() << " changed from [" << oldVlo << "," << oldVhi
00751                << "] to [" << pmin << "," << pmax << "]" << endl ;
00752         }
00753 
00754         // If oldVerr=0, then parameter was previously fixed
00755         if (oldVerr!=pstep && oldVerr!=0) {
00756         coutI(Minimization) << "RooMinuit::synchronize: error/step size of parameter " << par->GetName() << " changed from " << oldVerr << " to " << pstep << endl ;
00757         }
00758       }
00759     }
00760   }
00761 
00762 
00763   gMinuit->fNwrmes[0] = 0;  // to clear buffer
00764   oldWarn = setWarnLevel(oldWarn) ;
00765   oldPrint = setPrintLevel(oldPrint) ;
00766 
00767   if (_optConst) {
00768     if (constStatChange) {
00769 
00770       RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00771 
00772       coutI(Minimization) << "RooMinuit::synchronize: set of constant parameters changed, rerunning const optimizer" << endl ;
00773       _func->constOptimizeTestStatistic(RooAbsArg::ConfigChange) ;
00774     } else if (constValChange) {
00775       coutI(Minimization) << "RooMinuit::synchronize: constant parameter values changed, rerunning const optimizer" << endl ;
00776       _func->constOptimizeTestStatistic(RooAbsArg::ValueChange) ;
00777     }
00778 
00779     RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00780 
00781   }
00782 
00783   return 0 ;
00784 }
00785 
00786 
00787 
00788 
00789 //_____________________________________________________________________________
00790 void RooMinuit::optimizeConst(Bool_t flag)
00791 {
00792   // If flag is true, perform constant term optimization on
00793   // function being minimized.
00794 
00795   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::CollectErrors) ;
00796 
00797   if (_optConst && !flag){
00798     if (_printLevel>-1) coutI(Minimization) << "RooMinuit::optimizeConst: deactivating const optimization" << endl ;
00799     _func->constOptimizeTestStatistic(RooAbsArg::DeActivate) ;
00800     _optConst = flag ;
00801   } else if (!_optConst && flag) {
00802     if (_printLevel>-1) coutI(Minimization) << "RooMinuit::optimizeConst: activating const optimization" << endl ;
00803     _func->constOptimizeTestStatistic(RooAbsArg::Activate) ;
00804     _optConst = flag ;
00805   } else if (_optConst && flag) {
00806     if (_printLevel>-1) coutI(Minimization) << "RooMinuit::optimizeConst: const optimization already active" << endl ;
00807   } else {
00808     if (_printLevel>-1) coutI(Minimization) << "RooMinuit::optimizeConst: const optimization wasn't active" << endl ;
00809   }
00810 
00811   RooAbsReal::setEvalErrorLoggingMode(RooAbsReal::PrintErrors) ;
00812 
00813 }
00814 
00815 
00816 
00817 //_____________________________________________________________________________
00818 RooFitResult* RooMinuit::save(const char* userName, const char* userTitle)
00819 {
00820   // Save and return a RooFitResult snaphot of current minimizer status.
00821   // This snapshot contains the values of all constant parameters,
00822   // the value of all floating parameters at RooMinuit construction and
00823   // after the last MINUIT operation, the MINUIT status, variance quality,
00824   // EDM setting, number of calls with evaluation problems, the minimized
00825   // function value and the full correlation matrix
00826 
00827   TString name,title ;
00828   name = userName ? userName : Form("%s", _func->GetName()) ;
00829   title = userTitle ? userTitle : Form("%s", _func->GetTitle()) ;
00830 
00831   if (_floatParamList->getSize()==0) {
00832     RooFitResult* fitRes = new RooFitResult(name,title) ;
00833     fitRes->setConstParList(*_constParamList) ;
00834     fitRes->setInitParList(RooArgList()) ;
00835     fitRes->setFinalParList(RooArgList()) ;
00836     fitRes->setStatus(-999) ;
00837     fitRes->setCovQual(-999) ;
00838     fitRes->setMinNLL(_func->getVal()) ;
00839     fitRes->setNumInvalidNLL(0) ;
00840     fitRes->setEDM(-999) ;
00841     return fitRes ;
00842   }
00843 
00844   RooFitResult* fitRes = new RooFitResult(name,title) ;
00845 
00846   // Move eventual fixed paramaters in floatList to constList
00847   Int_t i ;
00848   RooArgList saveConstList(*_constParamList) ;
00849   RooArgList saveFloatInitList(*_initFloatParamList) ;
00850   RooArgList saveFloatFinalList(*_floatParamList) ;
00851   for (i=0 ; i<_floatParamList->getSize() ; i++) {
00852     RooAbsArg* par = _floatParamList->at(i) ;
00853     if (par->isConstant()) {
00854       saveFloatInitList.remove(*saveFloatInitList.find(par->GetName()),kTRUE) ;
00855       saveFloatFinalList.remove(*par) ;
00856       saveConstList.add(*par) ;
00857     }
00858   }
00859   saveConstList.sort() ;
00860 
00861   fitRes->setConstParList(saveConstList) ;
00862   fitRes->setInitParList(saveFloatInitList) ;
00863 
00864   Double_t edm, errdef, minVal;
00865   Int_t nvpar, nparx;
00866   Int_t icode = _theFitter->GetStats(minVal, edm, errdef, nvpar, nparx);
00867   fitRes->setStatus(_status) ;
00868   fitRes->setCovQual(icode) ;
00869   fitRes->setMinNLL(minVal) ;
00870   fitRes->setNumInvalidNLL(_numBadNLL) ;
00871   fitRes->setEDM(edm) ;
00872   fitRes->setFinalParList(saveFloatFinalList) ;
00873   if (!_extV) {
00874     fitRes->fillCorrMatrix() ;
00875   } else {
00876     fitRes->setCovarianceMatrix(*_extV) ;
00877   }
00878 
00879   return fitRes ;
00880 }
00881 
00882 
00883 
00884 
00885 //_____________________________________________________________________________
00886 RooPlot* RooMinuit::contour(RooRealVar& var1, RooRealVar& var2, Double_t n1, Double_t n2, Double_t n3, Double_t n4, Double_t n5, Double_t n6)
00887 {
00888   // Create and draw a TH2 with the error contours in parameters var1 and v2 at up to 6 'sigma' settings
00889   // where 'sigma' is calculated as n*n*errorLevel
00890 
00891 
00892   _theFitter->SetObjectFit(this) ;
00893 
00894   RooArgList* paramSave = (RooArgList*) _floatParamList->snapshot() ;
00895 
00896   // Verify that both variables are floating parameters of PDF
00897   Int_t index1= _floatParamList->index(&var1);
00898   if(index1 < 0) {
00899     coutE(Minimization) << "RooMinuit::contour(" << GetName()
00900                         << ") ERROR: " << var1.GetName() << " is not a floating parameter of " << _func->GetName() << endl ;
00901     return 0;
00902   }
00903 
00904   Int_t index2= _floatParamList->index(&var2);
00905   if(index2 < 0) {
00906     coutE(Minimization) << "RooMinuit::contour(" << GetName()
00907                         << ") ERROR: " << var2.GetName() << " is not a floating parameter of PDF " << _func->GetName() << endl ;
00908     return 0;
00909   }
00910 
00911   // create and draw a frame
00912   RooPlot* frame = new RooPlot(var1,var2) ;
00913 
00914   // draw a point at the current parameter values
00915   TMarker *point= new TMarker(var1.getVal(), var2.getVal(), 8);
00916   frame->addObject(point) ;
00917 
00918   // remember our original value of ERRDEF
00919   Double_t errdef= gMinuit->fUp;
00920 
00921   Double_t n[6] ;
00922   n[0] = n1 ; n[1] = n2 ; n[2] = n3 ; n[3] = n4 ; n[4] = n5 ; n[5] = n6 ;
00923 
00924 
00925   for (Int_t ic = 0 ; ic<6 ; ic++) {
00926     if(n[ic] > 0) {
00927       // set the value corresponding to an n1-sigma contour
00928       gMinuit->SetErrorDef(n[ic]*n[ic]*errdef);
00929       // calculate and draw the contour
00930       TGraph* graph= (TGraph*)gMinuit->Contour(50, index1, index2);
00931       if (!graph) {
00932         coutE(Minimization) << "RooMinuit::contour(" << GetName() << ") ERROR: MINUIT did not return a contour graph for n=" << n[ic] << endl ;
00933       } else {
00934         graph->SetName(Form("contour_%s_n%f",_func->GetName(),n[ic])) ;
00935         graph->SetLineStyle(ic+1) ;
00936         graph->SetLineWidth(2) ;
00937         graph->SetLineColor(kBlue) ;
00938         frame->addObject(graph,"L") ;
00939       }
00940     }
00941   }
00942 
00943   // restore the original ERRDEF
00944   gMinuit->SetErrorDef(errdef);
00945 
00946   // restore parameter values
00947   *_floatParamList = *paramSave ;
00948   delete paramSave ;
00949 
00950 
00951   return frame ;
00952 }
00953 
00954 
00955 
00956 //_____________________________________________________________________________
00957 Bool_t RooMinuit::setLogFile(const char* inLogfile)
00958 {
00959   // Change the file name for logging of a RooMinuit of all MINUIT steppings
00960   // through the parameter space. If inLogfile is null, the current log file
00961   // is closed and logging is stopped.
00962 
00963   if (_logfile) {
00964     coutI(Minimization) << "RooMinuit::setLogFile: closing previous log file" << endl ;
00965     _logfile->close() ;
00966     delete _logfile ;
00967     _logfile = 0 ;
00968   }
00969   _logfile = new ofstream(inLogfile) ;
00970   if (!_logfile->good()) {
00971     coutI(Minimization) << "RooMinuit::setLogFile: cannot open file " << inLogfile << endl ;
00972     _logfile->close() ;
00973     delete _logfile ;
00974     _logfile= 0;
00975   }
00976   return kFALSE ;
00977 }
00978 
00979 
00980 
00981 //_____________________________________________________________________________
00982 Double_t RooMinuit::getPdfParamVal(Int_t index)
00983 {
00984   // Access PDF parameter value by ordinal index (needed by MINUIT)
00985 
00986   return ((RooRealVar*)_floatParamList->at(index))->getVal() ;
00987 }
00988 
00989 
00990 
00991 //_____________________________________________________________________________
00992 Double_t RooMinuit::getPdfParamErr(Int_t index)
00993 {
00994   // Access PDF parameter error by ordinal index (needed by MINUIT)
00995 
00996   return ((RooRealVar*)_floatParamList->at(index))->getError() ;
00997 }
00998 
00999 
01000 
01001 //_____________________________________________________________________________
01002 Bool_t RooMinuit::setPdfParamVal(Int_t index, Double_t value, Bool_t verbose)
01003 {
01004   // Modify PDF parameter value by ordinal index (needed by MINUIT)
01005 
01006   RooRealVar* par = (RooRealVar*)_floatParamList->at(index) ;
01007 
01008   if (par->getVal()!=value) {
01009     if (verbose) cout << par->GetName() << "=" << value << ", " ;
01010     par->setVal(value) ;
01011     return kTRUE ;
01012   }
01013 
01014   return kFALSE ;
01015 }
01016 
01017 
01018 
01019 //_____________________________________________________________________________
01020 void RooMinuit::setPdfParamErr(Int_t index, Double_t value)
01021 {
01022   // Modify PDF parameter error by ordinal index (needed by MINUIT)
01023 
01024   ((RooRealVar*)_floatParamList->at(index))->setError(value) ;
01025 }
01026 
01027 
01028 
01029 //_____________________________________________________________________________
01030 void RooMinuit::clearPdfParamAsymErr(Int_t index)
01031 {
01032   // Modify PDF parameter error by ordinal index (needed by MINUIT)
01033 
01034   ((RooRealVar*)_floatParamList->at(index))->removeAsymError() ;
01035 }
01036 
01037 
01038 //_____________________________________________________________________________
01039 void RooMinuit::setPdfParamErr(Int_t index, Double_t loVal, Double_t hiVal)
01040 {
01041   // Modify PDF parameter error by ordinal index (needed by MINUIT)
01042 
01043   ((RooRealVar*)_floatParamList->at(index))->setAsymError(loVal,hiVal) ;
01044 }
01045 
01046 
01047 
01048 //_____________________________________________________________________________
01049 void RooMinuit::profileStart()
01050 {
01051   // Start profiling timer
01052   if (_profile) {
01053     _timer.Start() ;
01054     _cumulTimer.Start(kFALSE) ;
01055   }
01056 }
01057 
01058 
01059 
01060 
01061 //_____________________________________________________________________________
01062 void RooMinuit::profileStop()
01063 {
01064   // Stop profiling timer and report results of last session
01065   if (_profile) {
01066     _timer.Stop() ;
01067     _cumulTimer.Stop() ;
01068     coutI(Minimization) << "Command timer: " ; _timer.Print() ;
01069     coutI(Minimization) << "Session timer: " ; _cumulTimer.Print() ;
01070   }
01071 }
01072 
01073 
01074 
01075 
01076 
01077 //_____________________________________________________________________________
01078 void RooMinuit::backProp()
01079 {
01080   // Transfer MINUIT fit results back into RooFit objects
01081 
01082   Double_t val,err,vlo,vhi, eplus, eminus, eparab, globcc;
01083   char buffer[10240];
01084   Int_t index ;
01085   for(index= 0; index < _nPar; index++) {
01086     _theFitter->GetParameter(index, buffer, val, err, vlo, vhi);
01087     setPdfParamVal(index, val);
01088     _theFitter->GetErrors(index, eplus, eminus, eparab, globcc);
01089 
01090     // Set the parabolic error
01091     setPdfParamErr(index, err);
01092 
01093     if(eplus > 0 || eminus < 0) {
01094       // Store the asymmetric error, if it is available
01095       setPdfParamErr(index, eminus,eplus);
01096     } else {
01097       // Clear the asymmetric error
01098       clearPdfParamAsymErr(index) ;
01099     }
01100   }
01101 }
01102 
01103 
01104 
01105 
01106 //_____________________________________________________________________________
01107 void RooMinuit::applyCovarianceMatrix(TMatrixDSym& V)
01108 {
01109   // Apply results of given external covariance matrix. i.e. propagate its errors
01110   // to all RRV parameter representations and give this matrix instead of the
01111   // HESSE matrix at the next save() call
01112 
01113   _extV = (TMatrixDSym*) V.Clone() ;
01114 
01115   for (Int_t i=0 ; i<getNPar() ; i++) {
01116     // Skip fixed parameters
01117     if (_floatParamList->at(i)->isConstant()) {
01118       continue ;
01119     }
01120     setPdfParamErr(i, sqrt((*_extV)(i,i))) ;
01121   }
01122 
01123 }
01124 
01125 
01126 
01127 
01128 void RooMinuitGlue(Int_t& /*np*/, Double_t* /*gin*/,
01129                    Double_t &f, Double_t *par, Int_t /*flag*/)
01130 {
01131   // Static function that interfaces minuit with RooMinuit
01132 
01133   // Retrieve fit context and its components
01134   RooMinuit* context = (RooMinuit*) RooMinuit::_theFitter->GetObjectFit() ;
01135   ofstream* logf   = context->logfile() ;
01136   Double_t& maxFCN = context->maxFCN() ;
01137   Bool_t verbose   = context->_verbose ;
01138 
01139   // Set the parameter values for this iteration
01140   Int_t nPar= context->getNPar();
01141   for(Int_t index= 0; index < nPar; index++) {
01142     if (logf) (*logf) << par[index] << " " ;
01143     context->setPdfParamVal(index, par[index],verbose);
01144   }
01145 
01146   // Calculate the function for these parameters
01147   f= context->_func->getVal() ;
01148   if ( RooAbsPdf::evalError() || RooAbsReal::numEvalErrors()>0 ) {
01149 
01150     if (context->_printEvalErrors>=0) {
01151 
01152       if (context->_doEvalErrorWall) {
01153         oocoutW(context,Minimization) << "RooFitGlue: Minimized function has error status." << endl
01154                                       << "Returning maximum FCN so far (" << maxFCN
01155                                       << ") to force MIGRAD to back out of this region. Error log follows" << endl ;
01156       } else {
01157         oocoutW(context,Minimization) << "RooFitGlue: Minimized function has error status but is ignored" << endl ;
01158       }
01159 
01160       TIterator* iter = context->_floatParamList->createIterator() ;
01161       RooRealVar* var ;
01162       Bool_t first(kTRUE) ;
01163       ooccoutW(context,Minimization) << "Parameter values: " ;
01164       while((var=(RooRealVar*)iter->Next())) {
01165         if (first) { first = kFALSE ; } else ooccoutW(context,Minimization) << ", " ;
01166         ooccoutW(context,Minimization) << var->GetName() << "=" << var->getVal() ;
01167       }
01168       delete iter ;
01169       ooccoutW(context,Minimization) << endl ;
01170 
01171       RooAbsReal::printEvalErrors(ooccoutW(context,Minimization),context->_printEvalErrors) ;
01172       ooccoutW(context,Minimization) << endl ;
01173     }
01174 
01175     if (context->_doEvalErrorWall) {
01176       f = maxFCN ;
01177     }
01178 
01179     RooAbsPdf::clearEvalError() ;
01180     RooAbsReal::clearEvalErrorLog() ;
01181     context->_numBadNLL++ ;
01182   } else if (f>maxFCN) {
01183     maxFCN = f ;
01184   }
01185 
01186   // Optional logging
01187   if (logf) (*logf) << setprecision(15) << f << setprecision(4) << endl;
01188   if (verbose) {
01189     cout << "\nprevFCN = " << setprecision(10) << f << setprecision(4) << "  " ;
01190     cout.flush() ;
01191   }
01192 }

Generated on Tue Jul 5 15:06:51 2011 for ROOT_528-00b_version by  doxygen 1.5.1