/*************************************************************************** PFitter.cpp Author: Andreas Suter e-mail: andreas.suter@psi.ch $Id$ ***************************************************************************/ /*************************************************************************** * Copyright (C) 2007 by Andreas Suter * * andreas.suter@psi.c * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include using namespace std; #include "Minuit2/FunctionMinimum.h" #include "Minuit2/MnMinimize.h" #include "Minuit2/MnMigrad.h" #include "Minuit2/MnMinos.h" #include "Minuit2/MnSimplex.h" #include "PFitter.h" //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- /** *

* * \param runInfo * \param runListCollection */ PFitter::PFitter(PMsrHandler *runInfo, PRunListCollection *runListCollection) : fRunInfo(runInfo) { fUseChi2 = true; // chi^2 is the default fParams = *(runInfo->GetMsrParamList()); fCmdLines = *runInfo->GetMsrCommands(); // init class variables fFitterFcn = 0; fFcnMin = 0; // check msr minuit commands if (!CheckCommands()) { return; } // create fit function object fFitterFcn = new PFitterFcn(runListCollection, fUseChi2); if (!fFitterFcn) { fIsValid = false; return; } } //-------------------------------------------------------------------------- // Destructor //-------------------------------------------------------------------------- /** *

* */ PFitter::~PFitter() { fCmdList.clear(); if (fFitterFcn) { delete fFitterFcn; fFitterFcn = 0; } } //-------------------------------------------------------------------------- // DoFit //-------------------------------------------------------------------------- /** *

* */ bool PFitter::DoFit() { if (fUseChi2) cout << endl << "Chi Square fit will be executed" << endl; else cout << endl << "Maximum Likelihood fit will be executed" << endl; // feed minuit parameters SetParameters(); bool status; for (unsigned int i=0; i * */ bool PFitter::CheckCommands() { fIsValid = true; PMsrLines::iterator it; for (it = fCmdLines.begin(); it != fCmdLines.end(); ++it) { it->fLine.ToUpper(); if (it->fLine.Contains("COMMANDS")) { continue; } else if (it->fLine.Contains("SET BATCH")) { // needed for backward compatibility continue; } else if (it->fLine.Contains("END RETURN")) { // needed for backward compatibility continue; } else if (it->fLine.Contains("CHI_SQUARE")) { fUseChi2 = true; } else if (it->fLine.Contains("MAX_LIKELIHOOD")) { fUseChi2 = false; } else if (it->fLine.Contains("INTERACTIVE")) { fCmdList.push_back(PMN_INTERACTIVE); } else if (it->fLine.Contains("CONTOURS")) { fCmdList.push_back(PMN_CONTOURS); } else if (it->fLine.Contains("EIGEN")) { fCmdList.push_back(PMN_EIGEN); } else if (it->fLine.Contains("HESSE")) { fCmdList.push_back(PMN_HESSE); } else if (it->fLine.Contains("MACHINE_PRECISION")) { fCmdList.push_back(PMN_MACHINE_PRECISION); } else if (it->fLine.Contains("MIGRAD")) { fCmdList.push_back(PMN_MIGRAD); } else if (it->fLine.Contains("MINIMIZE")) { fCmdList.push_back(PMN_MINIMIZE); } else if (it->fLine.Contains("MINOS")) { fCmdList.push_back(PMN_MINOS); } else if (it->fLine.Contains("PLOT")) { fCmdList.push_back(PMN_PLOT); } else if (it->fLine.Contains("SAVE")) { fCmdList.push_back(PMN_SAVE); } else if (it->fLine.Contains("SCAN")) { fCmdList.push_back(PMN_SCAN); } else if (it->fLine.Contains("SIMPLEX")) { fCmdList.push_back(PMN_SIMPLEX); } else if (it->fLine.Contains("STRATEGY")) { fCmdList.push_back(PMN_STRATEGY); } else if (it->fLine.Contains("USER_COVARIANCE")) { fCmdList.push_back(PMN_USER_COVARIANCE); } else if (it->fLine.Contains("USER_PARAM_STATE")) { fCmdList.push_back(PMN_USER_PARAM_STATE); } else if (it->fLine.Contains("PRINT")) { fCmdList.push_back(PMN_PRINT); } else { // unkown command cout << endl << "FATAL ERROR:"; cout << endl << "PFitter::CheckCommands(): In line " << it->fLineNo << " an unkown command is found:"; cout << endl << " " << it->fLine.Data(); cout << endl << "Will stop ..."; cout << endl; fIsValid = false; } } return fIsValid; } //-------------------------------------------------------------------------- // SetParameters //-------------------------------------------------------------------------- /** *

* */ bool PFitter::SetParameters() { PMsrParamList::iterator it; for (it = fParams.begin(); it != fParams.end(); ++it) { // check if parameter is fixed if (it->fStep == 0.0) { // add fixed parameter fMnUserParams.Add(it->fName.Data(), it->fValue); } else { // add free parameter // check if boundaries are given if (it->fNoOfParams > 5) { // boundaries given fMnUserParams.Add(it->fName.Data(), it->fValue, it->fStep, it->fLowerBoundary, it->fUpperBoundary); } else { // no boundaries given fMnUserParams.Add(it->fName.Data(), it->fValue, it->fStep); } } } return true; } //-------------------------------------------------------------------------- // ExecuteMigrad //-------------------------------------------------------------------------- /** *

* */ bool PFitter::ExecuteMigrad() { cout << "PFitter::ExecuteMigrad(): will call migrad ..." << endl; // if already some minimization is done use the minuit2 output as input if (fFcnMin) fMnUserParams = fFcnMin->UserParameters(); // create migrad object ROOT::Minuit2::MnMigrad migrad((*fFitterFcn), fMnUserParams); // minimize ROOT::Minuit2::FunctionMinimum min = migrad(); if (!min.IsValid()) { cout << endl << "**WARNING**: PFitter::ExecuteMigrad(): Fit did not converge, sorry ..."; return false; } // keep FunctionMinimum object if (fFcnMin) { // fFcnMin exist hence clean up first delete fFcnMin; } fFcnMin = new ROOT::Minuit2::FunctionMinimum(min); // fill run info for (unsigned int i=0; iSetMsrParamValue(i, min.UserState().Value(i)); fRunInfo->SetMsrParamStep(i, min.UserState().Error(i)); } // handle statistics double minVal = min.Fval(); unsigned int ndf = fFitterFcn->GetTotalNoOfFittedBins(); // subtract number of varied parameters from total no of fitted bins -> ndf for (unsigned int i=0; iSetMsrStatisticMin(minVal); fRunInfo->SetMsrStatisticNdf(ndf); return true; } //-------------------------------------------------------------------------- // ExecuteMinimize //-------------------------------------------------------------------------- /** *

* */ bool PFitter::ExecuteMinimize() { cout << "PFitter::ExecuteMinimize(): will call minimize ..." << endl; // if already some minimization is done use the minuit2 output as input if (fFcnMin) fMnUserParams = fFcnMin->UserParameters(); // create minimizer object ROOT::Minuit2::MnMinimize minimize((*fFitterFcn), fMnUserParams); // minimize ROOT::Minuit2::FunctionMinimum min = minimize(); if (!min.IsValid()) { cout << endl << "**WARNING**: PFitter::ExecuteMinimize(): Fit did not converge, sorry ..."; return false; } // keep FunctionMinimum object if (fFcnMin) { // fFcnMin exist hence clean up first delete fFcnMin; } fFcnMin = new ROOT::Minuit2::FunctionMinimum(min); // fill run info for (unsigned int i=0; iSetMsrParamValue(i, min.UserState().Value(i)); fRunInfo->SetMsrParamStep(i, min.UserState().Error(i)); } // handle statistics double minVal = min.Fval(); unsigned int ndf = fFitterFcn->GetTotalNoOfFittedBins(); // subtract number of varied parameters from total no of fitted bins -> ndf for (unsigned int i=0; iSetMsrStatisticMin(minVal); fRunInfo->SetMsrStatisticNdf(ndf); return true; } //-------------------------------------------------------------------------- // ExecuteMinos //-------------------------------------------------------------------------- /** *

* */ bool PFitter::ExecuteMinos() { cout << "PFitter::ExecuteMinos(): will call minos ..." << endl; // if already some minimization is done use the minuit2 output as input if (!fFcnMin) { cout << endl << "**ERROR**: MINOS musn't be called before any minimization (MINIMIZE/MIGRAD/SIMPLEX) is done!!"; cout << endl; return false; } // check if minimum was valid if (!fFcnMin->IsValid()) { cout << endl << "**ERROR**: MINOS cannot started since the previews minimization faild :-("; cout << endl; return false; } fMnUserParams = fFcnMin->UserParameters(); // make minos analysis ROOT::Minuit2::MnMinos minos((*fFitterFcn), (*fFcnMin)); for (unsigned int i=0; i err = minos(i); // fill msr-file structure fRunInfo->SetMsrParamStep(i, err.first); fRunInfo->SetMsrParamPosError(i, err.second); } } return true; } //-------------------------------------------------------------------------- // ExecuteSave //-------------------------------------------------------------------------- /** *

* */ bool PFitter::ExecuteSave() { cout << "PFitter::ExecuteSave(): not yet implemented ..." << endl; // if any minimization was done, otherwise get out immediately if (!fFcnMin) { cout << endl << "PFitter::ExecuteSave(): nothing to be saved ..."; return false; } return true; } //-------------------------------------------------------------------------- // ExecuteSimplex //-------------------------------------------------------------------------- /** *

* */ bool PFitter::ExecuteSimplex() { cout << "PFitter::ExecuteSimplex(): will call minimize ..." << endl; // if already some minimization is done use the minuit2 output as input if (fFcnMin) fMnUserParams = fFcnMin->UserParameters(); // create minimizer object ROOT::Minuit2::MnSimplex simplex((*fFitterFcn), fMnUserParams); // minimize ROOT::Minuit2::FunctionMinimum min = simplex(); if (!min.IsValid()) { cout << endl << "**WARNING**: PFitter::ExecuteSimplex(): Fit did not converge, sorry ..."; return false; } // keep FunctionMinimum object if (fFcnMin) { // fFcnMin exist hence clean up first delete fFcnMin; } fFcnMin = new ROOT::Minuit2::FunctionMinimum(min); // fill run info for (unsigned int i=0; iSetMsrParamValue(i, min.UserState().Value(i)); fRunInfo->SetMsrParamStep(i, min.UserState().Error(i)); } // handle statistics double minVal = min.Fval(); unsigned int ndf = fFitterFcn->GetTotalNoOfFittedBins(); // subtract number of varied parameters from total no of fitted bins -> ndf for (unsigned int i=0; iSetMsrStatisticMin(minVal); fRunInfo->SetMsrStatisticNdf(ndf); return true; }