From 8d828095f91cc0fb11b706bfc960a03f47e21c87 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm <philipp@uvos.xyz> Date: Mon, 17 Feb 2025 17:45:23 +0100 Subject: [PATCH] Add the ability to check if all elements of a spectra contribute --- componant/paralellseriel.cpp | 32 +++++++ eisgenerator/componant/paralellseriel.h | 13 ++- eisgenerator/model.h | 17 ++++ kissplotcsv | 2 +- main.cpp | 3 +- model.cpp | 106 ++++++++++++++++++++++-- test.cpp | 67 +++++++++++++++ 7 files changed, 226 insertions(+), 14 deletions(-) diff --git a/componant/paralellseriel.cpp b/componant/paralellseriel.cpp index bd4a275..4139f1d 100644 --- a/componant/paralellseriel.cpp +++ b/componant/paralellseriel.cpp @@ -20,9 +20,19 @@ #include "componant/paralellseriel.h" #include "componant/componant.h" +#include "type.h" using namespace eis; +std::vector<bool> ParallelSerial::contributes(fvalue omega, fvalue threshold) +{ + std::vector<fvalue> ratios = contributionRatio(omega); + std::vector<bool> out(ratios.size()); + for(size_t i = 0; i < ratios.size(); ++i) + out[i] = ratios[i] > threshold; + return out; +} + Parallel::Parallel(std::vector<Componant*> componantsIn): componants(componantsIn) { } @@ -108,6 +118,17 @@ std::string Parallel::getTorchScript(std::vector<std::string>& parameters) return out; } +std::vector<fvalue> Parallel::contributionRatio(fvalue omega) +{ + std::vector<fvalue> out(componants.size()); + for(size_t i = 0; i < componants.size(); ++i) + out[i] = std::abs(componants[i]->execute(omega)); + fvalue max = *std::min_element(out.begin(), out.end()); + for(fvalue& val : out) + val = max / val; + return out; +} + Serial::Serial(std::vector<Componant*> componantsIn): componants(componantsIn) { } @@ -195,3 +216,14 @@ std::string Serial::getTorchScript(std::vector<std::string>& parameters) out.push_back(')'); return out; } + +std::vector<fvalue> Serial::contributionRatio(fvalue omega) +{ + std::vector<fvalue> out(componants.size()); + for(size_t i = 0; i < componants.size(); ++i) + out[i] = std::abs(componants[i]->execute(omega)); + fvalue max = *std::max_element(out.begin(), out.end()); + for(fvalue& val : out) + val = val / max; + return out; +} diff --git a/eisgenerator/componant/paralellseriel.h b/eisgenerator/componant/paralellseriel.h index 914e127..3071737 100644 --- a/eisgenerator/componant/paralellseriel.h +++ b/eisgenerator/componant/paralellseriel.h @@ -26,7 +26,14 @@ namespace eis { -class Parallel: public Componant +class ParallelSerial: public Componant +{ +public: + virtual std::vector<fvalue> contributionRatio(fvalue omega) = 0; + std::vector<bool> contributes(fvalue omega, fvalue threshold = 0.01); +}; + +class Parallel: public ParallelSerial { public: std::vector<Componant*> componants; @@ -43,9 +50,10 @@ public: virtual bool compileable() override; virtual std::string getCode(std::vector<std::string>& parameters) override; virtual std::string getTorchScript(std::vector<std::string>& parameters) override; + virtual std::vector<fvalue> contributionRatio(fvalue omega) override; }; -class Serial: public Componant +class Serial: public ParallelSerial { public: std::vector<Componant*> componants; @@ -62,6 +70,7 @@ public: virtual bool compileable() override; virtual std::string getCode(std::vector<std::string>& parameters) override; virtual std::string getTorchScript(std::vector<std::string>& parameters) override; + virtual std::vector<fvalue> contributionRatio(fvalue omega) override; }; } diff --git a/eisgenerator/model.h b/eisgenerator/model.h index 65cd099..0c5d1c4 100644 --- a/eisgenerator/model.h +++ b/eisgenerator/model.h @@ -309,6 +309,23 @@ public: */ std::vector<size_t> getRecommendedParamIndices(eis::Range omegaRange, double distance, bool threaded = false); + /** + * @brief Attempts to check if all elements contribute to the result + + * @param threashold contribution ratio below which the contribution is considered irrelivant + * @param omegaRange range of frequencies to consider + * @return True if all Contribute false otherwise + */ + bool allElementsContribute(eis::Range omegaRange, fvalue threashold = 0.01); + + /** + * @brief Checks if all elements in series with one another dont have too similar impedance + + * @param threashold contribution ratio below which the contribution is considered irrelivant + * @param omegaRange range of frequencies to consider + * @return True if all series have a difference false otherwise. + */ + bool hasSeriesDifference(eis::Range omegaRange, fvalue threashold = 0.1); /** * @brief Removes the series reistance from a model string (if any) diff --git a/kissplotcsv b/kissplotcsv index d608fcf..a823e49 100755 --- a/kissplotcsv +++ b/kissplotcsv @@ -124,5 +124,5 @@ set tics font \"Sans,12\"; \ set xlabel font \"Sans,15\"; \ set ylabel font \"Sans,15\"; \ set datafile separator ','; \ -plot '-' using $mode skip 3 notitle w l; +plot '-' using $mode skip 5 notitle w l; " diff --git a/main.cpp b/main.cpp index a724bfd..6152ebd 100644 --- a/main.cpp +++ b/main.cpp @@ -308,8 +308,7 @@ static void findRanges(const Config& config, eis::Model& model) static void outputRanges(const Config& config, eis::Model& model) { - std::vector<size_t> indices; - getRangeValuesForModel(config, model, &indices); + std::vector<size_t> indices = model.getRecommendedParamIndices(config.omegaRange, config.rangeDistance, config.threaded); if(indices.empty()) { diff --git a/model.cpp b/model.cpp index eb61a2a..27593f9 100644 --- a/model.cpp +++ b/model.cpp @@ -590,14 +590,6 @@ std::vector<size_t> Model::getRecommendedParamIndices(eis::Range omegaRange, dou continue; } - fvalue nonConstantess = std::abs(pearsonCorrelation(data)); - if(nonConstantess < 0.1) - { - eis::Log(eis::Log::DEBUG)<<"skipping output for step "<<i - <<" as data is too constant: "<<nonConstantess; - continue; - } - std::vector<std::vector<eis::DataPoint>>::iterator search; if(threaded) { @@ -622,8 +614,23 @@ std::vector<size_t> Model::getRecommendedParamIndices(eis::Range omegaRange, dou std::cout<<std::flush; } } + + std::vector<size_t> out; + out.reserve(indices.size()); + for(size_t candidate : indices) + { + resolveSteps(candidate); + if(!allElementsContribute(omegaRange)) + eis::Log(eis::Log::DEBUG)<<"skipping "<<candidate<<" as not all elements contribute"; + else if(!hasSeriesDifference(omegaRange)) + eis::Log(eis::Log::DEBUG)<<"skipping "<<candidate<<" as not all elements in series are different"; + else + out.push_back(candidate); + + } + eis::Log(eis::Log::INFO, false)<<'\n'; - return indices; + return out; } size_t Model::getUuid() const @@ -761,3 +768,84 @@ void Model::removeSeriesResitance(std::string& model) } } } + +bool Model::allElementsContribute(eis::Range omegaRange, fvalue threashold) +{ + std::vector<Componant*> componants = getFlatComponants(); + componants.push_back(_model); + std::vector<ParallelSerial*> combiners; + for(Componant* componant : componants) + { + ParallelSerial* candidate = dynamic_cast<ParallelSerial*>(componant); + if(candidate) + combiners.push_back(candidate); + } + + std::vector<bool> contributesGlobal; + for(fvalue omega : omegaRange.getRangeVector()) + { + std::vector<bool> contributes; + for(ParallelSerial* combiner : combiners) + { + std::vector<bool> contributesLocal = combiner->contributes(omega); + contributes.insert(contributes.end(), contributesLocal.begin(), contributesLocal.end()); + } + if(contributesGlobal.empty()) + { + contributesGlobal = contributes; + } + else + { + for(size_t i = 0; i < contributesGlobal.size(); ++i) + contributesGlobal[i] = contributes[i] || contributesGlobal[i]; + } + + if(std::find(contributesGlobal.begin(), contributesGlobal.end(), false) == contributesGlobal.end()) + break; + } + + return std::find(contributesGlobal.begin(), contributesGlobal.end(), false) == contributesGlobal.end(); +} + + +bool Model::hasSeriesDifference(eis::Range omegaRange, fvalue threashold) +{ + std::vector<Componant*> componants = getFlatComponants(); + componants.push_back(_model); + std::vector<Serial*> serials; + for(Componant* componant : componants) + { + Serial* candidate = dynamic_cast<Serial*>(componant); + if(candidate) + serials.push_back(candidate); + } + + std::vector<bool> isDifferentGlobal; + for(fvalue omega : omegaRange.getRangeVector()) + { + bool allContribute = true; + for(Serial* serial : serials) + { + std::vector<std::complex<fvalue>> impedances; + for(Componant* componant : serial->componants) + impedances.push_back(componant->execute(omega)); + for(size_t i = 0; i < impedances.size() && allContribute; ++i) + { + for(size_t j = i+1; j < impedances.size(); ++j) + { + if(std::abs(impedances[i] - impedances[j])/std::abs(impedances[i]) < threashold) + { + allContribute = false; + break; + } + } + } + if(!allContribute) + break; + } + if(allContribute) + return true; + } + + return false; +} diff --git a/test.cpp b/test.cpp index 0d5f026..b721418 100644 --- a/test.cpp +++ b/test.cpp @@ -545,6 +545,67 @@ bool testResize() return true; } +bool testContribution() +{ + eis::Range omega(1, 1e6, 50, true); + eis::Model model("r{0.001}c{1e-10~0.0001L}", 100, true); + + bool contributes = model.allElementsContribute(omega); + if(contributes) + { + eis::Log(eis::Log::ERROR)<<__func__<<" expected 0 got "<<contributes; + return false; + } + + model = eis::Model("r{1000}c{1e-10~0.0001L}", 100, true); + contributes = model.allElementsContribute(omega); + if(!contributes) + { + eis::Log(eis::Log::ERROR)<<__func__<<" expected 1 got "<<contributes; + return false; + } + + model = eis::Model("r{1}-r{1000}", 100, true); + contributes = model.allElementsContribute(omega); + if(contributes) + { + eis::Log(eis::Log::ERROR)<<__func__<<" expected 0 got "<<contributes; + return false; + } + + model = eis::Model("r{10}-r{10}", 100, true); + contributes = model.allElementsContribute(omega); + if(!contributes) + { + eis::Log(eis::Log::ERROR)<<__func__<<" expected 1 got "<<contributes; + return false; + } + + return true; +} + +bool testSeriesContribution() +{ + eis::Range omega(1, 1e6, 50, true); + eis::Model model("r{10}c{1e-5}-r{10}c{1e-5}", 100, true); + + bool contributes = model.hasSeriesDifference(omega); + if(contributes) + { + eis::Log(eis::Log::ERROR)<<__func__<<" expected 0 got "<<contributes; + return false; + } + + model = eis::Model("r{10}c{1e-5}-r{10}p{1e-5, 0.8}", 100, true); + contributes = model.hasSeriesDifference(omega); + if(!contributes) + { + eis::Log(eis::Log::ERROR)<<__func__<<" expected 1 got "<<contributes; + return false; + } + return true; +} + int main(int argc, char** argv) { eis::Log::headers = true; @@ -616,5 +677,11 @@ int main(int argc, char** argv) if(!testResize()) return 22; + if(!testContribution()) + return 23; + + if(!testSeriesContribution()) + return 24; + return 0; } -- GitLab