diff --git a/main.cpp b/main.cpp index 28fad67d0208275cbe48d4a871a0f7487c2a33a6..31467fdd2c65030b6294fec2caac46ba102440bd 100644 --- a/main.cpp +++ b/main.cpp @@ -2,6 +2,7 @@ #include <complex> #include <chrono> #include <cmath> +#include <filesystem> #include "basicmath.h" #include "model.h" @@ -13,6 +14,8 @@ #define M_PI 3.14159265358979323846 #endif +static constexpr char PARA_SWEEP_OUTPUT_DIR[] = "./sweep"; + static void printComponants(eis::Model& model) { eis::Log(eis::Log::DEBUG)<<"Compnants:"; @@ -29,14 +32,6 @@ static void printComponants(eis::Model& model) } } -static void paramSweepCb(std::vector<eis::DataPoint>& data, const std::vector<fvalue>& parameters) -{ - static size_t i = 0; - ++i; - if((i & 0x3FF) == 0) - std::cout<<'.'<<std::flush; -} - static void runSweep(const std::string& modelString, eis::Range omega, bool normalize = false, bool reduce = false, bool hertz = false, bool invert = false, double noise = 0) { @@ -77,19 +72,68 @@ static void runSweep(const std::string& modelString, eis::Range omega, bool norm eis::Log(eis::Log::INFO)<<"time taken: "<<duration.count()<<" us"; } -static void runParamSweep() +std::vector<eis::Range> rangesFromParamString(const std::string& parameterString, size_t modelParamCount, size_t steps) +{ + std::vector<std::string> tokens = tokenize(parameterString, ','); + + if(tokens.size() != modelParamCount) + { + eis::Log(eis::Log::ERROR)<<"Model requires "<<modelParamCount<<" parameters but "<<tokens.size()<<" parameters where provided\n"; + return std::vector<eis::Range>(); + } + + std::vector<eis::Range> ranges; + + try + { + for(const std::string& str : tokens) + { + std::vector<std::string> subtokens = tokenize(str, '-', '\0', '\0', 'e'); + if(subtokens.size() > 2) + { + eis::Log(eis::Log::ERROR)<<"a range requires two numbers only "<<str<<" provides "<<subtokens.size()<<" numbers\n"; + return std::vector<eis::Range>(); + } + else if(subtokens.size() == 1) + { + ranges.push_back(eis::Range(std::stod(subtokens[0]), std::stod(subtokens[0]), 1, true)); + } + else + { + ranges.push_back(eis::Range(std::stod(subtokens[0]), std::stod(subtokens[1]), steps, true)); + } + } + } + catch (const std::invalid_argument& ia) + { + eis::Log(eis::Log::ERROR)<<ia.what(); + return std::vector<eis::Range>(); + } + return ranges; +} + +static void paramSweepCb(std::vector<eis::DataPoint>& data, const std::vector<fvalue>& parameters) +{ + static size_t i = 0; + size_t outputSize = data.size(); + data = eis::reduceRegion(data); + data = eis::rescale(data, outputSize); + eis::saveToDisk(data, std::string(PARA_SWEEP_OUTPUT_DIR)+std::string("/")+std::to_string(++i)+".csv"); + eis::Log(eis::Log::INFO, false)<<'.'; +} + +static void runParamSweep(const std::string& modelstr, const eis::Range& omega, const std::string& parameterString, size_t steps) { - eis::Log(eis::Log::INFO)<<__func__; - std::string modelStr("w{20e3}p{1e-7, 0.9}"); + std::string modelStr(modelstr); eis::Model model(modelStr); - std::vector<eis::Range> parameters; - parameters.push_back(eis::Range(1e3, 50e3, 100)); - parameters.push_back(eis::Range(1e-7, 20e-7, 100)); - parameters.push_back(eis::Range(0.7, 1.2, 100)); + std::vector<eis::Range> parameters = rangesFromParamString(parameterString, model.getFlatParametersCount(), steps); + if(parameters.empty()) + return; - eis::Range omega(0, 1e6, 25); + eis::Log(eis::Log::INFO)<<"Saving sweep to "<<PARA_SWEEP_OUTPUT_DIR; + std::filesystem::create_directory(PARA_SWEEP_OUTPUT_DIR); auto start = std::chrono::high_resolution_clock::now(); model.executeParamSweep(parameters, omega, ¶mSweepCb); @@ -115,7 +159,7 @@ int main(int argc, char** argv) runSweep(config.modelStr, config.omegaRange, config.normalize, config.reduce, config.hertz, config.invert, config.noise); break; case MODE_PARAM_SWEEP: - runParamSweep(); + runParamSweep(config.modelStr, config.omegaRange, config.parameterString, config.paramSteps); break; } return 0; diff --git a/options.h b/options.h index 4ee02f38b0cdc4b54c1453d894ff0d785a2062e5..a09c2fad293cd191a4918bd65f576901475a86a5 100644 --- a/options.h +++ b/options.h @@ -15,7 +15,8 @@ static struct argp_option options[] = { {"verbose", 'v', 0, 0, "Show debug messages" }, {"quiet", 'q', 0, 0, "only output data" }, - {"param", 'p', 0, 0, "select parameter sweep mode" }, + {"param", 'p', "[STRING]", 0, "select parameter sweep mode" }, + {"param", 's', "[COUNT]", 0, "parameter sweep steps" }, {"model", 'm', "[STRING]", 0, "set model string" }, {"omega", 'o', "[START-END]", 0, "set omega range" }, {"omegasteps", 'c', "[COUNT]", 0, "set omega range steps" }, @@ -38,6 +39,8 @@ struct Config { std::string modelStr = "c{1e-6}r{1e3}-r{1e3}"; unsigned int mode = MODE_SWEEP; + std::string parameterString; + size_t paramSteps = 10; eis::Range omegaRange; bool normalize = false; bool reduce = false; @@ -45,7 +48,7 @@ struct Config bool invert = false; double noise = 0; - Config(): omegaRange(1, 1001, 1, true) + Config(): omegaRange(1, 1e6, 50, true) {} }; @@ -63,10 +66,11 @@ parse_opt (int key, char *arg, struct argp_state *state) eis::Log::level = eis::Log::DEBUG; break; case 's': - config->mode = MODE_SWEEP; + config->paramSteps = std::stod(arg); break; case 'p': config->mode = MODE_PARAM_SWEEP; + config->parameterString.assign(arg); break; case 'm': config->modelStr.assign(arg); diff --git a/tokenize.cpp b/tokenize.cpp index f09da75ba3233d51c0501535cae2281c8d3f9c13..b752e8c6efa1930f79e92664830c1daaacd940de 100644 --- a/tokenize.cpp +++ b/tokenize.cpp @@ -1,27 +1,26 @@ #include "tokenize.h" -std::vector<std::string> tokenize(const std::string& str, const char delim, const char ignBracketStart, const char ignBracketEnd) +std::vector<std::string> tokenize(const std::string& str, const char delim, const char ignBracketStart, const char ignBracketEnd, const char escapeChar) { - std::stringstream ss(str); std::vector<std::string> tokens; std::string token; size_t bracketCounter = 0; - for(char ch : str) + for(size_t i = 0; i < str.size(); ++i) { - if(ch == delim && bracketCounter == 0) + if(str[i] == delim && bracketCounter == 0 && (i == 0 || str[i-1] != escapeChar)) { tokens.push_back(token); token.clear(); } else { - token.push_back(ch); + token.push_back(str[i]); } - if(ignBracketStart == ch) + if(ignBracketStart == str[i]) ++bracketCounter; - else if(ignBracketEnd == ch) + else if(ignBracketEnd == str[i]) --bracketCounter; } if(bracketCounter == 0) diff --git a/tokenize.h b/tokenize.h index 5f36a46bfc73ef851a72abb638c739f8c27839cf..637fdf580c588e65d28ad1602b2a6e41be0683a7 100644 --- a/tokenize.h +++ b/tokenize.h @@ -3,4 +3,5 @@ #include <vector> #include <sstream> -std::vector<std::string> tokenize(const std::string& str, const char delim = ' ', const char ignBracketStart = '\0', const char ignBracketEnd = '\0'); +std::vector<std::string> tokenize(const std::string& str, const char delim = ' ', const char ignBracketStart = '\0', + const char ignBracketEnd = '\0', const char escapeChar = '\0');