Line data Source code
1 : /* Copyright (C) 2025 Robert Schiwon 2 : * 3 : * This file is part of libjdx. 4 : * 5 : * libjdx is free software: you can redistribute it and/or modify it under the 6 : * terms of the GNU Lesser General Public License as published by the Free 7 : * Software Foundation, either version 3 of the License, or (at your option) any 8 : * later version. 9 : * 10 : * libjdx is distributed in the hope that it will be useful, but WITHOUT ANY 11 : * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 : * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 13 : * details. 14 : * 15 : * You should have received a copy of the GNU Lesser General Public License 16 : * along with libjdx. If not, see <https://www.gnu.org/licenses/>. 17 : */ 18 : #include "jdx/Data2D.hpp" 19 : #include "jdx/ParseException.hpp" 20 : #include "util/DataParser.hpp" 21 : #include "util/LdrUtils.hpp" 22 : 23 : #include <tuple> 24 : 25 136 : libjdx::jdx::Data2D::Data2D( 26 136 : std::string label, std::string variableList, io::TextReader& reader) 27 136 : : DataLdr(std::move(label), std::move(variableList), reader) 28 : { 29 136 : } 30 : 31 23 : std::vector<std::pair<double, double>> libjdx::jdx::Data2D::parseXppYYData( 32 : const std::string& label, io::TextReader& reader, double firstX, 33 : double lastX, double yFactor, uint64_t nPoints) const 34 : { 35 : // parse 36 23 : auto func = [&]() { 37 23 : return libjdx::jdx::util::DataParser::readXppYYData(reader); 38 23 : }; 39 46 : auto yData = callAndResetStreamPos<std::vector<double>>(func); 40 : 41 23 : if (yData.size() != nPoints) 42 : { 43 : throw ParseException( 44 1 : "Mismatch between NPOINTS and actual number of points in \"" + label 45 3 : + "\". NPOINTS: " + std::to_string(nPoints) 46 3 : + ", actual: " + std::to_string(yData.size())); 47 : } 48 : // prepare processing 49 22 : std::vector<std::pair<double, double>> xyData{}; 50 22 : xyData.reserve(yData.size()); 51 : // cover special cases nPoints == 0 and nPoints == 1 52 22 : if (nPoints == 0) 53 : { 54 1 : return xyData; 55 : } 56 21 : auto nominator = nPoints == 1 ? firstX : (lastX - firstX); 57 21 : auto denominator = nPoints == 1 ? 1 : nPoints - 1; 58 : // generate and return xy data 59 21 : uint64_t count = 0; 60 86 : for (auto yRaw : yData) 61 : { 62 : auto x = firstX 63 65 : + nominator / static_cast<double>(denominator) 64 65 : * static_cast<double>(count++); 65 65 : auto y = yFactor * yRaw; 66 65 : xyData.emplace_back(x, y); 67 : } 68 : // TODO: check if parsed data matches firstX, lastX 69 21 : return xyData; 70 : } 71 : 72 14 : std::vector<std::pair<double, double>> libjdx::jdx::Data2D::parseXyXyData( 73 : const std::string& label, io::TextReader& reader, double xFactor, 74 : double yFactor, std::optional<size_t> nPoints) const 75 : { 76 : // parse 77 : auto func 78 14 : = [&]() { return libjdx::jdx::util::DataParser::readXyXyData(reader); }; 79 : auto xyData 80 17 : = callAndResetStreamPos<std::vector<std::pair<double, double>>>(func); 81 : 82 11 : if (nPoints.has_value() && xyData.size() != nPoints.value()) 83 : { 84 : throw ParseException( 85 1 : "Mismatch between NPOINTS and actual number of points in \"" + label 86 3 : + "\". NPOINTS: " + std::to_string(nPoints.value()) 87 3 : + ", actual: " + std::to_string(xyData.size())); 88 : } 89 47 : for (auto& pair : xyData) 90 : { 91 37 : pair.first *= xFactor; 92 37 : pair.second *= yFactor; 93 : } 94 20 : return xyData; 95 : }