polaroid-pp

Schlieren and contour plot tool
git clone https://git.0xfab.ch/polaroid-pp.git
Log | Files | Refs | Submodules | README | LICENSE

commit 0bf715057339239463139b3831f73d5c9d2f66c6
parent cd91cc4be424b8c0ff76f99101126ac911aaf795
Author: Fabian Wermelinger <fabianw@mavt.ethz.ch>
Date:   Mon,  3 Jul 2017 10:03:48 +0200

added -outpath option for different output path (than input)

Diffstat:
Mapps/polaroidCamera/SceneProcessor.cpp | 10++--------
Mapps/polaroidCamera/SceneProcessor.h | 40++++++++++++++++++++++++++++++++++++++++
Minclude/ArgumentParser.h | 222+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
3 files changed, 209 insertions(+), 63 deletions(-)

diff --git a/apps/polaroidCamera/SceneProcessor.cpp b/apps/polaroidCamera/SceneProcessor.cpp @@ -87,10 +87,7 @@ void SceneProcessor::process1212(const vector<char*>& scenes) { _load_cam(mycam, scenes[i]); - string basename(scenes[i]); - if (basename.find_last_of(".") != string::npos) - basename = basename.substr(0, basename.find_last_of(".")); - + std::string basename = _outpath(std::string(scenes[i])); m_photo->set_name(basename); mycam.capture(*m_photo); @@ -139,10 +136,7 @@ void SceneProcessor::process1122(const vector<char*>& scenes) { Polaroid& cam = mycams[i]; - string basename(scenes[i]); - if (basename.find_last_of(".") != string::npos) - basename = basename.substr(0, basename.find_last_of(".")); - + std::string basename = _outpath(std::string(scenes[i])); m_photo->set_name(basename); cam.capture(*m_photo); diff --git a/apps/polaroidCamera/SceneProcessor.h b/apps/polaroidCamera/SceneProcessor.h @@ -7,6 +7,9 @@ #define SCENEPROCESSOR_H_UWGYBVIW #include <vector> +#include <string> +#include <sstream> +#include <set> #include "ArgumentParser.h" #include "OrganizerMPI.h" @@ -33,6 +36,43 @@ private: m_photo = nullptr; } + std::vector<std::string> _splitpath(const std::string& str, const char delim='/') + { + std::vector<std::string> result; + const std::set<char> delimiters{delim}; + std::string path(""); + + char const* pch = str.c_str(); + char const* start = pch; + for(; *pch; ++pch) + { + if (delimiters.find(*pch) != delimiters.end()) + { + if (start != pch) + { + std::string subpath(start, pch); + path += subpath; + start = pch; + } + } + } + result.push_back(path); + result.push_back(start+1); + return result; + } + + std::string _outpath(const std::string& input, const char delim='/') + { + const std::vector<std::string> splitp = _splitpath(input, delim); + std::ostringstream output; + if (m_parser.exist("outpath")) + output << m_parser("outpath").asString(); + else + output << splitp[0]; + output << delim << splitp[1]; + return output.str(); + } + public: SceneProcessor(ArgumentParser& parser, OrganizerMPI& mpi) : m_parser(parser), m_mpi(mpi), m_cartridge(nullptr), m_photo(nullptr) {} ~SceneProcessor() { _dispose(); } diff --git a/include/ArgumentParser.h b/include/ArgumentParser.h @@ -18,6 +18,7 @@ #include <cstdio> #include <cstdlib> #include <cstring> +#include <ctime> #include <map> #include <vector> #include <string> @@ -25,6 +26,7 @@ #include <sstream> #include <iomanip> #include <fstream> +#include <ostream> #include <limits> @@ -41,6 +43,21 @@ public: Value(string content_) : content(content_) { /*printf("%s\n",content.c_str());*/ } + Value(const Value& c) : content(c.content) {} + + Value& operator=(const Value& rhs) + { + if (this != &rhs) + content = rhs.content; + return *this; + } + Value& operator+=(const Value& rhs) + { + content += " " + rhs.content; + return *this; + } + Value operator+(const Value& rhs) { return Value(content + " " + rhs.content); } + double asDouble(double def=0) { if (content == "") @@ -82,8 +99,15 @@ public: return content; } + + friend std::ostream& operator<<(std::ostream& lhs, const Value& rhs) + { + lhs << rhs.content; + return lhs; + } }; + class CommandlineParser { private: @@ -94,28 +118,40 @@ private: protected: map<string,Value> mapArguments; + inline void _normalizeKey(std::string& key) const + { + if (key[0] == '-') key.erase(0,1); + if (key[0] == '+') key.erase(0,1); + } + + inline bool _existKey(const std::string& key, const std::map<std::string,Value>& container) const + { + std::map<std::string,Value>::const_iterator it = container.find(key); + return it != container.end(); + } + public: - Value& operator()(const string arg) + Value& operator()(string key) { + _normalizeKey(key); if (bStrictMode) { - map<string,Value>::const_iterator it = mapArguments.find(arg); - - if (it == mapArguments.end()) + if (!_existKey(key,mapArguments)) { - printf("Runtime option NOT SPECIFIED! ABORTING! name: %s\n",arg.data()); + printf("Runtime option NOT SPECIFIED! ABORTING! name: %s\n",key.data()); abort(); } } - if (bVerbose) printf("%s is %s\n", arg.data(), mapArguments[arg].asString().data()); - return mapArguments[arg]; + if (bVerbose) printf("%s is %s\n", key.data(), mapArguments[key].asString().data()); + return mapArguments[key]; } - bool check(const string arg) const + inline bool check(string key) const { - return mapArguments.find(arg) != mapArguments.end(); + _normalizeKey(key); + return _existKey(key,mapArguments); } CommandlineParser(const int argc, const char ** argv) : mapArguments(), iArgC(argc), vArgV(argv), bStrictMode(false), bVerbose(true) @@ -127,7 +163,11 @@ public: int itemCount = 0; for (int j=i+1; j<argc; j++) - if (argv[j][0] == '-') + { + const bool leadingDash = (argv[j][0] == '-'); + const char c = argv[j][1]; + const bool firstNumeric = ((c >= '0' && c <= '9') || c == 0) ? true : false; + if (leadingDash && !firstNumeric) break; else { @@ -137,11 +177,27 @@ public: values += argv[j]; itemCount++; } + } if (itemCount == 0) values = "true"; - mapArguments[argv[i]] = Value(values); + std::string key(argv[i]); + key.erase(0,1); // remove leading '-' + if (key[0] == '+') + { + key.erase(0,1); + if (!_existKey(key,mapArguments)) + mapArguments[key] = Value(values); // skip leading white space + else + mapArguments[key] += Value(values); + } + else + { + if (!_existKey(key,mapArguments)) + mapArguments[key] = Value(values); + } + i += itemCount; } @@ -210,13 +266,18 @@ class ArgumentParser: public CommandlineParser typedef std::map<std::string, Value*> pArgMap; typedef std::map<std::string, ArgMap* > FileMap; - // keep a reference form option origin + const char commentStart; + + // keep a reference from option origin ArgMap from_commandline; FileMap from_files; pArgMap from_code; + // for runtime interaction (we keep the original map) + ArgMap mapRuntime; + // helper - void _ignoreComments(std::ifstream& stream, const char commentChar = '#') + void _ignoreComments(std::istream& stream, const char commentChar) { stream >> std::ws; int nextchar = stream.peek(); @@ -228,37 +289,52 @@ class ArgumentParser: public CommandlineParser } } - bool _existKey(std::string& key) const + void _parseFile(std::ifstream& stream, ArgMap& container) { - const std::string og_key = key; - bool bExist = true; - - // look for both possible keys (i.e. with leading "-" and without) - ArgMap::const_iterator it = mapArguments.find(key); - if (it == mapArguments.end()) + // read (key value) pairs from input file, ignore comments + // beginning with commentStart + _ignoreComments(stream, commentStart); + while (!stream.eof()) { - if (key[0] == '-') key = key.erase(0, 1); - else key = "-" + key; - it = mapArguments.find(key); - if (it == mapArguments.end()) + std::string line, key, val; + std::getline(stream, line); + std::istringstream lineStream(line); + lineStream >> key; + lineStream >> val; + _ignoreComments(lineStream, commentStart); + while(!lineStream.eof()) { - key = og_key; - bExist = false; + std::string multiVal; + lineStream >> multiVal; + val += (" " + multiVal); + _ignoreComments(lineStream, commentStart); } - } - return bExist; - } - inline std::string _stripKey(std::string key) const - { - if (key[0] == '-') key = key.erase(0, 1); - return key; + const Value V(val); + if (key[0] == '-') + key.erase(0,1); + + if (key[0] == '+') + { + key.erase(0,1); + if (!_existKey(key,container)) // skip leading white space + container[key] = V; + else + container[key] += V; + } + else if (!_existKey(key,container)) + container[key] = V; + _ignoreComments(stream, commentStart); + } } public: - ArgumentParser(const int _argc, const char ** _argv): - CommandlineParser(_argc, _argv) { from_commandline = mapArguments; } + ArgumentParser(const int _argc, const char ** _argv, const char cstart='#'): + CommandlineParser(_argc, _argv), commentStart(cstart) + { + from_commandline = mapArguments; + } virtual ~ArgumentParser() { @@ -272,33 +348,69 @@ public: ArgMap& myFMap = *(from_files[filepath]); std::ifstream confFile(filepath.c_str()); - if (confFile.is_open()) + if (confFile.good()) { - // read (key value) pairs from input file, ignore comments - // beginning with "#" - std::string key, val; - while (!confFile.eof()) - { - _ignoreComments(confFile); - confFile >> key >> val; - if (_existKey(key)) continue; - std::pair<string, Value> item(key, Value(val)); - mapArguments.insert(item); // add to parent container - myFMap.insert(item); // add to private container - } + _parseFile(confFile, mapArguments); + confFile.clear(); + confFile.seekg(0, ios::beg); + _parseFile(confFile, myFMap); // we keep a reference for each separate file read } + confFile.close(); } Value& operator()(std::string key) { - const bool bDefaultInCode = !_existKey(key); + _normalizeKey(key); + const bool bDefaultInCode = !_existKey(key,mapArguments); Value& retval = CommandlineParser::operator()(key); if (bDefaultInCode) from_code[key] = &retval; return retval; } - inline bool check(std::string key) const { return _existKey(key); } - inline bool exist(std::string key) const { return _existKey(key); } + inline bool exist(std::string key) const { return check(key); } + + void write_runtime_environment() const + { + time_t rawtime; + std::time(&rawtime); + struct tm* timeinfo = std::localtime(&rawtime); + char buf[256]; + std::strftime(buf, 256, "%A, %h %d %Y, %r", timeinfo); + + std::ofstream runtime("runtime_environment.conf"); + runtime << commentStart << " RUNTIME ENVIRONMENT SETTINGS" << std::endl; + runtime << commentStart << " ============================" << std::endl; + runtime << commentStart << " " << buf << std::endl; + runtime << commentStart << " Use this file to set runtime parameter interactively." << std::endl; + runtime << commentStart << " The parameter are read every \"refreshperiod\" steps." << std::endl; + runtime << commentStart << " When editing this file, you may use comments and string concatenation." << std::endl; + runtime << commentStart << " The simulation can be terminated without killing it by setting \"exit\" to true." << std::endl; + runtime << commentStart << " (This will write a serialized restart state. Set \"exitsave\" to false if not desired.)" << std::endl; + runtime << commentStart << std::endl; + runtime << commentStart << " !!! WARNING !!! EDITING THIS FILE CAN POTENTIALLY CRASH YOUR SIMULATION !!! WARNING !!!" << std::endl; + for (typename std::map<std::string,Value>::const_iterator it = mapArguments.begin(); it != mapArguments.end(); ++it) + runtime << it->first << '\t' << it->second << std::endl; + } + + void read_runtime_environment() + { + mapRuntime.clear(); + std::ifstream runtime("runtime_environment.conf"); + if (runtime.good()) + _parseFile(runtime, mapRuntime); + runtime.close(); + } + + Value& parseRuntime(std::string key) + { + _normalizeKey(key); + if (!_existKey(key,mapRuntime)) + { + printf("ERROR: Runtime parsing for key %s NOT FOUND!! Check your runtime_environment.conf file\n",key.data()); + abort(); + } + return mapRuntime[key]; + } void print_args() { @@ -329,7 +441,7 @@ public: { std::cout.width(50); std::cout.fill('.'); - std::cout << std::left << _stripKey(it->first); + std::cout << std::left << it->first; std::cout << ": " << it->second.asString() << std::endl; } std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; @@ -349,7 +461,7 @@ public: { std::cout.width(50); std::cout.fill('.'); - std::cout << std::left << _stripKey(it->first); + std::cout << std::left << it->first; std::cout << ": " << it->second.asString() << std::endl; } std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; @@ -360,13 +472,13 @@ public: // defaults defined in code if (!from_code.empty()) { - std::cout << "* Defined in Code:" << std::endl; + std::cout << "* Defaults in Code:" << std::endl; std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; for(pArgMap::iterator it=from_code.begin(); it!=from_code.end(); it++) { std::cout.width(50); std::cout.fill('.'); - std::cout << std::left << _stripKey(it->first); + std::cout << std::left << it->first; std::cout << ": " << it->second->asString() << std::endl; } std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl;