From 29d0c5f754c27cb54c5c1d7970a870c71d8b9d85 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm <philipp@uvos.xyz> Date: Thu, 27 Jun 2024 15:16:04 +0200 Subject: [PATCH] Add header description field to EisSpectra, split EisSpectra into a seperate translation unit --- CMakeLists.txt | 1 + eisgenerator/eistype.h | 190 +--------------------------- eisgenerator/spectra.h | 206 +++++++++++++++++++++++++++++++ eistype.cpp | 247 ------------------------------------- spectra.cpp | 274 +++++++++++++++++++++++++++++++++++++++++ strops.cpp | 5 + strops.h | 5 + test.cpp | 2 +- 8 files changed, 493 insertions(+), 437 deletions(-) create mode 100644 eisgenerator/spectra.h create mode 100644 spectra.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fa71b8f..3c043c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ set(SRC_FILES normalize.cpp basicmath.cpp eistype.cpp + spectra.cpp strops.cpp translators.cpp randomgen.cpp diff --git a/eisgenerator/eistype.h b/eisgenerator/eistype.h index c71f87d..8670153 100644 --- a/eisgenerator/eistype.h +++ b/eisgenerator/eistype.h @@ -256,192 +256,6 @@ public: } }; -class EisSpectra -{ -public: - static constexpr int F_VERSION_MAJOR = 1; - static constexpr int F_VERSION_MINOR = 0; - static constexpr int F_VERSION_PATCH = 0; - static constexpr char F_MAGIC[] = "EISF"; - -public: - std::vector<DataPoint> data; - std::string model; - std::string header; - std::vector<double> labels; - std::vector<std::string> labelNames; - -public: - /** - * @brief Constructs an EisSpectra. - * - * @param data Vector of the data points of the spectra. - * @param model Model description string for this spectra. - * @param header A free-form text that will be included in any save of this spectra. - * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. - * @param labelNames An optional vector of names describing every input of the model. - */ - EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, - std::vector<double> labels = std::vector<double>(), - std::vector<std::string> labelNames = std::vector<std::string>()); - - /** - * @brief Constructs an EisSpectra. - * - * This function differs from the above only in the datatype of the label. - * - * @param data Vector of the data points of the spectra. - * @param model Model description string for this spectra. - * @param header A free-form text that will be included in any save of this spectra. - * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. - * @param labelNames An optional vector of names describing every input of the model. - */ - EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, - std::vector<float> labels, std::vector<std::string> labelNames = std::vector<std::string>()); - - /** - * @brief Constructs an EisSpectra. - * - * This function differs from the above only in the datatype of the label. - * - * @param data Vector of the data points of the spectra. - * @param model Model description string for this spectra. - * @param header A free-from text that will be included in any save of this spectra. - * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. - * @param labelNames An optional vector of names describing every input of the model. - */ - EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, - std::vector<size_t> labels, std::vector<std::string> labelNames = std::vector<std::string>()); - - /** - * @brief Constructs an EisSpectra. - * - * This function differs from the above only in the datatype of the label. - * - * @param data Vector of the data points of the spectra. - * @param model Model description string for this spectra. - * @param header A free-form text that will be included in any save of this spectra. - * @param label A value corresponding to all inputs of the model. - * @param maxLabel The number of inputs of the model. - */ - EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, - size_t label, size_t maxLabel, std::vector<std::string> labelNames = std::vector<std::string>()); - - /** - * @brief Constructs a EisSpectra by loading an EIS file from disk. - * - * @throw eis::file_error if there is an error loading the file - * @param path The path to the file. - */ - EisSpectra(const std::filesystem::path& path){*this = loadFromDisk(path);} - - EisSpectra(){} - - /** - * @brief Constructs a EisSpectra by loading a EIS file from disk. - * - * This function has the attribute [[nodiscard]] - * - * @throw eis::file_error if there is an error loading the file - * @param path The path to the file. - * @return The EisSpectra parsed from the file. - */ - [[nodiscard]] static EisSpectra loadFromDisk(const std::filesystem::path& path); - - /** - * @brief Constructs a EisSpectra by loading a EIS file from a stream. - * - * This function has the attribute [[nodiscard]] - * - * @throw eis::file_error if there is an error loading the file - * @param stream The stream that contains the EIS file. - * @return The EisSpectra parsed from the stream. - */ - [[nodiscard]] static EisSpectra loadFromStream(std::istream& stream); - - /** - * @brief Sets all input values up to a maximum given by maxLabel to the value given by label. - * - * @param label The value to apply to all inputs. - * @param maxLabel The maximum number of values to set. - */ - void setLabel(size_t label, size_t maxLabel); - - /** - * @brief Gets the input value of this model, where it is a single value. - * - * @return The input value, - */ - size_t getLabel(); - - /** - * @brief Sets the input values of this model. - * - * @param label The input values. - */ - void setSzLabels(std::vector<size_t> label); - - /** - * @brief Sets the input values of this model. - * - * @param label The input values. - */ - void setLabels(const std::vector<double>& labelsIn); - - /** - * @brief Sets the input values of this model. - * - * @param label The input values. - */ - void setLabels(const std::vector<float>& labelsIn); - - /** - * @brief Sets the input values of this model. - * - * @param label The input values. - */ - std::vector<size_t> getSzLabels() const; - - /** - * @brief Returns true if there are multiple inputs, false otherwise. - * - * @return true if there are multiple inputs, false otherwise. - */ - bool isMulticlass(); - - /** - * @brief Returns the inputs as a vector. - * - * @return The inputs as a vector. - */ - std::vector<fvalue> getFvalueLabels(); - - /** - * @brief Saves the spectra to disk. - * - * @param path A path to the file on disk where the spectra shall be saved. - * @return true on success, false on failure. - */ - bool saveToDisk(const std::filesystem::path& path) const; - - /** - * @brief Saves the spectra in the given stream. - * - * @param stream A std::ostream into which the spectra will be saved. - */ - void saveToStream(std::ostream& stream) const; -}; - -/** - * @brief Deprecated function use eis::EisSpectra::saveToDisk instead. - */ -[[deprecated]] bool saveToDisk(const EisSpectra& data, const std::filesystem::path& path); - -/** - * @brief Deprecated function use eis::EisSpectra::loadFromDisk instead. - */ -[[deprecated]] [[nodiscard]] EisSpectra loadFromDisk(const std::filesystem::path& path); - /** * @brief Returns the a vector of DataPoints as a pair of valarrays. * @@ -468,6 +282,4 @@ std::ostream &operator<<(std::ostream &s, eis::DataPoint const& dp); std::ostream &operator<<(std::ostream &s, eis::Range const& range); -std::ostream &operator<<(std::ostream &s, eis::EisSpectra const& spectra); - - +#include "spectra.h" diff --git a/eisgenerator/spectra.h b/eisgenerator/spectra.h new file mode 100644 index 0000000..2d7a430 --- /dev/null +++ b/eisgenerator/spectra.h @@ -0,0 +1,206 @@ +#pragma once +/** + * @addtogroup TYPES + * @{ + */ + +#include <string> +#include <vector> + +#include "eistype.h" + +namespace eis +{ + +class EisSpectra +{ +public: + static constexpr int F_VERSION_MAJOR = 1; + static constexpr int F_VERSION_MINOR = 1; + static constexpr int F_VERSION_PATCH = 0; + static constexpr char F_MAGIC[] = "EISF"; + +public: + std::vector<DataPoint> data; + std::string model; + std::string headerDescription; + std::string header; + std::vector<double> labels; + std::vector<std::string> labelNames; + +public: + /** + * @brief Constructs an EisSpectra. + * + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-form text that will be included in any save of this spectra. + * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. + * @param labelNames An optional vector of names describing every input of the model. + */ + EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, + std::vector<double> labels = std::vector<double>(), + std::vector<std::string> labelNames = std::vector<std::string>()); + + /** + * @brief Constructs an EisSpectra. + * + * This function differs from the above only in the datatype of the label. + * + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-form text that will be included in any save of this spectra. + * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. + * @param labelNames An optional vector of names describing every input of the model. + */ + EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, + std::vector<float> labels, std::vector<std::string> labelNames = std::vector<std::string>()); + + /** + * @brief Constructs an EisSpectra. + * + * This function differs from the above only in the datatype of the label. + * + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-from text that will be included in any save of this spectra. + * @param labels An optional vector of giving the values of the inputs of the model to get this spectra. + * @param labelNames An optional vector of names describing every input of the model. + */ + EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, + std::vector<size_t> labels, std::vector<std::string> labelNames = std::vector<std::string>()); + + /** + * @brief Constructs an EisSpectra. + * + * This function differs from the above only in the datatype of the label. + * + * @param data Vector of the data points of the spectra. + * @param model Model description string for this spectra. + * @param header A free-form text that will be included in any save of this spectra. + * @param label A value corresponding to all inputs of the model. + * @param maxLabel The number of inputs of the model. + */ + EisSpectra(const std::vector<DataPoint>& data, const std::string& model, const std::string& header, + size_t label, size_t maxLabel, std::vector<std::string> labelNames = std::vector<std::string>()); + + /** + * @brief Constructs a EisSpectra by loading an EIS file from disk. + * + * @throw eis::file_error if there is an error loading the file + * @param path The path to the file. + */ + EisSpectra(const std::filesystem::path& path){*this = loadFromDisk(path);} + + EisSpectra(){} + + /** + * @brief Constructs a EisSpectra by loading a EIS file from disk. + * + * This function has the attribute [[nodiscard]] + * + * @throw eis::file_error if there is an error loading the file + * @param path The path to the file. + * @return The EisSpectra parsed from the file. + */ + [[nodiscard]] static EisSpectra loadFromDisk(const std::filesystem::path& path); + + /** + * @brief Constructs a EisSpectra by loading a EIS file from a stream. + * + * This function has the attribute [[nodiscard]] + * + * @throw eis::file_error if there is an error loading the file + * @param stream The stream that contains the EIS file. + * @return The EisSpectra parsed from the stream. + */ + [[nodiscard]] static EisSpectra loadFromStream(std::istream& stream); + + /** + * @brief Sets all input values up to a maximum given by maxLabel to the value given by label. + * + * @param label The value to apply to all inputs. + * @param maxLabel The maximum number of values to set. + */ + void setLabel(size_t label, size_t maxLabel); + + /** + * @brief Gets the input value of this model, where it is a single value. + * + * @return The input value, + */ + size_t getLabel(); + + /** + * @brief Sets the input values of this model. + * + * @param label The input values. + */ + void setSzLabels(std::vector<size_t> label); + + /** + * @brief Sets the input values of this model. + * + * @param label The input values. + */ + void setLabels(const std::vector<double>& labelsIn); + + /** + * @brief Sets the input values of this model. + * + * @param label The input values. + */ + void setLabels(const std::vector<float>& labelsIn); + + /** + * @brief Sets the input values of this model. + * + * @param label The input values. + */ + std::vector<size_t> getSzLabels() const; + + /** + * @brief Returns true if there are multiple inputs, false otherwise. + * + * @return true if there are multiple inputs, false otherwise. + */ + bool isMulticlass(); + + /** + * @brief Returns the inputs as a vector. + * + * @return The inputs as a vector. + */ + std::vector<fvalue> getFvalueLabels(); + + /** + * @brief Saves the spectra to disk. + * + * @param path A path to the file on disk where the spectra shall be saved. + * @return true on success, false on failure. + */ + bool saveToDisk(const std::filesystem::path& path) const; + + /** + * @brief Saves the spectra in the given stream. + * + * @param stream A std::ostream into which the spectra will be saved. + */ + void saveToStream(std::ostream& stream) const; +}; + +/** + * @brief Deprecated function use eis::EisSpectra::saveToDisk instead. + */ +[[deprecated]] bool saveToDisk(const EisSpectra& data, const std::filesystem::path& path); + +/** + * @brief Deprecated function use eis::EisSpectra::loadFromDisk instead. + */ +[[deprecated]] [[nodiscard]] EisSpectra loadFromDisk(const std::filesystem::path& path); + +} + +std::ostream &operator<<(std::ostream &s, eis::EisSpectra const& spectra); + +/** @} */ diff --git a/eistype.cpp b/eistype.cpp index 6061d79..638821c 100644 --- a/eistype.cpp +++ b/eistype.cpp @@ -20,14 +20,12 @@ // #include "eistype.h" -#include <fstream> #include <sstream> #include <string> #include <vector> #include "strops.h" #include "log.h" -#include "basicmath.h" using namespace eis; @@ -155,245 +153,6 @@ std::ostream &operator<<(std::ostream &s, Range const& range) return s; } -EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, - const std::string& headerIn, std::vector<double> labelsIn, std::vector<std::string> labelNamesIn): -data(dataIn), model(modelIn), header(headerIn), labels(labelsIn), labelNames(labelNamesIn) -{ - -} - -EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, - const std::string& headerIn, std::vector<float> labelsIn, std::vector<std::string> labelNamesIn): -data(dataIn), model(modelIn), header(headerIn), labelNames(labelNamesIn) -{ - setLabels(labelsIn); -} - -EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, const std::string& headerIn, - std::vector<size_t> labelsIn, std::vector<std::string> labelNamesIn): -data(dataIn), model(modelIn), header(headerIn), labelNames(labelNamesIn) -{ - setSzLabels(labelsIn); -} - -EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, const std::string& headerIn, - size_t label, size_t maxLabel, std::vector<std::string> labelNamesIn): -data(dataIn), model(modelIn), header(headerIn), labelNames(labelNamesIn) -{ - setLabel(label, maxLabel); -} - -void EisSpectra::setLabel(size_t label, size_t maxLabel) -{ - labels.assign(maxLabel, 0); - labels[label] = 1; -} - -void EisSpectra::setSzLabels(std::vector<size_t> labelsIn) -{ - labels.assign(labelsIn.size(), 0); - for(size_t i = 0; i < labelsIn.size(); ++i) - labels[i] = static_cast<double>(labelsIn[i]); -} - -std::vector<size_t> EisSpectra::getSzLabels() const -{ - std::vector<size_t> out(labels.size()); - for(size_t i = 0; i < labels.size(); ++i) - out[i] = static_cast<size_t>(labels[i]); - return out; -} - -size_t EisSpectra::getLabel() -{ - for(size_t i = 0; i < labels.size(); ++i) - if(labels[i] != 0) - return i; - return 0; -} - -bool EisSpectra::isMulticlass() -{ - bool foundFirst = false; - for(size_t i = 0; i < labels.size(); ++i) - { - if(labels[i] != 0) - { - if(foundFirst) - return true; - else - foundFirst = true; - } - } - return false; -} - -void EisSpectra::setLabels(const std::vector<float>& labelsIn) -{ - labels.assign(labelsIn.size(), 0); - for(size_t i = 0; i < labels.size(); ++i) - labels[i] = labelsIn[i]; -} - -void EisSpectra::setLabels(const std::vector<double>& labelsIn) -{ - labels = labelsIn; -} - -std::vector<fvalue> EisSpectra::getFvalueLabels() -{ - if constexpr(std::is_same<fvalue, double>::value) - { - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wstrict-aliasing" - return *reinterpret_cast<std::vector<fvalue>*>(&labels); - #pragma GCC diagnostic pop - } - else - { - std::vector<fvalue> out(labels.size()); - for(size_t i = 0; i < labels.size(); ++i) - out[i] = static_cast<fvalue>(labels[i]); - return out; - } -} - -void EisSpectra::saveToStream(std::ostream& stream) const -{ - stream<<std::scientific; - stream<<F_MAGIC<<", "<<std::to_string(F_VERSION_MAJOR)<<'.' - <<std::to_string(F_VERSION_MINOR)<<'.'<<std::to_string(F_VERSION_PATCH)<<'\n'; - - stream<<'"'<<model<<'"'<<(!header.empty() ? ", " : ""); - stream<<header; - - if(!labels.empty()) - { - if(!labelNames.empty()) - { - stream<<"\nlabelsNames\n"; - std::string labelLine; - for(const std::string& name : labelNames) - labelLine += "\"" + name + "\", "; - labelLine.pop_back(); - labelLine.pop_back(); - stream<<labelLine; - } - stream<<"\nlabels\n"; - - std::stringstream labelSs; - for(double label : labels) - labelSs<<label<<", "; - std::string labelLine = labelSs.str(); - labelLine.pop_back(); - labelLine.pop_back(); - stream<<labelLine; - } - - stream<<"\nomega, real, im\n"; - - for(const eis::DataPoint& point : data) - stream<<point.omega<<", "<<point.im.real()<<", "<<point.im.imag()<<'\n'; -} - -bool EisSpectra::saveToDisk(const std::filesystem::path& path) const -{ - std::fstream file; - file.open(path, std::ios_base::out | std::ios_base::trunc); - if(!file.is_open()) - { - Log(Log::ERROR)<<"can not open "<<path<<" for writing\n"; - return false; - } - - saveToStream(file); - - file.close(); - return true; -} - -EisSpectra EisSpectra::loadFromStream(std::istream& stream) -{ - EisSpectra out; - std::string line; - std::getline(stream, line); - std::vector<std::string> tokens = tokenizeBinaryIgnore(line, ',', '"', '\\'); - - if(tokens.size() < 2 || tokens[0] != F_MAGIC) - { - throw file_error("not a valid EISGenerator file or stream"); - } - else - { - std::vector<std::string> versionTokens = tokenize(tokens[1], '.'); - if(versionTokens.size() != 3 || std::stoi(versionTokens[0]) > F_VERSION_MAJOR || std::stoi(versionTokens[1]) > F_VERSION_MINOR) - throw file_error("saved by a newer version of EISGenerator, can not open"); - } - - std::getline(stream, line); - tokens = tokenizeBinaryIgnore(line, ',', '"', '\\'); - stripQuotes(tokens[0]); - out.model = tokens[0]; - line.erase(line.begin(), line.begin()+tokens.size()); - out.header = line; - - while(stream.good()) - { - std::getline(stream, line); - if(line.starts_with("labelsNames")) - { - std::getline(stream, line); - out.labelNames = tokenizeBinaryIgnore(line, ',', '"', '\\'); - continue; - } - else if(line.starts_with("labels")) - { - std::getline(stream, line); - std::vector<std::string> tokens = tokenizeBinaryIgnore(line, ',', '"', '\\'); - for(const std::string& token : tokens) - out.labels.push_back(std::stod(token)); - continue; - } - else if(line.empty() || line[0] == '#' || line.starts_with("omega")) - { - continue; - } - tokens = tokenize(line, ','); - if(tokens.size() != 3) - throw file_error("invalid line: " + line); - - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wnarrowing" - if constexpr (std::is_same<fvalue, double>::value) - out.data.push_back(DataPoint({std::stod(tokens[1]), std::stod(tokens[2])}, std::stod(tokens[0]))); - else - out.data.push_back(DataPoint({std::stof(tokens[1]), std::stof(tokens[2])}, std::stof(tokens[0]))); - #pragma GCC diagnostic pop - - eis::removeDuplicates(out.data); - } - - return out; -} - -EisSpectra EisSpectra::loadFromDisk(const std::filesystem::path& path) -{ - std::fstream file; - file.open(path, std::ios_base::in); - if(!file.is_open()) - throw file_error("can not open " + path.string() + " for reading\n"); - - try - { - EisSpectra out = loadFromStream(file); - return out; - } - catch(const file_error& err) - { - throw file_error(path.string() + std::string(": ") + err.what()); - } -} - static VersionFixed version = {VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH}; const VersionFixed& getVersion() @@ -401,12 +160,6 @@ const VersionFixed& getVersion() return version; } -std::ostream &operator<<(std::ostream &s, EisSpectra const& spectra) -{ - spectra.saveToStream(s); - return s; -} - std::ostream &operator<<(std::ostream &s, DataPoint const& dp) { s<<dp.im; diff --git a/spectra.cpp b/spectra.cpp new file mode 100644 index 0000000..3c139fc --- /dev/null +++ b/spectra.cpp @@ -0,0 +1,274 @@ +#include <fstream> + +#include "spectra.h" +#include "eistype.h" +#include "strops.h" +#include "log.h" +#include "basicmath.h" + +namespace eis +{ + +EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, + const std::string& headerIn, std::vector<double> labelsIn, std::vector<std::string> labelNamesIn): +data(dataIn), model(modelIn), header(headerIn), labels(labelsIn), labelNames(labelNamesIn) +{ + +} + +EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, + const std::string& headerIn, std::vector<float> labelsIn, std::vector<std::string> labelNamesIn): +data(dataIn), model(modelIn), header(headerIn), labelNames(labelNamesIn) +{ + setLabels(labelsIn); +} + +EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, const std::string& headerIn, + std::vector<size_t> labelsIn, std::vector<std::string> labelNamesIn): +data(dataIn), model(modelIn), header(headerIn), labelNames(labelNamesIn) +{ + setSzLabels(labelsIn); +} + +EisSpectra::EisSpectra(const std::vector<DataPoint>& dataIn, const std::string& modelIn, const std::string& headerIn, + size_t label, size_t maxLabel, std::vector<std::string> labelNamesIn): +data(dataIn), model(modelIn), header(headerIn), labelNames(labelNamesIn) +{ + setLabel(label, maxLabel); +} + +void EisSpectra::setLabel(size_t label, size_t maxLabel) +{ + labels.assign(maxLabel, 0); + labels[label] = 1; +} + +void EisSpectra::setSzLabels(std::vector<size_t> labelsIn) +{ + labels.assign(labelsIn.size(), 0); + for(size_t i = 0; i < labelsIn.size(); ++i) + labels[i] = static_cast<double>(labelsIn[i]); +} + +std::vector<size_t> EisSpectra::getSzLabels() const +{ + std::vector<size_t> out(labels.size()); + for(size_t i = 0; i < labels.size(); ++i) + out[i] = static_cast<size_t>(labels[i]); + return out; +} + +size_t EisSpectra::getLabel() +{ + for(size_t i = 0; i < labels.size(); ++i) + if(labels[i] != 0) + return i; + return 0; +} + +bool EisSpectra::isMulticlass() +{ + bool foundFirst = false; + for(size_t i = 0; i < labels.size(); ++i) + { + if(labels[i] != 0) + { + if(foundFirst) + return true; + else + foundFirst = true; + } + } + return false; +} + +void EisSpectra::setLabels(const std::vector<float>& labelsIn) +{ + labels.assign(labelsIn.size(), 0); + for(size_t i = 0; i < labels.size(); ++i) + labels[i] = labelsIn[i]; +} + +void EisSpectra::setLabels(const std::vector<double>& labelsIn) +{ + labels = labelsIn; +} + +std::vector<fvalue> EisSpectra::getFvalueLabels() +{ + if constexpr(std::is_same<fvalue, double>::value) + { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" + return *reinterpret_cast<std::vector<fvalue>*>(&labels); + #pragma GCC diagnostic pop + } + else + { + std::vector<fvalue> out(labels.size()); + for(size_t i = 0; i < labels.size(); ++i) + out[i] = static_cast<fvalue>(labels[i]); + return out; + } +} + +void EisSpectra::saveToStream(std::ostream& stream) const +{ + stream<<std::scientific; + stream<<F_MAGIC<<", "<<std::to_string(F_VERSION_MAJOR)<<'.' + <<std::to_string(F_VERSION_MINOR)<<'.'<<std::to_string(F_VERSION_PATCH)<<'\n'; + + stream<<'"'<<model<<'"'<<'\n'<<(headerDescription.empty() ? "None" : headerDescription)<<'\n'<<(header.empty() ? "None" : header); + + if(!labels.empty()) + { + if(!labelNames.empty()) + { + stream<<"\nlabelsNames\n"; + std::string labelLine; + for(const std::string& name : labelNames) + labelLine += "\"" + name + "\", "; + labelLine.pop_back(); + labelLine.pop_back(); + stream<<labelLine; + } + stream<<"\nlabels\n"; + + std::stringstream labelSs; + for(double label : labels) + labelSs<<label<<", "; + std::string labelLine = labelSs.str(); + labelLine.pop_back(); + labelLine.pop_back(); + stream<<labelLine; + } + + stream<<"\nomega, real, im\n"; + + for(const eis::DataPoint& point : data) + stream<<point.omega<<", "<<point.im.real()<<", "<<point.im.imag()<<'\n'; +} + +bool EisSpectra::saveToDisk(const std::filesystem::path& path) const +{ + std::fstream file; + file.open(path, std::ios_base::out | std::ios_base::trunc); + if(!file.is_open()) + { + Log(Log::ERROR)<<"can not open "<<path<<" for writing\n"; + return false; + } + + saveToStream(file); + + file.close(); + return true; +} + +EisSpectra EisSpectra::loadFromStream(std::istream& stream) +{ + EisSpectra out; + std::string line; + std::getline(stream, line); + std::vector<std::string> tokens = tokenizeBinaryIgnore(line, ',', '"', '\\'); + VersionFixed fileVersion; + + if(tokens.size() < 2 || tokens[0] != F_MAGIC) + { + throw file_error("not a valid EISGenerator file or stream"); + } + else + { + std::vector<std::string> versionTokens = tokenize(tokens[1], '.'); + if(versionTokens.size() != 3) + throw file_error("could not load file version from file"); + fileVersion.major = std::stoi(versionTokens[0]); + fileVersion.minor = std::stoi(versionTokens[1]); + fileVersion.patch = std::stoi(versionTokens[3]); + if(fileVersion.major > F_VERSION_MAJOR || fileVersion.minor > F_VERSION_MINOR) + throw file_error("saved by a newer version of EISGenerator, can not open"); + } + + if(fileVersion.minor == F_VERSION_MINOR) + { + std::getline(stream, line); + out.model = line; + std::getline(stream, line); + out.headerDescription = line == "None" ? "" : line; + std::getline(stream, line); + out.header = line == "None" ? "" : line; + } + else + { + std::getline(stream, line); + tokens = tokenizeBinaryIgnore(line, ',', '"', '\\'); + stripQuotes(tokens[0]); + out.model = tokens[0]; + line.erase(line.begin(), line.begin()+tokens.size()); + out.header = line; + } + + while(stream.good()) + { + std::getline(stream, line); + if(line.starts_with("labelsNames")) + { + std::getline(stream, line); + out.labelNames = tokenizeBinaryIgnore(line, ',', '"', '\\'); + continue; + } + else if(line.starts_with("labels")) + { + std::getline(stream, line); + std::vector<std::string> tokens = tokenizeBinaryIgnore(line, ',', '"', '\\'); + for(const std::string& token : tokens) + out.labels.push_back(std::stod(token)); + continue; + } + else if(line.empty() || line[0] == '#' || line.starts_with("omega")) + { + continue; + } + tokens = tokenize(line, ','); + if(tokens.size() != 3) + throw file_error("invalid line: " + line); + + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wnarrowing" + if constexpr (std::is_same<fvalue, double>::value) + out.data.push_back(DataPoint({std::stod(tokens[1]), std::stod(tokens[2])}, std::stod(tokens[0]))); + else + out.data.push_back(DataPoint({std::stof(tokens[1]), std::stof(tokens[2])}, std::stof(tokens[0]))); + #pragma GCC diagnostic pop + + eis::removeDuplicates(out.data); + } + + return out; +} + +EisSpectra EisSpectra::loadFromDisk(const std::filesystem::path& path) +{ + std::fstream file; + file.open(path, std::ios_base::in); + if(!file.is_open()) + throw file_error("can not open " + path.string() + " for reading\n"); + + try + { + EisSpectra out = loadFromStream(file); + return out; + } + catch(const file_error& err) + { + throw file_error(path.string() + std::string(": ") + err.what()); + } +} + +} + +std::ostream &operator<<(std::ostream &s, eis::EisSpectra const& spectra) +{ + spectra.saveToStream(s); + return s; +} diff --git a/strops.cpp b/strops.cpp index 5fc6644..767f8e0 100644 --- a/strops.cpp +++ b/strops.cpp @@ -25,6 +25,9 @@ #include "log.h" +namespace eis +{ + char getOpposingBracketChar(const char ch) { switch(ch) @@ -214,3 +217,5 @@ std::string stripWhitespace(const std::string& in) } return out; } + +} diff --git a/strops.h b/strops.h index e844c74..6db94a2 100644 --- a/strops.h +++ b/strops.h @@ -24,6 +24,9 @@ #include <sstream> #include <algorithm> +namespace eis +{ + std::vector<std::string> tokenize(const std::string& str, const char delim = ' ', const char ignBracketStart = '\0', const char ignBracketEnd = '\0', const char escapeChar = '\0'); std::vector<std::string> tokenizeBinaryIgnore(const std::string& str, const char delim, const char ignoreBraket = '\0', @@ -40,3 +43,5 @@ std::string stripWhitespace(const std::string& in); void stripQuotes(std::string& in); size_t eisRemoveUnneededBrackets(std::string& in, long int bracketStart = -1); + +} diff --git a/test.cpp b/test.cpp index 5ed71c0..3727152 100644 --- a/test.cpp +++ b/test.cpp @@ -342,7 +342,7 @@ static bool modelConsistancy() static bool uneededBrackets() { std::string tst("(c-(rc)-(r-c(r)))"); - eisRemoveUnneededBrackets(tst); + eis::eisRemoveUnneededBrackets(tst); std::string expected("c-rc-(r-cr)"); if(tst == expected) { -- GitLab