diff --git a/src/io/inputs/data-series-csv-importer/CMakeLists.txt b/src/io/inputs/data-series-csv-importer/CMakeLists.txt index d509060bed..5762518f09 100644 --- a/src/io/inputs/data-series-csv-importer/CMakeLists.txt +++ b/src/io/inputs/data-series-csv-importer/CMakeLists.txt @@ -15,9 +15,9 @@ target_include_directories(data-series-csv-importer # Link dependencies target_link_libraries(data-series-csv-importer - PRIVATE - linear-problem-data-impl PUBLIC + linear-problem-data-impl + PRIVATE Boost::headers ) diff --git a/src/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.cpp b/src/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.cpp index 0d596546ac..27b641931e 100644 --- a/src/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.cpp +++ b/src/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.cpp @@ -23,8 +23,6 @@ #include #include -#include -#include namespace Antares::IO::Inputs::DataSeriesCsvImporter { @@ -32,64 +30,78 @@ using namespace std; using namespace boost; using namespace Optimisation::LinearProblemDataImpl; -DataSeriesRepository DataSeriesRepoImporter::importFromDirectory(const string& path, +DataSeriesRepository DataSeriesRepoImporter::importFromDirectory(const std::filesystem::path& path, char csvSeparator) { - return DataSeriesRepository(); + if (!is_directory(path)) + { + throw invalid_argument("Not a directory: " + path.string()); + } + DataSeriesRepository repo{}; + for (const auto& entry: std::filesystem::directory_iterator(path)) + { + if (!is_regular_file(entry)) + { + continue; + } + if (entry.path().extension() == ".csv") + { + std::unique_ptr timeSeriesSet = make_unique( + TimeSeriesSetImporter::importFromFile(entry, csvSeparator)); + repo.addDataSeries(std::move(timeSeriesSet)); + } + } + return repo; } -TimeSeriesSet TimeSeriesSetImporter::importFromFile(const string& path, char csvSeparator) +vector> TimeSeriesSetImporter::csvToMatrix(const std::filesystem::path& path, + char csvSeparator) { - // used to split the file in lines - const regex linesregx("\\r\\n|\\n\\r|\\n|\\r"); - // used to split each line to tokens, assuming ',' as column separator - const regex fieldsregx(csvSeparator + "(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"); + // TODO: add logs? + // logs.debug() << "Loading data-series from " << path; vector> result; - ifstream infile; - infile.open(path); - char data[1024]; - infile.read(data, sizeof(data)); - data[infile.tellg()] = '\0'; - unsigned int length = strlen(data); - - // iterator splits data to lines - cregex_token_iterator li(data, data + length, linesregx, -1); - cregex_token_iterator end; - - while (li != end) + ifstream infile(path, std::ios_base::binary | std::ios_base::in); + if (!infile.is_open()) + { + throw invalid_argument("Could not open file " + path.filename().string()); + } + string line; + string element; + while (!infile.eof()) { - string line = li->str(); - ++li; - - // Split line to tokens - sregex_token_iterator ti(line.begin(), line.end(), fieldsregx, -1); - sregex_token_iterator end2; - vector row; - while (ti != end2) + getline(infile, line); + std::stringstream ss(line); + while (getline(ss, element, csvSeparator)) { - double token = stod(ti->str()); - ++ti; - row.push_back(token); + row.push_back(stod(element)); } result.push_back(row); } + return move(result); +} + +TimeSeriesSet TimeSeriesSetImporter::importFromFile(const std::filesystem::path& path, + char csvSeparator) +{ + auto csvMatrix = csvToMatrix(path, csvSeparator); // We have to transpose the matrix - string id = path; // TODO - if (result.empty()) + // TODO: we may want to improve this by reading directly into the TimeSeriesSet object, or + // by creating a specific IDataSeries implementation + int nTimestamps = csvMatrix.size(); + TimeSeriesSet timeSeriesSet(path.stem(), nTimestamps); + if (nTimestamps == 0) { - return TimeSeriesSet(id, 0); + return timeSeriesSet; } - int nTimestamps = result.size(); - TimeSeriesSet timeSeriesSet(id, nTimestamps); - int nSets = result[0].size(); + int nSets = csvMatrix[0].size(); for (int i = 0; i < nSets; ++i) { vector set; set.reserve(nTimestamps); for (int j = 0; j < nTimestamps; ++j) { - set.push_back(result[j][i]); + set.push_back(csvMatrix[j][i]); } timeSeriesSet.add(set); } diff --git a/src/io/inputs/data-series-csv-importer/include/antares/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.h b/src/io/inputs/data-series-csv-importer/include/antares/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.h index d72b1f581e..64e3a49c34 100644 --- a/src/io/inputs/data-series-csv-importer/include/antares/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.h +++ b/src/io/inputs/data-series-csv-importer/include/antares/io/inputs/data-series-csv-importer/DataSeriesRepoImporter.h @@ -20,13 +20,10 @@ */ #pragma once -#include +#include -namespace Antares::Optimisation::LinearProblemDataImpl -{ -class DataSeriesRepository; -class TimeSeriesSet; -} // namespace Antares::Optimisation::LinearProblemDataImpl +#include +#include /** * Reads a DataSeriesRepo from a directory @@ -38,16 +35,22 @@ namespace Antares::IO::Inputs::DataSeriesCsvImporter class TimeSeriesSetImporter { public: + TimeSeriesSetImporter() = delete; // must not be used static Optimisation::LinearProblemDataImpl::TimeSeriesSet importFromFile( - const std::string& path, + const std::filesystem::path& path, char csvSeparator = ';'); + +private: + static std::vector> csvToMatrix(const std::filesystem::path& path, + char csvSeparator = ';'); }; class DataSeriesRepoImporter { public: + DataSeriesRepoImporter() = delete; // must not be used static Optimisation::LinearProblemDataImpl::DataSeriesRepository importFromDirectory( - const std::string& path, + const std::filesystem::path&, char csvSeparator = ';'); }; diff --git a/src/optimisation/linear-problem-data-impl/include/antares/optimisation/linear-problem-data-impl/linearProblemData.h b/src/optimisation/linear-problem-data-impl/include/antares/optimisation/linear-problem-data-impl/linearProblemData.h index 4f2b201947..0a99e805f2 100644 --- a/src/optimisation/linear-problem-data-impl/include/antares/optimisation/linear-problem-data-impl/linearProblemData.h +++ b/src/optimisation/linear-problem-data-impl/include/antares/optimisation/linear-problem-data-impl/linearProblemData.h @@ -34,6 +34,13 @@ namespace Antares::Optimisation::LinearProblemDataImpl class LinearProblemData: public LinearProblemApi::ILinearProblemData { public: + LinearProblemData() = default; + + LinearProblemData(DataSeriesRepository& data_series_repository): + dataSeriesRepository_(std::move(data_series_repository)) + { + } + double getData(const std::string& dataSetId, const std::string& scenarioGroup, const unsigned scenario, diff --git a/src/optimisation/linear-problem-data-impl/linearProblemData.cpp b/src/optimisation/linear-problem-data-impl/linearProblemData.cpp index 7b7bb02446..ca4ce21e19 100644 --- a/src/optimisation/linear-problem-data-impl/linearProblemData.cpp +++ b/src/optimisation/linear-problem-data-impl/linearProblemData.cpp @@ -40,7 +40,9 @@ double LinearProblemData::getData(const std::string& dataSetId, const unsigned scenario, const unsigned hour) { - unsigned rank = groupRepository_.getDataRank(scenarioGroup, scenario); + // TODO: use the following line to add scenario group support + // unsigned rank = groupRepository_.getDataRank(scenarioGroup, scenario); + unsigned rank = scenario; return dataSeriesRepository_.getDataSeries(dataSetId).getData(rank, hour); } diff --git a/src/solver/modeler/CMakeLists.txt b/src/solver/modeler/CMakeLists.txt index dcd1eb937a..b12ac1dc37 100644 --- a/src/solver/modeler/CMakeLists.txt +++ b/src/solver/modeler/CMakeLists.txt @@ -24,6 +24,7 @@ target_link_libraries(modeler-lib Antares::linear-problem-api # TODO FIXME don't depend on implementations Antares::linear-problem-mpsolver-impl + Antares::data-series-csv-importer ) target_link_libraries(antares-modeler @@ -32,6 +33,7 @@ target_link_libraries(antares-modeler linear-problem-data-impl linear-problem-mpsolver-impl optim-model-filler + data-series-csv-importer ) import_std_libs(antares-modeler) diff --git a/src/solver/modeler/main.cpp b/src/solver/modeler/main.cpp index 116ac7d3a1..4e04d0b80b 100644 --- a/src/solver/modeler/main.cpp +++ b/src/solver/modeler/main.cpp @@ -21,19 +21,21 @@ #include +#include #include +#include #include #include #include #include #include #include -#include "antares/optimisation/linear-problem-api/linearProblem.h" using namespace Antares::Optimisation::LinearProblemMpsolverImpl; using namespace Antares; using namespace Antares::Solver; using namespace Antares::Optimisation::LinearProblemApi; +using namespace Antares::Optimisation::LinearProblemDataImpl; class SystemLinearProblem { @@ -45,7 +47,9 @@ class SystemLinearProblem ~SystemLinearProblem() = default; - void Provide(ILinearProblem& pb, const ModelerParameters& parameters) + void Provide(ILinearProblem& pb, + const ModelerParameters& parameters, + DataSeriesRepository& dataSeriesRepo) { std::vector> fillers; std::vector fillers_ptr; @@ -60,9 +64,9 @@ class SystemLinearProblem } LinearProblemBuilder linear_problem_builder(fillers_ptr); - Optimisation::LinearProblemDataImpl::LinearProblemData dummy_data; + LinearProblemData data(dataSeriesRepo); FillContext dummy_time_scenario_ctx = {parameters.firstTimeStep, parameters.lastTimeStep}; - linear_problem_builder.build(pb, dummy_data, dummy_time_scenario_ctx); + linear_problem_builder.build(pb, data, dummy_time_scenario_ctx); } private: @@ -102,6 +106,18 @@ int main(int argc, const char** argv) logs.info() << "Libraries loaded"; const auto system = LoadFiles::loadSystem(studyPath, libraries); logs.info() << "System loaded"; + DataSeriesRepository dataSeriesRepository; + try + { + dataSeriesRepository = IO::Inputs::DataSeriesCsvImporter::DataSeriesRepoImporter:: + importFromDirectory(studyPath / "input" / "data-series", ';'); + logs.info() << "Data-series loaded"; + } + catch (const std::exception& e) + { + // Only warning, because data-series are not mandatory + logs.warning() << "Data series could not be imported: " << e.what(); + } SystemLinearProblem system_linear_problem(system); auto outputPath = studyPath / "output"; @@ -119,7 +135,7 @@ int main(int argc, const char** argv) logs.info() << "linear problem of System loaded"; OrtoolsLinearProblem ortools_linear_problem(true, parameters.solver); - system_linear_problem.Provide(ortools_linear_problem, parameters); + system_linear_problem.Provide(ortools_linear_problem, parameters, dataSeriesRepository); logs.info() << "Linear problem provided"; diff --git a/src/tests/io/data-series-csv-importer/CMakeLists.txt b/src/tests/io/data-series-csv-importer/CMakeLists.txt deleted file mode 100644 index fdc10c8fe5..0000000000 --- a/src/tests/io/data-series-csv-importer/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) - -add_boost_test(TestDataSeriesCsvImporter - SRC - testDataSeriesRepoImporter.cpp - LIBS - Antares::data-series-csv-importer) diff --git a/src/tests/io/data-series-csv-importer/testDataSeriesRepoImporter.cpp b/src/tests/io/data-series-csv-importer/testDataSeriesRepoImporter.cpp deleted file mode 100644 index ae958395bd..0000000000 --- a/src/tests/io/data-series-csv-importer/testDataSeriesRepoImporter.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* -** Copyright 2007-2024, RTE (https://www.rte-france.com) -** See AUTHORS.txt -** SPDX-License-Identifier: MPL-2.0 -** This file is part of Antares-Simulator, -** Adequacy and Performance assessment for interconnected energy networks. -** -** Antares_Simulator is free software: you can redistribute it and/or modify -** it under the terms of the Mozilla Public Licence 2.0 as published by -** the Mozilla Foundation, either version 2 of the License, or -** (at your option) any later version. -** -** Antares_Simulator is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** Mozilla Public Licence 2.0 for more details. -** -** You should have received a copy of the Mozilla Public Licence 2.0 -** along with Antares_Simulator. If not, see . -*/ -#include \ No newline at end of file diff --git a/src/tests/src/CMakeLists.txt b/src/tests/src/CMakeLists.txt index 9e85ba46af..e589f26526 100644 --- a/src/tests/src/CMakeLists.txt +++ b/src/tests/src/CMakeLists.txt @@ -9,4 +9,5 @@ add_subdirectory(solver) add_subdirectory(expressions) add_subdirectory(optimisation) add_subdirectory(study) +add_subdirectory(io) add_subdirectory(modeler) \ No newline at end of file diff --git a/src/tests/io/CMakeLists.txt b/src/tests/src/io/CMakeLists.txt similarity index 100% rename from src/tests/io/CMakeLists.txt rename to src/tests/src/io/CMakeLists.txt diff --git a/src/tests/src/io/data-series-csv-importer/CMakeLists.txt b/src/tests/src/io/data-series-csv-importer/CMakeLists.txt new file mode 100644 index 0000000000..fd640f4899 --- /dev/null +++ b/src/tests/src/io/data-series-csv-importer/CMakeLists.txt @@ -0,0 +1,10 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(TestDataSeriesCsvImporter + SRC + test_main.cpp + testDataSeriesCsvImporter.cpp + LIBS + Antares::data-series-csv-importer + Boost::unit_test_framework + test_utils_unit) diff --git a/src/tests/src/io/data-series-csv-importer/testDataSeriesCsvImporter.cpp b/src/tests/src/io/data-series-csv-importer/testDataSeriesCsvImporter.cpp new file mode 100644 index 0000000000..edde4eccc9 --- /dev/null +++ b/src/tests/src/io/data-series-csv-importer/testDataSeriesCsvImporter.cpp @@ -0,0 +1,231 @@ +/* +** Copyright 2007-2024, RTE (https://www.rte-france.com) +** See AUTHORS.txt +** SPDX-License-Identifier: MPL-2.0 +** This file is part of Antares-Simulator, +** Adequacy and Performance assessment for interconnected energy networks. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the Mozilla Public Licence 2.0 as published by +** the Mozilla Foundation, either version 2 of the License, or +** (at your option) any later version. +** +** Antares_Simulator is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** Mozilla Public Licence 2.0 for more details. +** +** You should have received a copy of the Mozilla Public Licence 2.0 +** along with Antares_Simulator. If not, see . +*/ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include + +#include + +#include + +using namespace std; +using namespace Antares::IO::Inputs::DataSeriesCsvImporter; +using namespace Antares::Optimisation::LinearProblemDataImpl; + +struct CsvCreationFixture +{ + filesystem::path temp_path; + + CsvCreationFixture() + { + temp_path = filesystem::temp_directory_path() /= std::tmpnam(nullptr); + filesystem::create_directories(temp_path); + } + + filesystem::path writeFile(string filename, string content); +}; + +filesystem::path CsvCreationFixture::writeFile(const string filename, const string content) +{ + auto filepath = temp_path / (filename + ".csv"); + std::ofstream outfile(filepath); + outfile << content; + outfile.close(); + return filepath; +} + +BOOST_FIXTURE_TEST_SUITE(_DataSeriesImport_OneCsvFile_, CsvCreationFixture) + +BOOST_AUTO_TEST_CASE(invalid_file) +{ + BOOST_CHECK_EXCEPTION(TimeSeriesSetImporter::importFromFile(temp_path / "dummy_123.csv"), + std::invalid_argument, + checkMessage("Could not open file dummy_123.csv")); +} + +BOOST_AUTO_TEST_CASE(empty_file) +{ + auto path = writeFile("empty", ""); + auto timeSeriesSet = TimeSeriesSetImporter::importFromFile(path); + BOOST_CHECK_EQUAL(timeSeriesSet.name(), "empty"); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(0, 0), + TimeSeriesSet::Empty, + checkMessage( + "TS set 'empty' : empty, requesting a value makes no sense")); +} + +BOOST_AUTO_TEST_CASE(one_line_one_column) +{ + auto path = writeFile("one", "138.583"); + auto timeSeriesSet = TimeSeriesSetImporter::importFromFile(path); + BOOST_CHECK_EQUAL(timeSeriesSet.name(), "one"); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(0, 0), 138.583); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(1, 0), + TimeSeriesSet::RankTooBig, + checkMessage("TS set 'one' : rank 1 exceeds TS set's width")); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(0, 1), + TimeSeriesSet::HourTooBig, + checkMessage("TS set 'one' : hour 1 exceeds TS set's height")); +} + +BOOST_AUTO_TEST_CASE(one_line_two_columns) +{ + auto path = writeFile("one_by_two", "123,456.789"); + auto timeSeriesSet = TimeSeriesSetImporter::importFromFile(path, ','); + BOOST_CHECK_EQUAL(timeSeriesSet.name(), "one_by_two"); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(0, 0), 123); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(1, 0), 456.789); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(2, 0), + TimeSeriesSet::RankTooBig, + checkMessage("TS set 'one_by_two' : rank 2 exceeds TS set's width")); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(0, 1), + TimeSeriesSet::HourTooBig, + checkMessage("TS set 'one_by_two' : hour 1 exceeds TS set's height")); +} + +BOOST_AUTO_TEST_CASE(two_lines_one_column) +{ + auto path = writeFile("two_by_one", "123\n20"); + auto timeSeriesSet = TimeSeriesSetImporter::importFromFile(path); + BOOST_CHECK_EQUAL(timeSeriesSet.name(), "two_by_one"); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(0, 0), 123); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(0, 1), 20); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(1, 0), + TimeSeriesSet::RankTooBig, + checkMessage("TS set 'two_by_one' : rank 1 exceeds TS set's width")); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(0, 2), + TimeSeriesSet::HourTooBig, + checkMessage("TS set 'two_by_one' : hour 2 exceeds TS set's height")); +} + +BOOST_AUTO_TEST_CASE(two_lines_two_columns) +{ + auto path = writeFile("two_by_two", "1;2\n3;4"); + auto timeSeriesSet = TimeSeriesSetImporter::importFromFile(path, ';'); + BOOST_CHECK_EQUAL(timeSeriesSet.name(), "two_by_two"); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(0, 0), 1); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(0, 1), 3); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(1, 0), 2); + BOOST_CHECK_EQUAL(timeSeriesSet.getData(1, 1), 4); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(2, 1), + TimeSeriesSet::RankTooBig, + checkMessage("TS set 'two_by_two' : rank 2 exceeds TS set's width")); + BOOST_CHECK_EXCEPTION(timeSeriesSet.getData(1, 2), + TimeSeriesSet::HourTooBig, + checkMessage("TS set 'two_by_two' : hour 2 exceeds TS set's height")); +} + +BOOST_AUTO_TEST_SUITE_END() + +BOOST_FIXTURE_TEST_SUITE(_DataSeriesImport_AllCsvFiles_, CsvCreationFixture) + +BOOST_AUTO_TEST_CASE(empty_dir) +{ + auto repo = DataSeriesRepoImporter::importFromDirectory(temp_path); + BOOST_CHECK_EXCEPTION(repo.getDataSeries("any"), + DataSeriesRepository::Empty, + checkMessage( + "Data series repo is empty, and somebody requests data from it")); +} + +BOOST_AUTO_TEST_CASE(one_simple_file) +{ + writeFile("one", "123"); + auto repo = DataSeriesRepoImporter::importFromDirectory(temp_path); + BOOST_CHECK_EQUAL(repo.getDataSeries("one").name(), "one"); + BOOST_CHECK_EQUAL(repo.getDataSeries("one").getData(0, 0), 123); +} + +BOOST_AUTO_TEST_CASE(two_simple_files) +{ + writeFile("one", "123"); + writeFile("two", "456"); + auto repo = DataSeriesRepoImporter::importFromDirectory(temp_path); + BOOST_CHECK_EQUAL(repo.getDataSeries("one").name(), "one"); + BOOST_CHECK_EQUAL(repo.getDataSeries("two").name(), "two"); + BOOST_CHECK_EQUAL(repo.getDataSeries("one").getData(0, 0), 123); + BOOST_CHECK_EQUAL(repo.getDataSeries("two").getData(0, 0), 456); +} + +BOOST_AUTO_TEST_CASE(three_small_files) +{ + writeFile("gen1_p_max", "1;2;3;4\n5;6;7;8\n9;10;11;12\n13;14;15;16.17"); + writeFile("gen2_p_max", "10\n20\n30\n40"); + writeFile("node1_load", "20;30\n21;31\n22;32\n23;33"); + auto repo = DataSeriesRepoImporter::importFromDirectory(temp_path); + + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").name(), "gen1_p_max"); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(0, 0), 1); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(1, 0), 2); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(2, 0), 3); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(3, 0), 4); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(0, 1), 5); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(1, 1), 6); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(2, 1), 7); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(3, 1), 8); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(0, 2), 9); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(1, 2), 10); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(2, 2), 11); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(3, 2), 12); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(0, 3), 13); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(1, 3), 14); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(2, 3), 15); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen1_p_max").getData(3, 3), 16.17); + BOOST_CHECK_EXCEPTION(repo.getDataSeries("gen1_p_max").getData(4, 0), + TimeSeriesSet::RankTooBig, + checkMessage("TS set 'gen1_p_max' : rank 4 exceeds TS set's width")); + BOOST_CHECK_EXCEPTION(repo.getDataSeries("gen1_p_max").getData(0, 4), + TimeSeriesSet::HourTooBig, + checkMessage("TS set 'gen1_p_max' : hour 4 exceeds TS set's height")); + + BOOST_CHECK_EQUAL(repo.getDataSeries("gen2_p_max").name(), "gen2_p_max"); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen2_p_max").getData(0, 0), 10); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen2_p_max").getData(0, 1), 20); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen2_p_max").getData(0, 2), 30); + BOOST_CHECK_EQUAL(repo.getDataSeries("gen2_p_max").getData(0, 3), 40); + BOOST_CHECK_EXCEPTION(repo.getDataSeries("gen2_p_max").getData(1, 0), + TimeSeriesSet::RankTooBig, + checkMessage("TS set 'gen2_p_max' : rank 1 exceeds TS set's width")); + BOOST_CHECK_EXCEPTION(repo.getDataSeries("gen2_p_max").getData(0, 4), + TimeSeriesSet::HourTooBig, + checkMessage("TS set 'gen2_p_max' : hour 4 exceeds TS set's height")); + + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").name(), "node1_load"); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(0, 0), 20); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(0, 1), 21); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(0, 2), 22); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(0, 3), 23); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(1, 0), 30); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(1, 1), 31); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(1, 2), 32); + BOOST_CHECK_EQUAL(repo.getDataSeries("node1_load").getData(1, 3), 33); + BOOST_CHECK_EXCEPTION(repo.getDataSeries("node1_load").getData(2, 0), + TimeSeriesSet::RankTooBig, + checkMessage("TS set 'node1_load' : rank 2 exceeds TS set's width")); + BOOST_CHECK_EXCEPTION(repo.getDataSeries("node1_load").getData(0, 4), + TimeSeriesSet::HourTooBig, + checkMessage("TS set 'node1_load' : hour 4 exceeds TS set's height")); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/io/data-series-csv-importer/test_main.cpp b/src/tests/src/io/data-series-csv-importer/test_main.cpp new file mode 100644 index 0000000000..75c2d3f7d2 --- /dev/null +++ b/src/tests/src/io/data-series-csv-importer/test_main.cpp @@ -0,0 +1,25 @@ +/* + * Copyright 2007-2024, RTE (https://www.rte-france.com) + * See AUTHORS.txt + * SPDX-License-Identifier: MPL-2.0 + * This file is part of Antares-Simulator, + * Adequacy and Performance assessment for interconnected energy networks. + * + * Antares_Simulator is free software: you can redistribute it and/or modify + * it under the terms of the Mozilla Public Licence 2.0 as published by + * the Mozilla Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Antares_Simulator is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Mozilla Public Licence 2.0 for more details. + * + * You should have received a copy of the Mozilla Public Licence 2.0 + * along with Antares_Simulator. If not, see . + */ + +#define BOOST_TEST_MODULE dataSeriesCsvImporter +#define WIN32_LEAN_AND_MEAN + +#include diff --git a/src/tests/io/yml-importers/CMakeLists.txt b/src/tests/src/io/yml-importers/CMakeLists.txt similarity index 100% rename from src/tests/io/yml-importers/CMakeLists.txt rename to src/tests/src/io/yml-importers/CMakeLists.txt diff --git a/src/tests/io/yml-importers/enum_operators.h b/src/tests/src/io/yml-importers/enum_operators.h similarity index 100% rename from src/tests/io/yml-importers/enum_operators.h rename to src/tests/src/io/yml-importers/enum_operators.h diff --git a/src/tests/io/yml-importers/testConvertorVisitor.cpp b/src/tests/src/io/yml-importers/testConvertorVisitor.cpp similarity index 99% rename from src/tests/io/yml-importers/testConvertorVisitor.cpp rename to src/tests/src/io/yml-importers/testConvertorVisitor.cpp index f9115ddde2..ca1e2ea64a 100644 --- a/src/tests/io/yml-importers/testConvertorVisitor.cpp +++ b/src/tests/src/io/yml-importers/testConvertorVisitor.cpp @@ -29,7 +29,7 @@ #include "antares/io/inputs/yml-model/Library.h" using namespace Antares::Expressions; -using namespace Antares::Solver; +using namespace Antares::IO::Inputs; class ExpressionToNodeConvertorEmptyModel { diff --git a/src/tests/io/yml-importers/testModelTranslator.cpp b/src/tests/src/io/yml-importers/testModelTranslator.cpp similarity index 99% rename from src/tests/io/yml-importers/testModelTranslator.cpp rename to src/tests/src/io/yml-importers/testModelTranslator.cpp index b80f3b0a34..a4bf60db20 100644 --- a/src/tests/io/yml-importers/testModelTranslator.cpp +++ b/src/tests/src/io/yml-importers/testModelTranslator.cpp @@ -31,7 +31,7 @@ #include "enum_operators.h" -using namespace Antares::Solver; +using namespace Antares::IO::Inputs; using namespace Antares::Study; struct Fixture diff --git a/src/tests/io/yml-importers/testSystemConverter.cpp b/src/tests/src/io/yml-importers/testSystemConverter.cpp similarity index 99% rename from src/tests/io/yml-importers/testSystemConverter.cpp rename to src/tests/src/io/yml-importers/testSystemConverter.cpp index 6950d97ab3..5e135de0f4 100644 --- a/src/tests/io/yml-importers/testSystemConverter.cpp +++ b/src/tests/src/io/yml-importers/testSystemConverter.cpp @@ -31,7 +31,7 @@ #include "antares/study/system-model/library.h" using namespace std::string_literals; -using namespace Antares::Solver; +using namespace Antares::IO::Inputs; using namespace Antares::Study; struct LibraryObjects diff --git a/src/tests/io/yml-importers/testYmlModel.cpp b/src/tests/src/io/yml-importers/testYmlModel.cpp similarity index 100% rename from src/tests/io/yml-importers/testYmlModel.cpp rename to src/tests/src/io/yml-importers/testYmlModel.cpp diff --git a/src/tests/io/yml-importers/testYmlSystem.cpp b/src/tests/src/io/yml-importers/testYmlSystem.cpp similarity index 99% rename from src/tests/io/yml-importers/testYmlSystem.cpp rename to src/tests/src/io/yml-importers/testYmlSystem.cpp index 25df8406aa..5dca113c8d 100644 --- a/src/tests/io/yml-importers/testYmlSystem.cpp +++ b/src/tests/src/io/yml-importers/testYmlSystem.cpp @@ -28,7 +28,7 @@ #include using namespace std::string_literals; -using namespace Antares::Solver; +using namespace Antares::IO::Inputs; using namespace Antares::Study; BOOST_AUTO_TEST_CASE(empty_system) diff --git a/src/tests/io/yml-importers/test_full.cpp b/src/tests/src/io/yml-importers/test_full.cpp similarity index 99% rename from src/tests/io/yml-importers/test_full.cpp rename to src/tests/src/io/yml-importers/test_full.cpp index 36d0e182a9..fc6bc3ff59 100644 --- a/src/tests/io/yml-importers/test_full.cpp +++ b/src/tests/src/io/yml-importers/test_full.cpp @@ -34,7 +34,7 @@ #include "enum_operators.h" using namespace std::string_literals; -using namespace Antares::Solver; +using namespace Antares::IO::Inputs; using namespace Antares::Study; void checkParameter(const SystemModel::Parameter& parameter,