CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/PhysicsTools/Utilities/interface/RootMinuitCommands.h

Go to the documentation of this file.
00001 #ifndef PhysicsTools_Utilities_RootMinuitCommands_h
00002 #define PhysicsTools_Utilities_RootMinuitCommands_h
00003 #include "PhysicsTools/Utilities/interface/RootMinuit.h"
00004 #include "PhysicsTools/Utilities/interface/ParameterMap.h"
00005 #include "FWCore/Utilities/interface/EDMException.h"
00006 #include "Utilities/General/interface/FileInPath.h"
00007 #include "PhysicsTools/Utilities/interface/Parameter.h"
00008 #include <map>
00009 #include <string>
00010 #include <cstdlib>
00011 #include <fstream>
00012 #include <sstream>
00013 #include <iostream>
00014 #include<boost/tokenizer.hpp>
00015 
00016 const char * kParameter = "par";
00017 const char * kFix = "fix";
00018 const char * kRelease = "release";
00019 const char * kSet = "set";
00020 const char * kMinimize = "minimize";
00021 const char * kMigrad = "migrad";
00022 const char * kPrintAll = "print_all";
00023 
00024 namespace fit {
00025 
00026   struct RootMinuitCommand {
00027     std::string name;
00028     std::vector<std::string> stringArgs;
00029     std::vector<double> doubleArgs;
00030     void print(std::ostream& cout) const {
00031       cout << name;
00032       if(stringArgs.size() > 0) {
00033         for(size_t i = 0; i != stringArgs.size(); ++i) {
00034           if(i != 0) cout << ",";
00035           cout << " \"" << stringArgs[i] << "\"";
00036         }
00037       }
00038       if(doubleArgs.size() > 0) {
00039         for(size_t i = 0; i != doubleArgs.size(); ++i) {
00040           if(i != 0) cout << ",";
00041           cout << " " << doubleArgs[i];
00042         }
00043       }
00044     }
00045   };
00046 
00047   template<class Function>
00048   class RootMinuitCommands {
00049   public:
00050     typedef RootMinuit<Function> minuit;
00051     typedef RootMinuitCommand command;
00052     RootMinuitCommands(bool verbose = true) :
00053       verbose_(verbose) {
00054     }
00055     RootMinuitCommands(const char * fileName, bool verbose = true) :
00056       verbose_(verbose) {
00057       init(fileName);
00058     }
00059     void init(const char * fileName);
00060     double par(const std::string& name) {
00061       return parameter(name).val;
00062     }
00063     double err(const std::string& name) {
00064       return parameter(name).err;
00065     }  
00066     double min(const std::string& name) {
00067       return parameter(name).min;
00068     }
00069     double max(const std::string& name) {
00070       return parameter(name).max;
00071     }  
00072     bool fixed(const std::string& name) {
00073       return parameter(name).fixed;
00074     }   
00075     void add(RootMinuit<Function>& minuit, funct::Parameter& p) const {
00076       const std::string & name = p.name();
00077       const parameter_t & par = parameter(name);
00078       minuit.addParameter(p, par.err, par.min, par.max);
00079       if(par.fixed) minuit.fixParameter(name);
00080     }
00081     void run(RootMinuit<Function>& minuit) const;
00082 
00083   private:
00084     typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00085     bool verbose_;
00086     unsigned int lineNumber_;
00087     parameterVector_t pars_;
00088     std::map<std::string, size_t> parIndices_;
00089     std::vector<command> commands_;
00090     double string2double(const std::string & str) const {
00091       const char * begin = str.c_str();
00092       char * end;
00093       double val = strtod(begin, &end);
00094       size_t s = end - begin;
00095       if(s < str.size()) {
00096         throw edm::Exception(edm::errors::Configuration)
00097           << "RootMinuitCommands: invalid double value: " 
00098           << str  << "\n";
00099       }
00100       return val;
00101     }
00102     const parameter_t & parameter(const std::string& name) const {
00103       typename std::map<std::string, size_t>::const_iterator p = parIndices_.find(name);
00104       if(p == parIndices_.end())
00105         throw edm::Exception(edm::errors::Configuration)
00106           << "RootMinuit: can't find parameter " << name << "\n";
00107       return pars_[p->second].second;
00108     }
00109     std::string errorHeader() const {
00110       std::ostringstream out;
00111       out << "RootMinuitCommands config. error, line " << lineNumber_<< ": ";
00112       return out.str();
00113     }
00114     std::string nextToken(typename tokenizer::iterator & i,
00115                           const typename tokenizer::iterator & end) const {
00116       ++i;
00117       if(i == end)
00118         throw edm::Exception(edm::errors::Configuration)
00119           << errorHeader() << "missing parameter\n";
00120       return *i;
00121     }
00122   };
00123 
00124   template<typename Function>
00125   void RootMinuitCommands<Function>::init(const char * fileName) {
00126     using namespace std;
00127     string cmssw_release_base = getenv("CMSSW_RELEASE_BASE");
00128     string cmssw_base = getenv("CMSSW_BASE");
00129     string path = "."; 
00130     if(!cmssw_release_base.empty()) {
00131       path += ':';
00132       path += (cmssw_release_base + "/src");
00133     }
00134     if(!cmssw_base.empty()) {
00135       path += ':';
00136       path += (cmssw_base + "/src");
00137     }
00138     FileInPath fileInPath(path, fileName);
00139     ifstream * file = fileInPath();
00140     if(file==0 || !file->is_open())
00141       throw edm::Exception(edm::errors::Configuration)
00142         << "RootMinuitCommands: can't open file: " << fileName 
00143         << " in path: " << path << "\n";
00144     if (verbose_) 
00145       cout << ">>> configuration file: " << fileName << endl;
00146     string line;
00147     lineNumber_ = 0;
00148     bool commands = false;
00149     while(getline(*file, line)) {
00150       ++lineNumber_;
00151       if(line.size()==0) continue;
00152       char last = *line.rbegin();
00153       if(!(last >= '0' && last <= 'z')) line.erase(line.end() - 1);
00154       boost::char_separator<char> sep(" ");
00155       tokenizer tokens(line, sep);
00156       tokenizer::iterator i = tokens.begin(), e = tokens.end();
00157       if(tokens.begin()==tokens.end()) continue;
00158       if(*(i->begin()) != '#') {
00159         if(*i == kParameter) {
00160           if(commands)
00161             throw edm::Exception(edm::errors::Configuration)
00162               << errorHeader() 
00163               << "please, declare all parameter before all other minuit commands.\n";
00164           string name = nextToken(i, e);
00165           parameter_t par;
00166           par.val = string2double(nextToken(i, e));
00167           par.err = string2double(nextToken(i, e));
00168           par.min = string2double(nextToken(i, e));
00169           par.max = string2double(nextToken(i, e));
00170           tokenizer::iterator j = i; ++j;
00171           if(j != e) {
00172             string fixed = nextToken(i, e);
00173             if(fixed == "fixed") 
00174               par.fixed = true;
00175             else if(fixed == "free")
00176               par.fixed = false;
00177             else
00178               throw edm::Exception(edm::errors::Configuration)
00179                 << errorHeader()
00180                 << "fix parameter option unknown: " << *i << "\n"
00181                 << "valid options are: fixed, free.\n";
00182           } else {
00183             par.fixed = false;
00184           }
00185           pars_.push_back(std::make_pair(name, par));
00186           size_t s = parIndices_.size();
00187           parIndices_[name] = s;
00188           if(verbose_)
00189             cout << ">>> " << kParameter << " " << name 
00190                  << " " << par.val 
00191                  << " [" << par.min << ", " << par.max << "],"
00192                  << " err: " << par.err
00193                  << endl;
00194         } else if(*i == kFix || *i == kRelease) {
00195           commands = true;
00196           command com;
00197           com.name = *i;
00198           string arg = nextToken(i, e);
00199           com.stringArgs.push_back(arg);
00200           commands_.push_back(com);
00201           if(verbose_) {
00202             cout << ">>> "; com.print(cout); cout << endl;
00203           }
00204         } else if(*i == kSet) {
00205           commands = true;
00206           command com;
00207           com.name = *i;
00208           string arg = nextToken(i, e);
00209           com.stringArgs.push_back(arg);
00210           com.doubleArgs.push_back(string2double(nextToken(i, e)));
00211           commands_.push_back(com);
00212           if(verbose_) {
00213             cout << ">>> "; com.print(cout); cout << endl;
00214           }
00215         } else if(*i == kMinimize || *i == kMigrad || *i == kPrintAll) {
00216           commands = true;
00217           command com;
00218           com.name = *i;
00219           commands_.push_back(com);
00220           if(verbose_) {
00221             cout << ">>> "; com.print(cout); cout << endl;
00222           }
00223         } else {
00224           throw edm::Exception(edm::errors::Configuration)
00225             << errorHeader()
00226             << "unkonwn command:: " << *i << "\n";
00227           
00228         }
00229       }
00230     }
00231     if (verbose_) 
00232       cout << ">>> end configuration" << endl;
00233   }
00234   
00235   template<typename Function>
00236   void RootMinuitCommands<Function>::run(RootMinuit<Function>& minuit) const {
00237     using namespace std;
00238     typename vector<command>::const_iterator c = commands_.begin(), end = commands_.end();
00239     for(; c != end; ++c) {
00240       if(verbose_) {
00241         cout << ">>> minuit command: ";
00242         c->print(cout);
00243         cout << endl;
00244       }
00245       if(c->name == kMinimize)
00246         minuit.minimize();
00247       else if(c->name == kMigrad)
00248         minuit.migrad();
00249       else if(c->name == kPrintAll)
00250         minuit.printFitResults();
00251       else if(c->name == kFix) 
00252         minuit.fixParameter(c->stringArgs[0]);
00253       else if(c->name == kRelease) 
00254         minuit.releaseParameter(c->stringArgs[0]);
00255       else if(c->name == kSet)
00256         minuit.setParameter(c->stringArgs[0], c->doubleArgs[0]);
00257     }
00258   }
00259   
00260 }
00261 
00262 #endif