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 line.erase(line.end() - 1); 00152 boost::char_separator<char> sep(" "); 00153 tokenizer tokens(line, sep); 00154 tokenizer::iterator i = tokens.begin(), e = tokens.end(); 00155 if(tokens.begin()==tokens.end()) continue; 00156 if(*(i->begin()) != '#') { 00157 if(*i == kParameter) { 00158 if(commands) 00159 throw edm::Exception(edm::errors::Configuration) 00160 << errorHeader() 00161 << "please, declare all parameter before all other minuit commands.\n"; 00162 string name = nextToken(i, e); 00163 parameter_t par; 00164 par.val = string2double(nextToken(i, e)); 00165 par.err = string2double(nextToken(i, e)); 00166 par.min = string2double(nextToken(i, e)); 00167 par.max = string2double(nextToken(i, e)); 00168 tokenizer::iterator j = i; ++j; 00169 if(j != e) { 00170 string fixed = nextToken(i, e); 00171 if(fixed == "fixed") 00172 par.fixed = true; 00173 else if(fixed == "free") 00174 par.fixed = false; 00175 else 00176 throw edm::Exception(edm::errors::Configuration) 00177 << errorHeader() 00178 << "fix parameter option unknown: " << *i << "\n" 00179 << "valid options are: fixed, free.\n"; 00180 } else { 00181 par.fixed = false; 00182 } 00183 pars_.push_back(std::make_pair(name, par)); 00184 size_t s = parIndices_.size(); 00185 parIndices_[name] = s; 00186 if(verbose_) 00187 cout << ">>> " << kParameter << " " << name 00188 << " " << par.val 00189 << " [" << par.min << ", " << par.max << "]," 00190 << " err: " << par.err 00191 << endl; 00192 } else if(*i == kFix || *i == kRelease) { 00193 commands = true; 00194 command com; 00195 com.name = *i; 00196 string arg = nextToken(i, e); 00197 com.stringArgs.push_back(arg); 00198 commands_.push_back(com); 00199 if(verbose_) { 00200 cout << ">>> "; com.print(cout); cout << endl; 00201 } 00202 } else if(*i == kSet) { 00203 commands = true; 00204 command com; 00205 com.name = *i; 00206 string arg = nextToken(i, e); 00207 com.stringArgs.push_back(arg); 00208 com.doubleArgs.push_back(string2double(nextToken(i, e))); 00209 commands_.push_back(com); 00210 if(verbose_) { 00211 cout << ">>> "; com.print(cout); cout << endl; 00212 } 00213 } else if(*i == kMinimize || *i == kMigrad || *i == kPrintAll) { 00214 commands = true; 00215 command com; 00216 com.name = *i; 00217 commands_.push_back(com); 00218 if(verbose_) { 00219 cout << ">>> "; com.print(cout); cout << endl; 00220 } 00221 } else { 00222 throw edm::Exception(edm::errors::Configuration) 00223 << errorHeader() 00224 << "unkonwn command:: " << *i << "\n"; 00225 00226 } 00227 } 00228 } 00229 if (verbose_) 00230 cout << ">>> end configuration" << endl; 00231 } 00232 00233 template<typename Function> 00234 void RootMinuitCommands<Function>::run(RootMinuit<Function>& minuit) const { 00235 using namespace std; 00236 typename vector<command>::const_iterator c = commands_.begin(), end = commands_.end(); 00237 for(; c != end; ++c) { 00238 if(verbose_) { 00239 cout << ">>> minuit command: "; 00240 c->print(cout); 00241 cout << endl; 00242 } 00243 if(c->name == kMinimize) 00244 minuit.minimize(); 00245 else if(c->name == kMigrad) 00246 minuit.migrad(); 00247 else if(c->name == kPrintAll) 00248 minuit.printFitResults(); 00249 else if(c->name == kFix) 00250 minuit.fixParameter(c->stringArgs[0]); 00251 else if(c->name == kRelease) 00252 minuit.releaseParameter(c->stringArgs[0]); 00253 else if(c->name == kSet) 00254 minuit.setParameter(c->stringArgs[0], c->doubleArgs[0]); 00255 } 00256 } 00257 00258 } 00259 00260 #endif