#include "io.h" #include #include #include #include #include #include #include #include #include #include #include std::pair get_optional_parameter(std::vector::const_iterator &it) { std::string stripped_arg; if (it->size() > 2 && it->at(0) == '-' && it->at(1) == '-') { stripped_arg = it->substr(2, it->size()); } else if (it->size() > 1 && it->at(0) == '-') { stripped_arg = it->substr(1, it->size()); } std::transform(stripped_arg.begin(), stripped_arg.end(), stripped_arg.begin(), [](unsigned char c) { return std::tolower(c); }); const auto stripped_value = std::stod(*(++it), nullptr); return std::make_pair(stripped_arg, stripped_value); } /** * @brief Read and parse arguments coming from the command line * @param argc Number of command-line arguments * @param argv List of command-line arguments * @return Arguments */ Arguments parse_args(const int argc, char* argv[]) { if (argc < 3) { throw std::runtime_error("Not enough arguments: missing parameter file"); } Arguments args; // convert to vector to use iterator for loop const std::vector input_args(argv + 1, argv + argc); for (auto it = input_args.begin(); it != input_args.end(); ++it) { // check for optional parameter if (it->at(0) == '-') { // only --spectrum and --ste are parameter that are predefined if (*it == "--spectrum") { args.spectrum = true; continue; } if (*it == "--ste") { args.ste = true; continue; } // all other optional parameter are auto [option_name, option_value] = get_optional_parameter(it); args.optional[option_name] = option_value; continue; } // Two positional parameters are defined: 1. Location of config file; 2. Name of motion model if (args.parameter_file.empty()) { args.parameter_file = *it; continue; } if (args.motion_type.empty()) { args.motion_type = *it; continue; } throw std::invalid_argument("too many positional arguments"); } if (args.parameter_file.empty() || args.motion_type.empty()) { throw std::invalid_argument("Missing argument"); } return args; } std::unordered_map read_parameter(const std::filesystem::path& infile) { if (!std::filesystem::exists(infile)) { std::cerr << "File " << infile << " does not exist" << std::endl; exit(1); } std::ifstream instream(infile); std::unordered_map parameter; std::string line; std::string delim = "="; std::string key; std::string value; size_t delim_pos; while (std::getline(instream, line)) { // skip comment lines starting with #, and empty lines if (line[0] == '#' || line.length() == 1) continue; // strip spaces from line to have always key=value line.erase(std::remove(line.begin(), line.end(), ' '), line.end()); // split at '=' character and add to map delim_pos = line.find('='); key = line.substr(0, delim_pos); value = line.substr(delim_pos+1); parameter[key] = std::stod(value); } return parameter; } void fid_write_out(const std::string& filename, const std::vector& x, const std::vector& y, const double tau, const double t_evo) { auto size = x.size(); std::ostringstream sfile; sfile << filename << "_"; sfile << std::setprecision(6) << std::scientific; sfile << "tau=" << tau << "_tevo=" << t_evo << ".dat"; { std::string outfile = sfile.str(); std::ofstream fid_file(outfile, std::ios::out); for (unsigned int i = 0; i < size; i++) { fid_file << x[i] << "\t" << y[i] << "\n"; } } } void fid_write_out(const std::string& filename, const std::vector& x, const std::map>& y, const double tau) { auto size = x.size(); std::ostringstream sfile; sfile << filename << "_"; sfile << std::setprecision(6) << std::scientific; sfile << "tau=" << tau << ".dat"; { std::string outfile = sfile.str(); std::ofstream fid_file(outfile, std::ios::out); fid_file << "#"; for (const auto& [t_echo_j, _] : y) { fid_file << t_echo_j << "\t"; } fid_file << std::endl; for (unsigned int i = 0; i < size; i++) { fid_file << x[i]; for (const auto& [_, fid_j] : y) { fid_file << "\t" << fid_j[i]; } fid_file << "\n"; } } }