00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "psana/PSAnaApp.h"
00017
00018
00019
00020
00021 #include <iostream>
00022 #include <fstream>
00023 #include <unistd.h>
00024 #include <boost/make_shared.hpp>
00025
00026
00027
00028
00029 #include "MsgLogger/MsgFormatter.h"
00030 #include "MsgLogger/MsgLogger.h"
00031 #include "psana/Exceptions.h"
00032 #include "psana/PSAna.h"
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 namespace {
00043
00044 const std::string dumpConfigFileOption("psana.dump_config_file");
00045
00046 bool dumpConfigFileOptionSet(const std::map<std::string, std::string> &options) {
00047 std::map<std::string, std::string>::const_iterator pos = options.find(dumpConfigFileOption);
00048 if (pos == options.end()) {
00049 return false;
00050 }
00051 return true;
00052 }
00053
00054 void dumpConfigFile(const std::string &cfgFile) {
00055 if (cfgFile.size()==0) return;
00056 std::cout << "--------- psana config file: " << cfgFile << " ------------" << std::endl;
00057 std::ifstream cfgFileStream;
00058 cfgFileStream.open(cfgFile.c_str(), std::ifstream::in);
00059 if ( (cfgFileStream.rdstate() & std::ifstream::failbit ) == 0 ) {
00060 char c = cfgFileStream.get();
00061 while (cfgFileStream.good()) {
00062 std::cout << c;
00063 c = cfgFileStream.get();
00064 }
00065 cfgFileStream.close();
00066 } else {
00067 std::cout << " ** unable to open file ** " << std::endl;
00068 }
00069 std::cout << std::endl << "------- end psana config file ---------" << std::endl;
00070 }
00071
00072 void removeDumpConfigFileOption(std::map<std::string, std::string> &options) {
00073 std::map<std::string, std::string>::iterator pos = options.find(dumpConfigFileOption);
00074 if (pos != options.end()) {
00075 options.erase(pos);
00076 }
00077 }
00078
00079 }
00080
00081 namespace psana {
00082
00083
00084
00085
00086
00087
00088
00089
00090 PSAnaApp::PSAnaApp ( const std::string& appName )
00091 : AppUtils::AppBase( appName )
00092 , m_calibDirOpt( parser(), "b,calib-dir", "path", "calibration directory name, may include {exp} and {instr}, if left empty then do not do calibrations", "" )
00093 , m_configOpt( parser(), "c,config", "path", "configuration file, by default use psana.cfg if it exists", "" )
00094 , m_expNameOpt( parser(), "e,experiment", "string", "experiment name, format: XPP:xpp12311 or xpp12311, by default guess it from data", "" )
00095 , m_jobNameOpt( parser(), "j,job-name", "string", "job name, default is to generate from input file names", "" )
00096 , m_modulesOpt( parser(), "m,module", "name", "module name, more than one possible" )
00097 , m_maxEventsOpt( parser(), "n,num-events", "number", "maximum number of events to process, 0 means all", 0U )
00098 , m_skipEventsOpt( parser(), "s,skip-events", "number", "number of events to skip", 0U )
00099 , m_parallelOpt( parser(), "p,num-cpu", "number", "number greater than 0 enables multi-processing", 0U )
00100 , m_optionsOpt( parser(), "o,option", "string", "configuration options, format: module.option[=value]" )
00101 , m_datasets( parser(), "dataset", "input dataset specification (list of file names or exp=cxi12345:run=123:...)", std::vector<std::string>() )
00102 {
00103 }
00104
00105
00106
00107
00108 PSAnaApp::~PSAnaApp ()
00109 {
00110 }
00111
00112
00113
00114
00115
00116
00117 int
00118 PSAnaApp::run(const std::vector<std::string>& argv)
00119 {
00120
00121 size_t size = 0;
00122 for (std::vector<std::string>::const_iterator it = argv.begin(); it != argv.end(); ++ it) {
00123 size += it->size() + 1;
00124 }
00125
00126 char* buf = new char[size];
00127
00128 std::vector<char*> cargv;
00129 cargv.reserve(argv.size()+1);
00130 char* p = buf;
00131 for (std::vector<std::string>::const_iterator it = argv.begin(); it != argv.end(); ++ it) {
00132 cargv.push_back(p);
00133 p = std::copy(it->begin(), it->end(), p);
00134 *p++ = '\0';
00135 }
00136 cargv.push_back(0);
00137
00138
00139 int code = this->run(argv.size(), &cargv[0]);
00140
00141
00142 delete [] buf;
00143
00144 return code;
00145 }
00146
00147
00148
00149
00150
00151 int
00152 PSAnaApp::preRunApp ()
00153 {
00154 AppBase::preRunApp();
00155
00156
00157 const char* fmt = "[%(level):%(logger)] %(message)" ;
00158 const char* errfmt = "[%(level):%(time):%(file):%(line)] %(message)" ;
00159 const char* trcfmt = "[%(level):%(time):%(logger)] %(message)" ;
00160 const char* dbgfmt = errfmt ;
00161 MsgLogger::MsgFormatter::addGlobalFormat ( fmt ) ;
00162 MsgLogger::MsgFormatter::addGlobalFormat ( MsgLogger::MsgLogLevel::debug, dbgfmt ) ;
00163 MsgLogger::MsgFormatter::addGlobalFormat ( MsgLogger::MsgLogLevel::trace, trcfmt ) ;
00164 MsgLogger::MsgFormatter::addGlobalFormat ( MsgLogger::MsgLogLevel::warning, errfmt ) ;
00165 MsgLogger::MsgFormatter::addGlobalFormat ( MsgLogger::MsgLogLevel::error, errfmt ) ;
00166 MsgLogger::MsgFormatter::addGlobalFormat ( MsgLogger::MsgLogLevel::fatal, errfmt ) ;
00167
00168 return 0;
00169 }
00170
00171
00172
00173
00174 int
00175 PSAnaApp::runApp ()
00176 {
00177 std::string cfgFile;
00178 std::map<std::string, std::string> options;
00179 setConfigFileAndOptions(cfgFile, options);
00180
00181
00182 PSAna fwk(cfgFile, options);
00183
00184
00185 if (fwk.modules().empty()) {
00186 MsgLogRoot(error, "no analysis modules specified");
00187 return 2;
00188 }
00189
00190
00191 std::vector<std::string> input = inputDataSets();
00192
00193
00194 DataSource dataSource = fwk.dataSource(input);
00195 if (dataSource.empty()) return 2;
00196
00197
00198 EventIter iter = dataSource.events();
00199
00200
00201 while (boost::shared_ptr<PSEvt::Event> evt = iter.next()) {
00202
00203 }
00204
00205
00206 return 0 ;
00207 }
00208
00209 void
00210 PSAnaApp::setConfigFileAndOptions(std::string &cfgFile, std::map<std::string, std::string> &options)
00211 {
00212 cfgFile.clear();
00213 options.clear();
00214
00215 cfgFile = m_configOpt.value();
00216 if (not m_configOpt.valueChanged()) {
00217 if (access("psana.cfg", R_OK) == 0) {
00218 cfgFile = "psana.cfg";
00219 }
00220 }
00221
00222
00223 if (not m_modulesOpt.value().empty()) {
00224 std::string modlist;
00225 const std::vector<std::string>& modules = m_modulesOpt.value();
00226 for(std::vector<std::string>::const_iterator it = modules.begin(); it != modules.end(); ++ it) {
00227 if (not modlist.empty()) modlist += ' ';
00228 modlist += *it;
00229 }
00230 MsgLogRoot(trace, "set module list to '" << modlist << "'");
00231 options["psana.modules"] = modlist;
00232 }
00233
00234
00235 if (not m_expNameOpt.value().empty()) {
00236 std::string instrName;
00237 std::string expName = m_expNameOpt.value();
00238 std::string::size_type pos = expName.find(':');
00239 if (pos == std::string::npos) {
00240 instrName = expName.substr(0, 3);
00241 boost::to_upper(instrName);
00242 } else {
00243 instrName = expName.substr(0, pos);
00244 expName.erase(0, pos+1);
00245 }
00246 MsgLogRoot(debug, "cmd line: instrument = " << instrName << " experiment = " << expName);
00247 options["psana.instrument"] = instrName;
00248 options["psana.experiment"] = expName;
00249 }
00250
00251
00252 if (m_maxEventsOpt.value()) {
00253 options["psana.events"] = boost::lexical_cast<std::string>(m_maxEventsOpt.value());
00254 }
00255 if (m_skipEventsOpt.value()) {
00256 options["psana.skip-events"] = boost::lexical_cast<std::string>(m_skipEventsOpt.value());
00257 }
00258
00259
00260 if (m_parallelOpt.value()) {
00261 options["psana.parallel"] = boost::lexical_cast<std::string>(m_parallelOpt.value());
00262 }
00263
00264
00265 if (not m_calibDirOpt.value().empty()) {
00266 options["psana.calib-dir"] = m_calibDirOpt.value();
00267 }
00268
00269
00270 typedef AppUtils::AppCmdOptList<std::string>::const_iterator OptIter;
00271 for (OptIter it = m_optionsOpt.begin(); it != m_optionsOpt.end(); ++ it) {
00272 std::string optname = *it;
00273 std::string optval;
00274 std::string::size_type p = optname.find('=');
00275 if (p != std::string::npos) {
00276 optval = std::string(optname, p+1);
00277 optname.erase(p);
00278 }
00279 options[optname] = optval;
00280 }
00281
00282
00283 if (dumpConfigFileOptionSet(options)) {
00284 dumpConfigFile(cfgFile);
00285 removeDumpConfigFileOption(options);
00286 }
00287 }
00288
00289 std::vector<std::string>
00290 PSAnaApp::inputDataSets() const
00291 {
00292 std::vector<std::string> input(m_datasets.begin(), m_datasets.end());
00293 return input;
00294 }
00295
00296 }