Skip to content
Snippets Groups Projects
Select Git revision
  • fa12d4a6140f14e71fdcc4d90df7482f3124d790
  • master default
  • 1.1
  • 1.0
4 results

translators.cpp

Blame
  • eistype.cpp 9.74 KiB
    #include "eistype.h"
    #include <fstream>
    #include <sstream>
    #include <algorithm>
    #include <string>
    #include <vector>
    
    #include "strops.h"
    #include "log.h"
    #include "basicmath.h"
    
    using namespace eis;
    
    bool eis::saveToDisk(const EisSpectra& data, const std::filesystem::path& path)
    {
    	Log(Log::INFO)<<__func__<<" is deprecated";
    	return data.saveToDisk(path);
    }
    
    EisSpectra eis::loadFromDisk(const std::filesystem::path& path)
    {
    	Log(Log::INFO)<<__func__<<" is deprecated";
    	return EisSpectra(path);
    }
    
    void eis::Range::print(int level) const
    {
    	Log(static_cast<Log::Level>(level))<<"Range "<<start<<'-'<<end<<' '<<count<<" steps"<<(log ? " Log" : "");
    }
    
    std::vector<fvalue> eis::Range::getRangeVector() const
    {
    	std::vector<fvalue> out(count, 0);
    	for(size_t i = 0; i < count; ++i)
    		out[i] = at(i);
    	return out;
    }
    
    std::vector<Range> eis::Range::rangesFromParamString(const std::string& paramStr, size_t count)
    {
    	std::vector<std::string> tokens = tokenize(paramStr, ',');
    
    	std::vector<Range> ranges(tokens.size());
    	for(size_t i = 0; i < tokens.size(); ++i)
    	{
    		bool log = false;
    		std::string& token = tokens[i];
    		std::vector<std::string> subTokens = tokenize(token, '~');
    
    		if(token.back() == 'l' || token.back() == 'L')
    		{
    			log = true;
    			token.pop_back();
    		}
    
    		try
    		{
    			if(subTokens.size() == 1)
    			{
    				ranges[i] = Range(std::stod(subTokens[0]), std::stod(subTokens[0]), 1, log);
    			}
    			else
    			{
    				ranges[i] = Range(std::stod(subTokens[0]), std::stod(subTokens[1]), count, log);
    				if(subTokens.size() > 2)
    					throw std::invalid_argument("");
    			}
    
    		}
    		catch(const std::invalid_argument& ia)
    		{
    			throw std::invalid_argument("invalid parameter string \"{"+ paramStr + "}\"");
    		}
    	}
    	return ranges;
    }
    
    std::string eis::Range::getString() const
    {
    	std::stringstream ss;
    
    	ss<<start;
    	if(count > 1)
    	{
    		ss<<'~'<<end;
    		if(log)
    			ss<<'L';
    	}
    
    	return ss.str();
    }
    
    bool eis::Range::isSane() const
    {
    	if(log && (start == 0 || end == 0))
    		return false;
    	if(end < start)
    		return false;
    	return true;
    }
    
    //Compute simmuliarity on a bode plot
    fvalue eis::eisDistance(const std::vector<eis::DataPoint>& a, const std::vector<eis::DataPoint>& b)
    {
    	assert(a.size() == b.size());
    
    	double accum = 0;
    	for(size_t i = 0; i < a.size(); ++i)
    	{
    		double diffRe = std::pow(b[i].im.real() - a[i].im.real(), 2);
    		double diffIm = std::pow(b[i].im.imag() - a[i].im.imag(), 2);
    		accum += diffRe+diffIm;
    	}
    	return sqrt(accum/a.size());
    }
    
    //Compute simmuliarity on a nyquist plot
    fvalue eis::eisNyquistDistance(const std::vector<eis::DataPoint>& a, const std::vector<eis::DataPoint>& b)
    {
    	assert(a.size() > 2 && b.size() > 3);
    	double accum = 0;
    	for(size_t i = 0; i < a.size(); ++i)
    	{
    		std::vector<std::pair<double, const eis::DataPoint*>> distances;
    		for(size_t j = 0; j < b.size(); ++j)
    		{
    			double diffRe = std::pow(b[j].im.real() - a[i].im.real(), 2);
    			double diffIm = std::pow(b[j].im.imag() - a[i].im.imag(), 2);
    			std::pair<double, const eis::DataPoint*> dp;
    			dp.first = sqrt(diffRe+diffIm);
    			dp.second = &b[j];
    			distances.push_back(dp);
    		}
    		std::sort(distances.begin(), distances.end(),
    				  [](const std::pair<double, const eis::DataPoint*>& a, const std::pair<double, const eis::DataPoint*>& b) -> bool
    				  {return a.first < b.first;});
    
    		eis::DataPoint base = (*distances[0].second)-(*distances[1].second);
    		base = base/base.complexVectorLength();
    		eis::DataPoint diff = (*distances[0].second)-a[i];
    		diff = diff/diff.complexVectorLength();
    		fvalue dprod = base.im.real()*diff.im.real() + base.im.imag()*diff.im.imag();
    		fvalue dist = diff.complexVectorLength()*(1-dprod);
    		accum += std::pow(dist, 2);
    	}
    	return std::sqrt(accum/a.size());
    }
    
    
    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());
    	}
    }