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