From 1959d3b3af467d368b97be95a9aacca6e0ca8fa9 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Thu, 16 Oct 2025 19:58:36 +0000 Subject: [PATCH 01/26] Simplify parameters io --- cpp/memilio/io/parameters_io.cpp | 39 ++ cpp/memilio/io/parameters_io.h | 108 +++-- cpp/models/ode_secir/parameters_io.h | 180 ++++----- cpp/models/ode_secirts/parameters_io.h | 227 +++-------- cpp/models/ode_secirvvs/parameters_io.h | 504 ++++++++++-------------- 5 files changed, 439 insertions(+), 619 deletions(-) diff --git a/cpp/memilio/io/parameters_io.cpp b/cpp/memilio/io/parameters_io.cpp index dff30087e7..906bc132b8 100644 --- a/cpp/memilio/io/parameters_io.cpp +++ b/cpp/memilio/io/parameters_io.cpp @@ -30,6 +30,45 @@ namespace mio { +IOResult> compute_divi_data(const std::vector& divi_data, const std::vector& vregion, Date date) +{ + + auto max_date_entry = std::max_element(divi_data.begin(), divi_data.end(), [](auto&& a, auto&& b) { + return a.date < b.date; + }); + if (max_date_entry == divi_data.end()) { + log_error("DIVI data is empty."); + return failure(StatusCode::InvalidValue, "DIVI data is empty."); + } + auto max_date = max_date_entry->date; + if (max_date < date) { + log_error("DIVI data does not contain the specified date."); + return failure(StatusCode::OutOfRange, "DIVI data does not contain the specified date."); + } + + std::vector vnum_icu(vregion.size(), 0.0); + + + for (auto&& entry : divi_data) { + auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { + return r == 0 || r == get_region_id(entry); + }); + auto date_df = entry.date; + if (it != vregion.end() && date_df == date) { + auto region_idx = size_t(it - vregion.begin()); + vnum_icu[region_idx] = entry.num_icu; + } + } + + return success(vnum_icu); +} + +IOResult> read_divi_data(const std::string& path, const std::vector& vregion, Date date) +{ + BOOST_OUTCOME_TRY(auto&& divi_data, mio::read_divi_data(path)); + return compute_divi_data(divi_data, vregion, date); +} + IOResult>> read_population_data(const std::vector& population_data, const std::vector& vregion) { diff --git a/cpp/memilio/io/parameters_io.h b/cpp/memilio/io/parameters_io.h index 9dee5046f2..52125c1f57 100644 --- a/cpp/memilio/io/parameters_io.h +++ b/cpp/memilio/io/parameters_io.h @@ -52,42 +52,66 @@ int get_region_id(const EpiDataEntry& data_entry) /** * @brief Extracts the number of individuals in critical condition (ICU) for each region - * on a specified date from the provided DIVI data. + * on a specified date from the provided DIVI data- * + * @param[in] divi_data Vector of DIVI data entries containing date, region, and ICU information. + * @param[in] vregion Vector of region IDs for which the data is computed. + * @param[in] date Date for which the ICU data is computed. + * @return An IOResult containing a vector with the number of ICU cases for each region, or an + * error if the function fails. + */ +IOResult> compute_divi_data(const std::vector& divi_data, const std::vector& vregion, Date date); + +/** + * @brief Reads DIVI data from a file and computes the ICU data for specified regions and date. + * + * @param[in] path Path to the file containing DIVI data. + * @param[in] vregion Vector of region IDs for which the data is computed. + * @param[in] date Date for which the ICU data is computed. + * @return An IOResult containing a vector with the number of ICU cases for each region, or an + * error if the function fails. + */ +IOResult> read_divi_data(const std::string& path, const std::vector& vregion, Date date); + +/** + * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. + * + * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) + * for each region, and sets these values in the model. The ICU cases are distributed across age groups + * using the transition probabilities from severe to critical. + * + * @tparam Model The type of the model used. * @tparam FP Floating point type (default: double). * - * @param[in] divi_data Vector of DIVI data entries containing date, region, and ICU information. + * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. + * @param[in] num_icu vector of icu data * @param[in] vregion Vector of region IDs for which the data is computed. * @param[in] date Date for which the ICU data is computed. - * @param[in, out] vnum_icu Output vector containing the number of ICU cases for each region. + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. * * @return An IOResult indicating success or failure. */ -template -IOResult compute_divi_data(const std::vector& divi_data, const std::vector& vregion, Date date, - std::vector& vnum_icu) +template +IOResult set_divi_data(std::vector& model, const std::vector& num_icu, const std::vector& vregion, + Date date, FP scaling_factor_icu) { - auto max_date_entry = std::max_element(divi_data.begin(), divi_data.end(), [](auto&& a, auto&& b) { - return a.date < b.date; - }); - if (max_date_entry == divi_data.end()) { - log_error("DIVI data is empty."); - return failure(StatusCode::InvalidValue, "DIVI data is empty."); - } - auto max_date = max_date_entry->date; - if (max_date < date) { - log_error("DIVI data does not contain the specified date."); - return failure(StatusCode::OutOfRange, "DIVI data does not contain the specified date."); + std::vector sum_mu_I_U(vregion.size(), 0); + std::vector> mu_I_U{model.size()}; + for (size_t region = 0; region < vregion.size(); region++) { + auto num_groups = model[region].parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + sum_mu_I_U[region] += model[region].parameters.template get>()[i] * + model[region].parameters.template get>()[i]; + mu_I_U[region].push_back(model[region].parameters.template get>()[i] * + model[region].parameters.template get>()[i]); + } } - for (auto&& entry : divi_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { - return r == 0 || r == get_region_id(entry); - }); - auto date_df = entry.date; - if (it != vregion.end() && date_df == date) { - auto region_idx = size_t(it - vregion.begin()); - vnum_icu[region_idx] = entry.num_icu; + for (size_t region = 0; region < vregion.size(); region++) { + auto num_groups = model[region].parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + model[region].populations[{i, InfectionState::InfectedCriticalNaive}] = + scaling_factor_icu * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region]; } } @@ -95,23 +119,27 @@ IOResult compute_divi_data(const std::vector& divi_data, const } /** - * @brief Reads DIVI data from a file and computes the ICU data for specified regions and date. - * - * @tparam FP Floating point type (default: double). - * - * @param[in] path Path to the file containing DIVI data. - * @param[in] vregion Vector of region IDs for which the data is computed. - * @param[in] date Date for which the ICU data is computed. - * @param[in, out] vnum_icu Output vector containing the number of ICU cases for each region. - * - * @return An IOResult indicating success or failure. + * @brief sets populations data from DIVI register into Model + * @param[in, out] model vector of objects in which the data is set + * @param[in] path Path to transformed DIVI file + * @param[in] vregion vector of keys of the regions of interest + * @param[in] date Date for which the arrays are initialized + * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data */ -template -IOResult read_divi_data(const std::string& path, const std::vector& vregion, Date date, - std::vector& vnum_icu) +template +IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, + Date date, double scaling_factor_icu) { - BOOST_OUTCOME_TRY(auto&& divi_data, mio::read_divi_data(path)); - return compute_divi_data(divi_data, vregion, date, vnum_icu); + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + BOOST_OUTCOME_TRY(set_divi_data(model, num_icu, rki_data, vregion, date, scaling_factor_icu)); + return success(); } /** diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 0505d45563..057d2511a2 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -220,22 +220,16 @@ IOResult set_confirmed_cases_data(std::vector>& model, const std * @brief Sets populations data from DIVI register into Model. * @tparam FP floating point data type, e.g., double. * @param[in, out] model Vector of models in which the data is set. - * @param[in] path Path to DIVI file. + * @param[in] num_icu vector of icu data * @param[in] vregion Vector of keys of the regions of interest. * @param[in] date Date for which the arrays are initialized. * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data. */ template -IOResult set_divi_data(std::vector>& model, const std::string& path, const std::vector& vregion, +IOResult set_divi_data(std::vector>& model, const std::vector& num_icu, const std::vector& vregion, Date date, double scaling_factor_icu) { - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); - } + std::vector sum_mu_I_U(vregion.size(), 0); std::vector> mu_I_U{model.size()}; for (size_t region = 0; region < vregion.size(); region++) { @@ -247,8 +241,6 @@ IOResult set_divi_data(std::vector>& model, const std::string& p model[region].parameters.template get>()[i]); } } - std::vector num_icu(model.size(), 0.0); - BOOST_OUTCOME_TRY(read_divi_data(path, vregion, date, num_icu)); for (size_t region = 0; region < vregion.size(); region++) { auto num_groups = model[region].parameters.get_num_groups(); @@ -261,6 +253,30 @@ IOResult set_divi_data(std::vector>& model, const std::string& p return success(); } +/** + * @brief sets populations data from DIVI register into Model + * @param[in, out] model vector of objects in which the data is set + * @param[in] path Path to transformed DIVI file + * @param[in] vregion vector of keys of the regions of interest + * @param[in] date Date for which the arrays are initialized + * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + */ +template +IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, + Date date, double scaling_factor_icu) +{ + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + BOOST_OUTCOME_TRY(set_divi_data(model, num_icu, rki_data, vregion, date, scaling_factor_icu)); + return success(); +} + /** * @brief Sets population data from census data which has been read into num_population. * @tparam FP floating point data type, e.g., double. @@ -324,63 +340,81 @@ IOResult set_population_data(std::vector>& model, const std::str * Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. * @param[in] models Vector of models in which the data is set. Copy is made to avoid changing the original model. * @param[in] results_dir Path to result files. -* @param[in] region Vector of keys of the region of interest. * @param[in] date Date for which the data should be read. +* @param[in] counties Vector of keys of the counties of interest. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. * @param[in] num_days Number of days to be simulated/initialized. -* @param[in] divi_data_path Path to DIVI file. -* @param[in] confirmed_cases_path Path to confirmed cases file. -* @param[in] population_data_path Path to population data file. +* @param[in] pydata_dir Directory that contains the data files. */ template IOResult export_input_data_county_timeseries( - std::vector models, const std::string& results_dir, std::vector const& region, Date date, + std::vector models, const std::string& results_dir, Date date, const std::vector& counties, const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, - const std::string& divi_data_path, const std::string& confirmed_cases_path, const std::string& population_data_path) + const std::string& pydata_dir) { const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); // allow scalar scaling factor as convenience for 1-group models assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); - assert(models.size() == region.size()); + assert(models.size() == counties.size()); std::vector> extrapolated_data( - region.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); - - BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(population_data_path, region)); - BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(confirmed_cases_path)); + counties.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); - BOOST_OUTCOME_TRY(details::set_divi_data(models, divi_data_path, region, offset_day, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(models, case_data, region, offset_day, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(models, num_population, region)); - for (size_t r = 0; r < region.size(); r++) { + BOOST_OUTCOME_TRY(read_input_data_county(model, date, county, scaling_factor_inf, scaling_factor_icu, + pydata_dir, num_days)); + + for (size_t r = 0; r < counties.size(); r++) { extrapolated_data[r][t] = models[r].get_initial_values(); } } - BOOST_OUTCOME_TRY( - save_result(extrapolated_data, region, (int)num_age_groups, path_join(results_dir, "Results_rki.h5"))); + BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_age_groups), + path_join(results_dir, "Results_rki.h5"))); - auto rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); - BOOST_OUTCOME_TRY( - save_result({rki_data_sum[0][0]}, {0}, (int)num_age_groups, path_join(results_dir, "Results_rki_sum.h5"))); + auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); + BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), + path_join(results_dir, "Results_rki_sum.h5"))); return success(); } #else template -IOResult export_input_data_county_timeseries( - std::vector models, const std::string& results_dir, std::vector const& region, Date date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, - const std::string& divi_data_path, const std::string& confirmed_cases_path, const std::string& population_data_path) +IOResult export_input_data_county_timeseries(std::vector, const std::string&, Date, const std::vector&, + const std::vector&, const double, const int, + const std::string&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); return success(); } #endif // MEMILIO_HAS_HDF5 +/** + * @brief reads population data from population files for the specified nodes + * @param[in, out] model vector of model in which the data is set + * @param[in] date Date for which the data should be read + * @param[in] county vector of region keys of interest + * @param[in] scaling_factor_inf factors by which to scale the confirmed cases of rki data + * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + * @param[in] pydata_dir directory of files + * @param[in] age_group_names strings specifying age group names + */ +template +IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, + const std::vector& scaling_factor_inf, double scaling_factor_icu, + const std::string& pydata_dir, const std::string& divi_data_file_name, + const std::string& confirmed_cases_data_file_name, const std::string& population_data_file_name) +{ + BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, divi_data_file_name), node_ids, date, + scaling_factor_icu)); + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, + date, scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, population_data_file_name), node_ids)); + return success(); +} + /** * @brief Reads population data from population files for the whole country. * @param[in, out] model Vector of model in which the data is set. @@ -394,12 +428,8 @@ IOResult read_input_data_germany(std::vector& model, Date date, const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_dir) { - BOOST_OUTCOME_TRY( - details::set_divi_data(model, path_join(pydata_dir, "germany_divi.json"), {0}, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "cases_all_age_ma7.json"), {0}, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY( - details::set_population_data(model, path_join(pydata_dir, "county_current_population.json"), {0})); + BOOST_OUTCOME_TRY(read_input_data(model, date, {0}, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, + "germany_divi_ma7.json", "cases_all_age_ma7.json", "county_current_population.json")); return success(); } @@ -417,13 +447,8 @@ IOResult read_input_data_state(std::vector& model, Date date, std:: const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_dir) { - - BOOST_OUTCOME_TRY( - details::set_divi_data(model, path_join(pydata_dir, "state_divi.json"), state, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "cases_all_state_age_ma7.json"), - state, date, scaling_factor_inf)); - BOOST_OUTCOME_TRY( - details::set_population_data(model, path_join(pydata_dir, "county_current_population.json"), state)); + BOOST_OUTCOME_TRY(read_input_data(model, date, state, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, + "state_divi_ma7.json", "cases_all_state_age_ma7.json", "county_current_population.json")); return success(); } @@ -435,67 +460,14 @@ IOResult read_input_data_state(std::vector& model, Date date, std:: * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. * @param[in] pydata_dir Directory of files. - * @param[in] num_days [Default: 0] Number of days to be simulated; required to extrapolate real data. - * @param[in] export_time_series [Default: false] If true, reads data for each day of simulation and writes it in the same directory as the input files. */ template IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days = 0, bool export_time_series = false) + const std::string& pydata_dir) { - BOOST_OUTCOME_TRY( - details::set_divi_data(model, path_join(pydata_dir, "county_divi_ma7.json"), county, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "cases_all_county_age_ma7.json"), - county, date, scaling_factor_inf)); - BOOST_OUTCOME_TRY( - details::set_population_data(model, path_join(pydata_dir, "county_current_population.json"), county)); - - if (export_time_series) { - // Use only if extrapolated real data is needed for comparison. EXPENSIVE ! - // Run time equals run time of the previous functions times the num_days ! - // (This only represents the vectorization of the previous function over all simulation days...) - log_warning("Exporting time series of extrapolated real data. This may take some minutes. " - "For simulation runs over the same time period, deactivate it."); - BOOST_OUTCOME_TRY(export_input_data_county_timeseries( - model, pydata_dir, county, date, scaling_factor_inf, scaling_factor_icu, num_days, - path_join(pydata_dir, "county_divi_ma7.json"), path_join(pydata_dir, "cases_all_county_age_ma7.json"), - path_join(pydata_dir, "county_current_population.json"))); - } - return success(); -} - -/** - * @brief reads population data from population files for the specified nodes - * @param[in, out] model vector of model in which the data is set - * @param[in] date Date for which the data should be read - * @param[in] county vector of region keys of interest - * @param[in] scaling_factor_inf factors by which to scale the confirmed cases of rki data - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data - * @param[in] pydata_dir directory of files - * @param[in] age_group_names strings specifying age group names - */ -template -IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days = 0, bool export_time_series = false) -{ - BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, "critical_cases.json"), node_ids, date, - scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "confirmed_cases.json"), node_ids, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, "population_data.json"), node_ids)); - - if (export_time_series) { - // Use only if extrapolated real data is needed for comparison. EXPENSIVE ! - // Run time equals run time of the previous functions times the num_days ! - // (This only represents the vectorization of the previous function over all simulation days...) - log_warning("Exporting time series of extrapolated real data. This may take some minutes. " - "For simulation runs over the same time period, deactivate it."); - BOOST_OUTCOME_TRY(export_input_data_county_timeseries( - model, pydata_dir, node_ids, date, scaling_factor_inf, scaling_factor_icu, num_days, - path_join(pydata_dir, "critical_cases.json"), path_join(pydata_dir, "confirmed_cases.json"), - path_join(pydata_dir, "population_data.json"))); - } + BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, + "county_divi_ma7.json", "cases_all_county_age_ma7.json", "county_current_population.json")); return success(); } diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index c86263e717..709a300b30 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -562,60 +562,6 @@ IOResult set_confirmed_cases_data(std::vector& model, const std::st return success(); } -/** - * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. - * - * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) - * for each region, and sets these values in the model. The ICU cases are distributed across age groups - * using the transition probabilities from severe to critical. - * - * @tparam Model The type of the model used. - * @tparam FP Floating point type (default: double). - * - * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. - * @param[in] path Path to the file containing DIVI data. - * @param[in] vregion Vector of region IDs for which the data is computed. - * @param[in] date Date for which the ICU data is computed. - * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. - * - * @return An IOResult indicating success or failure. - */ -template -IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, - Date date, FP scaling_factor_icu) -{ - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); - } - std::vector sum_mu_I_U(vregion.size(), 0); - std::vector> mu_I_U{model.size()}; - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - sum_mu_I_U[region] += model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]; - mu_I_U[region].push_back(model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]); - } - } - std::vector num_icu(model.size(), 0.0); - BOOST_OUTCOME_TRY(read_divi_data(path, vregion, date, num_icu)); - - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] = - scaling_factor_icu * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region]; - } - } - - return success(); -} - /** * @brief Sets the population data for the given models based on the provided population distribution and immunity levels. * @@ -900,74 +846,52 @@ IOResult set_vaccination_data(std::vector>& model, const std::st * * @param[in] models A vector of models for which the extrapolated data is set. * @param[in] results_dir Path to the directory where the extrapolated results will be saved in a h5 file. - * @param[in] counties A vector of region identifiers for which the time series will be exported. - * @param[in] date The starting date of the time series. + * @param[in] date Date for which the data should be read. + * @param[in] counties Vector of keys of the counties of interest. * @param[in] scaling_factor_inf A vector of scaling factors applied to confirmed cases. * @param[in] scaling_factor_icu A scaling factor applied to ICU cases. * @param[in] num_days The number of days for which will be extrapolated. - * @param[in] divi_data_path Path to the DIVI ICU data file. - * @param[in] confirmed_cases_path Path to the confirmed cases data file. - * @param[in] population_data_path Path to the population data file. + * @param[in] pydata_dir Directory that contains the data files. * @param[in] immunity_population A vector of vectors specifying immunity for each age group and immunity layer. - * @param[in] vaccination_data_path Path to the vaccination data file (optional). * * @return An IOResult indicating success or failure. */ template IOResult export_input_data_county_timeseries( - std::vector models, const std::string& results_dir, const std::vector& counties, Date date, + std::vector models, const std::string& results_dir, Date date, const std::vector& counties, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, - const std::string& divi_data_path, const std::string& confirmed_cases_path, const std::string& population_data_path, - const std::vector> immunity_population, const std::string& vaccination_data_path = "") + const std::string& pydata_dir, const std::vector> immunity_population) { - const auto num_groups = (size_t)models[0].parameters.get_num_groups(); - assert(scaling_factor_inf.size() == num_groups); - assert(num_groups == ConfirmedCasesDataEntry::age_group_names.size()); + const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); + assert(scaling_factor_inf.size() == num_age_groups); + assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); assert(models.size() == counties.size()); std::vector> extrapolated_data( - models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_groups)); - - BOOST_OUTCOME_TRY(auto&& case_data, read_confirmed_cases_data(confirmed_cases_path)); - BOOST_OUTCOME_TRY(auto&& population_data, read_population_data(population_data_path, counties)); - - // empty vector if set_vaccination_data is not set - std::vector vacc_data; - if (!vaccination_data_path.empty()) { - BOOST_OUTCOME_TRY(vacc_data, read_vaccination_data(vaccination_data_path)); - } + models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); - if (!vaccination_data_path.empty()) { - BOOST_OUTCOME_TRY(details::set_vaccination_data(models, vacc_data, offset_day, counties, num_days)); - } - - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(models, divi_data_path, counties, offset_day, scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(models, case_data, counties, offset_day, scaling_factor_inf, - immunity_population)); - - BOOST_OUTCOME_TRY(details::set_population_data(models, population_data, counties, immunity_population)); + // TODO: empty vaccination data path guard + BOOST_OUTCOME_TRY(read_input_data_county(model, date, county, scaling_factor_inf, scaling_factor_icu, + pydata_dir, num_days, immunity_population)); for (size_t r = 0; r < counties.size(); r++) { extrapolated_data[r][t] = models[r].get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. - for (size_t age = 0; age < num_groups; age++) { + for (size_t age = 0; age < num_age_groups; age++) { extrapolated_data[r][t][(size_t)InfectionState::SusceptibleImprovedImmunity + age * (size_t)InfectionState::Count] += extrapolated_data[r][t][(size_t)InfectionState::DeadNaive + age * (size_t)InfectionState::Count]; } } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_groups), + BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); - BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_groups), + BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), path_join(results_dir, "Results_rki_sum.h5"))); return success(); @@ -975,10 +899,9 @@ IOResult export_input_data_county_timeseries( #else template -IOResult export_input_data_county_timeseries(std::vector, const std::string&, const std::vector&, - Date, const std::vector&, const double, const int, - const std::string&, const std::string&, const std::string&, - const std::vector>, const std::string&) +IOResult export_input_data_county_timeseries(std::vector, const std::string&, Date, const std::vector&, + const std::vector&, const double, const int, + const std::string&, const std::vector>) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); return success(); @@ -986,63 +909,6 @@ IOResult export_input_data_county_timeseries(std::vector, const std #endif //MEMILIO_HAS_HDF5 -/** - * @brief Reads input data for specified counties and initializes the model accordingly. - * - * This function loads real-world data for specified counties and initializes - * the corresponding model compartments. Optionally, it can extrapolate real-world data - * using the export_input_data_county_timeseries function. - * - * @tparam Model The model type used. - * - * @param[in,out] model Vector of model objects that will be initialized with the input data. - * @param[in] date The starting date for the simulation. - * @param[in] county Vector of county IDs for which the data is read. - * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. - * @param[in] scaling_factor_icu Scaling factor for ICU data. - * @param[in] pydata_dir Path to the directory containing input data files. - * @param[in] num_days The number of days for which the simulation runs. - * @param[in] immunity_population Vector of vectors representing immunity proportions for each age group and immunity layer. - * @param[in] export_time_series Boolean flag indicating whether to export time series of extrapolated data (default: false). - * - * @return An IOResult indicating success or failure. - */ -template -IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days, - const std::vector> immunity_population, - bool export_time_series = false) -{ - BOOST_OUTCOME_TRY(details::set_vaccination_data(model, path_join(pydata_dir, "vacc_county_ageinf_ma7.json"), date, - county, num_days)); - - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY( - details::set_divi_data(model, path_join(pydata_dir, "county_divi_ma7.json"), county, date, scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "cases_all_county_age_ma7.json"), - county, date, scaling_factor_inf, immunity_population)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, "county_current_population.json"), - county, immunity_population)); - - if (export_time_series) { - // Use only if extrapolated real data is needed for comparison. EXPENSIVE ! - // Run time equals run time of the previous functions times the num_days ! - // (This only represents the vectorization of the previous function over all simulation days...) - log_info("Exporting time series of extrapolated real data. This may take some minutes. " - "For simulation runs over the same time period, deactivate it."); - BOOST_OUTCOME_TRY(export_input_data_county_timeseries( - model, pydata_dir, county, date, scaling_factor_inf, scaling_factor_icu, num_days, - path_join(pydata_dir, "county_divi_ma7.json"), path_join(pydata_dir, "cases_all_county_age_ma7.json"), - path_join(pydata_dir, "county_current_population.json"), immunity_population, - path_join(pydata_dir, "vacc_county_ageinf_ma7.json"))); - } - - return success(); -} - /** * @brief Reads compartments for geographic units at a specified date from data files. * @@ -1058,7 +924,6 @@ IOResult read_input_data_county(std::vector& model, Date date, cons * @param[in] pydata_dir Directory containing the input data files. * @param[in] num_days Number of days to simulate. * @param[in] immunity_population Matrix containing immunity proportions for each age group and immunity layer. - * @param[in] export_time_series Boolean flag indicating whether to export time series of extrapolated data (default: false). * * @return An IOResult indicating success or failure. */ @@ -1066,36 +931,54 @@ template IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_dir, int num_days, - const std::vector> immunity_population, - bool export_time_series = false) + const std::vector> immunity_population, + const std::string& vaccination_data_file_name, const std::string& divi_data_file_name, + const std::string& confirmed_cases_data_file_name, const std::string& population_data_file_name) { BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, path_join(pydata_dir, "vaccination_data.json"), date, node_ids, num_days)); + details::set_vaccination_data(model, path_join(pydata_dir, vaccination_data_file_name), date, node_ids, num_days)); // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, "critical_cases.json"), node_ids, date, + BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, divi_data_file_name), node_ids, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "confirmed_cases.json"), node_ids, + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, date, scaling_factor_inf, immunity_population)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, "population_data.json"), node_ids, + BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, population_data_file_name), node_ids, immunity_population)); + return success(); +} - if (export_time_series) { - // Use only if extrapolated real data is needed for comparison. EXPENSIVE ! - // Run time equals run time of the previous functions times the num_days ! - // (This only represents the vectorization of the previous function over all simulation days...) - log_info("Exporting time series of extrapolated real data. This may take some minutes. " - "For simulation runs over the same time period, deactivate it."); - BOOST_OUTCOME_TRY(export_input_data_county_timeseries( - model, pydata_dir, node_ids, date, scaling_factor_inf, scaling_factor_icu, num_days, - path_join(pydata_dir, "critical_cases.json"), path_join(pydata_dir, "confirmed_cases.json"), - path_join(pydata_dir, "population_data.json"), immunity_population, - path_join(pydata_dir, "vaccination_data.json"))); - } - +/** + * @brief Reads input data for specified counties and initializes the model accordingly. + * + * This function loads real-world data for specified counties and initializes + * the corresponding model compartments. Optionally, it can extrapolate real-world data + * using the export_input_data_county_timeseries function. + * + * @tparam Model The model type used. + * + * @param[in,out] model Vector of model objects that will be initialized with the input data. + * @param[in] date The starting date for the simulation. + * @param[in] county Vector of county IDs for which the data is read. + * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. + * @param[in] scaling_factor_icu Scaling factor for ICU data. + * @param[in] pydata_dir Path to the directory containing input data files. + * @param[in] num_days The number of days for which the simulation runs. + * @param[in] immunity_population Vector of vectors representing immunity proportions for each age group and immunity layer. + * + * @return An IOResult indicating success or failure. + */ +template +IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, + const std::vector& scaling_factor_inf, double scaling_factor_icu, + const std::string& pydata_dir, int num_days, + const std::vector> immunity_population) +{ + BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, immunity_population, + "vacc_county_ageinf_ma7.json", "county_divi_ma7.json", "cases_all_county_age_ma7.json", "county_current_population.json")); return success(); } diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 3cd0a412c0..33cb71c462 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -423,50 +423,6 @@ IOResult set_confirmed_cases_data(std::vector& model, const std::st return success(); } -/** - * @brief sets populations data from DIVI register into Model - * @param[in, out] model vector of objects in which the data is set - * @param[in] path Path to transformed DIVI file - * @param[in] vregion vector of keys of the regions of interest - * @param[in] date Date for which the arrays are initialized - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data - */ -template -IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu) -{ - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); - } - std::vector sum_mu_I_U(vregion.size(), 0); - std::vector> mu_I_U{model.size()}; - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - sum_mu_I_U[region] += model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]; - mu_I_U[region].push_back(model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]); - } - } - std::vector num_icu(model.size(), 0.0); - BOOST_OUTCOME_TRY(read_divi_data(path, vregion, date, num_icu)); - - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] = - scaling_factor_icu * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region]; - } - } - - return success(); -} - /** * @brief sets population data from census data which has been read into num_population * @param[in, out] model vector of objects in which the data is set @@ -490,173 +446,174 @@ IOResult set_population_data(std::vector& model, const std::vector< if (std::accumulate(num_population[region].begin(), num_population[region].end(), double(0.0), [](const double& a, const double& b) { return evaluate_intermediate(a + b); - }) > 0) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - - double S_v = std::min( - model[region].parameters.template get>()[{i, SimulationDay(0)}] + - vnum_rec[region][size_t(i)], - num_population[region][size_t(i)]); - double S_pv = std::max( - model[region].parameters.template get>()[{i, SimulationDay(0)}] - - model[region].parameters.template get>()[{i, SimulationDay(0)}], - 0.0); // use std::max with 0 - double S; - if (num_population[region][size_t(i)] - S_pv - S_v < 0.0) { - log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", - region, size_t(i)); - S = 0.0; - S_v = num_population[region][size_t(i)] - S_pv; - } - else { - S = num_population[region][size_t(i)] - S_pv - S_v; - } + }) <= 0) + { + log_warning("No population data available for region " + std::to_string(region) + + ". Population data has not been set."); + continue; + } + + auto num_groups = model[region].parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { - double denom_E = - 1 / (S + S_pv * model[region].parameters.template get>()[i] + - S_v * model[region].parameters.template get>()[i]); - double denom_C = - 1 / (S + S_pv * model[region].parameters.template get>()[i] + - S_v * model[region].parameters.template get>()[i]); - double denom_I = - 1 / - (S + - S_pv * model[region].parameters.template get>()[i] + - S_v * model[region].parameters.template get>()[i]); - double denom_HU = - 1 / - (S + - S_pv * model[region] - .parameters.template get>()[i] + - S_v * model[region] - .parameters.template get>()[i]); - - model[region].populations[{i, InfectionState::ExposedNaive}] = - S * model[region].populations[{i, InfectionState::ExposedNaive}] * denom_E; - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] = - S_pv * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] * denom_E; - model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] = - S_v * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] * denom_E; - - model[region].populations[{i, InfectionState::InfectedNoSymptomsNaive}] = - S * model[region].populations[{i, InfectionState::InfectedNoSymptomsNaive}] * denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] = - S_pv * model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] * denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] = - S_v * model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] * denom_C; - - model[region].populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] = - S * model[region].populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] * denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = - S_pv * model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] * - denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = - S_v * model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] * - denom_C; - - model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] = - S * model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] = - S_pv * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] = - S_v * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] * denom_I; - - model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] = - S * model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = - S_pv * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = - S_v * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] * denom_I; - - model[region].populations[{i, InfectionState::InfectedSevereNaive}] = - S * model[region].populations[{i, InfectionState::InfectedSevereNaive}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] = - S_pv * - model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] = - S_v * - model[region] - .parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] * denom_HU; - - model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] = - S_pv * - model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] = - S_v * - model[region] - .parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] = - S * model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - - model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = - model[region].parameters.template get>()[{i, SimulationDay(0)}] + - model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] - - (model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] + - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSevereNaive}] + - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] + - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] + - model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + - model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + - model[region].populations[{i, InfectionState::DeadNaive}] + - model[region].populations[{i, InfectionState::DeadPartialImmunity}] + - model[region].populations[{i, InfectionState::DeadImprovedImmunity}]); - - model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::min( - S_v - model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - - model[region].populations[{i, InfectionState::DeadImprovedImmunity}], - std::max(0.0, double(model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); - - model[region].populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( - 0.0, - S_pv - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - - model[region].populations[{i, InfectionState::DeadPartialImmunity}]); - - model[region].populations.template set_difference_from_group_total( - {i, InfectionState::SusceptibleNaive}, num_population[region][size_t(i)]); + double S_v = std::min( + model[region].parameters.template get>()[{i, SimulationDay(0)}] + + vnum_rec[region][size_t(i)], + num_population[region][size_t(i)]); + double S_pv = std::max( + model[region].parameters.template get>()[{i, SimulationDay(0)}] - + model[region].parameters.template get>()[{i, SimulationDay(0)}], + 0.0); // use std::max with 0 + double S; + if (num_population[region][size_t(i)] - S_pv - S_v < 0.0) { + log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", + region, size_t(i)); + S = 0.0; + S_v = num_population[region][size_t(i)] - S_pv; + } + else { + S = num_population[region][size_t(i)] - S_pv - S_v; } - for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { - for (auto j = Index(0); j < InfectionState::Count; ++j) { - if (model[region].populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model[region].populations[{i, j}] / num_population[region][size_t(i)]); - } + double denom_E = + 1 / (S + S_pv * model[region].parameters.template get>()[i] + + S_v * model[region].parameters.template get>()[i]); + double denom_C = + 1 / (S + S_pv * model[region].parameters.template get>()[i] + + S_v * model[region].parameters.template get>()[i]); + double denom_I = + 1 / + (S + + S_pv * model[region].parameters.template get>()[i] + + S_v * model[region].parameters.template get>()[i]); + double denom_HU = + 1 / + (S + + S_pv * model[region] + .parameters.template get>()[i] + + S_v * model[region] + .parameters.template get>()[i]); + + model[region].populations[{i, InfectionState::ExposedNaive}] = + S * model[region].populations[{i, InfectionState::ExposedNaive}] * denom_E; + model[region].populations[{i, InfectionState::ExposedPartialImmunity}] = + S_pv * model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::ExposedPartialImmunity}] * denom_E; + model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] = + S_v * model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] * denom_E; + + model[region].populations[{i, InfectionState::InfectedNoSymptomsNaive}] = + S * model[region].populations[{i, InfectionState::InfectedNoSymptomsNaive}] * denom_C; + model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] = + S_pv * model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] * denom_C; + model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] = + S_v * model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] * denom_C; + + model[region].populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] = + S * model[region].populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] * denom_C; + model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = + S_pv * model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] * + denom_C; + model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = + S_v * model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] * + denom_C; + + model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] = + S * model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] * denom_I; + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] = + S_pv * model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] * denom_I; + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] = + S_v * model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] * denom_I; + + model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] = + S * model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] * denom_I; + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = + S_pv * model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] * denom_I; + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = + S_v * model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] * denom_I; + + model[region].populations[{i, InfectionState::InfectedSevereNaive}] = + S * model[region].populations[{i, InfectionState::InfectedSevereNaive}] * denom_HU; + model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] = + S_pv * + model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] * denom_HU; + model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] = + S_v * + model[region] + .parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] * denom_HU; + + model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] = + S_pv * + model[region].parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] = + S_v * + model[region] + .parameters.template get>()[i] * + model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + model[region].populations[{i, InfectionState::InfectedCriticalNaive}] = + S * model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + + model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = + model[region].parameters.template get>()[{i, SimulationDay(0)}] + + model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] - + (model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] + + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + + model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + + model[region].populations[{i, InfectionState::InfectedSevereNaive}] + + model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] + + model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + + model[region].populations[{i, InfectionState::InfectedCriticalNaive}] + + model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + + model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + + model[region].populations[{i, InfectionState::DeadNaive}] + + model[region].populations[{i, InfectionState::DeadPartialImmunity}] + + model[region].populations[{i, InfectionState::DeadImprovedImmunity}]); + + model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::min( + S_v - model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] - + model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - + model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - + model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - + model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - + model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - + model[region].populations[{i, InfectionState::DeadImprovedImmunity}], + std::max(0.0, double(model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); + + model[region].populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( + 0.0, + S_pv - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] - + model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - + model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - + model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - + model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] - + model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - + model[region].populations[{i, InfectionState::DeadPartialImmunity}]); + + model[region].populations.template set_difference_from_group_total( + {i, InfectionState::SusceptibleNaive}, num_population[region][size_t(i)]); + } + + for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { + for (auto j = Index(0); j < InfectionState::Count; ++j) { + if (model[region].populations[{i, j}] < 0) { + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), + size_t(j), model[region].populations[{i, j}] / num_population[region][size_t(i)]); } } } - else { - log_warning("No population data available for region " + std::to_string(region) + - ". Population data has not been set."); - } } return success(); @@ -880,79 +837,57 @@ IOResult set_vaccination_data(std::vector>& model, const std::st * Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. * @param[in] models Vector of models in which the data is set. Copy is made to avoid changing the original model. * @param[in] results_dir Path to result files. -* @param[in] counties Vector of keys of the counties of interest. * @param[in] date Date for which the data should be read. +* @param[in] counties Vector of keys of the counties of interest. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. * @param[in] num_days Number of days to be simulated/initialized. -* @param[in] divi_data_path Path to DIVI file. -* @param[in] confirmed_cases_path Path to confirmed cases file. -* @param[in] population_data_path Path to population data file. -* @param[in] vaccination_data_path Path to vaccination data file. +* @param[in] pydata_dir Directory that contains the data files. */ template IOResult export_input_data_county_timeseries( - std::vector models, const std::string& results_dir, const std::vector& counties, Date date, + std::vector models, const std::string& results_dir, Date date, const std::vector& counties, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, - const std::string& divi_data_path, const std::string& confirmed_cases_path, const std::string& population_data_path, - const std::string& vaccination_data_path = "") + const std::string& pydata_dir) { - const auto num_groups = (size_t)models[0].parameters.get_num_groups(); - assert(scaling_factor_inf.size() == num_groups); - assert(num_groups == ConfirmedCasesDataEntry::age_group_names.size()); + const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); + assert(scaling_factor_inf.size() == num_age_groups); + assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); assert(models.size() == counties.size()); std::vector> extrapolated_data( - models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_groups)); - - BOOST_OUTCOME_TRY(auto&& case_data, read_confirmed_cases_data(confirmed_cases_path)); - BOOST_OUTCOME_TRY(auto&& population_data, read_population_data(population_data_path, counties)); - - // empty vector if set_vaccination_data is not set - std::vector vacc_data; - if (!vaccination_data_path.empty()) { - BOOST_OUTCOME_TRY(vacc_data, read_vaccination_data(vaccination_data_path)); - } + models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); - if (!vaccination_data_path.empty()) { - BOOST_OUTCOME_TRY(details::set_vaccination_data(models, vacc_data, offset_day, counties, num_days)); - } - - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(models, divi_data_path, counties, offset_day, scaling_factor_icu)); - - BOOST_OUTCOME_TRY( - details::set_confirmed_cases_data(models, case_data, counties, offset_day, scaling_factor_inf, true)); - BOOST_OUTCOME_TRY(details::set_population_data(models, population_data, case_data, counties, offset_day)); + // TODO: empty vaccination data path guard + BOOST_OUTCOME_TRY(read_input_data_county(model, date, county, scaling_factor_inf, scaling_factor_icu, + pydata_dir, num_days)); for (size_t r = 0; r < counties.size(); r++) { extrapolated_data[r][t] = models[r].get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. - for (size_t age = 0; age < num_groups; age++) { + for (size_t age = 0; age < num_age_groups; age++) { extrapolated_data[r][t][(size_t)InfectionState::SusceptibleImprovedImmunity + age * (size_t)InfectionState::Count] += extrapolated_data[r][t][(size_t)InfectionState::DeadNaive + age * (size_t)InfectionState::Count]; } } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_groups), + BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); - BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_groups), + BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), path_join(results_dir, "Results_rki_sum.h5"))); return success(); } #else template -IOResult export_input_data_county_timeseries(std::vector, const std::string&, const std::vector&, - Date, const std::vector&, const double, const int, - const std::string&, const std::string&, const std::string&, +IOResult export_input_data_county_timeseries(std::vector, const std::string&, Date, const std::vector&, + const std::vector&, const double, const int, const std::string&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); @@ -968,44 +903,32 @@ IOResult export_input_data_county_timeseries(std::vector, const std * Uses data files that contain centered 7-day moving average. * @param[in, out] model Vector of SECIRVVS models, one per county. * @param[in] date Date for which the data should be read. - * @param[in] county Ids of the counties. + * @param[in] node_ids Ids of the nodes. * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. * @param[in] pydata_dir Directory that contains the data files. * @param[in] num_days Number of days to be simulated; required to load data for vaccinations during the simulation. - * @param[in] export_time_series If true, reads data for each day of simulation and writes it in the same directory as the input files. */ template -IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days, bool export_time_series = false) +IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, + const std::vector& scaling_factor_inf, double scaling_factor_icu, + const std::string& pydata_dir, int num_days, const std::string& vaccination_data_file_name, + const std::string& divi_data_file_name, const std::string& confirmed_cases_data_file_name, + const std::string& population_data_file_name) { - BOOST_OUTCOME_TRY(details::set_vaccination_data(model, path_join(pydata_dir, "vacc_county_ageinf_ma7.json"), date, - county, num_days)); + + BOOST_OUTCOME_TRY( + details::set_vaccination_data(model, path_join(pydata_dir, vaccination_data_file_name), date, node_ids, num_days)); // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY( - details::set_divi_data(model, path_join(pydata_dir, "county_divi_ma7.json"), county, date, scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "cases_all_county_age_ma7.json"), - county, date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, "county_current_population.json"), - path_join(pydata_dir, "cases_all_county_age_ma7.json"), county, - date)); - - if (export_time_series) { - // Use only if extrapolated real data is needed for comparison. EXPENSIVE ! - // Run time equals run time of the previous functions times the num_days ! - // (This only represents the vectorization of the previous function over all simulation days...) - log_warning("Exporting time series of extrapolated real data. This may take some minutes. " - "For simulation runs over the same time period, deactivate it."); - BOOST_OUTCOME_TRY(export_input_data_county_timeseries( - model, pydata_dir, county, date, scaling_factor_inf, scaling_factor_icu, num_days, - path_join(pydata_dir, "county_divi_ma7.json"), path_join(pydata_dir, "cases_all_county_age_ma7.json"), - path_join(pydata_dir, "county_current_population.json"), - path_join(pydata_dir, "vacc_county_ageinf_ma7.json"))); - } + BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, divi_data_file_name), node_ids, date, + scaling_factor_icu)); + + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, + date, scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, population_data_file_name), + path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, date)); return success(); } @@ -1017,44 +940,19 @@ IOResult read_input_data_county(std::vector& model, Date date, cons * Uses data files that contain centered 7-day moving average. * @param[in, out] model Vector of SECIRVVS models, one per county. * @param[in] date Date for which the data should be read. - * @param[in] node_ids Ids of the nodes. + * @param[in] county Ids of the counties. * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. * @param[in] pydata_dir Directory that contains the data files. - * @param[in] num_days Number of days to be simulated; required to load data for vaccinations during the simulation. - * @param[in] export_time_series If true, reads data for each day of simulation and writes it in the same directory as the input files. */ template -IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days, bool export_time_series = false) +IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, + const std::vector& scaling_factor_inf, double scaling_factor_icu, + const std::string& pydata_dir, int num_days) { - - BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, path_join(pydata_dir, "vaccination_data.json"), date, node_ids, num_days)); - - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, "critical_cases.json"), node_ids, date, - scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "confirmed_cases.json"), node_ids, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, "population_data.json"), - path_join(pydata_dir, "confirmed_cases.json"), node_ids, date)); - - if (export_time_series) { - // Use only if extrapolated real data is needed for comparison. EXPENSIVE ! - // Run time equals run time of the previous functions times the num_days ! - // (This only represents the vectorization of the previous function over all simulation days...) - log_warning("Exporting time series of extrapolated real data. This may take some minutes. " - "For simulation runs over the same time period, deactivate it."); - BOOST_OUTCOME_TRY(export_input_data_county_timeseries( - model, pydata_dir, node_ids, date, scaling_factor_inf, scaling_factor_icu, num_days, - path_join(pydata_dir, "divi_data.json"), path_join(pydata_dir, "confirmed_cases.json"), - path_join(pydata_dir, "population_data.json"), path_join(pydata_dir, "vaccination_data.json"))); - } - + BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, + "vacc_county_ageinf_ma7.json", "county_divi_ma7.json", "cases_all_county_age_ma7.json", + "county_current_population.json")); return success(); } From 664689fb2ff757e5e0a6c5812f1efcce8ace2fbc Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 21 Oct 2025 12:54:11 +0000 Subject: [PATCH 02/26] data setter redesign --- cpp/memilio/geography/regions.h | 52 + cpp/memilio/io/parameters_io.h | 6 +- cpp/memilio/mobility/graph.h | 143 ++- cpp/memilio/utils/stl_util.h | 6 + cpp/models/ode_secir/parameters_io.cpp | 215 ++-- cpp/models/ode_secir/parameters_io.h | 461 ++++---- cpp/models/ode_secirts/parameters_io.h | 1121 +++++++++---------- cpp/models/ode_secirvvs/parameters_io.cpp | 226 ++-- cpp/models/ode_secirvvs/parameters_io.h | 1213 ++++++++++----------- 9 files changed, 1598 insertions(+), 1845 deletions(-) diff --git a/cpp/memilio/geography/regions.h b/cpp/memilio/geography/regions.h index 6901d15f22..dca434113f 100644 --- a/cpp/memilio/geography/regions.h +++ b/cpp/memilio/geography/regions.h @@ -103,7 +103,59 @@ get_holidays(StateId state); Range>::const_iterator, std::vector>::const_iterator>> get_holidays(StateId state, Date start_date, Date end_date); +namespace de +{ + struct EpidataFilenames + { + private: + + EpidataFilenames(std::string& pydata) : + population_data_path(mio::path_join(pydata, "county_current_population.json")) + { + } + + static EpidataFilenames county(std::string& pydata) + { + EpidataFilenames s(pydata); + + s.case_data_path = mio::path_join(pydata, "cases_all_county_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "county_divi_ma7.json"); + s.vaccination_data_path = mio::path_join(pydata, "vacc_county_ageinf_ma7.json"); + + return s; + } + + static EpidataFilenames states(std::string& pydata) + { + EpidataFilenames s(pydata); + + s.case_data_path = mio::path_join(pydata, "cases_all_state_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "state_divi_ma7.json"); + s.vaccination_data_path = mio::path_join(pydata, "vacc_state_ageinf_ma7.json"); + + return s; + } + + static EpidataFilenames country(std::string& pydata) + { + EpidataFilenames s(pydata); + + s.case_data_path = mio::path_join(pydata, "cases_all_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "germany_divi_ma7.json"); + s.vaccination_data_path = mio::path_join(pydata, "vacc_ageinf_ma7.json"); + + return s; + } + + std::string population_data_path; + std::string case_data_path; + std::string divi_data_path; + std::string vaccination_data_path; + }; +} // namespace de + } // namespace regions + } // namespace mio #endif //MIO_EPI_REGIONS_H diff --git a/cpp/memilio/io/parameters_io.h b/cpp/memilio/io/parameters_io.h index 52125c1f57..3d8ebbc279 100644 --- a/cpp/memilio/io/parameters_io.h +++ b/cpp/memilio/io/parameters_io.h @@ -92,7 +92,7 @@ IOResult> read_divi_data(const std::string& path, const * @return An IOResult indicating success or failure. */ template -IOResult set_divi_data(std::vector& model, const std::vector& num_icu, const std::vector& vregion, +IOResult set_divi_data(mio::VectorRange& model, const std::vector& num_icu, const std::vector& vregion, Date date, FP scaling_factor_icu) { std::vector sum_mu_I_U(vregion.size(), 0); @@ -127,7 +127,7 @@ IOResult set_divi_data(std::vector& model, const std::vector -IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, +IOResult set_divi_data(mio::VectorRange& model, const std::string& path, const std::vector& vregion, Date date, double scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. @@ -138,7 +138,7 @@ IOResult set_divi_data(std::vector& model, const std::string& path, return success(); } BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - BOOST_OUTCOME_TRY(set_divi_data(model, num_icu, rki_data, vregion, date, scaling_factor_icu)); + BOOST_OUTCOME_TRY(set_divi_data(model, num_icu, vregion, date, scaling_factor_icu)); return success(); } diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index 26a8bb5a6a..5dc1493bf8 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -152,6 +152,21 @@ class Graph using NodeProperty = NodePropertyT; using EdgeProperty = EdgePropertyT; + Graph(std::vector nodes, std::vector edges) + : m_nodes(nodes) + , m_edges(edges) + { + } + + template + Graph(std::vector& node_ids, Args&&... args) + { + for (int id : node_ids) { + add_node(id, std::forward(args)...); + } + } + + /** * @brief add a node to the graph. property of the node is constructed from arguments. */ @@ -240,6 +255,75 @@ class Graph std::vector> m_edges; }; // namespace mio +template +void set_german_holidays(Model& node, const int node_id, + const mio::Date& start_date, const mio::Date& end_date) +{ + auto state_id = regions::get_state_id(node_id); + auto holiday_periods = regions::get_holidays(state_id, start_date, end_date); + + auto& contacts = node.parameters.template get(); + contacts.get_school_holidays() = + std::vector, mio::SimulationTime>>(holiday_periods.size()); + std::transform( + holiday_periods.begin(), holiday_periods.end(), contacts.get_school_holidays().begin(), [=](auto& period) { + return std::make_pair(mio::SimulationTime(mio::get_offset_in_days(period.first, start_date)), + mio::SimulationTime(mio::get_offset_in_days(period.second, start_date))); + }); +} + +/** + * @brief Sets the graph nodes for counties or districts. + * Reads the node ids which could refer to districts or counties and the epidemiological + * data from json files and creates one node for each id. Every node contains a model. + * @param[in] params Model Parameters that are used for every node. + * @param[in] start_date Start date for which the data should be read. + * @param[in] end_data End date for which the data should be read. + * @param[in] data_dir Directory that contains the data files. + * @param[in, out] params_graph Graph whose nodes are set by the function. + * @param[in] read_func Function that reads input data for german counties and sets Model compartments. + * @param[in] node_func Function that returns the county ids. + * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. + * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. + * @param[in] tnt_capacity_factor Factor for test and trace capacity. + */ +template +IOResult set_nodes(const Parameters& params, Date start_date, Date end_date, const fs::path& data_dir, + Graph& params_graph, ReadFunction&& read_func, + const std::vector& node_ids, const std::vector& scaling_factor_inf, FP scaling_factor_icu, + bool add_uncertainty_to_population = true) + +{ + std::vector nodes(node_ids.size(), Model(int(size_t(params.get_num_groups())))); + for (auto& node : nodes) { + node.parameters = params; + } + + BOOST_OUTCOME_TRY(read_func(nodes, start_date, node_ids, scaling_factor_inf, scaling_factor_icu, data_dir.string())); + + for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { + + set_german_holidays(nodes[node_idx], node_ids[node_idx], start_date, end_date); + if (add_uncertainty_to_population) + { + //uncertainty in populations + for (auto i = mio::AgeGroup(0); i < params.get_num_groups(); i++) { + for (auto j = Index(0); j < Model::Compartments::Count; ++j) { + auto& compartment_value = nodes[node_idx].populations[{i, j}]; + compartment_value = + UncertainValue(compartment_value.value()); + compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), + 1.1 * compartment_value.value())); + } + } + } + + params_graph.add_node(node_ids[node_idx], nodes[node_idx]); + } + return success(); +} + /** * @brief Sets the graph nodes for counties or districts. * Reads the node ids which could refer to districts or counties and the epidemiological @@ -248,72 +332,49 @@ class Graph * @param[in] start_date Start date for which the data should be read. * @param[in] end_data End date for which the data should be read. * @param[in] data_dir Directory that contains the data files. - * @param[in] population_data_path Path to json file containing the population data. - * @param[in] is_node_for_county Specifies whether the node ids should be county ids (true) or district ids (false). * @param[in, out] params_graph Graph whose nodes are set by the function. * @param[in] read_func Function that reads input data for german counties and sets Model compartments. * @param[in] node_func Function that returns the county ids. * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. * @param[in] tnt_capacity_factor Factor for test and trace capacity. - * @param[in] num_days Number of days to be simulated; required to load data for vaccinations during the simulation. - * @param[in] export_time_series If true, reads data for each day of simulation and writes it in the same directory as the input files. - * @param[in] rki_age_groups Specifies whether rki-age_groups should be used. */ template + class ReadFunction> IOResult set_nodes(const Parameters& params, Date start_date, Date end_date, const fs::path& data_dir, - const std::string& population_data_path, bool is_node_for_county, Graph& params_graph, ReadFunction&& read_func, - NodeIdFunction&& node_func, const std::vector& scaling_factor_inf, FP scaling_factor_icu, - FP tnt_capacity_factor, int num_days = 0, bool export_time_series = false, - bool rki_age_groups = true) + const std::vector& node_ids, const std::vector& scaling_factor_inf, FP scaling_factor_icu, + FP tnt_capacity_factor, bool add_uncertainty_to_population = true) { - BOOST_OUTCOME_TRY(auto&& node_ids, node_func(population_data_path, is_node_for_county, rki_age_groups)); std::vector nodes(node_ids.size(), Model(int(size_t(params.get_num_groups())))); for (auto& node : nodes) { node.parameters = params; } - BOOST_OUTCOME_TRY(read_func(nodes, start_date, node_ids, scaling_factor_inf, scaling_factor_icu, data_dir.string(), - num_days, export_time_series)); + BOOST_OUTCOME_TRY(read_func(nodes, start_date, node_ids, scaling_factor_inf, scaling_factor_icu, data_dir.string())); for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { auto tnt_capacity = nodes[node_idx].populations.get_total() * tnt_capacity_factor; - //local parameters + // local parameters auto& tnt_value = nodes[node_idx].parameters.template get(); - tnt_value = UncertainValue(0.5 * (1.2 * tnt_capacity + 0.8 * tnt_capacity)); + tnt_value = UncertainValue(tnt_capacity); tnt_value.set_distribution(mio::ParameterDistributionUniform(0.8 * tnt_capacity, 1.2 * tnt_capacity)); - auto id = 0; - if (is_node_for_county) { - id = int(regions::CountyId(node_ids[node_idx])); - } - else { - id = int(regions::DistrictId(node_ids[node_idx])); - } - //holiday periods - auto holiday_periods = regions::get_holidays(regions::get_state_id(id), start_date, end_date); - auto& contacts = nodes[node_idx].parameters.template get(); - contacts.get_school_holidays() = - std::vector, mio::SimulationTime>>(holiday_periods.size()); - std::transform( - holiday_periods.begin(), holiday_periods.end(), contacts.get_school_holidays().begin(), [=](auto& period) { - return std::make_pair(mio::SimulationTime(mio::get_offset_in_days(period.first, start_date)), - mio::SimulationTime(mio::get_offset_in_days(period.second, start_date))); - }); - - //uncertainty in populations - for (auto i = mio::AgeGroup(0); i < params.get_num_groups(); i++) { - for (auto j = Index(0); j < Model::Compartments::Count; ++j) { - auto& compartment_value = nodes[node_idx].populations[{i, j}]; - compartment_value = - UncertainValue(0.5 * (1.1 * compartment_value.value() + 0.9 * compartment_value.value())); - compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), - 1.1 * compartment_value.value())); + set_german_holidays(nodes[node_idx], node_ids[node_idx], start_date, end_date); + if (add_uncertainty_to_population) + { + //uncertainty in populations + for (auto i = mio::AgeGroup(0); i < params.get_num_groups(); i++) { + for (auto j = Index(0); j < Model::Compartments::Count; ++j) { + auto& compartment_value = nodes[node_idx].populations[{i, j}]; + compartment_value = + UncertainValue(compartment_value.value()); + compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), + 1.1 * compartment_value.value())); + } } } diff --git a/cpp/memilio/utils/stl_util.h b/cpp/memilio/utils/stl_util.h index f1deb46c04..67efd672cd 100644 --- a/cpp/memilio/utils/stl_util.h +++ b/cpp/memilio/utils/stl_util.h @@ -315,6 +315,12 @@ constexpr std::array enum_members() return enum_members; } +template +using VectorRange = mio::Range::iterator, typename std::vector::iterator>>; + +template +using ConstVectorRange = mio::Range::const_iterator, typename std::vector::const_iterator>>; + } // namespace mio #endif //STL_UTIL_H diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index 621efbf276..08a9841ef7 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -43,28 +43,23 @@ namespace osecir namespace details { -//overload for integers, so the comparison of data entry to integers is symmetric (required by e.g. equal_range) -int get_region_id(int id) -{ - return id; -} -IOResult read_confirmed_cases_data( - std::vector& rki_data, std::vector const& vregion, Date date, - std::vector>& vnum_Exposed, std::vector>& vnum_InfectedNoSymptoms, - std::vector>& vnum_InfectedSymptoms, std::vector>& vnum_InfectedSevere, - std::vector>& vnum_icu, std::vector>& vnum_death, - std::vector>& vnum_rec, const std::vector>& vt_Exposed, - const std::vector>& vt_InfectedNoSymptoms, - const std::vector>& vt_InfectedSymptoms, const std::vector>& vt_InfectedSevere, - const std::vector>& vt_InfectedCritical, const std::vector>& vmu_C_R, - const std::vector>& vmu_I_H, const std::vector>& vmu_H_U, +IOResult compute_confirmed_cases_data( + std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, + const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, const std::vector& scaling_factor_inf) { - auto max_date_entry = std::max_element(rki_data.begin(), rki_data.end(), [](auto&& a, auto&& b) { + auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; }); - if (max_date_entry == rki_data.end()) { + if (max_date_entry == case_data.end()) { log_error("RKI data file is empty."); return failure(StatusCode::InvalidFileFormat, "RKI file is empty."); } @@ -75,127 +70,81 @@ IOResult read_confirmed_cases_data( } auto days_surplus = std::min(get_offset_in_days(max_date, date) - 6, 0); - //this statement causes maybe-uninitialized warning for some versions of gcc. - //the error is reported in an included header, so the warning is disabled for the whole file - std::sort(rki_data.begin(), rki_data.end(), [](auto&& a, auto&& b) { - return std::make_tuple(get_region_id(a), a.date) < std::make_tuple(get_region_id(b), b.date); - }); - for (auto region_idx = size_t(0); region_idx < vregion.size(); ++region_idx) { - auto region_entry_range_it = - std::equal_range(rki_data.begin(), rki_data.end(), vregion[region_idx], [](auto&& a, auto&& b) { - return get_region_id(a) < get_region_id(b); - }); - auto region_entry_range = make_range(region_entry_range_it); - if (region_entry_range.begin() == region_entry_range.end()) { - log_error("No entries found for region {}", vregion[region_idx]); - return failure(StatusCode::InvalidFileFormat, - "No entries found for region " + std::to_string(vregion[region_idx])); + for (auto&& entry : case_data) { + + auto date_df = entry.date; + auto age = size_t(entry.age_group); + + if (date_df == offset_date_by_days(date, 0)) { + num_InfectedSymptoms[age] += scaling_factor_inf[age] * entry.num_confirmed; + // We intentionally do NOT multiply recovered with the scaling_factor_inf here. + // If we apply the scaling factor to recovered as well, we would implicitly + // assume that this factor holds for the entire historical period up to t0, which is not valid. + num_rec[age] += entry.num_confirmed; } - for (auto&& region_entry : region_entry_range) { - - auto& t_Exposed = vt_Exposed[region_idx]; - auto& t_InfectedNoSymptoms = vt_InfectedNoSymptoms[region_idx]; - auto& t_InfectedSymptoms = vt_InfectedSymptoms[region_idx]; - auto& t_InfectedSevere = vt_InfectedSevere[region_idx]; - auto& t_InfectedCritical = vt_InfectedCritical[region_idx]; - - auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx]; - auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx]; - auto& num_rec = vnum_rec[region_idx]; - auto& num_Exposed = vnum_Exposed[region_idx]; - auto& num_InfectedSevere = vnum_InfectedSevere[region_idx]; - auto& num_death = vnum_death[region_idx]; - auto& num_icu = vnum_icu[region_idx]; - - auto& mu_C_R = vmu_C_R[region_idx]; - auto& mu_I_H = vmu_I_H[region_idx]; - auto& mu_H_U = vmu_H_U[region_idx]; - - auto date_df = region_entry.date; - auto age = size_t(region_entry.age_group); - - if (date_df == offset_date_by_days(date, 0)) { - num_InfectedSymptoms[age] += scaling_factor_inf[age] * region_entry.num_confirmed; - // We intentionally do NOT multiply recovered with the scaling_factor_inf here. - // If we apply the scaling factor to recovered as well, we would implicitly - // assume that this factor holds for the entire historical period up to t0, which is not valid. - num_rec[age] += region_entry.num_confirmed; - } - if (date_df == offset_date_by_days(date, days_surplus)) { - num_InfectedNoSymptoms[age] -= - 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * region_entry.num_confirmed; - } - if (date_df == offset_date_by_days(date, t_InfectedNoSymptoms[age] + days_surplus)) { - num_InfectedNoSymptoms[age] += - 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * region_entry.num_confirmed; - num_Exposed[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * region_entry.num_confirmed; - } - if (date_df == offset_date_by_days(date, t_Exposed[age] + t_InfectedNoSymptoms[age] + days_surplus)) { - num_Exposed[age] += 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * region_entry.num_confirmed; - } - if (date_df == offset_date_by_days(date, -t_InfectedSymptoms[age])) { - num_InfectedSymptoms[age] -= scaling_factor_inf[age] * region_entry.num_confirmed; - num_InfectedSevere[age] += mu_I_H[age] * scaling_factor_inf[age] * region_entry.num_confirmed; - } - if (date_df == offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age])) { - num_InfectedSevere[age] -= mu_I_H[age] * scaling_factor_inf[age] * region_entry.num_confirmed; - num_icu[age] += mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * region_entry.num_confirmed; - } - if (date_df == - offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age] - t_InfectedCritical[age])) { - num_death[age] += region_entry.num_deaths; - num_icu[age] -= mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * region_entry.num_confirmed; - } + if (date_df == offset_date_by_days(date, days_surplus)) { + num_InfectedNoSymptoms[age] -= + 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (date_df == offset_date_by_days(date, t_InfectedNoSymptoms[age] + days_surplus)) { + num_InfectedNoSymptoms[age] += + 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + num_Exposed[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (date_df == offset_date_by_days(date, t_Exposed[age] + t_InfectedNoSymptoms[age] + days_surplus)) { + num_Exposed[age] += 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (date_df == offset_date_by_days(date, -t_InfectedSymptoms[age])) { + num_InfectedSymptoms[age] -= scaling_factor_inf[age] * entry.num_confirmed; + num_InfectedSevere[age] += mu_I_H[age] * scaling_factor_inf[age] * entry.num_confirmed; + } + if (date_df == offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age])) { + num_InfectedSevere[age] -= mu_I_H[age] * scaling_factor_inf[age] * entry.num_confirmed; + num_icu[age] += mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * entry.num_confirmed; + } + if (date_df == + offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age] - t_InfectedCritical[age])) { + num_death[age] += entry.num_deaths; + num_icu[age] -= mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * entry.num_confirmed; } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - auto region = vregion[region_idx]; - - auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx]; - auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx]; - auto& num_rec = vnum_rec[region_idx]; - auto& num_Exposed = vnum_Exposed[region_idx]; - auto& num_InfectedSevere = vnum_InfectedSevere[region_idx]; - auto& num_death = vnum_death[region_idx]; - auto& num_icu = vnum_icu[region_idx]; - - for (size_t i = 0; i < ConfirmedCasesDataEntry::age_group_names.size(); i++) { - // R(t0) = ΣC(t0) − I(t0) − H(t0) − U(t0) − D(t0) - // subtract currently infectious/hospitalized/ICU/dead - // Note: We divide I/H/U/D by scaling_factor_inf to "unscale" these contributions back to the - // reported level before subtracting from recovered. If we also applied the scaling factor to - // recovered, we would implicitly assume that the same underreporting applies to the entire - // history up to t0, which would be wrong. The scaling factor should reflect underreporting - // around t0 only. - num_rec[i] -= - (num_InfectedSymptoms[i] / scaling_factor_inf[i] + num_InfectedSevere[i] / scaling_factor_inf[i] + - num_icu[i] / scaling_factor_inf[i] + num_death[i] / scaling_factor_inf[i]); - - auto try_fix_constraints = [region, i](double& value, double error, auto str) { - if (value < error) { - //this should probably return a failure - //but the algorithm is not robust enough to avoid large negative values and there are tests that rely on it - log_error("{:s} for age group {:s} is {:.4f} for region {:d}, exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - else if (value < 0) { - log_info("{:s} for age group {:s} is {:.4f} for region {:d}, automatically corrected", str, - ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - }; - - try_fix_constraints(num_InfectedSymptoms[i], -5, "InfectedSymptoms"); - try_fix_constraints(num_InfectedNoSymptoms[i], -5, "InfectedNoSymptoms"); - try_fix_constraints(num_Exposed[i], -5, "Exposed"); - try_fix_constraints(num_InfectedSevere[i], -5, "InfectedSevere"); - try_fix_constraints(num_death[i], -5, "Dead"); - try_fix_constraints(num_icu[i], -5, "InfectedCritical"); - try_fix_constraints(num_rec[i], -20, "Recovered"); - } + + for (size_t i = 0; i < ConfirmedCasesDataEntry::age_group_names.size(); i++) { + // R(t0) = ΣC(t0) − I(t0) − H(t0) − U(t0) − D(t0) + // subtract currently infectious/hospitalized/ICU/dead + // Note: We divide I/H/U/D by scaling_factor_inf to "unscale" these contributions back to the + // reported level before subtracting from recovered. If we also applied the scaling factor to + // recovered, we would implicitly assume that the same underreporting applies to the entire + // history up to t0, which would be wrong. The scaling factor should reflect underreporting + // around t0 only. + num_rec[i] -= + (num_InfectedSymptoms[i] / scaling_factor_inf[i] + num_InfectedSevere[i] / scaling_factor_inf[i] + + num_icu[i] / scaling_factor_inf[i] + num_death[i] / scaling_factor_inf[i]); + + auto try_fix_constraints = [region, i](double& value, double error, auto str) { + if (value < error) { + //this should probably return a failure + //but the algorithm is not robust enough to avoid large negative values and there are tests that rely on it + log_error("{:s} for age group {:s} is {:.4f} for region {:d}, exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + else if (value < 0) { + log_info("{:s} for age group {:s} is {:.4f} for region {:d}, automatically corrected", str, + ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + }; + + try_fix_constraints(num_InfectedSymptoms[i], -5, "InfectedSymptoms"); + try_fix_constraints(num_InfectedNoSymptoms[i], -5, "InfectedNoSymptoms"); + try_fix_constraints(num_Exposed[i], -5, "Exposed"); + try_fix_constraints(num_InfectedSevere[i], -5, "InfectedSevere"); + try_fix_constraints(num_death[i], -5, "Dead"); + try_fix_constraints(num_icu[i], -5, "InfectedCritical"); + try_fix_constraints(num_rec[i], -20, "Recovered"); } return success(); diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 057d2511a2..bdb6306f0a 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -26,6 +26,7 @@ #ifdef MEMILIO_HAS_JSONCPP #include "ode_secir/model.h" +#include "memilio/geography/regions.h" #include "memilio/io/epi_data.h" #include "memilio/io/parameters_io.h" #include "memilio/io/result_io.h" @@ -41,24 +42,24 @@ namespace details { /** * @brief reads populations data from RKI. - * @param[in] rki_data Vector of ConfirmedCasesDataEntry%s. - * @param[in] vregion Vector of keys of the region of interest. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Vector of keys of the region of interest. * @param[in] date Date at which the data is read. - * @param[in, out] vnum_* Output vector for number of people in the corresponding compartement. - * @param[in] vt_* vector Average time it takes to get from one compartement to another for each age group. - * @param[in] vmu_* vector Probabilities to get from one compartement to another for each age group. + * @param[in, out] num_* Output vector for number of people in the corresponding compartement. + * @param[in] t_* vector Average time it takes to get from one compartement to another for each age group. + * @param[in] mu_* vector Probabilities to get from one compartement to another for each age group. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. */ -IOResult read_confirmed_cases_data( - std::vector& rki_data, std::vector const& vregion, Date date, - std::vector>& vnum_Exposed, std::vector>& vnum_InfectedNoSymptoms, - std::vector>& vnum_InfectedSymptoms, std::vector>& vnum_InfectedSevere, - std::vector>& vnum_icu, std::vector>& vnum_death, - std::vector>& vnum_rec, const std::vector>& vt_Exposed, - const std::vector>& vt_InfectedNoSymptoms, - const std::vector>& vt_InfectedSymptoms, const std::vector>& vt_InfectedSevere, - const std::vector>& vt_InfectedCritical, const std::vector>& vmu_C_R, - const std::vector>& vmu_I_H, const std::vector>& vmu_H_U, +IOResult compute_confirmed_cases_data( + std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, + const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, const std::vector& scaling_factor_inf); /** @@ -71,9 +72,8 @@ IOResult read_confirmed_cases_data( * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. */ template -IOResult set_confirmed_cases_data(std::vector>& model, std::vector& case_data, - const std::vector& region, Date date, - const std::vector& scaling_factor_inf) +IOResult set_confirmed_cases_data(Model& model, std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf) { const size_t num_age_groups = ConfirmedCasesDataEntry::age_group_names.size(); // allow single scalar scaling that is broadcast to all age groups @@ -88,110 +88,103 @@ IOResult set_confirmed_cases_data(std::vector>& model, std::vect scaling_factor_inf_full = scaling_factor_inf; } - std::vector> t_InfectedNoSymptoms{model.size()}; - std::vector> t_Exposed{model.size()}; - std::vector> t_InfectedSymptoms{model.size()}; - std::vector> t_InfectedSevere{model.size()}; - std::vector> t_InfectedCritical{model.size()}; - - std::vector> mu_C_R{model.size()}; - std::vector> mu_I_H{model.size()}; - std::vector> mu_H_U{model.size()}; - std::vector> mu_U_D{model.size()}; - - for (size_t node = 0; node < model.size(); ++node) { - const size_t model_groups = (size_t)model[node].parameters.get_num_groups(); - assert(model_groups == 1 || model_groups == num_age_groups); - for (size_t ag = 0; ag < num_age_groups; ag++) { - // If the model has fewer groups than casedata entries available, - // reuse group 0 parameters for all RKI age groups - const size_t group = (model_groups == num_age_groups) ? ag : 0; - - t_Exposed[node].push_back( - static_cast(std::round(model[node].parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms[node].push_back(static_cast( - std::round(model[node].parameters.template get>()[(AgeGroup)group]))); - t_InfectedSymptoms[node].push_back(static_cast( - std::round(model[node].parameters.template get>()[(AgeGroup)group]))); - t_InfectedSevere[node].push_back(static_cast( - std::round(model[node].parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical[node].push_back(static_cast( - std::round(model[node].parameters.template get>()[(AgeGroup)group]))); - - mu_C_R[node].push_back( - model[node].parameters.template get>()[(AgeGroup)group]); - mu_I_H[node].push_back( - model[node].parameters.template get>()[(AgeGroup)group]); - mu_H_U[node].push_back(model[node].parameters.template get>()[(AgeGroup)group]); - mu_U_D[node].push_back(model[node].parameters.template get>()[(AgeGroup)group]); - } + std::vector t_InfectedNoSymptoms; + std::vector t_Exposed; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; + + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; + std::vector mu_U_D; + + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_rec(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + + const size_t model_groups = (size_t)model.parameters.get_num_groups(); + assert(model_groups == 1 || model_groups == num_age_groups); + for (size_t ag = 0; ag < num_age_groups; ag++) { + // If the model has fewer groups than casedata entries available, + // reuse group 0 parameters for all RKI age groups + const size_t group = (model_groups == num_age_groups) ? ag : 0; + + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + mu_C_R.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back( + model.parameters.template get>()[(AgeGroup)group]); } - std::vector> num_InfectedSymptoms(model.size(), std::vector(num_age_groups, 0.0)); - std::vector> num_death(model.size(), std::vector(num_age_groups, 0.0)); - std::vector> num_rec(model.size(), std::vector(num_age_groups, 0.0)); - std::vector> num_Exposed(model.size(), std::vector(num_age_groups, 0.0)); - std::vector> num_InfectedNoSymptoms(model.size(), std::vector(num_age_groups, 0.0)); - std::vector> num_InfectedSevere(model.size(), std::vector(num_age_groups, 0.0)); - std::vector> num_icu(model.size(), std::vector(num_age_groups, 0.0)); - - BOOST_OUTCOME_TRY(read_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf_full)); - - for (size_t node = 0; node < model.size(); node++) { - - if (std::accumulate(num_InfectedSymptoms[node].begin(), num_InfectedSymptoms[node].end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) > 0.0) { - size_t num_groups = (size_t)model[node].parameters.get_num_groups(); - if (num_groups == num_age_groups) { - for (size_t i = 0; i < num_groups; i++) { - model[node].populations[{AgeGroup(i), InfectionState::Exposed}] = num_Exposed[node][i]; - model[node].populations[{AgeGroup(i), InfectionState::InfectedNoSymptoms}] = - num_InfectedNoSymptoms[node][i]; - model[node].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsConfirmed}] = 0; - model[node].populations[{AgeGroup(i), InfectionState::InfectedSymptoms}] = - num_InfectedSymptoms[node][i]; - model[node].populations[{AgeGroup(i), InfectionState::InfectedSymptomsConfirmed}] = 0; - model[node].populations[{AgeGroup(i), InfectionState::InfectedSevere}] = - num_InfectedSevere[node][i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model[node].populations[{AgeGroup(i), InfectionState::InfectedCritical}] = num_icu[node][i]; - } - model[node].populations[{AgeGroup(i), InfectionState::Dead}] = num_death[node][i]; - model[node].populations[{AgeGroup(i), InfectionState::Recovered}] = num_rec[node][i]; - } - } - else { - const auto sum_vec = [](const std::vector& v) { - return std::accumulate(v.begin(), v.end(), FP(0.0), [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }); - }; - const size_t i0 = 0; - model[node].populations[{AgeGroup(i0), InfectionState::Exposed}] = sum_vec(num_Exposed[node]); - model[node].populations[{AgeGroup(i0), InfectionState::InfectedNoSymptoms}] = - sum_vec(num_InfectedNoSymptoms[node]); - model[node].populations[{AgeGroup(i0), InfectionState::InfectedNoSymptomsConfirmed}] = 0; - model[node].populations[{AgeGroup(i0), InfectionState::InfectedSymptoms}] = - sum_vec(num_InfectedSymptoms[node]); - model[node].populations[{AgeGroup(i0), InfectionState::InfectedSymptomsConfirmed}] = 0; - model[node].populations[{AgeGroup(i0), InfectionState::InfectedSevere}] = - sum_vec(num_InfectedSevere[node]); - if (!is_divi_data_available(date)) { - model[node].populations[{AgeGroup(i0), InfectionState::InfectedCritical}] = sum_vec(num_icu[node]); - } - model[node].populations[{AgeGroup(i0), InfectionState::Dead}] = sum_vec(num_death[node]); - model[node].populations[{AgeGroup(i0), InfectionState::Recovered}] = sum_vec(num_rec[node]); + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf_full)); + + if (model_groups == num_age_groups) { + for (size_t i = 0; i < model_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::Exposed}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptoms}] = + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptoms}] = + num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevere}] = + num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCritical}] = num_icu[i]; } + model.populations[{AgeGroup(i), InfectionState::Recovered}] = num_rec[i]; + model.populations[{AgeGroup(i), InfectionState::Dead}] = num_death[i]; } - else { - log_warning("No infections reported on date {} for region {}. Population data has not been set.", date, - region[node]); + } + else { + const auto sum_vec = [](const std::vector& v) { + return std::accumulate(v.begin(), v.end(), FP(0.0), [](const FP& a, const FP& b) { + return evaluate_intermediate(a + b); + }); + }; + model.populations[{AgeGroup(0), InfectionState::Exposed}] = sum_vec(num_Exposed); + model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptoms}] = + sum_vec(num_InfectedNoSymptoms); + model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(0), InfectionState::InfectedSymptoms}] = + sum_vec(num_InfectedSymptoms); + model.populations[{AgeGroup(0), InfectionState::InfectedSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(0), InfectionState::InfectedSevere}] = + sum_vec(num_InfectedSevere); + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(0), InfectionState::InfectedCritical}] = sum_vec(num_icu); } + model.populations[{AgeGroup(0), InfectionState::Dead}] = sum_vec(num_death); + model.populations[{AgeGroup(0), InfectionState::Recovered}] = sum_vec(num_rec); + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), + [](const double& a, const double& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning( + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", + date, region); } return success(); } @@ -207,73 +200,28 @@ IOResult set_confirmed_cases_data(std::vector>& model, std::vect * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. */ template -IOResult set_confirmed_cases_data(std::vector>& model, const std::string& path, +IOResult set_confirmed_cases_data(mio::VectorRange>& model, const std::string& path, std::vector const& region, Date date, const std::vector& scaling_factor_inf) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - BOOST_OUTCOME_TRY(set_confirmed_cases_data(model, case_data, region, date, scaling_factor_inf)); - return success(); -} - -/** - * @brief Sets populations data from DIVI register into Model. - * @tparam FP floating point data type, e.g., double. - * @param[in, out] model Vector of models in which the data is set. - * @param[in] num_icu vector of icu data - * @param[in] vregion Vector of keys of the regions of interest. - * @param[in] date Date for which the arrays are initialized. - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data. - */ -template -IOResult set_divi_data(std::vector>& model, const std::vector& num_icu, const std::vector& vregion, - Date date, double scaling_factor_icu) -{ - - std::vector sum_mu_I_U(vregion.size(), 0); - std::vector> mu_I_U{model.size()}; - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - sum_mu_I_U[region] += model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]; - mu_I_U[region].push_back(model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]); - } - } - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - model[region].populations[{i, InfectionState::InfectedCritical}] = - scaling_factor_icu * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region]; + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { + return r == 0 || get_region_id(entry) == r; + }); + if (it != vregion.end()) { + auto region_idx = size_t(it - vregion.begin()); + vcase_data[region_idx].pushback(entry); } } - return success(); -} - -/** - * @brief sets populations data from DIVI register into Model - * @param[in, out] model vector of objects in which the data is set - * @param[in] path Path to transformed DIVI file - * @param[in] vregion vector of keys of the regions of interest - * @param[in] date Date for which the arrays are initialized - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data - */ -template -IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu) -{ - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY( + set_confirmed_cases_data(model[region_idx], vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf)); } - BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - BOOST_OUTCOME_TRY(set_divi_data(model, num_icu, rki_data, vregion, date, scaling_factor_icu)); return success(); } @@ -285,29 +233,43 @@ IOResult set_divi_data(std::vector& model, const std::string& path, * @param[in] vregion Vector of keys of the regions of interest. */ template -IOResult set_population_data(std::vector>& model, const std::vector>& num_population, - const std::vector& vregion) +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region) { - assert(num_population.size() == vregion.size()); - assert(model.size() == vregion.size()); - for (size_t region = 0; region < vregion.size(); region++) { - const auto model_groups = (size_t)model[region].parameters.get_num_groups(); - const auto data_groups = num_population[region].size(); - assert(data_groups == model_groups || (model_groups == 1 && data_groups >= 1)); - - if (data_groups == model_groups) { - for (auto i = AgeGroup(0); i < model[region].parameters.get_num_groups(); i++) { - model[region].populations.template set_difference_from_group_total( - {i, InfectionState::Susceptible}, num_population[region][(size_t)i]); - } + if (std::accumulate(num_population.begin(), num_population.end(), double(0.0), + [](const double& a, const double& b) { + return evaluate_intermediate(a + b); + }) <= 0) + { + log_warning("No population data available for region " + std::to_string(region) + + ". Population data has not been set."); + return success(); + } + + auto num_groups = model.parameters.get_num_groups(); + auto data_groups = num_population.size(); + + if (data_groups == model_groups) { + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations.template set_difference_from_group_total( + {i, InfectionState::Susceptible}, num_population[(size_t)i]); } - else if (model_groups == 1 && data_groups >= 1) { - const FP total = std::accumulate(num_population[region].begin(), num_population[region].end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }); - model[region].populations.template set_difference_from_group_total( - {AgeGroup(0), InfectionState::Susceptible}, total); + } + else if (model_groups == 1 && data_groups >= 1) { + const FP total = std::accumulate(num_population.begin(), num_population.end(), FP(0.0), + [](const FP& a, const FP& b) { + return evaluate_intermediate(a + b); + }); + model.populations.template set_difference_from_group_total( + {AgeGroup(0), InfectionState::Susceptible}, total); + } + + for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { + for (auto j = Index(0); j < InfectionState::Count; ++j) { + if (model.populations[{i, j}] < 0) { + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), + size_t(j), model.populations[{i, j}]); + } } } return success(); @@ -321,11 +283,14 @@ IOResult set_population_data(std::vector>& model, const std::vec * @param[in] vregion Vector of keys of the regions of interest. */ template -IOResult set_population_data(std::vector>& model, const std::string& path, +IOResult set_population_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion) { BOOST_OUTCOME_TRY(const auto&& num_population, read_population_data(path, vregion)); - BOOST_OUTCOME_TRY(set_population_data(model, num_population, vregion)); + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_population_data(model[region_idx], num_population[region_idx], vregion[region_idx])); + } return success(); } @@ -341,37 +306,37 @@ IOResult set_population_data(std::vector>& model, const std::str * @param[in] models Vector of models in which the data is set. Copy is made to avoid changing the original model. * @param[in] results_dir Path to result files. * @param[in] date Date for which the data should be read. -* @param[in] counties Vector of keys of the counties of interest. +* @param[in] node_ids Vector of keys of the node_ids of interest. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. * @param[in] num_days Number of days to be simulated/initialized. * @param[in] pydata_dir Directory that contains the data files. */ -template -IOResult export_input_data_county_timeseries( - std::vector models, const std::string& results_dir, Date date, const std::vector& counties, +template +IOResult export_input_data_timeseries( + mio::VectorRange> models, const std::string& results_dir, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, - const std::string& pydata_dir) + const mio::regions::de::EpidataFilenames& epidata_filenames) { const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); // allow scalar scaling factor as convenience for 1-group models assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); - assert(models.size() == counties.size()); + assert(models.size() == node_ids.size()); std::vector> extrapolated_data( - counties.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); + node_ids.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); - BOOST_OUTCOME_TRY(read_input_data_county(model, date, county, scaling_factor_inf, scaling_factor_icu, - pydata_dir, num_days)); + BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, + num_days, epidata_filenames)); - for (size_t r = 0; r < counties.size(); r++) { + for (size_t r = 0; r < node_ids.size(); r++) { extrapolated_data[r][t] = models[r].get_initial_values(); } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_age_groups), + BOOST_OUTCOME_TRY(save_result(extrapolated_data, node_ids, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); @@ -381,10 +346,10 @@ IOResult export_input_data_county_timeseries( return success(); } #else -template -IOResult export_input_data_county_timeseries(std::vector, const std::string&, Date, const std::vector&, +template +IOResult export_input_data_county_timeseries(mio::VectorRange>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, - const std::string&) + const mio::regions::de::EpidataFilenames&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); return success(); @@ -401,73 +366,17 @@ IOResult export_input_data_county_timeseries(std::vector, const std * @param[in] pydata_dir directory of files * @param[in] age_group_names strings specifying age group names */ -template -IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, +template +IOResult read_input_data(mio::VectorRange>& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, const std::string& divi_data_file_name, - const std::string& confirmed_cases_data_file_name, const std::string& population_data_file_name) + const mio::regions::de::EpidataFilenames& epidata_filenames) { - BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, divi_data_file_name), node_ids, date, + BOOST_OUTCOME_TRY(set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, population_data_file_name), node_ids)); - return success(); -} -/** - * @brief Reads population data from population files for the whole country. - * @param[in, out] model Vector of model in which the data is set. - * @param[in] date Date for which the data should be read. - * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. - * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. - * @param[in] pydata_dir Directory of files. - */ -template -IOResult read_input_data_germany(std::vector& model, Date date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir) -{ - BOOST_OUTCOME_TRY(read_input_data(model, date, {0}, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, - "germany_divi_ma7.json", "cases_all_age_ma7.json", "county_current_population.json")); - return success(); -} - -/** - * @brief Reads population data from population files for the specefied state. - * @param[in, out] model Vector of model in which the data is set. - * @param[in] date Date for which the data should be read. - * @param[in] state Vector of region keys of states of interest. - * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. - * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. - * @param[in] pydata_dir Directory of files. - */ -template -IOResult read_input_data_state(std::vector& model, Date date, std::vector& state, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir) -{ - BOOST_OUTCOME_TRY(read_input_data(model, date, state, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, - "state_divi_ma7.json", "cases_all_state_age_ma7.json", "county_current_population.json")); - return success(); -} - -/** - * @brief Reads population data from population files for the specefied county. - * @param[in, out] model Vector of model in which the data is set. - * @param[in] date Date for which the data should be read. - * @param[in] county Vector of region keys of counties of interest. - * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. - * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. - * @param[in] pydata_dir Directory of files. - */ -template -IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir) -{ - BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, - "county_divi_ma7.json", "cases_all_county_age_ma7.json", "county_current_population.json")); + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, + date, scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, node_ids)); return success(); } diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index 709a300b30..69edcd4351 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -26,6 +26,7 @@ #include "ode_secirts/model.h" #include "ode_secirts/analyze_result.h" +#include "memilio/geography/regions.h" #include "memilio/math/eigen_util.h" #include "memilio/math/math_utils.h" #include "memilio/mobility/graph.h" @@ -45,24 +46,133 @@ namespace osecirts namespace details { + +template +IOResult compute_confirmed_cases_data( + const ConfirmedCasesDataEntry& case_data_entry, std::vector& num_Exposed, + std::vector& num_InfectedNoSymptoms, std::vector& num_InfectedSymptoms, + std::vector& num_InfectedSevere, std::vector& num_icu, + std::vector& num_death, std::vector& num_timm_i, + Date date, const int days_surplus, const Model& model, + const std::vector& scaling_factor_inf, const size_t layer) +{ + auto params_region = model.parameters; + + auto age = (size_t)case_data_entry.age_group; + // (rounded) transition times + const int t_exposed = + static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); + int t_InfectedNoSymptoms = + static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); + int t_InfectedSymptoms = + static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); + const int t_InfectedSevere = + static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); + const int t_InfectedCritical = + static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); + const int t_imm_interval_i = static_cast( + std::round(params_region.template get>()[case_data_entry.age_group])); + + // transition probabilities + FP recoveredPerInfectedNoSymptoms = + params_region.template get>()[case_data_entry.age_group]; + FP severePerInfectedSymptoms = params_region.template get>()[case_data_entry.age_group]; + FP criticalPerSevere = params_region.template get>()[case_data_entry.age_group]; + + // if we select a layer with better immunity (layer > 0), we need to adjust the times and transition rates + if (layer == 1) { + t_InfectedNoSymptoms = static_cast(std::round( + t_InfectedNoSymptoms * params_region.template get>()[case_data_entry.age_group])); + t_InfectedSymptoms = static_cast(std::round( + t_InfectedSymptoms * params_region.template get>()[case_data_entry.age_group])); + + const FP red_fact_exp = + params_region.template get>()[case_data_entry.age_group]; + + const FP red_fact_inf = + params_region.template get>()[case_data_entry.age_group]; + + const FP red_fact_sev = + lparams_region.template get>()[case_data_entry.age_group]; + + recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms); + severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms; + } + else if (layer > 1) { + t_InfectedNoSymptoms = static_cast(std::round( + t_InfectedNoSymptoms * params_region.template get>()[case_data_entry.age_group])); + t_InfectedSymptoms = static_cast(std::round( + t_InfectedSymptoms * params_region.template get>()[case_data_entry.age_group])); + + const FP red_fact_exp = + params_region.template get>()[case_data_entry.age_group]; + + const FP red_fact_inf = + params_region.template get>()[case_data_entry.age_group]; + + const FP red_fact_sev = + params_region.template get>()[case_data_entry.age_group]; + + recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms); + severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms; + } + + if (case_data_entry.date == offset_date_by_days(date, 0)) { + num_InfectedSymptoms[age] += scaling_factor_inf[age] * case_data_entry.num_confirmed; + num_imm[age] += case_data_entry.num_confirmed; + } + if (case_data_entry.date == offset_date_by_days(date, t_InfectedNoSymptoms + days_surplus)) { + num_InfectedNoSymptoms[age] += + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; + num_Exposed[age] -= + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; + } + if (case_data_entry.date == offset_date_by_days(date, days_surplus)) { + num_InfectedNoSymptoms[age] -= + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; + } + if (case_data_entry.date == offset_date_by_days(date, t_exposed + t_InfectedNoSymptoms + days_surplus)) { + num_Exposed[age] += + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; + } + if (case_data_entry.date == offset_date_by_days(date, -t_InfectedSymptoms)) { + num_InfectedSymptoms[age] -= scaling_factor_inf[age] * case_data_entry.num_confirmed; + num_InfectedSevere[age] += severePerInfectedSymptoms * scaling_factor_inf[age] * case_data_entry.num_confirmed; + } + if (case_data_entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere)) { + num_InfectedSevere[age] -= severePerInfectedSymptoms * scaling_factor_inf[age] * case_data_entry.num_confirmed; + num_icu[age] += + severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * case_data_entry.num_confirmed; + } + if (case_data_entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere - t_InfectedCritical)) { + num_death[age] += case_data_entry.num_deaths; + num_icu[age] -= + severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * case_data_entry.num_confirmed; + } + if (case_data_entry.date == offset_date_by_days(date, 0 - t_imm_interval_i)) { + num_imm[age] -= case_data_entry.num_confirmed; + } + + return success(); +} + /** * @brief Computes the distribution of confirmed cases across infection states based on Case (RKI) data. * * This function processes case data for given regions and distributes the cases across different * infection states, considering the corresponding transition times and probabilities defined in the model. * - * @tparam Model The type of the model used. * @tparam FP Floating point type (default: double). * * @param[in] case_data Vector of confirmed case data entries (defined in epi_data.h). - * @param[out] vnum_Exposed Output vector for the number of exposed individuals per age group and region. - * @param[out] vnum_InfectedNoSymptoms Output vector for the number of infected individuals without symptoms. - * @param[out] vnum_InfectedSymptoms Output vector for the number of infected individuals with symptoms. - * @param[out] vnum_InfectedSevere Output vector for the number of severely infected individuals. - * @param[out] vnum_icu Output vector for the number of individuals in critical condition (ICU). - * @param[out] vnum_death Output vector for the number of deaths. - * @param[out] vnum_timm_i Output vector for the number of individuals in temporary immunity state. - * @param[in] vregion Vector of region IDs representing the regions in the model vector. + * @param[out] num_Exposed Output vector for the number of exposed individuals per age group and region. + * @param[out] num_InfectedNoSymptoms Output vector for the number of infected individuals without symptoms. + * @param[out] num_InfectedSymptoms Output vector for the number of infected individuals with symptoms. + * @param[out] num_InfectedSevere Output vector for the number of severely infected individuals. + * @param[out] num_icu Output vector for the number of individuals in critical condition (ICU). + * @param[out] num_death Output vector for the number of deaths. + * @param[out] num_timm_i Output vector for the number of individuals in temporary immunity state. + * @param[in] region Vector of region IDs representing the regions in the model vector. * @param[in] date Date for which the simulation starts. * @param[in] model Vector of models, each representing a region and containing the parameters. * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases for @@ -70,13 +180,13 @@ namespace details * * @return An IOResult showing success or failure. */ -template +template IOResult compute_confirmed_cases_data( - const std::vector& case_data, std::vector>& vnum_Exposed, - std::vector>& vnum_InfectedNoSymptoms, std::vector>& vnum_InfectedSymptoms, - std::vector>& vnum_InfectedSevere, std::vector>& vnum_icu, - std::vector>& vnum_death, std::vector>& vnum_timm_i, - std::vector const& vregion, Date date, const std::vector& model, + const std::vector& case_data, std::vector& num_Exposed, + std::vector& num_InfectedNoSymptoms, std::vector& num_InfectedSymptoms, + std::vector& num_InfectedSevere, std::vector& num_icu, + std::vector& num_death, std::vector& num_timm_i, + const int region, Date date, const Model& model, const std::vector& scaling_factor_inf, const size_t layer) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { @@ -101,198 +211,50 @@ IOResult compute_confirmed_cases_data( } for (auto&& entry : case_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { - return r == 0 || get_region_id(entry) == r; - }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - - auto params_region = model[region_idx].parameters; - auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx]; - auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx]; - auto& num_Exposed = vnum_Exposed[region_idx]; - auto& num_InfectedSevere = vnum_InfectedSevere[region_idx]; - auto& num_death = vnum_death[region_idx]; - auto& num_icu = vnum_icu[region_idx]; - auto& num_imm = vnum_timm_i[region_idx]; - - auto age = (size_t)entry.age_group; - // (rounded) transition times - const int t_exposed = - static_cast(std::round(params_region.template get>()[entry.age_group])); - int t_InfectedNoSymptoms = - static_cast(std::round(params_region.template get>()[entry.age_group])); - int t_InfectedSymptoms = - static_cast(std::round(params_region.template get>()[entry.age_group])); - const int t_InfectedSevere = - static_cast(std::round(params_region.template get>()[entry.age_group])); - const int t_InfectedCritical = - static_cast(std::round(params_region.template get>()[entry.age_group])); - const int t_imm_interval_i = static_cast( - std::round(params_region.template get>()[entry.age_group])); - - // transition probabilities - FP recoveredPerInfectedNoSymptoms = - params_region.template get>()[entry.age_group]; - FP severePerInfectedSymptoms = params_region.template get>()[entry.age_group]; - FP criticalPerSevere = params_region.template get>()[entry.age_group]; - - // if we select a layer with better immunity (layer > 0), we need to adjust the times and transition rates - if (layer > 0) { - t_InfectedNoSymptoms = static_cast(std::round( - t_InfectedNoSymptoms * params_region.template get>()[entry.age_group])); - t_InfectedSymptoms = static_cast(std::round( - t_InfectedSymptoms * params_region.template get>()[entry.age_group])); - - const FP red_fact_exp = - layer == 1 ? params_region.template get>()[entry.age_group] - : params_region.template get>()[entry.age_group]; - - const FP red_fact_inf = - layer == 1 - ? params_region.template get>()[entry.age_group] - : params_region.template get>()[entry.age_group]; - - const FP red_fact_sev = - layer == 1 - ? params_region - .template get>()[entry.age_group] - : params_region - .template get>()[entry.age_group]; - - recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms); - severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms; - } + compute_confirmed_cases_data(entry, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, + num_InfectedSevere, num_icu, num_death, num_timm_i, date, days_surplus, model, + scaling_factor_inf, layer) + } - if (entry.date == offset_date_by_days(date, 0)) { - num_InfectedSymptoms[age] += scaling_factor_inf[age] * entry.num_confirmed; - num_imm[age] += entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, t_InfectedNoSymptoms + days_surplus)) { - num_InfectedNoSymptoms[age] += - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; - num_Exposed[age] -= - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; + size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size(); + for (size_t i = 0; i < num_groups; i++) { + auto try_fix_constraints = [region, i](FP& value, FP error, auto str) { + if (value < error) { + // this should probably return a failure + // but the algorithm is not robust enough to avoid large negative + // values and there are tests that rely on it + log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " + "exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; } - if (entry.date == offset_date_by_days(date, days_surplus)) { - num_InfectedNoSymptoms[age] -= - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; + else if (value < 0) { + log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " + "automatically corrected", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; } - if (entry.date == offset_date_by_days(date, t_exposed + t_InfectedNoSymptoms + days_surplus)) { - num_Exposed[age] += - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms)) { - num_InfectedSymptoms[age] -= scaling_factor_inf[age] * entry.num_confirmed; - num_InfectedSevere[age] += severePerInfectedSymptoms * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere)) { - num_InfectedSevere[age] -= severePerInfectedSymptoms * scaling_factor_inf[age] * entry.num_confirmed; - num_icu[age] += - severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere - t_InfectedCritical)) { - num_death[age] += entry.num_deaths; - num_icu[age] -= - severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, 0 - t_imm_interval_i)) { - num_imm[age] -= entry.num_confirmed; - } - } - } - - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - auto region = vregion[region_idx]; - - auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx]; - auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx]; - auto& num_Exposed = vnum_Exposed[region_idx]; - auto& num_InfectedSevere = vnum_InfectedSevere[region_idx]; - auto& num_death = vnum_death[region_idx]; - auto& num_icu = vnum_icu[region_idx]; - auto& num_timm_i = vnum_timm_i[region_idx]; - - size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size(); - for (size_t i = 0; i < num_groups; i++) { - auto try_fix_constraints = [region, i](FP& value, FP error, auto str) { - if (value < error) { - // this should probably return a failure - // but the algorithm is not robust enough to avoid large negative - // values and there are tests that rely on it - log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " - "exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - else if (value < 0) { - log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " - "automatically corrected", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - }; - - const FP tol_error = -1e-8; - try_fix_constraints(num_InfectedSymptoms[i], tol_error, "InfectedSymptoms"); - try_fix_constraints(num_InfectedNoSymptoms[i], tol_error, "InfectedNoSymptoms"); - try_fix_constraints(num_Exposed[i], tol_error, "Exposed"); - try_fix_constraints(num_InfectedSevere[i], tol_error, "InfectedSevere"); - try_fix_constraints(num_death[i], tol_error, "Dead"); - try_fix_constraints(num_icu[i], tol_error, "InfectedCritical"); - try_fix_constraints(num_timm_i[i], tol_error, "Recently Recovered or Vaccinated"); - } + }; + + const FP tol_error = -1e-8; + try_fix_constraints(num_InfectedSymptoms[i], tol_error, "InfectedSymptoms"); + try_fix_constraints(num_InfectedNoSymptoms[i], tol_error, "InfectedNoSymptoms"); + try_fix_constraints(num_Exposed[i], tol_error, "Exposed"); + try_fix_constraints(num_InfectedSevere[i], tol_error, "InfectedSevere"); + try_fix_constraints(num_death[i], tol_error, "Dead"); + try_fix_constraints(num_icu[i], tol_error, "InfectedCritical"); + try_fix_constraints(num_timm_i[i], tol_error, "Recently Recovered or Vaccinated"); } return success(); } -/** - * @brief Reads confirmed case data from a file and computes the distribution of cases across infection states. - * - * This function reads transformed RKI data from a specified file and processes the confirmed cases - * to distribute them across different infection states and age groups. - * - * @tparam Model The type of the model used. - * @tparam FP Floating point type (default: double). - * - * @param[in] path Path to the file containing transformed case (rki) data. - * @param[in] vregion Vector of region IDs to process. - * @param[in] date Date for which the simulation starts. - * @param[out] vnum_Exposed Output vector for the number of exposed individuals per age group and region. - * @param[out] vnum_InfectedNoSymptoms Output vector for the number of infected individuals without symptoms. - * @param[out] vnum_InfectedSymptoms Output vector for the number of infected individuals with symptoms. - * @param[out] vnum_InfectedSevere Output vector for the number of severely infected individuals (Hospitalized). - * @param[out] vnum_icu Output vector for the number of individuals in critical condition (ICU). - * @param[out] vnum_death Output vector for the number of deaths. - * @param[out] vnum_timm_i Output vector for the number of individuals in a temporary immunity state. - * @param[in] model Vector of models, each representing a region and containing the parameters. - * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. - * @param[in] layer Specifies the immunity layer: 0 (Naive), 1 (Partial Immunity), 2 (Improved Immunity). - * - * @return An IOResult indicating success or failure. - */ -template -IOResult read_confirmed_cases_data( - std::string const& path, std::vector const& vregion, Date date, std::vector>& vnum_Exposed, - std::vector>& vnum_InfectedNoSymptoms, std::vector>& vnum_InfectedSymptoms, - std::vector>& vnum_InfectedSevere, std::vector>& vnum_icu, - std::vector>& vnum_death, std::vector>& vnum_timm_i, - const std::vector& model, const std::vector& scaling_factor_inf, const size_t layer) -{ - BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - return compute_confirmed_cases_data(case_data, vnum_Exposed, vnum_InfectedNoSymptoms, vnum_InfectedSymptoms, - vnum_InfectedSevere, vnum_icu, vnum_death, vnum_timm_i, vregion, date, model, - scaling_factor_inf, layer); -} - /** * @brief Sets the confirmed cases data in the model considering different immunity layers. * * This function distributes confirmed case data across infection states for regions and age groups * in the model. It considers different levels of immunity (naive, partial, and improved). * - * @tparam Model The type of the model used. * @tparam FP Floating point type (default: double). * * @param[in,out] model Vector of models, each representing a region, where the compartments are updated. @@ -304,24 +266,24 @@ IOResult read_confirmed_cases_data( * * @return An IOResult indicating success or failure. */ -template +template IOResult -set_confirmed_cases_data(std::vector& model, const std::vector& case_data, - std::vector const& region, Date date, const std::vector& scaling_factor_inf, +set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, const std::vector> immunity_population) { - auto num_age_groups = (size_t)model[0].parameters.get_num_groups(); + auto num_age_groups = (size_t)model.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups); - std::vector> num_InfectedSymptoms(model.size()); - std::vector> num_death(model.size()); - std::vector> num_Exposed(model.size()); - std::vector> num_InfectedNoSymptoms(model.size()); - std::vector> num_InfectedSevere(model.size()); - std::vector> num_icu(model.size()); - std::vector> num_timm1(model.size()); - std::vector> num_timm2(model.size()); + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + std::vector num_timm1(num_age_groups, 0.0); + std::vector num_timm2(num_age_groups, 0.0); std::vector denom_E(num_age_groups, 0.0); std::vector denom_I_NS(num_age_groups, 0.0); @@ -329,204 +291,184 @@ set_confirmed_cases_data(std::vector& model, const std::vector denom_I_Sev_Cr(num_age_groups, 0.0); /*----------- Naive immunity -----------*/ - for (size_t county = 0; county < model.size(); county++) { - num_InfectedSymptoms[county] = std::vector(num_age_groups, 0.0); - num_death[county] = std::vector(num_age_groups, 0.0); - num_Exposed[county] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[county] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[county] = std::vector(num_age_groups, 0.0); - num_icu[county] = std::vector(num_age_groups, 0.0); - num_timm1[county] = std::vector(num_age_groups, 0.0); - num_timm2[county] = std::vector(num_age_groups, 0.0); - for (size_t group = 0; group < num_age_groups; group++) { - // calculate the denominators to split the reported case numbers to the different immunity layers. - denom_E[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model[county].parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model[county].parameters.template get>()[(AgeGroup)group]); - - denom_I_NS[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model[county].parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model[county].parameters.template get>()[(AgeGroup)group]); - - denom_I_Sy[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model[county] - .parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model[county] - .parameters.template get>()[(AgeGroup)group]); - - denom_I_Sev_Cr[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model[county].parameters.template get>()[( - AgeGroup)group] + - immunity_population[2][group] * - model[county].parameters.template get>()[( - AgeGroup)group]); - } + for (size_t group = 0; group < num_age_groups; group++) { + // calculate the denominators to split the reported case numbers to the different immunity layers. + denom_E[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model.parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[(AgeGroup)group]); + + denom_I_NS[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model.parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[(AgeGroup)group]); + + denom_I_Sy[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model + .parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model + .parameters.template get>()[(AgeGroup)group]); + + denom_I_Sev_Cr[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model.parameters.template get>()[( + AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[( + AgeGroup)group]); } BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, region, date, model, scaling_factor_inf, 0)); - for (size_t county = 0; county < model.size(); county++) { - size_t num_groups = (size_t)model[county].parameters.get_num_groups(); - for (size_t i = 0; i < num_groups; i++) { - model[county].populations[{AgeGroup(i), InfectionState::ExposedNaive}] = - immunity_population[0][i] * denom_E[i] * num_Exposed[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = - immunity_population[0][i] * denom_I_NS[i] * num_InfectedNoSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = - immunity_population[0][i] * denom_I_Sy[i] * num_InfectedSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = - immunity_population[0][i] * denom_I_Sev_Cr[i] * num_InfectedSevere[county][i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = - immunity_population[0][i] * denom_I_Sev_Cr[i] * num_icu[county][i]; - } - } - if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) == 0) { - log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region[county]); + size_t num_groups = (size_t)model.parameters.get_num_groups(); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = + immunity_population[0][i] * denom_E[i] * num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = + immunity_population[0][i] * denom_I_NS[i] * num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = + immunity_population[0][i] * denom_I_Sy[i] * num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = + immunity_population[0][i] * denom_I_Sev_Cr[i] * num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = + immunity_population[0][i] * denom_I_Sev_Cr[i] * num_icu[i]; } } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), FP(0.0), + [](const FP& a, const FP& b) { + return evaluate_intermediate(a + b); + }) == 0) { + log_warning( + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", + date, region); + } /*----------- PARTIAL Immunity -----------*/ - for (size_t county = 0; county < model.size(); county++) { - num_InfectedSymptoms[county] = std::vector(num_age_groups, 0.0); - num_death[county] = std::vector(num_age_groups, 0.0); - num_Exposed[county] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[county] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[county] = std::vector(num_age_groups, 0.0); - num_icu[county] = std::vector(num_age_groups, 0.0); - } + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, region, date, model, scaling_factor_inf, 1)); - for (size_t county = 0; county < model.size(); county++) { - size_t num_groups = (size_t)model[county].parameters.get_num_groups(); - for (size_t i = 0; i < num_groups; i++) { - model[county].populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = - immunity_population[1][i] * - model[county].parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_Exposed[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = + size_t num_groups = (size_t)model.parameters.get_num_groups(); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * + denom_I_Sy[i] * num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = + immunity_population[1][i] * + model + .parameters.template get>()[(AgeGroup)i] * + denom_I_Sev_Cr[i] * num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = immunity_population[1][i] * - model[county].parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * - num_InfectedNoSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = - immunity_population[1][i] * - model[county].parameters.template get>()[(AgeGroup)i] * - denom_I_Sy[i] * num_InfectedSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = - immunity_population[1][i] * - model[county] + model .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_InfectedSevere[county][i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = - immunity_population[1][i] * - model[county] - .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_icu[county][i]; - } - // the += is necessary because we already set the previous vaccinated individuals - model[county].populations[{AgeGroup(i), InfectionState::TemporaryImmunePartialImmunity}] += - immunity_population[1][i] * - model[county].parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_timm1[county][i]; - } - if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) == 0) { - - log_warning("No infections for partially vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region[county]); + denom_I_Sev_Cr[i] * num_icu[i]; } + // the += is necessary because we already set the previous vaccinated individuals + model.populations[{AgeGroup(i), InfectionState::TemporaryImmunePartialImmunity}] += + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_timm1[i]; + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), FP(0.0), + [](const FP& a, const FP& b) { + return evaluate_intermediate(a + b); + }) == 0) { + + log_warning("No infections for partially vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); } /*----------- Improved Immunity -----------*/ - for (size_t county = 0; county < model.size(); county++) { - num_InfectedSymptoms[county] = std::vector(num_age_groups, 0.0); - num_death[county] = std::vector(num_age_groups, 0.0); - num_Exposed[county] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[county] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[county] = std::vector(num_age_groups, 0.0); - num_icu[county] = std::vector(num_age_groups, 0.0); - } + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm2, region, date, model, scaling_factor_inf, 2)); - for (size_t county = 0; county < model.size(); county++) { - size_t num_groups = (size_t)model[county].parameters.get_num_groups(); - for (size_t i = 0; i < num_groups; i++) { - model[county].populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = - immunity_population[2][i] * - model[county].parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_Exposed[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] = - immunity_population[2][i] * - model[county].parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * - num_InfectedNoSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = + size_t num_groups = (size_t)model.parameters.get_num_groups(); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] = + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * + denom_I_Sy[i] * num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = + immunity_population[2][i] * + model + .parameters.template get>()[(AgeGroup)i] * + denom_I_Sev_Cr[i] * num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = immunity_population[2][i] * - model[county].parameters.template get>()[(AgeGroup)i] * - denom_I_Sy[i] * num_InfectedSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = - immunity_population[2][i] * - model[county] + model .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_InfectedSevere[county][i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = - immunity_population[2][i] * - model[county] - .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_icu[county][i]; - } - - // the += is necessary because we already set the previous vaccinated individuals - model[county].populations[{AgeGroup(i), InfectionState::TemporaryImmuneImprovedImmunity}] += - immunity_population[2][i] * - model[county].parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_timm2[county][i]; - } - if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) == 0) { - log_warning("No infections for vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region[county]); + denom_I_Sev_Cr[i] * num_icu[i]; } + + // the += is necessary because we already set the previous vaccinated individuals + model.populations[{AgeGroup(i), InfectionState::TemporaryImmuneImprovedImmunity}] += + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_timm2[i]; + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), FP(0.0), + [](const FP& a, const FP& b) { + return evaluate_intermediate(a + b); + }) == 0) { + log_warning("No infections for vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); } return success(); } @@ -538,34 +480,48 @@ set_confirmed_cases_data(std::vector& model, const std::vector -IOResult set_confirmed_cases_data(std::vector& model, const std::string& path, - std::vector const& region, Date date, +template +IOResult set_confirmed_cases_data(mio::VectorRange>& model, const std::string& path, + std::vector const& vregion, Date date, const std::vector& scaling_factor_inf, const std::vector> immunity_population) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - BOOST_OUTCOME_TRY( - set_confirmed_cases_data(model, case_data, region, date, scaling_factor_inf, immunity_population)); + + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { + return r == 0 || get_region_id(entry) == r; + }); + if (it != vregion.end()) { + auto region_idx = size_t(it - vregion.begin()); + vcase_data[region_idx].pushback(entry); + } + } + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY( + set_confirmed_cases_data(model[region_idx], vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, immunity_population)); + } + return success(); } /** * @brief Sets the population data for the given models based on the provided population distribution and immunity levels. * - * @tparam Model The type of the model used. * @tparam FP Floating point type (default: double). * * @param[in,out] model A vector of models for which population data will be set. @@ -576,65 +532,63 @@ IOResult set_confirmed_cases_data(std::vector& model, const std::st * * @return An IOResult indicating success or failure. */ -template -IOResult set_population_data(std::vector& model, const std::vector>& num_population, - const std::vector& vregion, - const std::vector> immunity_population) +template +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region, const std::vector> immunity_population) { - for (size_t region = 0; region < vregion.size(); region++) { - if (std::accumulate(num_population[region].begin(), num_population[region].end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) > 0.0) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - - FP SN = num_population[region][size_t(i)] * immunity_population[0][size_t(i)]; - FP SPI = num_population[region][size_t(i)] * immunity_population[1][size_t(i)]; - FP SII = num_population[region][size_t(i)] - SN - SPI; - - model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::max( - 0.0, - FP(SII - - (model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + - model[region].populations[{i, InfectionState::DeadImprovedImmunity}] + - model[region].populations[{i, InfectionState::TemporaryImmuneImprovedImmunity}]))); - - model[region].populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( - 0.0, - SPI - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - - model[region].populations[{i, InfectionState::DeadPartialImmunity}] - - model[region].populations[{i, InfectionState::TemporaryImmunePartialImmunity}]); - - model[region].populations.template set_difference_from_group_total( - {i, InfectionState::SusceptibleNaive}, num_population[region][size_t(i)]); - } + if (std::accumulate(num_population.begin(), num_population.end(), double(0.0), + [](const double& a, const double& b) { + return evaluate_intermediate(a + b); + }) <= 0) + { + log_warning("No population data available for region " + std::to_string(region) + + ". Population data has not been set."); + return success(); + } - for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { - for (auto j = Index(0); j < InfectionState::Count; ++j) { - if (model[region].populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model[region].populations[{i, j}]); - } - } + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + + FP SN = num_population[size_t(i)] * immunity_population[0][size_t(i)]; + FP SPI = num_population[size_t(i)] * immunity_population[1][size_t(i)]; + FP SII = num_population[size_t(i)] - SN - SPI; + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::max( + 0.0, + FP(SII - + (model.populations[{i, InfectionState::ExposedImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + + model.populations[{i, InfectionState::DeadImprovedImmunity}] + + model.populations[{i, InfectionState::TemporaryImmuneImprovedImmunity}]))); + + model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( + 0.0, + SPI - model.populations[{i, InfectionState::ExposedPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - + model.populations[{i, InfectionState::DeadPartialImmunity}] - + model.populations[{i, InfectionState::TemporaryImmunePartialImmunity}]); + + model.populations.template set_difference_from_group_total( + {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); + } + + for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { + for (auto j = Index(0); j < InfectionState::Count; ++j) { + if (model.populations[{i, j}] < 0) { + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), + size_t(j), model.populations[{i, j}]); } } - else { - log_warning("No population data available for region " + std::to_string(region) + - ". Population data has not been set."); - } } return success(); @@ -643,8 +597,6 @@ IOResult set_population_data(std::vector& model, const std::vector< /** * @brief Reads population data from a file and sets it for the each given model. * - * @tparam Model The type of the model used. - * * @param[in,out] model A vector of models for which population data will be set. * @param[in] path The file path to the population data. * @param[in] vregion A vector of region identifiers corresponding to the population data. @@ -653,12 +605,70 @@ IOResult set_population_data(std::vector& model, const std::vector< * * @return An IOResult indicating success or failure. */ -template -IOResult set_population_data(std::vector& model, const std::string& path, const std::vector& vregion, +template +IOResult set_population_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, const std::vector> immunity_population) { BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion)); - BOOST_OUTCOME_TRY(set_population_data(model, num_population, vregion, immunity_population)); + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_population_data(model[region_idx], num_population[region_idx], vregion[region_idx], immunity_population)); + } + return success(); +} + +template +IOResult set_vaccination_data(Model& model, const VaccinationDataEntry& vacc_data_entry, + Date date, int num_days, Date max_date, const int days_until_effective_n, + const int days_until_effective_pi, const int days_until_effective_ii) +{ + auto num_groups = model.parameters.get_num_groups(); + + auto date_df = vacc_data_entry.date; + AgeGroup age = vacc_data_entry.age_group; + + // get daily vaccinations for each layer + for (size_t d = 0; d < (size_t)num_days + 1; ++d) { + auto offset_first_date = offset_date_by_days(date, (int)d - days_until_effective_n); + if (max_date >= offset_first_date) { + if (date_df == offset_first_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = + vacc_data_entry.num_vaccinations_partial; + } + } + else { + if (date_df == offset_first_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = 0; + } + } + + auto offset_full_date = offset_date_by_days(date, (int)d - days_until_effective_pi); + if (max_date >= offset_full_date) { + if (date_df == offset_full_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = + vacc_data_entry.num_vaccinations_completed; + } + } + else { + if (date_df == offset_first_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = 0; + } + } + + auto offset_booster_date = offset_date_by_days(date, (int)d - days_until_effective_ii); + if (max_date >= offset_booster_date) { + if (date_df == offset_booster_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = + vacc_data_entry.num_vaccinations_refreshed_first + + vacc_data_entry.num_vaccinations_refreshed_additional; + } + } + else { + if (date_df == offset_first_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = 0; + } + } + } return success(); } @@ -671,38 +681,14 @@ IOResult set_population_data(std::vector& model, const std::string& * @param[in,out] model A vector of models for which vaccination data will be set. * @param[in] vacc_data A vector of VaccinationDataEntry objects containing the vaccination data. * @param[in] date The starting date for the simulation. - * @param[in] vregion A vector of region identifiers corresponding to the vaccination data. * @param[in] num_days The number of days for which the simulation runs. * * @return An IOResult indicating success or failure. */ template -IOResult set_vaccination_data(std::vector>& model, const std::vector& vacc_data, - Date date, const std::vector& vregion, int num_days) +IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, + Date date, int num_days) { - auto num_groups = model[0].parameters.get_num_groups(); - - auto days_until_effective_n = - (int)(double)model[0].parameters.template get>()[AgeGroup(0)]; - auto days_until_effective_pi = - (int)(double)model[0].parameters.template get>()[AgeGroup(0)]; - auto days_until_effective_ii = - (int)(double)model[0].parameters.template get>()[AgeGroup(0)]; - // iterate over regions (e.g., counties) - for (size_t i = 0; i < model.size(); ++i) { - // iterate over age groups in region - for (auto g = AgeGroup(0); g < num_groups; ++g) { - - model[i].parameters.template get>().resize(SimulationDay(num_days + 1)); - model[i].parameters.template get>().resize(SimulationDay(num_days + 1)); - model[i].parameters.template get>().resize(SimulationDay(num_days + 1)); - for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { - model[i].parameters.template get>()[{g, d}] = 0.0; - model[i].parameters.template get>()[{g, d}] = 0.0; - model[i].parameters.template get>()[{g, d}] = 0.0; - } - } - } auto max_date_entry = std::max_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -721,66 +707,16 @@ IOResult set_vaccination_data(std::vector>& model, const std::ve min_date, max_date); } + auto days_until_effective_n = + (int)(double)model.parameters.template get>()[AgeGroup(0)]; + auto days_until_effective_pi = + (int)(double)model.parameters.template get>()[AgeGroup(0)]; + auto days_until_effective_ii = + (int)(double)model.parameters.template get>()[AgeGroup(0)]; + for (auto&& vacc_data_entry : vacc_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { - return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(r)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(r)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(r)); - }); - auto date_df = vacc_data_entry.date; - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - AgeGroup age = vacc_data_entry.age_group; - - // get daily vaccinations for each layer - for (size_t d = 0; d < (size_t)num_days + 1; ++d) { - auto offset_first_date = offset_date_by_days(date, (int)d - days_until_effective_n); - if (max_date >= offset_first_date) { - if (date_df == offset_first_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = - vacc_data_entry.num_vaccinations_partial; - } - } - else { - if (date_df == offset_first_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = 0; - } - } - - auto offset_full_date = offset_date_by_days(date, (int)d - days_until_effective_pi); - if (max_date >= offset_full_date) { - if (date_df == offset_full_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = - vacc_data_entry.num_vaccinations_completed; - } - } - else { - if (date_df == offset_first_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = 0; - } - } - - auto offset_booster_date = offset_date_by_days(date, (int)d - days_until_effective_ii); - if (max_date >= offset_booster_date) { - if (date_df == offset_booster_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = - vacc_data_entry.num_vaccinations_refreshed_first + - vacc_data_entry.num_vaccinations_refreshed_additional; - } - } - else { - if (date_df == offset_first_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = 0; - } - } - } - } + BOOST_OUTCOME_TRY(set_vaccination_data(model, vacc_data_entry, date, num_days, max_date, + days_until_effective_n, days_until_effective_pi, days_until_effective_ii)); } return success(); } @@ -802,32 +738,52 @@ IOResult set_vaccination_data(std::vector>& model, const std::ve * @return An IOResult indicating success or failure. */ template -IOResult set_vaccination_data(std::vector>& model, const std::string& path, Date date, +IOResult set_vaccination_data(mio::VectorRange>& model, const std::string& path, Date date, const std::vector& vregion, int num_days) { + // Set vaccination data to 0 for all models + for (auto& m : model) { + m.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.parameters.template get>().resize(SimulationDay(num_days + 1)); + for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { + for (auto a = AgeGroup(0); a < m.parameters.get_num_groups(); ++a) { + m.parameters.template get>()[{a, d}] = 0.0; + m.parameters.template get>()[{a, d}] = 0.0; + m.parameters.template get>()[{a, d}] = 0.0; + } + } + } + // Check if vaccination data is available for the given date range auto end_date = offset_date_by_days(date, num_days); if (!is_vaccination_data_available(date, end_date)) { log_warning("No vaccination data available in range from {} to {}. " "Vaccination data will be set to 0.", date, end_date); - // Set vaccination data to 0 for all models - for (auto& m : model) { - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { - for (auto a = AgeGroup(0); a < m.parameters.get_num_groups(); ++a) { - m.parameters.template get>()[{a, d}] = 0.0; - m.parameters.template get>()[{a, d}] = 0.0; - m.parameters.template get>()[{a, d}] = 0.0; - } - } - } return success(); } + BOOST_OUTCOME_TRY(auto&& vacc_data, read_vaccination_data(path)); - BOOST_OUTCOME_TRY(set_vaccination_data(model, vacc_data, date, vregion, num_days)); + + // Sort case_data into regions and ignore once with no region associated + std::vector> vvacc_data{model.size()}; + for (auto&& vacc_data_entry : vacc_data) { + auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { + return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(r)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(r)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(r)); + }); + if (it != vregion.end()) { + auto region_idx = size_t(it - vregion.begin()); + vvacc_data[region_idx].pushback(vacc_data_entry); + } + } + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx], vacc_data[region_idx], date, num_days)); + } + return success(); } @@ -842,12 +798,10 @@ IOResult set_vaccination_data(std::vector>& model, const std::st * used to initialize the model with real-world data. The resulting data represents the initialized states of * the model over the specified time range. * - * @tparam Model Type of the model used. - * * @param[in] models A vector of models for which the extrapolated data is set. * @param[in] results_dir Path to the directory where the extrapolated results will be saved in a h5 file. * @param[in] date Date for which the data should be read. - * @param[in] counties Vector of keys of the counties of interest. + * @param[in] node_ids Vector of keys of the node_ids of interest. * @param[in] scaling_factor_inf A vector of scaling factors applied to confirmed cases. * @param[in] scaling_factor_icu A scaling factor applied to ICU cases. * @param[in] num_days The number of days for which will be extrapolated. @@ -856,16 +810,16 @@ IOResult set_vaccination_data(std::vector>& model, const std::st * * @return An IOResult indicating success or failure. */ -template -IOResult export_input_data_county_timeseries( - std::vector models, const std::string& results_dir, Date date, const std::vector& counties, +template +IOResult export_input_data_timeseries( + mio::VectorRange> models, const std::string& results_dir, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, - const std::string& pydata_dir, const std::vector> immunity_population) + const std::vector> immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) { const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); - assert(models.size() == counties.size()); + assert(models.size() == node_ids.size()); std::vector> extrapolated_data( models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); @@ -873,10 +827,10 @@ IOResult export_input_data_county_timeseries( auto offset_day = offset_date_by_days(date, t); // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data_county(model, date, county, scaling_factor_inf, scaling_factor_icu, - pydata_dir, num_days, immunity_population)); + BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, + num_days, immunity_population, epidata_filenames)); - for (size_t r = 0; r < counties.size(); r++) { + for (size_t r = 0; r < node_ids.size(); r++) { extrapolated_data[r][t] = models[r].get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. @@ -887,7 +841,7 @@ IOResult export_input_data_county_timeseries( } } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_age_groups), + BOOST_OUTCOME_TRY(save_result(extrapolated_data, node_ids, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); @@ -898,10 +852,10 @@ IOResult export_input_data_county_timeseries( } #else -template -IOResult export_input_data_county_timeseries(std::vector, const std::string&, Date, const std::vector&, - const std::vector&, const double, const int, - const std::string&, const std::vector>) +template +IOResult export_input_data_timeseries(mio::VectorRange>, const std::string&, Date, const std::vector&, + const std::vector&, const double, const int, + const std::vector>, const mio::regions::de::EpidataFilenames&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); return success(); @@ -914,8 +868,6 @@ IOResult export_input_data_county_timeseries(std::vector, const std * * This function estimates all compartments from available data using the provided model parameters. * - * @tparam Model The type of tmodel used. - * * @param[in,out] model Vector of models, one per county, to be initialized with data. * @param[in] date Date for which the data should be read. * @param[in] node_ids Vector of IDs of the units for which data is read. @@ -927,61 +879,28 @@ IOResult export_input_data_county_timeseries(std::vector, const std * * @return An IOResult indicating success or failure. */ -template -IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, +template +IOResult read_input_data(mio::VectorRange>& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days, - const std::vector> immunity_population, - const std::string& vaccination_data_file_name, const std::string& divi_data_file_name, - const std::string& confirmed_cases_data_file_name, const std::string& population_data_file_name) + int num_days, const std::vector> immunity_population, + const mio::regions::de::EpidataFilenames& epidata_filenames) { BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, path_join(pydata_dir, vaccination_data_file_name), date, node_ids, num_days)); + details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, node_ids, num_days)); // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, divi_data_file_name), node_ids, date, + BOOST_OUTCOME_TRY(set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, date, scaling_factor_inf, immunity_population)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, population_data_file_name), node_ids, + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, node_ids, immunity_population)); return success(); } -/** - * @brief Reads input data for specified counties and initializes the model accordingly. - * - * This function loads real-world data for specified counties and initializes - * the corresponding model compartments. Optionally, it can extrapolate real-world data - * using the export_input_data_county_timeseries function. - * - * @tparam Model The model type used. - * - * @param[in,out] model Vector of model objects that will be initialized with the input data. - * @param[in] date The starting date for the simulation. - * @param[in] county Vector of county IDs for which the data is read. - * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. - * @param[in] scaling_factor_icu Scaling factor for ICU data. - * @param[in] pydata_dir Path to the directory containing input data files. - * @param[in] num_days The number of days for which the simulation runs. - * @param[in] immunity_population Vector of vectors representing immunity proportions for each age group and immunity layer. - * - * @return An IOResult indicating success or failure. - */ -template -IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days, - const std::vector> immunity_population) -{ - BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, immunity_population, - "vacc_county_ageinf_ma7.json", "county_divi_ma7.json", "cases_all_county_age_ma7.json", "county_current_population.json")); - return success(); -} - } // namespace osecirts } // namespace mio diff --git a/cpp/models/ode_secirvvs/parameters_io.cpp b/cpp/models/ode_secirvvs/parameters_io.cpp index b1f0dcddb2..300c6cedd9 100644 --- a/cpp/models/ode_secirvvs/parameters_io.cpp +++ b/cpp/models/ode_secirvvs/parameters_io.cpp @@ -29,40 +29,23 @@ namespace osecirvvs { namespace details { -IOResult read_confirmed_cases_data( - std::string const& path, std::vector const& vregion, Date date, std::vector>& vnum_Exposed, - std::vector>& vnum_InfectedNoSymptoms, std::vector>& vnum_InfectedSymptoms, - std::vector>& vnum_InfectedSevere, std::vector>& vnum_icu, - std::vector>& vnum_death, std::vector>& vnum_rec, - const std::vector>& vt_Exposed, const std::vector>& vt_InfectedNoSymptoms, - const std::vector>& vt_InfectedSymptoms, const std::vector>& vt_InfectedSevere, - const std::vector>& vt_InfectedCritical, const std::vector>& vmu_C_R, - const std::vector>& vmu_I_H, const std::vector>& vmu_H_U, - const std::vector& scaling_factor_inf) -{ - BOOST_OUTCOME_TRY(auto&& rki_data, mio::read_confirmed_cases_data(path)); - return read_confirmed_cases_data(rki_data, vregion, date, vnum_Exposed, vnum_InfectedNoSymptoms, - vnum_InfectedSymptoms, vnum_InfectedSevere, vnum_icu, vnum_death, vnum_rec, - vt_Exposed, vt_InfectedNoSymptoms, vt_InfectedSymptoms, vt_InfectedSevere, - vt_InfectedCritical, vmu_C_R, vmu_I_H, vmu_H_U, scaling_factor_inf); -} -IOResult read_confirmed_cases_data( - const std::vector& rki_data, std::vector const& vregion, Date date, - std::vector>& vnum_Exposed, std::vector>& vnum_InfectedNoSymptoms, - std::vector>& vnum_InfectedSymptoms, std::vector>& vnum_InfectedSevere, - std::vector>& vnum_icu, std::vector>& vnum_death, - std::vector>& vnum_rec, const std::vector>& vt_Exposed, - const std::vector>& vt_InfectedNoSymptoms, - const std::vector>& vt_InfectedSymptoms, const std::vector>& vt_InfectedSevere, - const std::vector>& vt_InfectedCritical, const std::vector>& vmu_C_R, - const std::vector>& vmu_I_H, const std::vector>& vmu_H_U, +IOResult compute_confirmed_cases_data( + const std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, + const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, const std::vector& scaling_factor_inf) { - auto max_date_entry = std::max_element(rki_data.begin(), rki_data.end(), [](auto&& a, auto&& b) { + auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; }); - if (max_date_entry == rki_data.end()) { + if (max_date_entry == case_data.end()) { log_error("RKI data file is empty."); return failure(StatusCode::InvalidValue, "RKI data is empty."); } @@ -80,130 +63,93 @@ IOResult read_confirmed_cases_data( days_surplus = 0; } - for (auto&& entry : rki_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { - return r == 0 || get_region_id(entry) == r; - }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - - auto& t_Exposed = vt_Exposed[region_idx]; - auto& t_InfectedNoSymptoms = vt_InfectedNoSymptoms[region_idx]; - auto& t_InfectedSymptoms = vt_InfectedSymptoms[region_idx]; - auto& t_InfectedSevere = vt_InfectedSevere[region_idx]; - auto& t_InfectedCritical = vt_InfectedCritical[region_idx]; - - auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx]; - auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx]; - auto& num_rec = vnum_rec[region_idx]; - auto& num_Exposed = vnum_Exposed[region_idx]; - auto& num_InfectedSevere = vnum_InfectedSevere[region_idx]; - auto& num_death = vnum_death[region_idx]; - auto& num_icu = vnum_icu[region_idx]; - - auto& mu_C_R = vmu_C_R[region_idx]; - auto& mu_I_H = vmu_I_H[region_idx]; - auto& mu_H_U = vmu_H_U[region_idx]; - - auto age = (size_t)entry.age_group; - if (entry.date == offset_date_by_days(date, 0)) { - num_InfectedSymptoms[age] += scaling_factor_inf[age] * entry.num_confirmed; - num_rec[age] += entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, t_InfectedNoSymptoms[age] + days_surplus)) { - num_InfectedNoSymptoms[age] += 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; - num_Exposed[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, days_surplus)) { - num_InfectedNoSymptoms[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, t_Exposed[age] + t_InfectedNoSymptoms[age] + days_surplus)) { - num_Exposed[age] += 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms[age])) { - num_InfectedSymptoms[age] -= scaling_factor_inf[age] * entry.num_confirmed; - num_InfectedSevere[age] += mu_I_H[age] * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age])) { - num_InfectedSevere[age] -= mu_I_H[age] * scaling_factor_inf[age] * entry.num_confirmed; - num_icu[age] += mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * entry.num_confirmed; - } - if (entry.date == - offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age] - t_InfectedCritical[age])) { - num_death[age] += entry.num_deaths; - num_icu[age] -= mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * entry.num_confirmed; - } + for (auto&& entry : case_data) { + + auto age = (size_t)entry.age_group; + if (entry.date == offset_date_by_days(date, 0)) { + num_InfectedSymptoms[age] += scaling_factor_inf[age] * entry.num_confirmed; + num_rec[age] += entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, t_InfectedNoSymptoms[age] + days_surplus)) { + num_InfectedNoSymptoms[age] += 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + num_Exposed[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, days_surplus)) { + num_InfectedNoSymptoms[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, t_Exposed[age] + t_InfectedNoSymptoms[age] + days_surplus)) { + num_Exposed[age] += 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms[age])) { + num_InfectedSymptoms[age] -= scaling_factor_inf[age] * entry.num_confirmed; + num_InfectedSevere[age] += mu_I_H[age] * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age])) { + num_InfectedSevere[age] -= mu_I_H[age] * scaling_factor_inf[age] * entry.num_confirmed; + num_icu[age] += mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == + offset_date_by_days(date, -t_InfectedSymptoms[age] - t_InfectedSevere[age] - t_InfectedCritical[age])) { + num_death[age] += entry.num_deaths; + num_icu[age] -= mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * entry.num_confirmed; } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - auto region = vregion[region_idx]; - - auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx]; - auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx]; - auto& num_rec = vnum_rec[region_idx]; - auto& num_Exposed = vnum_Exposed[region_idx]; - auto& num_InfectedSevere = vnum_InfectedSevere[region_idx]; - auto& num_death = vnum_death[region_idx]; - auto& num_icu = vnum_icu[region_idx]; - - size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size(); - for (size_t i = 0; i < num_groups; i++) { - // subtract infected confirmed cases which are not yet recovered - // and remove dark figure scaling factor - num_rec[i] -= num_InfectedSymptoms[i] / scaling_factor_inf[i]; - num_rec[i] -= num_InfectedSevere[i] / scaling_factor_inf[i]; - num_rec[i] -= - num_icu[i] / - scaling_factor_inf[i]; // TODO: this has to be adapted for scaling_factor_inf != 1 or != ***_icu - num_rec[i] -= num_death[i] / scaling_factor_inf[i]; - auto try_fix_constraints = [region, i](double& value, double error, auto str) { - if (value < error) { - // this should probably return a failure - // but the algorithm is not robust enough to avoid large negative - // values and there are tests that rely on it - log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " - "exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - else if (value < 0) { - log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " - "automatically corrected", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - }; - - try_fix_constraints(num_InfectedSymptoms[i], -5, "InfectedSymptoms"); - try_fix_constraints(num_InfectedNoSymptoms[i], -5, "InfectedNoSymptoms"); - try_fix_constraints(num_Exposed[i], -5, "Exposed"); - try_fix_constraints(num_InfectedSevere[i], -5, "InfectedSevere"); - try_fix_constraints(num_death[i], -5, "Dead"); - try_fix_constraints(num_icu[i], -5, "InfectedCritical"); - try_fix_constraints(num_rec[i], -20, "Recovered or vaccinated"); - } + for (size_t i = 0; i < ConfirmedCasesDataEntry::age_group_names.size(); i++) { + // subtract infected confirmed cases which are not yet recovered + // and remove dark figure scaling factor + num_rec[i] -= num_InfectedSymptoms[i] / scaling_factor_inf[i]; + num_rec[i] -= num_InfectedSevere[i] / scaling_factor_inf[i]; + num_rec[i] -= + num_icu[i] / + scaling_factor_inf[i]; // TODO: this has to be adapted for scaling_factor_inf != 1 or != ***_icu + num_rec[i] -= num_death[i] / scaling_factor_inf[i]; + auto try_fix_constraints = [region, i](double& value, double error, auto str) { + if (value < error) { + // this should probably return a failure + // but the algorithm is not robust enough to avoid large negative + // values and there are tests that rely on it + log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " + "exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + else if (value < 0) { + log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " + "automatically corrected", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + }; + + try_fix_constraints(num_InfectedSymptoms[i], -5, "InfectedSymptoms"); + try_fix_constraints(num_InfectedNoSymptoms[i], -5, "InfectedNoSymptoms"); + try_fix_constraints(num_Exposed[i], -5, "Exposed"); + try_fix_constraints(num_InfectedSevere[i], -5, "InfectedSevere"); + try_fix_constraints(num_death[i], -5, "Dead"); + try_fix_constraints(num_icu[i], -5, "InfectedCritical"); + try_fix_constraints(num_rec[i], -20, "Recovered or vaccinated"); } return success(); } -IOResult read_confirmed_cases_data_fix_recovered(std::string const& path, std::vector const& vregion, - Date date, std::vector>& vnum_rec, - double delay) +IOResult compute_confirmed_cases_data_fix_recovered(std::string const& path, std::vector const& vregion, + Date date, std::vector>& vnum_rec, + double delay) { - BOOST_OUTCOME_TRY(auto&& rki_data, mio::read_confirmed_cases_data(path)); - return read_confirmed_cases_data_fix_recovered(rki_data, vregion, date, vnum_rec, delay); + BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); + return compute_confirmed_cases_data_fix_recovered(case_data, vregion, date, vnum_rec, delay); } -IOResult read_confirmed_cases_data_fix_recovered(const std::vector& rki_data, - std::vector const& vregion, Date date, - std::vector>& vnum_rec, double delay) +IOResult compute_confirmed_cases_data_fix_recovered(const std::vector& case_data, + std::vector const& vregion, Date date, + std::vector>& vnum_rec, double delay) { - auto max_date_entry = std::max_element(rki_data.begin(), rki_data.end(), [](auto&& a, auto&& b) { + auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; }); - if (max_date_entry == rki_data.end()) { + if (max_date_entry == case_data.end()) { log_error("RKI data is empty."); return failure(StatusCode::InvalidValue, "RKI data is empty."); } @@ -221,7 +167,7 @@ IOResult read_confirmed_cases_data_fix_recovered(const std::vector read_confirmed_cases_data( - std::string const& path, std::vector const& vregion, Date date, std::vector>& num_Exposed, - std::vector>& num_InfectedNoSymptoms, std::vector>& num_InfectedSymptoms, - std::vector>& num_InfectedSevere, std::vector>& num_icu, - std::vector>& num_death, std::vector>& num_rec, - const std::vector>& t_Exposed, const std::vector>& t_InfectedNoSymptoms, - const std::vector>& t_InfectedSymptoms, const std::vector>& t_InfectedSevere, - const std::vector>& t_InfectedCritical, const std::vector>& mu_C_R, - const std::vector>& mu_I_H, const std::vector>& mu_H_U, - const std::vector& scaling_factor_inf); -IOResult read_confirmed_cases_data( - const std::vector& rki_data, std::vector const& vregion, Date date, - std::vector>& num_Exposed, std::vector>& num_InfectedNoSymptoms, - std::vector>& num_InfectedSymptoms, std::vector>& num_InfectedSevere, - std::vector>& num_icu, std::vector>& num_death, - std::vector>& num_rec, const std::vector>& t_Exposed, - const std::vector>& t_InfectedNoSymptoms, const std::vector>& t_InfectedSymptoms, - const std::vector>& t_InfectedSevere, const std::vector>& t_InfectedCritical, - const std::vector>& mu_C_R, const std::vector>& mu_I_H, - const std::vector>& mu_H_U, const std::vector& scaling_factor_inf); +IOResult compute_confirmed_cases_data( + const std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, + const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& scaling_factor_inf); /**@}*/ /** @@ -85,12 +65,12 @@ IOResult read_confirmed_cases_data( * @see mio::read_confirmed_cases_data * @{ */ -IOResult read_confirmed_cases_data_fix_recovered(const std::vector& rki_data, - std::vector const& vregion, Date date, - std::vector>& vnum_rec, double delay = 14.); -IOResult read_confirmed_cases_data_fix_recovered(std::string const& path, std::vector const& vregion, - Date date, std::vector>& vnum_rec, - double delay = 14.); +IOResult compute_confirmed_cases_data_fix_recovered(const std::vector& rki_data, + std::vector const& vregion, Date date, + std::vector>& vnum_rec, double delay = 14.); +IOResult compute_confirmed_cases_data_fix_recovered(std::string const& path, std::vector const& vregion, + Date date, std::vector>& vnum_rec, + double delay = 14.); /**@}*/ /** @@ -102,274 +82,242 @@ IOResult read_confirmed_cases_data_fix_recovered(std::string const& path, * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of RKI data. * @param[in] set_death If true, set the number of deaths. */ -template -IOResult set_confirmed_cases_data(std::vector& model, - const std::vector& case_data, - std::vector const& region, Date date, - const std::vector& scaling_factor_inf, bool set_death = false) +template +IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, + bool set_death = false) { - auto num_age_groups = (size_t)model[0].parameters.get_num_groups(); + auto num_age_groups = (size_t)model.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups); - std::vector> t_Exposed{model.size()}; - std::vector> t_InfectedNoSymptoms{model.size()}; - std::vector> t_InfectedSymptoms{model.size()}; - std::vector> t_InfectedSevere{model.size()}; - std::vector> t_InfectedCritical{model.size()}; + std::vector t_Exposed; + std::vector t_InfectedNoSymptoms; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; - std::vector> mu_C_R{model.size()}; - std::vector> mu_I_H{model.size()}; - std::vector> mu_H_U{model.size()}; + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; - std::vector> num_InfectedSymptoms(model.size()); - std::vector> num_death(model.size()); - std::vector> num_rec(model.size()); - std::vector> num_Exposed(model.size()); - std::vector> num_InfectedNoSymptoms(model.size()); - std::vector> num_InfectedSevere(model.size()); - std::vector> num_icu(model.size()); + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_rec(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); /*----------- UNVACCINATED -----------*/ - for (size_t county = 0; county < model.size(); county++) { - num_InfectedSymptoms[county] = std::vector(num_age_groups, 0.0); - num_death[county] = std::vector(num_age_groups, 0.0); - num_rec[county] = std::vector(num_age_groups, 0.0); - num_Exposed[county] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[county] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[county] = std::vector(num_age_groups, 0.0); - num_icu[county] = std::vector(num_age_groups, 0.0); - for (size_t group = 0; group < num_age_groups; group++) { - - t_Exposed[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedSymptoms[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedSevere[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - - mu_C_R[county].push_back( - model[county].parameters.template get>()[(AgeGroup)group]); - mu_I_H[county].push_back( - model[county].parameters.template get>()[(AgeGroup)group]); - mu_H_U[county].push_back( - model[county].parameters.template get>()[(AgeGroup)group]); - } + for (size_t group = 0; group < num_age_groups; group++) { + + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + mu_C_R.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back( + model.parameters.template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(read_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); - - for (size_t county = 0; county < model.size(); county++) { - // if (std::accumulate( - // num_InfectedSymptoms[county].begin(), - // num_InfectedSymptoms[county].end(), - // double(0.0), - // [](const double& a, const double& b) { return evaluate_intermediate(a + b); } - // ) > 0) - // { - size_t num_groups = (size_t)model[county].parameters.get_num_groups(); - for (size_t i = 0; i < num_groups; i++) { - model[county].populations[{AgeGroup(i), InfectionState::ExposedNaive}] = num_Exposed[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = - num_InfectedNoSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = - num_InfectedSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = - num_InfectedSevere[county][i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = num_icu[county][i]; - } - model[county].populations[{AgeGroup(i), InfectionState::SusceptibleImprovedImmunity}] = num_rec[county][i]; - if (set_death) { - // in set_confirmed_cases_data initilization, deaths are now set to 0. In order to visualize - // the extrapolated real number of deaths, they have to be set here. In the comparison of data - // it has to be paid attention to the fact, the the simulation starts with deaths=0 - // while this method starts with deaths=number of reported deaths so far... - // Additionally, we set the number of reported deaths to DeadNaive since no information on that is - // available here. - // Do only add deaths after substraction. - model[county].populations[{AgeGroup(i), InfectionState::DeadNaive}] = num_death[county][i]; - } + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); + + + size_t num_groups = (size_t)model.parameters.get_num_groups(); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = + num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = + num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = num_icu[i]; } - - // } - if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) == 0.0) { - log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region[county]); + model.populations[{AgeGroup(i), InfectionState::SusceptibleImprovedImmunity}] = num_rec[i]; + if (set_death) { + // in set_confirmed_cases_data initilization, deaths are now set to 0. In order to visualize + // the extrapolated real number of deaths, they have to be set here. In the comparison of data + // it has to be paid attention to the fact, the the simulation starts with deaths=0 + // while this method starts with deaths=number of reported deaths so far... + // Additionally, we set the number of reported deaths to DeadNaive since no information on that is + // available here. + // Do only add deaths after substraction. + model.populations[{AgeGroup(i), InfectionState::DeadNaive}] = num_death[i]; } } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), + [](const double& a, const double& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning( + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", + date, region); + } /*----------- PARTIALLY VACCINATED -----------*/ - for (size_t county = 0; county < model.size(); county++) { - t_InfectedNoSymptoms[county].clear(); - t_Exposed[county].clear(); - t_InfectedSymptoms[county].clear(); - t_InfectedSevere[county].clear(); - t_InfectedCritical[county].clear(); - - mu_C_R[county].clear(); - mu_I_H[county].clear(); - mu_H_U[county].clear(); - - num_InfectedSymptoms[county] = std::vector(num_age_groups, 0.0); - num_death[county] = std::vector(num_age_groups, 0.0); - num_rec[county] = std::vector(num_age_groups, 0.0); - num_Exposed[county] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[county] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[county] = std::vector(num_age_groups, 0.0); - num_icu[county] = std::vector(num_age_groups, 0.0); - for (size_t group = 0; group < num_age_groups; group++) { - double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; - t_Exposed[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms[county].push_back(static_cast(std::round( - model[county].parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSymptoms[county].push_back(static_cast(std::round( - model[county].parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSevere[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - - double exp_fac_part_immune = - model[county].parameters.template get>()[(AgeGroup)group]; - double inf_fac_part_immune = - model[county].parameters.template get>()[(AgeGroup)group]; - double hosp_fac_part_immune = - model[county] - .parameters.template get>()[(AgeGroup)group]; - double icu_fac_part_immune = - model[county] - .parameters.template get>()[(AgeGroup)group]; - mu_C_R[county].push_back(( - 1 - inf_fac_part_immune / exp_fac_part_immune * - (1 - model[county] - .parameters.template get>()[(AgeGroup)group]))); - mu_I_H[county].push_back( - hosp_fac_part_immune / inf_fac_part_immune * - model[county].parameters.template get>()[(AgeGroup)group]); - // transfer from H to U, D unchanged. - mu_H_U[county].push_back( - icu_fac_part_immune / hosp_fac_part_immune * - model[county].parameters.template get>()[(AgeGroup)group]); - } + t_InfectedNoSymptoms.clear(); + t_Exposed.clear(); + t_InfectedSymptoms.clear(); + t_InfectedSevere.clear(); + t_InfectedCritical.clear(); + + mu_C_R.clear(); + mu_I_H.clear(); + mu_H_U.clear(); + + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_rec = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + for (size_t group = 0; group < num_age_groups; group++) { + double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + double exp_fac_part_immune = + model.parameters.template get>()[(AgeGroup)group]; + double inf_fac_part_immune = + model.parameters.template get>()[(AgeGroup)group]; + double hosp_fac_part_immune = + model + .parameters.template get>()[(AgeGroup)group]; + double icu_fac_part_immune = + model + .parameters.template get>()[(AgeGroup)group]; + mu_C_R.push_back(( + 1 - inf_fac_part_immune / exp_fac_part_immune * + (1 - model + .parameters.template get>()[(AgeGroup)group]))); + mu_I_H.push_back( + hosp_fac_part_immune / inf_fac_part_immune * + model.parameters.template get>()[(AgeGroup)group]); + // transfer from H to U, D unchanged. + mu_H_U.push_back( + icu_fac_part_immune / hosp_fac_part_immune * + model.parameters.template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(read_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); - - for (size_t county = 0; county < model.size(); county++) { - // if (std::accumulate( - // num_InfectedSymptoms[county].begin(), - // num_InfectedSymptoms[county].end(), - // double(0.0), - // [](const double& a, const double& b) { return evaluate_intermediate(a + b); } - // ) > 0) - // { - size_t num_groups = (size_t)model[county].parameters.get_num_groups(); - for (size_t i = 0; i < num_groups; i++) { - model[county].populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = num_Exposed[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = - num_InfectedNoSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = - num_InfectedSymptoms[county][i]; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; - model[county].populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = - num_InfectedSevere[county][i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = - num_icu[county][i]; - } - } - // } - if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) == 0.0) { - log_warning("No infections for partially vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region[county]); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); + + + size_t num_groups = (size_t)model.parameters.get_num_groups(); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = + num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = + num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = + num_icu[i]; } } + // } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), + [](const double& a, const double& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning("No infections for partially vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); + } /*----------- FULLY VACCINATED -----------*/ - for (size_t county = 0; county < model.size(); county++) { - t_InfectedNoSymptoms[county].clear(); - t_Exposed[county].clear(); - t_InfectedSymptoms[county].clear(); - t_InfectedSevere[county].clear(); - t_InfectedCritical[county].clear(); - - mu_C_R[county].clear(); - mu_I_H[county].clear(); - mu_H_U[county].clear(); - - num_InfectedSymptoms[county] = std::vector(num_age_groups, 0.0); - num_death[county] = std::vector(num_age_groups, 0.0); - num_rec[county] = std::vector(num_age_groups, 0.0); - num_Exposed[county] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[county] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[county] = std::vector(num_age_groups, 0.0); - num_icu[county] = std::vector(num_age_groups, 0.0); - for (size_t group = 0; group < num_age_groups; group++) { - double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; - t_Exposed[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms[county].push_back(static_cast(std::round( - model[county].parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSymptoms[county].push_back(static_cast(std::round( - model[county].parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSevere[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical[county].push_back(static_cast( - std::round(model[county].parameters.template get>()[(AgeGroup)group]))); - - double reduc_immune_exp = - model[county].parameters.template get>()[(AgeGroup)group]; - double reduc_immune_inf = - model[county].parameters.template get>()[(AgeGroup)group]; - double reduc_immune_hosp = - model[county].parameters.template get>()[( - AgeGroup)group]; - double reduc_immune_icu = - model[county].parameters.template get>()[( - AgeGroup)group]; - mu_C_R[county].push_back(( - 1 - reduc_immune_inf / reduc_immune_exp * - (1 - model[county] - .parameters.template get>()[(AgeGroup)group]))); - mu_I_H[county].push_back( - reduc_immune_hosp / reduc_immune_inf * - model[county].parameters.template get>()[(AgeGroup)group]); - // transfer from H to U, D unchanged. - mu_H_U[county].push_back( - reduc_immune_icu / reduc_immune_hosp * - model[county].parameters.template get>()[(AgeGroup)group]); - } + t_InfectedNoSymptoms.clear(); + t_Exposed.clear(); + t_InfectedSymptoms.clear(); + t_InfectedSevere.clear(); + t_InfectedCritical.clear(); + + mu_C_R.clear(); + mu_I_H.clear(); + mu_H_U.clear(); + + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_rec = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + for (size_t group = 0; group < num_age_groups; group++) { + double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + double reduc_immune_exp = + model.parameters.template get>()[(AgeGroup)group]; + double reduc_immune_inf = + model.parameters.template get>()[(AgeGroup)group]; + double reduc_immune_hosp = + model.parameters.template get>()[( + AgeGroup)group]; + double reduc_immune_icu = + model.parameters.template get>()[( + AgeGroup)group]; + mu_C_R.push_back(( + 1 - reduc_immune_inf / reduc_immune_exp * + (1 - model + .parameters.template get>()[(AgeGroup)group]))); + mu_I_H.push_back( + reduc_immune_hosp / reduc_immune_inf * + model.parameters.template get>()[(AgeGroup)group]); + // transfer from H to U, D unchanged. + mu_H_U.push_back( + reduc_immune_icu / reduc_immune_hosp * + model.parameters.template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(read_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); for (size_t county = 0; county < model.size(); county++) { size_t num_groups = (size_t)model[county].parameters.get_num_groups(); @@ -413,13 +361,28 @@ IOResult set_confirmed_cases_data(std::vector& model, * rki data * @param set_death[in] If true, set the number of deaths. */ -template -IOResult set_confirmed_cases_data(std::vector& model, const std::string& path, - std::vector const& region, Date date, +template +IOResult set_confirmed_cases_data(mio::VectorRange>& model, const std::string& path, + std::vector const& vregion, Date date, const std::vector& scaling_factor_inf, bool set_death = false) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - BOOST_OUTCOME_TRY(set_confirmed_cases_data(model, case_data, region, date, scaling_factor_inf, set_death)); + + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { + return r == 0 || get_region_id(entry) == r; + }); + if (it != vregion.end()) { + auto region_idx = size_t(it - vregion.begin()); + vcase_data[region_idx].pushback(entry); + } + } + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_confirmed_cases_data(model[region_idx], vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, set_death)); + } return success(); } @@ -427,191 +390,181 @@ IOResult set_confirmed_cases_data(std::vector& model, const std::st * @brief sets population data from census data which has been read into num_population * @param[in, out] model vector of objects in which the data is set * @param[in] num_population vector of population data -* @param[in] case_data vector of case data. Each inner vector represents a different region * @param[in] vregion vector of keys of the regions of interest * @param[in] date Date for which the arrays are initialized */ -template -IOResult set_population_data(std::vector& model, const std::vector>& num_population, - const std::vector& case_data, - const std::vector& vregion, Date date) +template +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region, const std::vector& num_rec) { - auto num_age_groups = ConfirmedCasesDataEntry::age_group_names.size(); - std::vector> vnum_rec(model.size(), std::vector(num_age_groups, 0.0)); - - BOOST_OUTCOME_TRY(read_confirmed_cases_data_fix_recovered(case_data, vregion, date, vnum_rec, 14.)); - - for (size_t region = 0; region < vregion.size(); region++) { - - if (std::accumulate(num_population[region].begin(), num_population[region].end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) <= 0) - { - log_warning("No population data available for region " + std::to_string(region) + - ". Population data has not been set."); - continue; + if (std::accumulate(num_population.begin(), num_population.end(), double(0.0), + [](const double& a, const double& b) { + return evaluate_intermediate(a + b); + }) <= 0) + { + log_warning("No population data available for region " + std::to_string(region) + + ". Population data has not been set."); + return success(); + } + + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + + double S_v = std::min( + model.parameters.template get>()[{i, SimulationDay(0)}] + + num_rec[size_t(i)], + num_population[size_t(i)]); + double S_pv = std::max( + model.parameters.template get>()[{i, SimulationDay(0)}] - + model.parameters.template get>()[{i, SimulationDay(0)}], + 0.0); // use std::max with 0 + double S; + if (num_population[size_t(i)] - S_pv - S_v < 0.0) { + log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", + region, size_t(i)); + S = 0.0; + S_v = num_population[size_t(i)] - S_pv; } - - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - - double S_v = std::min( - model[region].parameters.template get>()[{i, SimulationDay(0)}] + - vnum_rec[region][size_t(i)], - num_population[region][size_t(i)]); - double S_pv = std::max( - model[region].parameters.template get>()[{i, SimulationDay(0)}] - - model[region].parameters.template get>()[{i, SimulationDay(0)}], - 0.0); // use std::max with 0 - double S; - if (num_population[region][size_t(i)] - S_pv - S_v < 0.0) { - log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", - region, size_t(i)); - S = 0.0; - S_v = num_population[region][size_t(i)] - S_pv; - } - else { - S = num_population[region][size_t(i)] - S_pv - S_v; - } - - double denom_E = - 1 / (S + S_pv * model[region].parameters.template get>()[i] + - S_v * model[region].parameters.template get>()[i]); - double denom_C = - 1 / (S + S_pv * model[region].parameters.template get>()[i] + - S_v * model[region].parameters.template get>()[i]); - double denom_I = - 1 / - (S + - S_pv * model[region].parameters.template get>()[i] + - S_v * model[region].parameters.template get>()[i]); - double denom_HU = - 1 / - (S + - S_pv * model[region] - .parameters.template get>()[i] + - S_v * model[region] - .parameters.template get>()[i]); - - model[region].populations[{i, InfectionState::ExposedNaive}] = - S * model[region].populations[{i, InfectionState::ExposedNaive}] * denom_E; - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] = - S_pv * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] * denom_E; - model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] = - S_v * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] * denom_E; - - model[region].populations[{i, InfectionState::InfectedNoSymptomsNaive}] = - S * model[region].populations[{i, InfectionState::InfectedNoSymptomsNaive}] * denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] = - S_pv * model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] * denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] = - S_v * model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] * denom_C; - - model[region].populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] = - S * model[region].populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] * denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = - S_pv * model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] * - denom_C; - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = - S_v * model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] * - denom_C; - - model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] = - S * model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] = - S_pv * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] = - S_v * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] * denom_I; - - model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] = - S * model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = - S_pv * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] * denom_I; - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = - S_v * model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] * denom_I; - - model[region].populations[{i, InfectionState::InfectedSevereNaive}] = - S * model[region].populations[{i, InfectionState::InfectedSevereNaive}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] = - S_pv * - model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] = - S_v * - model[region] - .parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] * denom_HU; - - model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] = - S_pv * - model[region].parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] = - S_v * - model[region] - .parameters.template get>()[i] * - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] = - S * model[region].populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - - model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = - model[region].parameters.template get>()[{i, SimulationDay(0)}] + - model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] - - (model[region].populations[{i, InfectionState::InfectedSymptomsNaive}] + - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + - model[region].populations[{i, InfectionState::InfectedSevereNaive}] + - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] + - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] + - model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + - model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + - model[region].populations[{i, InfectionState::DeadNaive}] + - model[region].populations[{i, InfectionState::DeadPartialImmunity}] + - model[region].populations[{i, InfectionState::DeadImprovedImmunity}]); - - model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::min( - S_v - model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - - model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - - model[region].populations[{i, InfectionState::DeadImprovedImmunity}], - std::max(0.0, double(model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); - - model[region].populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( - 0.0, - S_pv - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - - model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] - - model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - - model[region].populations[{i, InfectionState::DeadPartialImmunity}]); - - model[region].populations.template set_difference_from_group_total( - {i, InfectionState::SusceptibleNaive}, num_population[region][size_t(i)]); + else { + S = num_population[size_t(i)] - S_pv - S_v; } - for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { - for (auto j = Index(0); j < InfectionState::Count; ++j) { - if (model[region].populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model[region].populations[{i, j}] / num_population[region][size_t(i)]); - } + double denom_E = + 1 / (S + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); + double denom_C = + 1 / (S + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); + double denom_I = + 1 / + (S + + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); + double denom_HU = + 1 / + (S + + S_pv * model + .parameters.template get>()[i] + + S_v * model + .parameters.template get>()[i]); + + model.populations[{i, InfectionState::ExposedNaive}] = + S * model.populations[{i, InfectionState::ExposedNaive}] * denom_E; + model.populations[{i, InfectionState::ExposedPartialImmunity}] = + S_pv * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::ExposedPartialImmunity}] * denom_E; + model.populations[{i, InfectionState::ExposedImprovedImmunity}] = + S_v * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::ExposedImprovedImmunity}] * denom_E; + + model.populations[{i, InfectionState::InfectedNoSymptomsNaive}] = + S * model.populations[{i, InfectionState::InfectedNoSymptomsNaive}] * denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] = + S_pv * model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] * denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] = + S_v * model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] * denom_C; + + model.populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] = + S * model.populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] * denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = + S_pv * model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] * + denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = + S_v * model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] * + denom_C; + + model.populations[{i, InfectionState::InfectedSymptomsNaive}] = + S * model.populations[{i, InfectionState::InfectedSymptomsNaive}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] = + S_pv * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] = + S_v * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] * denom_I; + + model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] = + S * model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = + S_pv * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = + S_v * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] * denom_I; + + model.populations[{i, InfectionState::InfectedSevereNaive}] = + S * model.populations[{i, InfectionState::InfectedSevereNaive}] * denom_HU; + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] = + S_pv * + model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] * denom_HU; + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] = + S_v * + model + .parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] * denom_HU; + + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] = + S_pv * + model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] = + S_v * + model + .parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + model.populations[{i, InfectionState::InfectedCriticalNaive}] = + S * model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = + model.parameters.template get>()[{i, SimulationDay(0)}] + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] - + (model.populations[{i, InfectionState::InfectedSymptomsNaive}] + + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSevereNaive}] + + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] + + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalNaive}] + + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + + model.populations[{i, InfectionState::DeadNaive}] + + model.populations[{i, InfectionState::DeadPartialImmunity}] + + model.populations[{i, InfectionState::DeadImprovedImmunity}]); + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::min( + S_v - model.populations[{i, InfectionState::ExposedImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - + model.populations[{i, InfectionState::DeadImprovedImmunity}], + std::max(0.0, double(model.populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); + + model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( + 0.0, + S_pv - model.populations[{i, InfectionState::ExposedPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - + model.populations[{i, InfectionState::DeadPartialImmunity}]); + + model.populations.template set_difference_from_group_total( + {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); + } + + for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { + for (auto j = Index(0); j < InfectionState::Count; ++j) { + if (model.populations[{i, j}] < 0) { + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), + size_t(j), model.populations[{i, j}] / num_population[size_t(i)]); } } } @@ -627,14 +580,21 @@ IOResult set_population_data(std::vector& model, const std::vector< * @param[in] vregion Vector of keys of the regions of interest. * @param[in] date Date for which the arrays are initialized. */ -template -IOResult set_population_data(std::vector& model, const std::string& path, const std::string& path_rki, +template +IOResult set_population_data(mio::VectorRange>& model, const std::string& path, const std::string& path_rki, const std::vector& vregion, Date date) { - BOOST_OUTCOME_TRY(auto&& num_population, read_population_data(path, vregion)); - BOOST_OUTCOME_TRY(auto&& rki_data, mio::read_confirmed_cases_data(path_rki)); + BOOST_OUTCOME_TRY(auto&& vnum_population, read_population_data(path, vregion)); + BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path_rki)); - BOOST_OUTCOME_TRY(set_population_data(model, num_population, rki_data, vregion, date)); + auto num_age_groups = ConfirmedCasesDataEntry::age_group_names.size(); + std::vector> vnum_rec(model.size(), std::vector(num_age_groups, 0.0)); + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data_fix_recovered(case_data, vregion, date, vnum_rec, 14.)); + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_population_data(model[region_idx], vnum_population[region_idx], vregion[region_idx], vnum_rec[region_idx])); + } return success(); } @@ -645,37 +605,12 @@ IOResult set_population_data(std::vector& model, const std::string& * @param[in, out] model Vector of Model objects in which the vaccination data is set. * @param[in] vacc_data Vector of VaccinationDataEntry objects containing the vaccination data. * @param[in] date Start date for the simulation. - * @param[in] vregion Vector of region identifiers. * @param[in] num_days Number of days for which the simulation is run. */ -template -IOResult set_vaccination_data(std::vector>& model, const std::vector& vacc_data, - Date date, const std::vector& vregion, int num_days) +template +IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, + Date date, int num_days) { - auto num_groups = model[0].parameters.get_num_groups(); - - // type conversion from UncertainValue -> FP -> int - auto days_until_effective1 = static_cast( - static_cast(model[0].parameters.template get>()[AgeGroup(0)])); - auto days_until_effective2 = static_cast( - static_cast(model[0].parameters.template get>()[AgeGroup(0)])); - auto vaccination_distance = - static_cast(static_cast(model[0].parameters.template get>()[AgeGroup(0)])); - - // iterate over regions (e.g., counties) - for (size_t i = 0; i < model.size(); ++i) { - // iterate over age groups in region - for (auto g = AgeGroup(0); g < num_groups; ++g) { - - model[i].parameters.template get>().resize(SimulationDay(num_days + 1)); - model[i].parameters.template get>().resize(SimulationDay(num_days + 1)); - for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { - model[i].parameters.template get>()[{g, d}] = 0.0; - model[i].parameters.template get>()[{g, d}] = 0.0; - } - } - } - auto max_date_entry = std::max_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; }); @@ -695,91 +630,87 @@ IOResult set_vaccination_data(std::vector>& model, const std::ve min_date, max_date); } + auto num_groups = model.parameters.get_num_groups(); + + // type conversion from UncertainValue -> FP -> int + auto days_until_effective1 = static_cast( + static_cast(model.parameters.template get>()[AgeGroup(0)])); + auto days_until_effective2 = static_cast( + static_cast(model.parameters.template get>()[AgeGroup(0)])); + auto vaccination_distance = + static_cast(static_cast(model.parameters.template get>()[AgeGroup(0)])); + for (auto&& vacc_data_entry : vacc_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { - return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(r)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(r)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(r)); - }); auto date_df = vacc_data_entry.date; - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - auto age = vacc_data_entry.age_group; - - for (size_t d = 0; d < (size_t)num_days + 1; ++d) { - int days_plus; - // In the following, second dose means previous 'full immunization', now 'Grundimmunisierung'. - // --- - // date: start_date of the simulation (Input from IO call read_input_data_county_vaccmodel()) - // d: day of simulation, counted from 0 to num_days (for which we need (approximated) vaccination numbers) - // root[i]["Vacc_completed"]: accumulated number of total second doses up to day date_df; - // taken from input dataframe, single value, per county and age group - // ---- - // An averaged distance between first and second doses (vaccination_distance) is assumed in the following - // and the first doses are computed based on the second doses given 'vaccination_distance' days later. - // ---- - // a person whose second dose is reported at start_date + simulation_day - days_until_effective1 + vaccination_distance - // had the first dose on start_date + simulation_day - days_until_effective1. Furthermore, he/she has the full protection - // of the first dose at day X = start_date + simulation_day - // Storing its value in get() will eventually (in the simulation) - // transfer the difference (between get() at d and d-1) of - // N susceptible individuals to 'Susceptible Partially Vaccinated' state at day d; see secir_vaccinated.h - auto offset_first_date = - offset_date_by_days(date, (int)d - days_until_effective1 + vaccination_distance); - if (max_date >= offset_first_date) { - // Option 1: considered offset_first_date is available in input data frame - if (date_df == offset_first_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = - vacc_data_entry.num_vaccinations_completed; - } + AgeGroup age = vacc_data_entry.age_group; + + for (size_t d = 0; d < (size_t)num_days + 1; ++d) { + int days_plus; + // In the following, second dose means previous 'full immunization', now 'Grundimmunisierung'. + // --- + // date: start_date of the simulation (Input from IO call read_input_data_county_vaccmodel()) + // d: day of simulation, counted from 0 to num_days (for which we need (approximated) vaccination numbers) + // root[i]["Vacc_completed"]: accumulated number of total second doses up to day date_df; + // taken from input dataframe, single value, per county and age group + // ---- + // An averaged distance between first and second doses (vaccination_distance) is assumed in the following + // and the first doses are computed based on the second doses given 'vaccination_distance' days later. + // ---- + // a person whose second dose is reported at start_date + simulation_day - days_until_effective1 + vaccination_distance + // had the first dose on start_date + simulation_day - days_until_effective1. Furthermore, he/she has the full protection + // of the first dose at day X = start_date + simulation_day + // Storing its value in get() will eventually (in the simulation) + // transfer the difference (between get() at d and d-1) of + // N susceptible individuals to 'Susceptible Partially Vaccinated' state at day d; see secir_vaccinated.h + auto offset_first_date = + offset_date_by_days(date, (int)d - days_until_effective1 + vaccination_distance); + if (max_date >= offset_first_date) { + // Option 1: considered offset_first_date is available in input data frame + if (date_df == offset_first_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = + vacc_data_entry.num_vaccinations_completed; + } + } + else { // offset_first_date > max_date + // Option 2: considered offset_first_date is NOT available in input data frame + // Here, a constant number of first and second doses is assumed, i.e., + // the the number of vaccinationes at day d (N days after max_date) will be: + // total number of vaccinations up to day max_date + N * number of vaccinations ON max_date + // (where the latter is computed as the difference between the total number at max_date and max_date-1) + days_plus = get_offset_in_days(offset_first_date, max_date); + if (date_df == offset_date_by_days(max_date, -1)) { + model.parameters.template get>()[{age, SimulationDay(d)}] -= + days_plus * vacc_data_entry.num_vaccinations_completed; } - else { // offset_first_date > max_date - // Option 2: considered offset_first_date is NOT available in input data frame - // Here, a constant number of first and second doses is assumed, i.e., - // the the number of vaccinationes at day d (N days after max_date) will be: - // total number of vaccinations up to day max_date + N * number of vaccinations ON max_date - // (where the latter is computed as the difference between the total number at max_date and max_date-1) - days_plus = get_offset_in_days(offset_first_date, max_date); - if (date_df == offset_date_by_days(max_date, -1)) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] -= - days_plus * vacc_data_entry.num_vaccinations_completed; - } - else if (date_df == max_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] += - (days_plus + 1) * vacc_data_entry.num_vaccinations_completed; - } + else if (date_df == max_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] += + (days_plus + 1) * vacc_data_entry.num_vaccinations_completed; } + } - // a person whose second dose is reported at start_date + simulation_day - days_until_effective2 - // has the full protection of the second dose at day X = start_date + simulation_day - // Storing its value in get() will eventually (in the simulation) - // transfer the difference (between get() at d and d-1) of - // N susceptible, partially vaccinated individuals to 'SusceptibleImprovedImmunity' state at day d; see secir_vaccinated.h - auto offset_full_date = offset_date_by_days(date, (int)d - days_until_effective2); - if (max_date >= offset_full_date) { - // Option 1: considered offset_full_date is available in input data frame - if (date_df == offset_full_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] = - vacc_data_entry.num_vaccinations_completed; - } + // a person whose second dose is reported at start_date + simulation_day - days_until_effective2 + // has the full protection of the second dose at day X = start_date + simulation_day + // Storing its value in get() will eventually (in the simulation) + // transfer the difference (between get() at d and d-1) of + // N susceptible, partially vaccinated individuals to 'SusceptibleImprovedImmunity' state at day d; see secir_vaccinated.h + auto offset_full_date = offset_date_by_days(date, (int)d - days_until_effective2); + if (max_date >= offset_full_date) { + // Option 1: considered offset_full_date is available in input data frame + if (date_df == offset_full_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] = + vacc_data_entry.num_vaccinations_completed; } - else { // offset_full_date > max_full_date - // Option 2: considered offset_full_date is NOT available in input data frame - days_plus = get_offset_in_days(offset_full_date, max_date); - if (date_df == offset_date_by_days(max_date, -1)) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] -= - days_plus * vacc_data_entry.num_vaccinations_completed; - } - else if (date_df == max_date) { - model[region_idx] - .parameters.template get>()[{age, SimulationDay(d)}] += - (days_plus + 1) * vacc_data_entry.num_vaccinations_completed; - } + } + else { // offset_full_date > max_full_date + // Option 2: considered offset_full_date is NOT available in input data frame + days_plus = get_offset_in_days(offset_full_date, max_date); + if (date_df == offset_date_by_days(max_date, -1)) { + model.parameters.template get>()[{age, SimulationDay(d)}] -= + days_plus * vacc_data_entry.num_vaccinations_completed; + } + else if (date_df == max_date) { + model.parameters.template get>()[{age, SimulationDay(d)}] += + (days_plus + 1) * vacc_data_entry.num_vaccinations_completed; } } } @@ -797,32 +728,50 @@ IOResult set_vaccination_data(std::vector>& model, const std::ve * @param[in] vregion Vector of region identifiers. * @param[in] num_days Number of days for which the simulation is run. */ -template -IOResult set_vaccination_data(std::vector>& model, const std::string& path, Date date, +template +IOResult set_vaccination_data(mio::VectorRange>& model, const std::string& path, Date date, const std::vector& vregion, int num_days) { + // Set vaccination data to 0 for all models + for (auto& m : model) { + m.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.parameters.template get>().resize(SimulationDay(num_days + 1)); + for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { + for (auto a = AgeGroup(0); a < m.parameters.get_num_groups(); ++a) { + m.parameters.template get>()[{a, d}] = 0.0; + m.parameters.template get>()[{a, d}] = 0.0; + } + } + } + // Check if vaccination data is available for the given date range auto end_date = offset_date_by_days(date, num_days); if (!is_vaccination_data_available(date, end_date)) { log_warning("No vaccination data available in range from {} to {}. " "Vaccination data will be set to 0.", date, end_date); - // Set vaccination data to 0 for all models - for (auto& m : model) { - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - - for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { - for (auto a = AgeGroup(0); a < m.parameters.get_num_groups(); ++a) { - m.parameters.template get>()[{a, d}] = 0.0; - m.parameters.template get>()[{a, d}] = 0.0; - } - } - } return success(); } BOOST_OUTCOME_TRY(auto&& vacc_data, read_vaccination_data(path)); - BOOST_OUTCOME_TRY(set_vaccination_data(model, vacc_data, date, vregion, num_days)); + + // Sort case_data into regions and ignore once with no region associated + std::vector> vvacc_data{model.size()}; + for (auto&& vacc_data_entry : vacc_data) { + auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { + return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(r)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(r)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(r)); + }); + if (it != vregion.end()) { + auto region_idx = size_t(it - vregion.begin()); + vvacc_data[region_idx].pushback(vacc_data_entry); + } + } + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx], vacc_data[region_idx], date, num_days)); + } + return success(); } @@ -838,22 +787,22 @@ IOResult set_vaccination_data(std::vector>& model, const std::st * @param[in] models Vector of models in which the data is set. Copy is made to avoid changing the original model. * @param[in] results_dir Path to result files. * @param[in] date Date for which the data should be read. -* @param[in] counties Vector of keys of the counties of interest. +* @param[in] node_ids Vector of keys of the node_ids of interest. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. * @param[in] num_days Number of days to be simulated/initialized. * @param[in] pydata_dir Directory that contains the data files. */ -template -IOResult export_input_data_county_timeseries( - std::vector models, const std::string& results_dir, Date date, const std::vector& counties, +template +IOResult export_input_data_timeseries( + mio::VectorRange> models, const std::string& results_dir, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, - const std::string& pydata_dir) + const mio::regions::de::EpidataFilenames& epidata_filenames) { const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); - assert(models.size() == counties.size()); + assert(models.size() == node_ids.size()); std::vector> extrapolated_data( models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); @@ -861,10 +810,10 @@ IOResult export_input_data_county_timeseries( auto offset_day = offset_date_by_days(date, t); // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data_county(model, date, county, scaling_factor_inf, scaling_factor_icu, - pydata_dir, num_days)); + BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, + num_days, epidata_filenames)); - for (size_t r = 0; r < counties.size(); r++) { + for (size_t r = 0; r < node_ids.size(); r++) { extrapolated_data[r][t] = models[r].get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. @@ -875,7 +824,7 @@ IOResult export_input_data_county_timeseries( } } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast(num_age_groups), + BOOST_OUTCOME_TRY(save_result(extrapolated_data, node_ids, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); @@ -885,10 +834,10 @@ IOResult export_input_data_county_timeseries( return success(); } #else -template -IOResult export_input_data_county_timeseries(std::vector, const std::string&, Date, const std::vector&, +template +IOResult export_input_data_county_timeseries(mio::VectorRange>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, - const std::string&) + const mio::regions::de::EpidataFilenames&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); return success(); @@ -896,65 +845,27 @@ IOResult export_input_data_county_timeseries(std::vector, const std #endif //MEMILIO_HAS_HDF5 -/** - * Reads compartments for German counties at a specified date from data files. - * Estimates all compartments from available data using the model parameters, so the - * model parameters must be set before calling this function. - * Uses data files that contain centered 7-day moving average. - * @param[in, out] model Vector of SECIRVVS models, one per county. - * @param[in] date Date for which the data should be read. - * @param[in] node_ids Ids of the nodes. - * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. - * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. - * @param[in] pydata_dir Directory that contains the data files. - * @param[in] num_days Number of days to be simulated; required to load data for vaccinations during the simulation. - */ -template -IOResult read_input_data(std::vector& model, Date date, const std::vector& node_ids, +template +IOResult read_input_data(mio::VectorRange>& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days, const std::string& vaccination_data_file_name, - const std::string& divi_data_file_name, const std::string& confirmed_cases_data_file_name, - const std::string& population_data_file_name) + int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, path_join(pydata_dir, vaccination_data_file_name), date, node_ids, num_days)); + details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, node_ids, num_days)); // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, divi_data_file_name), node_ids, date, + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, population_data_file_name), - path_join(pydata_dir, confirmed_cases_data_file_name), node_ids, date)); - + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, + epidata_filenames.case_data_path, node_ids, date)); return success(); } -/** - * Reads compartments for German counties at a specified date from data files. - * Estimates all compartments from available data using the model parameters, so the - * model parameters must be set before calling this function. - * Uses data files that contain centered 7-day moving average. - * @param[in, out] model Vector of SECIRVVS models, one per county. - * @param[in] date Date for which the data should be read. - * @param[in] county Ids of the counties. - * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. - * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. - * @param[in] pydata_dir Directory that contains the data files. - */ -template -IOResult read_input_data_county(std::vector& model, Date date, const std::vector& county, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const std::string& pydata_dir, int num_days) -{ - BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, pydata_dir, num_days, - "vacc_county_ageinf_ma7.json", "county_divi_ma7.json", "cases_all_county_age_ma7.json", - "county_current_population.json")); - return success(); -} } // namespace osecirvvs } // namespace mio From 561f657f227562667ef8320639423a7298f7ef36 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 3 Nov 2025 22:07:15 +0000 Subject: [PATCH 03/26] remake divi data --- cpp/memilio/io/parameters_io.h | 69 ---- cpp/models/ode_secir/parameters_io.h | 65 +++- cpp/models/ode_secirts/parameters_io.cpp | 133 +++++++ cpp/models/ode_secirts/parameters_io.h | 446 ++++++++++------------- cpp/models/ode_secirvvs/parameters_io.h | 63 ++++ 5 files changed, 462 insertions(+), 314 deletions(-) diff --git a/cpp/memilio/io/parameters_io.h b/cpp/memilio/io/parameters_io.h index 3d8ebbc279..53128a9f00 100644 --- a/cpp/memilio/io/parameters_io.h +++ b/cpp/memilio/io/parameters_io.h @@ -73,75 +73,6 @@ IOResult> compute_divi_data(const std::vector */ IOResult> read_divi_data(const std::string& path, const std::vector& vregion, Date date); -/** - * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. - * - * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) - * for each region, and sets these values in the model. The ICU cases are distributed across age groups - * using the transition probabilities from severe to critical. - * - * @tparam Model The type of the model used. - * @tparam FP Floating point type (default: double). - * - * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. - * @param[in] num_icu vector of icu data - * @param[in] vregion Vector of region IDs for which the data is computed. - * @param[in] date Date for which the ICU data is computed. - * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. - * - * @return An IOResult indicating success or failure. - */ -template -IOResult set_divi_data(mio::VectorRange& model, const std::vector& num_icu, const std::vector& vregion, - Date date, FP scaling_factor_icu) -{ - std::vector sum_mu_I_U(vregion.size(), 0); - std::vector> mu_I_U{model.size()}; - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - sum_mu_I_U[region] += model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]; - mu_I_U[region].push_back(model[region].parameters.template get>()[i] * - model[region].parameters.template get>()[i]); - } - } - - for (size_t region = 0; region < vregion.size(); region++) { - auto num_groups = model[region].parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - model[region].populations[{i, InfectionState::InfectedCriticalNaive}] = - scaling_factor_icu * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region]; - } - } - - return success(); -} - -/** - * @brief sets populations data from DIVI register into Model - * @param[in, out] model vector of objects in which the data is set - * @param[in] path Path to transformed DIVI file - * @param[in] vregion vector of keys of the regions of interest - * @param[in] date Date for which the arrays are initialized - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data - */ -template -IOResult set_divi_data(mio::VectorRange& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu) -{ - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); - } - BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - BOOST_OUTCOME_TRY(set_divi_data(model, num_icu, vregion, date, scaling_factor_icu)); - return success(); -} - /** * @brief Reads population data from a vector of population data entries. * diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index bdb6306f0a..5f567068f6 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -294,6 +294,69 @@ IOResult set_population_data(mio::VectorRange>& model, const std return success(); } +/** + * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. + * + * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) + * for each region, and sets these values in the model. The ICU cases are distributed across age groups + * using the transition probabilities from severe to critical. + * @tparam FP Floating point type (default: double). + * + * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. + * @param[in] num_icu icu data + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + * + * @return An IOResult indicating success or failure. + */ +template +IOResult set_divi_data(Model& model, const double num_icu, double scaling_factor_icu) +{ + FP sum_mu_I_U = 0; + std::vector mu_I_U; + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + sum_mu_I_U += model.parameters.template get>()[i] * + model.parameters.template get>()[i]; + mu_I_U.push_back(model.parameters.template get>()[i] * + model.parameters.template get>()[i]); + } + + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations[{i, InfectionState::InfectedCriticalNaive}] = + scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; + } + + return success(); +} + +/** + * @brief sets populations data from DIVI register into Model + * @param[in, out] model vector of objects in which the data is set + * @param[in] path Path to transformed DIVI file + * @param[in] vregion vector of keys of the regions of interest + * @param[in] date Date for which the arrays are initialized + * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + */ +template +IOResult set_divi_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, + Date date, double scaling_factor_icu) +{ + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx], num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + } + + return success(); +} + } //namespace details #ifdef MEMILIO_HAS_HDF5 @@ -371,7 +434,7 @@ IOResult read_input_data(mio::VectorRange>& model, Date date, co const std::vector& scaling_factor_inf, double scaling_factor_icu, const mio::regions::de::EpidataFilenames& epidata_filenames) { - BOOST_OUTCOME_TRY(set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, scaling_factor_icu)); BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, diff --git a/cpp/models/ode_secirts/parameters_io.cpp b/cpp/models/ode_secirts/parameters_io.cpp index 0764859b02..d70e4c4066 100644 --- a/cpp/models/ode_secirts/parameters_io.cpp +++ b/cpp/models/ode_secirts/parameters_io.cpp @@ -52,6 +52,139 @@ namespace osecirts { namespace details { + +IOResult compute_confirmed_cases_data( + const std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_imm, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, + const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, + const std::vector& t_imm_interval_i, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, + const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, + const std::vector& scaling_factor_inf, const size_t layer) +{ + auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { + return a.date < b.date; + }); + if (max_date_entry == case_data.end()) { + log_error("Case data file is empty."); + return failure(StatusCode::InvalidValue, "Case data is empty."); + } + auto max_date = max_date_entry->date; + if (max_date < date) { + log_error("Specified date does not exist in case data"); + return failure(StatusCode::OutOfRange, "Case data does not contain specified date."); + } + + // shifts the initilization to the recent past if simulation starts + // around current day and data of the future would be required. + // Only needed for preinfection compartments, exposed and InfectedNoSymptoms. + auto days_surplus = get_offset_in_days(max_date, date) - 6; // 6 > T_E + T_C + if (days_surplus > 0) { + days_surplus = 0; + } + + for (auto&& entry : case_data) { + auto age = (size_t)entry.age_group; + + // transition probabilities + double recoveredPerInfectedNoSymptoms = mu_C_R[age]; + double severePerInfectedSymptoms = mu_I_H[age]; + double criticalPerSevere = mu_H_U[age]; + + // transition times + int timeInfectedNoSymptoms = t_InfectedNoSymptoms[age]; + int timeInfectedSymptoms = t_InfectedSymptoms[age]; + + // if we select a layer with better immunity (layer > 0), we need to adjust the times and transition rates + if (layer > 0) { + timeInfectedNoSymptoms = static_cast(std::round(timeInfectedNoSymptoms * reduc_t_Infected[age])); + timeInfectedSymptoms = static_cast(std::round(timeInfectedSymptoms * reduc_t_Infected[age])); + + const double red_fact_exp = reduc_Exposed[age]; + + const double red_fact_inf = reduc_InfectedSymptoms[age]; + + const double red_fact_sev = reduc_icu_death[age]; + + recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms); + severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms; + } + + if (entry.date == offset_date_by_days(date, 0)) { + num_InfectedSymptoms[age] += scaling_factor_inf[age] * entry.num_confirmed; + num_imm[age] += entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, timeInfectedNoSymptoms + days_surplus)) { + num_InfectedNoSymptoms[age] += + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; + num_Exposed[age] -= + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, days_surplus)) { + num_InfectedNoSymptoms[age] -= + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, t_Exposed[age] + timeInfectedNoSymptoms + days_surplus)) { + num_Exposed[age] += + 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, -timeInfectedSymptoms)) { + num_InfectedSymptoms[age] -= scaling_factor_inf[age] * entry.num_confirmed; + num_InfectedSevere[age] += severePerInfectedSymptoms * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, -timeInfectedSymptoms - t_InfectedSevere[age])) { + num_InfectedSevere[age] -= severePerInfectedSymptoms * scaling_factor_inf[age] * entry.num_confirmed; + num_icu[age] += + severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, -timeInfectedSymptoms - t_InfectedSevere[age] - t_InfectedCritical[age])) { + num_death[age] += entry.num_deaths; + num_icu[age] -= + severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed; + } + if (entry.date == offset_date_by_days(date, 0 - t_imm_interval_i[age])) { + num_imm[age] -= entry.num_confirmed; + } + } + + size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size(); + for (size_t i = 0; i < num_groups; i++) { + auto try_fix_constraints = [region, i](double& value, double error, auto str) { + if (value < error) { + // this should probably return a failure + // but the algorithm is not robust enough to avoid large negative + // values and there are tests that rely on it + log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " + "exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + else if (value < 0) { + log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " + "automatically corrected", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + }; + + const double tol_error = -1e-8; + try_fix_constraints(num_InfectedSymptoms[i], tol_error, "InfectedSymptoms"); + try_fix_constraints(num_InfectedNoSymptoms[i], tol_error, "InfectedNoSymptoms"); + try_fix_constraints(num_Exposed[i], tol_error, "Exposed"); + try_fix_constraints(num_InfectedSevere[i], tol_error, "InfectedSevere"); + try_fix_constraints(num_death[i], tol_error, "Dead"); + try_fix_constraints(num_icu[i], tol_error, "InfectedCritical"); + try_fix_constraints(num_timm_i[i], tol_error, "Recently Recovered or Vaccinated"); + } + + return success(); +} + } // namespace details } // namespace osecirts } // namespace mio diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index 69edcd4351..94e2741357 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -47,207 +47,20 @@ namespace osecirts namespace details { -template -IOResult compute_confirmed_cases_data( - const ConfirmedCasesDataEntry& case_data_entry, std::vector& num_Exposed, - std::vector& num_InfectedNoSymptoms, std::vector& num_InfectedSymptoms, - std::vector& num_InfectedSevere, std::vector& num_icu, - std::vector& num_death, std::vector& num_timm_i, - Date date, const int days_surplus, const Model& model, - const std::vector& scaling_factor_inf, const size_t layer) -{ - auto params_region = model.parameters; - - auto age = (size_t)case_data_entry.age_group; - // (rounded) transition times - const int t_exposed = - static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); - int t_InfectedNoSymptoms = - static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); - int t_InfectedSymptoms = - static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); - const int t_InfectedSevere = - static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); - const int t_InfectedCritical = - static_cast(std::round(params_region.template get>()[case_data_entry.age_group])); - const int t_imm_interval_i = static_cast( - std::round(params_region.template get>()[case_data_entry.age_group])); - - // transition probabilities - FP recoveredPerInfectedNoSymptoms = - params_region.template get>()[case_data_entry.age_group]; - FP severePerInfectedSymptoms = params_region.template get>()[case_data_entry.age_group]; - FP criticalPerSevere = params_region.template get>()[case_data_entry.age_group]; - - // if we select a layer with better immunity (layer > 0), we need to adjust the times and transition rates - if (layer == 1) { - t_InfectedNoSymptoms = static_cast(std::round( - t_InfectedNoSymptoms * params_region.template get>()[case_data_entry.age_group])); - t_InfectedSymptoms = static_cast(std::round( - t_InfectedSymptoms * params_region.template get>()[case_data_entry.age_group])); - - const FP red_fact_exp = - params_region.template get>()[case_data_entry.age_group]; - - const FP red_fact_inf = - params_region.template get>()[case_data_entry.age_group]; - - const FP red_fact_sev = - lparams_region.template get>()[case_data_entry.age_group]; - - recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms); - severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms; - } - else if (layer > 1) { - t_InfectedNoSymptoms = static_cast(std::round( - t_InfectedNoSymptoms * params_region.template get>()[case_data_entry.age_group])); - t_InfectedSymptoms = static_cast(std::round( - t_InfectedSymptoms * params_region.template get>()[case_data_entry.age_group])); - - const FP red_fact_exp = - params_region.template get>()[case_data_entry.age_group]; - - const FP red_fact_inf = - params_region.template get>()[case_data_entry.age_group]; - - const FP red_fact_sev = - params_region.template get>()[case_data_entry.age_group]; - - recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms); - severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms; - } - - if (case_data_entry.date == offset_date_by_days(date, 0)) { - num_InfectedSymptoms[age] += scaling_factor_inf[age] * case_data_entry.num_confirmed; - num_imm[age] += case_data_entry.num_confirmed; - } - if (case_data_entry.date == offset_date_by_days(date, t_InfectedNoSymptoms + days_surplus)) { - num_InfectedNoSymptoms[age] += - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; - num_Exposed[age] -= - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; - } - if (case_data_entry.date == offset_date_by_days(date, days_surplus)) { - num_InfectedNoSymptoms[age] -= - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; - } - if (case_data_entry.date == offset_date_by_days(date, t_exposed + t_InfectedNoSymptoms + days_surplus)) { - num_Exposed[age] += - 1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * case_data_entry.num_confirmed; - } - if (case_data_entry.date == offset_date_by_days(date, -t_InfectedSymptoms)) { - num_InfectedSymptoms[age] -= scaling_factor_inf[age] * case_data_entry.num_confirmed; - num_InfectedSevere[age] += severePerInfectedSymptoms * scaling_factor_inf[age] * case_data_entry.num_confirmed; - } - if (case_data_entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere)) { - num_InfectedSevere[age] -= severePerInfectedSymptoms * scaling_factor_inf[age] * case_data_entry.num_confirmed; - num_icu[age] += - severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * case_data_entry.num_confirmed; - } - if (case_data_entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere - t_InfectedCritical)) { - num_death[age] += case_data_entry.num_deaths; - num_icu[age] -= - severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * case_data_entry.num_confirmed; - } - if (case_data_entry.date == offset_date_by_days(date, 0 - t_imm_interval_i)) { - num_imm[age] -= case_data_entry.num_confirmed; - } - - return success(); -} - -/** - * @brief Computes the distribution of confirmed cases across infection states based on Case (RKI) data. - * - * This function processes case data for given regions and distributes the cases across different - * infection states, considering the corresponding transition times and probabilities defined in the model. - * - * @tparam FP Floating point type (default: double). - * - * @param[in] case_data Vector of confirmed case data entries (defined in epi_data.h). - * @param[out] num_Exposed Output vector for the number of exposed individuals per age group and region. - * @param[out] num_InfectedNoSymptoms Output vector for the number of infected individuals without symptoms. - * @param[out] num_InfectedSymptoms Output vector for the number of infected individuals with symptoms. - * @param[out] num_InfectedSevere Output vector for the number of severely infected individuals. - * @param[out] num_icu Output vector for the number of individuals in critical condition (ICU). - * @param[out] num_death Output vector for the number of deaths. - * @param[out] num_timm_i Output vector for the number of individuals in temporary immunity state. - * @param[in] region Vector of region IDs representing the regions in the model vector. - * @param[in] date Date for which the simulation starts. - * @param[in] model Vector of models, each representing a region and containing the parameters. - * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases for - * @param[in] layer Specifies the immunity layer: 0 (Naive), 1 (Partial Immunity), 2 (Improved Immunity). - * - * @return An IOResult showing success or failure. - */ -template IOResult compute_confirmed_cases_data( - const std::vector& case_data, std::vector& num_Exposed, - std::vector& num_InfectedNoSymptoms, std::vector& num_InfectedSymptoms, - std::vector& num_InfectedSevere, std::vector& num_icu, - std::vector& num_death, std::vector& num_timm_i, - const int region, Date date, const Model& model, - const std::vector& scaling_factor_inf, const size_t layer) -{ - auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { - return a.date < b.date; - }); - if (max_date_entry == case_data.end()) { - log_error("Case data file is empty."); - return failure(StatusCode::InvalidValue, "Case data is empty."); - } - auto max_date = max_date_entry->date; - if (max_date < date) { - log_error("Specified date does not exist in case data"); - return failure(StatusCode::OutOfRange, "Case data does not contain specified date."); - } - - // shifts the initilization to the recent past if simulation starts - // around current day and data of the future would be required. - // Only needed for preinfection compartments, exposed and InfectedNoSymptoms. - auto days_surplus = get_offset_in_days(max_date, date) - 6; // 6 > T_E + T_C - if (days_surplus > 0) { - days_surplus = 0; - } - - for (auto&& entry : case_data) { - compute_confirmed_cases_data(entry, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, - num_InfectedSevere, num_icu, num_death, num_timm_i, date, days_surplus, model, - scaling_factor_inf, layer) - } - - size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size(); - for (size_t i = 0; i < num_groups; i++) { - auto try_fix_constraints = [region, i](FP& value, FP error, auto str) { - if (value < error) { - // this should probably return a failure - // but the algorithm is not robust enough to avoid large negative - // values and there are tests that rely on it - log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " - "exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - else if (value < 0) { - log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " - "automatically corrected", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - }; - - const FP tol_error = -1e-8; - try_fix_constraints(num_InfectedSymptoms[i], tol_error, "InfectedSymptoms"); - try_fix_constraints(num_InfectedNoSymptoms[i], tol_error, "InfectedNoSymptoms"); - try_fix_constraints(num_Exposed[i], tol_error, "Exposed"); - try_fix_constraints(num_InfectedSevere[i], tol_error, "InfectedSevere"); - try_fix_constraints(num_death[i], tol_error, "Dead"); - try_fix_constraints(num_icu[i], tol_error, "InfectedCritical"); - try_fix_constraints(num_timm_i[i], tol_error, "Recently Recovered or Vaccinated"); - } - - return success(); -} + const std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_imm, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, + const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, + const std::vector& t_imm_interval_i, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, + const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, + const std::vector& scaling_factor_inf, const size_t layer); +/**@}*/ /** * @brief Sets the confirmed cases data in the model considering different immunity layers. @@ -270,29 +83,44 @@ template IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, const int region, Date date, const std::vector& scaling_factor_inf, - const std::vector> immunity_population) + const std::vector>& immunity_population) { auto num_age_groups = (size_t)model.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups); - std::vector num_InfectedSymptoms(num_age_groups, 0.0); - std::vector num_death(num_age_groups, 0.0); - std::vector num_Exposed(num_age_groups, 0.0); - std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); - std::vector num_InfectedSevere(num_age_groups, 0.0); - std::vector num_icu(num_age_groups, 0.0); - std::vector num_timm1(num_age_groups, 0.0); - std::vector num_timm2(num_age_groups, 0.0); - - std::vector denom_E(num_age_groups, 0.0); - std::vector denom_I_NS(num_age_groups, 0.0); - std::vector denom_I_Sy(num_age_groups, 0.0); - std::vector denom_I_Sev_Cr(num_age_groups, 0.0); - - /*----------- Naive immunity -----------*/ + std::vector t_Exposed; + std::vector t_InfectedNoSymptoms; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; + std::vector t_imm_interval_i; + + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; + + std::vector reduc_t_Infected; + std::vector reduc_Exposed; + std::vector reduc_InfectedSymptoms; + std::vector reduc_icu_death; + + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + std::vector num_timm1(num_age_groups, 0.0); + std::vector num_timm2(num_age_groups, 0.0); + + std::vector denom_E(num_age_groups, 0.0); + std::vector denom_I_NS(num_age_groups, 0.0); + std::vector denom_I_Sy(num_age_groups, 0.0); + std::vector denom_I_Sev_Cr(num_age_groups, 0.0); + + // calculate the denominators to split the reported case numbers to the different immunity layers. for (size_t group = 0; group < num_age_groups; group++) { - // calculate the denominators to split the reported case numbers to the different immunity layers. denom_E[group] = 1 / (immunity_population[0][group] + immunity_population[1][group] * @@ -326,9 +154,44 @@ set_confirmed_cases_data(Model& model, const std::vector( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_imm_interval_i.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + mu_C_R.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back( + model.parameters.template get>()[(AgeGroup)group]); + + reduc_t_Infected.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_Exposed.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_InfectedSymptoms.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_icu_death.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, + reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, + scaling_factor_inf, 0)); size_t num_groups = (size_t)model.parameters.get_num_groups(); for (size_t i = 0; i < num_groups; i++) { @@ -358,16 +221,32 @@ set_confirmed_cases_data(Model& model, const std::vector(num_age_groups, 0.0); - num_death = std::vector(num_age_groups, 0.0); - num_Exposed = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); - num_InfectedSevere = std::vector(num_age_groups, 0.0); - num_icu = std::vector(num_age_groups, 0.0); + reduc_Exposed.clear(); + reduc_InfectedSymptoms.clear(); + reduc_icu_death.clear(); - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, - num_InfectedSevere, num_icu, num_death, num_timm1, region, date, - model, scaling_factor_inf, 1)); + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + + for (size_t group = 0; group < num_age_groups; group++) { + reduc_Exposed.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_InfectedSymptoms.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_icu_death.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, + reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, + scaling_factor_inf, 1)); size_t num_groups = (size_t)model.parameters.get_num_groups(); for (size_t i = 0; i < num_groups; i++) { @@ -415,16 +294,32 @@ set_confirmed_cases_data(Model& model, const std::vector(num_age_groups, 0.0); - num_death = std::vector(num_age_groups, 0.0); - num_Exposed = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); - num_InfectedSevere = std::vector(num_age_groups, 0.0); - num_icu = std::vector(num_age_groups, 0.0); + reduc_Exposed.clear(); + reduc_InfectedSymptoms.clear(); + reduc_icu_death.clear(); + + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + + for (size_t group = 0; group < num_age_groups; group++) { + reduc_Exposed.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_InfectedSymptoms.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_icu_death.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, - num_InfectedSevere, num_icu, num_death, num_timm2, region, date, - model, scaling_factor_inf, 2)); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm2, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, + reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, + scaling_factor_inf, 2)); size_t num_groups = (size_t)model.parameters.get_num_groups(); for (size_t i = 0; i < num_groups; i++) { @@ -495,7 +390,7 @@ template IOResult set_confirmed_cases_data(mio::VectorRange>& model, const std::string& path, std::vector const& vregion, Date date, const std::vector& scaling_factor_inf, - const std::vector> immunity_population) + const std::vector>& immunity_population) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); @@ -534,7 +429,7 @@ IOResult set_confirmed_cases_data(mio::VectorRange>& model, cons */ template IOResult set_population_data(Model& model, const std::vector& num_population, - const int region, const std::vector> immunity_population) + const int region, const std::vector>& immunity_population) { if (std::accumulate(num_population.begin(), num_population.end(), double(0.0), [](const double& a, const double& b) { @@ -607,7 +502,7 @@ IOResult set_population_data(Model& model, const std::vector& */ template IOResult set_population_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, - const std::vector> immunity_population) + const std::vector>& immunity_population) { BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion)); @@ -787,6 +682,69 @@ IOResult set_vaccination_data(mio::VectorRange>& model, const st return success(); } +/** + * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. + * + * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) + * for each region, and sets these values in the model. The ICU cases are distributed across age groups + * using the transition probabilities from severe to critical. + * @tparam FP Floating point type (default: double). + * + * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. + * @param[in] num_icu icu data + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + * + * @return An IOResult indicating success or failure. + */ +template +IOResult set_divi_data(Model& model, const double num_icu, double scaling_factor_icu) +{ + FP sum_mu_I_U = 0; + std::vector mu_I_U; + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + sum_mu_I_U += model.parameters.template get>()[i] * + model.parameters.template get>()[i]; + mu_I_U.push_back(model.parameters.template get>()[i] * + model.parameters.template get>()[i]); + } + + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations[{i, InfectionState::InfectedCriticalNaive}] = + scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; + } + + return success(); +} + +/** + * @brief sets populations data from DIVI register into Model + * @param[in, out] model vector of objects in which the data is set + * @param[in] path Path to transformed DIVI file + * @param[in] vregion vector of keys of the regions of interest + * @param[in] date Date for which the arrays are initialized + * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + */ +template +IOResult set_divi_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, + Date date, double scaling_factor_icu) +{ + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx], num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + } + + return success(); +} + } // namespace details #ifdef MEMILIO_HAS_HDF5 @@ -814,7 +772,7 @@ template IOResult export_input_data_timeseries( mio::VectorRange> models, const std::string& results_dir, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, - const std::vector> immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) + const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) { const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); @@ -882,7 +840,7 @@ IOResult export_input_data_timeseries(mio::VectorRange>, const s template IOResult read_input_data(mio::VectorRange>& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, - int num_days, const std::vector> immunity_population, + int num_days, const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) { @@ -891,7 +849,7 @@ IOResult read_input_data(mio::VectorRange>& model, Date date, co // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, scaling_factor_icu)); BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index c3604c493f..55811462df 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -775,6 +775,69 @@ IOResult set_vaccination_data(mio::VectorRange>& model, const st return success(); } +/** + * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. + * + * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) + * for each region, and sets these values in the model. The ICU cases are distributed across age groups + * using the transition probabilities from severe to critical. + * @tparam FP Floating point type (default: double). + * + * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. + * @param[in] num_icu icu data + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + * + * @return An IOResult indicating success or failure. + */ +template +IOResult set_divi_data(Model& model, const double num_icu, double scaling_factor_icu) +{ + FP sum_mu_I_U = 0; + std::vector mu_I_U; + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + sum_mu_I_U += model.parameters.template get>()[i] * + model.parameters.template get>()[i]; + mu_I_U.push_back(model.parameters.template get>()[i] * + model.parameters.template get>()[i]); + } + + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations[{i, InfectionState::InfectedCriticalNaive}] = + scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; + } + + return success(); +} + +/** + * @brief sets populations data from DIVI register into Model + * @param[in, out] model vector of objects in which the data is set + * @param[in] path Path to transformed DIVI file + * @param[in] vregion vector of keys of the regions of interest + * @param[in] date Date for which the arrays are initialized + * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + */ +template +IOResult set_divi_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, + Date date, double scaling_factor_icu) +{ + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + + for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx], num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + } + + return success(); +} + } // namespace details #ifdef MEMILIO_HAS_HDF5 From a1d73a79eab4daf50da7fe60e2e5e1d57791ee77 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 3 Nov 2025 23:06:28 +0000 Subject: [PATCH 04/26] fix node range and de namespace --- cpp/memilio/geography/holiday_data.ipp | 9 +- cpp/memilio/geography/regions.cpp | 37 ++--- cpp/memilio/geography/regions.h | 93 ++++++------- cpp/memilio/io/epi_data.h | 48 +++---- cpp/memilio/io/parameters_io.cpp | 6 +- cpp/memilio/mobility/graph.h | 172 ++++++------------------ cpp/memilio/mobility/graph_simulation.h | 8 +- cpp/models/ode_secir/parameters_io.h | 22 +-- cpp/models/ode_secirts/parameters_io.h | 46 +++---- cpp/models/ode_secirvvs/parameters_io.h | 42 +++--- 10 files changed, 199 insertions(+), 284 deletions(-) diff --git a/cpp/memilio/geography/holiday_data.ipp b/cpp/memilio/geography/holiday_data.ipp index 5bdf29791a..1fdbb6e82f 100644 --- a/cpp/memilio/geography/holiday_data.ipp +++ b/cpp/memilio/geography/holiday_data.ipp @@ -25,7 +25,10 @@ #include #include -namespace holidays +namespace mio +{ + +namespace regions { namespace de @@ -299,4 +302,6 @@ static const std::vector> holidays_16_th = { } // namespace de -} //namespace holidays +} // namespace regions + +} // namespace mio diff --git a/cpp/memilio/geography/regions.cpp b/cpp/memilio/geography/regions.cpp index 55a688e92d..30a223f705 100644 --- a/cpp/memilio/geography/regions.cpp +++ b/cpp/memilio/geography/regions.cpp @@ -28,6 +28,9 @@ namespace mio namespace regions { +namespace de +{ + StateId get_state_id(int county) { return StateId(county / 1000); @@ -42,52 +45,52 @@ get_holidays(StateId state) auto data = &def; switch (int(state)) { case 1: - data = &holidays::de::holidays_01_sh; + data = &holidays_01_sh; break; case 2: - data = &holidays::de::holidays_02_hh; + data = &holidays_02_hh; break; case 3: - data = &holidays::de::holidays_03_ni; + data = &holidays_03_ni; break; case 4: - data = &holidays::de::holidays_04_hb; + data = &holidays_04_hb; break; case 5: - data = &holidays::de::holidays_05_nw; + data = &holidays_05_nw; break; case 6: - data = &holidays::de::holidays_06_he; + data = &holidays_06_he; break; case 7: - data = &holidays::de::holidays_07_rp; + data = &holidays_07_rp; break; case 8: - data = &holidays::de::holidays_08_bw; + data = &holidays_08_bw; break; case 9: - data = &holidays::de::holidays_09_by; + data = &holidays_09_by; break; case 10: - data = &holidays::de::holidays_10_sl; + data = &holidays_10_sl; break; case 11: - data = &holidays::de::holidays_11_be; + data = &holidays_11_be; break; case 12: - data = &holidays::de::holidays_12_bb; + data = &holidays_12_bb; break; case 13: - data = &holidays::de::holidays_13_mv; + data = &holidays_13_mv; break; case 14: - data = &holidays::de::holidays_14_sn; + data = &holidays_14_sn; break; case 15: - data = &holidays::de::holidays_15_st; + data = &holidays_15_st; break; case 16: - data = &holidays::de::holidays_16_th; + data = &holidays_16_th; break; default: break; @@ -110,6 +113,8 @@ get_holidays(StateId state, Date start_date, Date end_date) return {holidays_in_range}; } +} // namespace de + } // namespace regions } // namespace mio diff --git a/cpp/memilio/geography/regions.h b/cpp/memilio/geography/regions.h index dca434113f..4d5a79f12d 100644 --- a/cpp/memilio/geography/regions.h +++ b/cpp/memilio/geography/regions.h @@ -46,6 +46,9 @@ struct Region : public mio::Index { } }; +namespace de +{ + /** * Id of a state. * For Germany the Ids are: @@ -102,56 +105,54 @@ get_holidays(StateId state); */ Range>::const_iterator, std::vector>::const_iterator>> get_holidays(StateId state, Date start_date, Date end_date); - -namespace de +struct EpidataFilenames { - struct EpidataFilenames + private: + + EpidataFilenames(std::string& pydata) : + population_data_path(mio::path_join(pydata, "county_current_population.json")) + { + } + + static EpidataFilenames county(std::string& pydata) + { + EpidataFilenames s(pydata); + + s.case_data_path = mio::path_join(pydata, "cases_all_county_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "county_divi_ma7.json"); + s.vaccination_data_path = mio::path_join(pydata, "vacc_county_ageinf_ma7.json"); + + return s; + } + + static EpidataFilenames states(std::string& pydata) { - private: + EpidataFilenames s(pydata); - EpidataFilenames(std::string& pydata) : - population_data_path(mio::path_join(pydata, "county_current_population.json")) - { - } + s.case_data_path = mio::path_join(pydata, "cases_all_state_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "state_divi_ma7.json"); + s.vaccination_data_path = mio::path_join(pydata, "vacc_state_ageinf_ma7.json"); - static EpidataFilenames county(std::string& pydata) - { - EpidataFilenames s(pydata); - - s.case_data_path = mio::path_join(pydata, "cases_all_county_age_ma7.json"); - s.divi_data_path = mio::path_join(pydata, "county_divi_ma7.json"); - s.vaccination_data_path = mio::path_join(pydata, "vacc_county_ageinf_ma7.json"); - - return s; - } - - static EpidataFilenames states(std::string& pydata) - { - EpidataFilenames s(pydata); - - s.case_data_path = mio::path_join(pydata, "cases_all_state_age_ma7.json"); - s.divi_data_path = mio::path_join(pydata, "state_divi_ma7.json"); - s.vaccination_data_path = mio::path_join(pydata, "vacc_state_ageinf_ma7.json"); - - return s; - } - - static EpidataFilenames country(std::string& pydata) - { - EpidataFilenames s(pydata); - - s.case_data_path = mio::path_join(pydata, "cases_all_age_ma7.json"); - s.divi_data_path = mio::path_join(pydata, "germany_divi_ma7.json"); - s.vaccination_data_path = mio::path_join(pydata, "vacc_ageinf_ma7.json"); - - return s; - } - - std::string population_data_path; - std::string case_data_path; - std::string divi_data_path; - std::string vaccination_data_path; - }; + return s; + } + + static EpidataFilenames country(std::string& pydata) + { + EpidataFilenames s(pydata); + + s.case_data_path = mio::path_join(pydata, "cases_all_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "germany_divi_ma7.json"); + s.vaccination_data_path = mio::path_join(pydata, "vacc_ageinf_ma7.json"); + + return s; + } + + std::string population_data_path; + std::string case_data_path; + std::string divi_data_path; + std::string vaccination_data_path; +}; + } // namespace de } // namespace regions diff --git a/cpp/memilio/io/epi_data.h b/cpp/memilio/io/epi_data.h index ac62270809..3716a9b468 100644 --- a/cpp/memilio/io/epi_data.h +++ b/cpp/memilio/io/epi_data.h @@ -133,9 +133,9 @@ class ConfirmedCasesDataEntry ScalarType num_deaths; Date date; AgeGroup age_group; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IOContext& io) @@ -146,9 +146,9 @@ class ConfirmedCasesDataEntry auto num_deaths = obj.expect_element("Deaths", Tag{}); auto date = obj.expect_element("Date", Tag{}); auto age_group_str = obj.expect_element("Age_RKI", Tag{}); - auto state_id = obj.expect_optional("ID_State", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_State", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); return apply( io, [](auto&& nc, auto&& nr, auto&& nd, auto&& d, auto&& a_str, auto&& sid, auto&& cid, @@ -208,9 +208,9 @@ class DiviEntry public: ScalarType num_icu; Date date; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IoContext& io) @@ -218,9 +218,9 @@ class DiviEntry auto obj = io.expect_object("DiviEntry"); auto num_icu = obj.expect_element("ICU", Tag{}); auto date = obj.expect_element("Date", Tag{}); - auto state_id = obj.expect_optional("ID_State", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_State", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); return apply( io, [](auto&& ni, auto&& d, auto&& sid, auto&& cid, auto&& did) { @@ -304,17 +304,17 @@ class PopulationDataEntry static std::vector age_group_names; CustomIndexArray population; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IoContext& io) { auto obj = io.expect_object("PopulationDataEntry"); - auto state_id = obj.expect_optional("ID_State", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_State", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); std::vector> age_groups; age_groups.reserve(age_group_names.size()); std::transform(age_group_names.begin(), age_group_names.end(), std::back_inserter(age_groups), @@ -487,9 +487,9 @@ class VaccinationDataEntry num_vaccinations_refreshed_additional; Date date; AgeGroup age_group; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IoContext& io) @@ -501,9 +501,9 @@ class VaccinationDataEntry auto num_vaccinations_refreshed_additional = obj.expect_optional("Vacc_refreshed_2", Tag{}); auto date = obj.expect_element("Date", Tag{}); auto age_group_str = obj.expect_element("Age_RKI", Tag{}); - auto state_id = obj.expect_optional("ID_County", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_County", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); return mio::apply( io, [](auto np, auto nc, auto n_refreshed_1, auto n_refreshed_2, auto d, auto&& a_str, auto sid, auto cid, diff --git a/cpp/memilio/io/parameters_io.cpp b/cpp/memilio/io/parameters_io.cpp index 906bc132b8..68dfc02756 100644 --- a/cpp/memilio/io/parameters_io.cpp +++ b/cpp/memilio/io/parameters_io.cpp @@ -85,9 +85,9 @@ read_population_data(const std::vector& population_data, co auto it = std::find_if(vregion.begin(), vregion.end(), [&county_entry](auto r) { return r == 0 || (county_entry.county_id && - regions::StateId(r) == regions::get_state_id(int(*county_entry.county_id))) || - (county_entry.county_id && regions::CountyId(r) == *county_entry.county_id) || - (county_entry.district_id && regions::DistrictId(r) == *county_entry.district_id); + regions::de::StateId(r) == regions::de::get_state_id(int(*county_entry.county_id))) || + (county_entry.county_id && regions::de::CountyId(r) == *county_entry.county_id) || + (county_entry.district_id && regions::de::DistrictId(r) == *county_entry.district_id); }); if (it != vregion.end()) { auto region_idx = size_t(it - vregion.begin()); diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index 5dc1493bf8..17212cda15 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -152,10 +152,11 @@ class Graph using NodeProperty = NodePropertyT; using EdgeProperty = EdgePropertyT; - Graph(std::vector nodes, std::vector edges) - : m_nodes(nodes) - , m_edges(edges) + Graph(std::vector& node_ids, std::vector& node_properties) { + for (auto i = size_t(0); i < node_ids.size(); ++i) { + add_node(node_ids[i], node_properties[i]); + } } template @@ -253,136 +254,57 @@ class Graph private: std::vector> m_nodes; std::vector> m_edges; -}; // namespace mio - -template -void set_german_holidays(Model& node, const int node_id, - const mio::Date& start_date, const mio::Date& end_date) -{ - auto state_id = regions::get_state_id(node_id); - auto holiday_periods = regions::get_holidays(state_id, start_date, end_date); - - auto& contacts = node.parameters.template get(); - contacts.get_school_holidays() = - std::vector, mio::SimulationTime>>(holiday_periods.size()); - std::transform( - holiday_periods.begin(), holiday_periods.end(), contacts.get_school_holidays().begin(), [=](auto& period) { - return std::make_pair(mio::SimulationTime(mio::get_offset_in_days(period.first, start_date)), - mio::SimulationTime(mio::get_offset_in_days(period.second, start_date))); - }); -} - -/** - * @brief Sets the graph nodes for counties or districts. - * Reads the node ids which could refer to districts or counties and the epidemiological - * data from json files and creates one node for each id. Every node contains a model. - * @param[in] params Model Parameters that are used for every node. - * @param[in] start_date Start date for which the data should be read. - * @param[in] end_data End date for which the data should be read. - * @param[in] data_dir Directory that contains the data files. - * @param[in, out] params_graph Graph whose nodes are set by the function. - * @param[in] read_func Function that reads input data for german counties and sets Model compartments. - * @param[in] node_func Function that returns the county ids. - * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. - * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. - * @param[in] tnt_capacity_factor Factor for test and trace capacity. - */ -template -IOResult set_nodes(const Parameters& params, Date start_date, Date end_date, const fs::path& data_dir, - Graph& params_graph, ReadFunction&& read_func, - const std::vector& node_ids, const std::vector& scaling_factor_inf, FP scaling_factor_icu, - bool add_uncertainty_to_population = true) +}; +template +void set_test_and_trace_capacity(mio::VectorRange>& nodes) { - std::vector nodes(node_ids.size(), Model(int(size_t(params.get_num_groups())))); - for (auto& node : nodes) { - node.parameters = params; - } - - BOOST_OUTCOME_TRY(read_func(nodes, start_date, node_ids, scaling_factor_inf, scaling_factor_icu, data_dir.string())); - for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { - set_german_holidays(nodes[node_idx], node_ids[node_idx], start_date, end_date); - if (add_uncertainty_to_population) - { - //uncertainty in populations - for (auto i = mio::AgeGroup(0); i < params.get_num_groups(); i++) { - for (auto j = Index(0); j < Model::Compartments::Count; ++j) { - auto& compartment_value = nodes[node_idx].populations[{i, j}]; - compartment_value = - UncertainValue(compartment_value.value()); - compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), - 1.1 * compartment_value.value())); - } - } - } + auto tnt_capacity = nodes[node_idx].property.populations.get_total() * tnt_capacity_factor; - params_graph.add_node(node_ids[node_idx], nodes[node_idx]); + auto& tnt_value = nodes[node_idx].property.parameters.template get(); + tnt_value = UncertainValue(tnt_capacity); + tnt_value.set_distribution(mio::ParameterDistributionUniform(0.8 * tnt_capacity, 1.2 * tnt_capacity)); } - return success(); } -/** - * @brief Sets the graph nodes for counties or districts. - * Reads the node ids which could refer to districts or counties and the epidemiological - * data from json files and creates one node for each id. Every node contains a model. - * @param[in] params Model Parameters that are used for every node. - * @param[in] start_date Start date for which the data should be read. - * @param[in] end_data End date for which the data should be read. - * @param[in] data_dir Directory that contains the data files. - * @param[in, out] params_graph Graph whose nodes are set by the function. - * @param[in] read_func Function that reads input data for german counties and sets Model compartments. - * @param[in] node_func Function that returns the county ids. - * @param[in] scaling_factor_inf Factor of confirmed cases to account for undetected cases in each county. - * @param[in] scaling_factor_icu Factor of ICU cases to account for underreporting. - * @param[in] tnt_capacity_factor Factor for test and trace capacity. - */ -template -IOResult set_nodes(const Parameters& params, Date start_date, Date end_date, const fs::path& data_dir, - Graph& params_graph, ReadFunction&& read_func, - const std::vector& node_ids, const std::vector& scaling_factor_inf, FP scaling_factor_icu, - FP tnt_capacity_factor, bool add_uncertainty_to_population = true) - +template +void set_german_holidays(mio::VectorRange>& nodes, const std::vector& node_ids, + const mio::Date& start_date, const mio::Date& end_date) { - std::vector nodes(node_ids.size(), Model(int(size_t(params.get_num_groups())))); - for (auto& node : nodes) { - node.parameters = params; + for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { + auto state_id = regions::de::get_state_id(node_id[node_idx]); + auto holiday_periods = regions::de::get_holidays(state_id, start_date, end_date); + + auto& contacts = nodes[node_idx].property.parameters.template get(); + contacts.get_school_holidays() = + std::vector, mio::SimulationTime>>(holiday_periods.size()); + std::transform( + holiday_periods.begin(), holiday_periods.end(), contacts.get_school_holidays().begin(), [=](auto& period) { + return std::make_pair(mio::SimulationTime(mio::get_offset_in_days(period.first, start_date)), + mio::SimulationTime(mio::get_offset_in_days(period.second, start_date))); + }); } +} - BOOST_OUTCOME_TRY(read_func(nodes, start_date, node_ids, scaling_factor_inf, scaling_factor_icu, data_dir.string())); - +template +void set_uncertainty_on_population(mio::VectorRange>& nodes) +{ for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { - - auto tnt_capacity = nodes[node_idx].populations.get_total() * tnt_capacity_factor; - - // local parameters - auto& tnt_value = nodes[node_idx].parameters.template get(); - tnt_value = UncertainValue(tnt_capacity); - tnt_value.set_distribution(mio::ParameterDistributionUniform(0.8 * tnt_capacity, 1.2 * tnt_capacity)); - - set_german_holidays(nodes[node_idx], node_ids[node_idx], start_date, end_date); - if (add_uncertainty_to_population) - { - //uncertainty in populations - for (auto i = mio::AgeGroup(0); i < params.get_num_groups(); i++) { - for (auto j = Index(0); j < Model::Compartments::Count; ++j) { - auto& compartment_value = nodes[node_idx].populations[{i, j}]; - compartment_value = - UncertainValue(compartment_value.value()); - compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), - 1.1 * compartment_value.value())); - } + for (auto i = mio::AgeGroup(0); i < params.get_num_groups(); i++) { + for (auto j = Index(0); j < Model::Compartments::Count; ++j) { + auto& compartment_value = nodes[node_idx].property.populations[{i, j}]; + compartment_value = + UncertainValue(compartment_value.value()); + compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), + 1.1 * compartment_value.value())); } } - - params_graph.add_node(node_ids[node_idx], nodes[node_idx]); } - return success(); } + /** * @brief Sets the graph edges. * Reads the commuting matrices from txt files and sets the graph edges with that. @@ -444,24 +366,6 @@ IOResult set_edges(const fs::path& mobility_data_file, Graph -auto create_graph_without_edges(const std::vector& node_properties, const std::vector& node_ids) -{ - // create a graph without edges for writing to file - auto graph = mio::Graph(); - for (auto i = size_t(0); i < node_ids.size(); ++i) { - graph.add_node(node_ids[i], node_properties[i]); - } - return graph; -} - template std::enable_if_t::value, void> print_graph_object(std::ostream& os, size_t idx, const T&) { diff --git a/cpp/memilio/mobility/graph_simulation.h b/cpp/memilio/mobility/graph_simulation.h index 33770f8a47..0577be7fa3 100644 --- a/cpp/memilio/mobility/graph_simulation.h +++ b/cpp/memilio/mobility/graph_simulation.h @@ -368,7 +368,7 @@ class FeedbackGraphSimulation { std::unordered_map regional_population; for (auto& node : m_graph.nodes()) { - auto region_id = mio::regions::get_state_id(node.id).get(); + auto region_id = mio::regions::de::get_state_id(node.id).get(); regional_population[region_id] += node.property.get_simulation().get_model().populations.get_total(); } @@ -386,7 +386,7 @@ class FeedbackGraphSimulation // Sum up for (auto& node : m_graph.nodes()) { - auto region_id = mio::regions::get_state_id(node.id).get(); + auto region_id = mio::regions::de::get_state_id(node.id).get(); auto& sim = node.property.get_simulation(); auto& icu_history = sim.get_parameters().template get>(); FP pop = node.property.get_simulation().get_model().populations.get_total(); @@ -434,7 +434,7 @@ class FeedbackGraphSimulation for (auto& [region_id, regional_data] : m_regional_icu_occupancy) { Eigen::VectorXd sum = Eigen::VectorXd::Zero(regional_data.get_num_elements()); for (auto& node : m_graph.nodes()) { - if (mio::regions::get_state_id(node.id).get() == region_id) { + if (mio::regions::de::get_state_id(node.id).get() == region_id) { auto& sim = node.property.get_simulation(); auto& icu_history = sim.get_parameters().template get>(); sum += icu_history.get_last_value() * @@ -454,7 +454,7 @@ class FeedbackGraphSimulation void distribute_icu_data() { for (auto& node : m_graph.nodes()) { - auto region_id = mio::regions::get_state_id(node.id).get(); + auto region_id = mio::regions::de::get_state_id(node.id).get(); auto& sim = node.property.get_simulation(); sim.set_regional_icu_occupancy(m_regional_icu_occupancy.at(region_id)); sim.set_global_icu_occupancy(m_global_icu_occupancy); diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 5f567068f6..2a75cafe67 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -200,7 +200,7 @@ IOResult set_confirmed_cases_data(Model& model, std::vector -IOResult set_confirmed_cases_data(mio::VectorRange>& model, const std::string& path, +IOResult set_confirmed_cases_data(mio::VectorRange>>& model, const std::string& path, std::vector const& region, Date date, const std::vector& scaling_factor_inf) { @@ -220,7 +220,7 @@ IOResult set_confirmed_cases_data(mio::VectorRange>& model, cons for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { BOOST_OUTCOME_TRY( - set_confirmed_cases_data(model[region_idx], vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf)); + set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf)); } return success(); } @@ -283,13 +283,13 @@ IOResult set_population_data(Model& model, const std::vector& * @param[in] vregion Vector of keys of the regions of interest. */ template -IOResult set_population_data(mio::VectorRange>& model, const std::string& path, +IOResult set_population_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion) { BOOST_OUTCOME_TRY(const auto&& num_population, read_population_data(path, vregion)); for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx], num_population[region_idx], vregion[region_idx])); + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], vregion[region_idx])); } return success(); } @@ -338,7 +338,7 @@ IOResult set_divi_data(Model& model, const double num_icu, double scal * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data */ template -IOResult set_divi_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, +IOResult set_divi_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, Date date, double scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. @@ -351,7 +351,7 @@ IOResult set_divi_data(mio::VectorRange>& model, const std::stri BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx], num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); } return success(); @@ -377,11 +377,11 @@ IOResult set_divi_data(mio::VectorRange>& model, const std::stri */ template IOResult export_input_data_timeseries( - mio::VectorRange> models, const std::string& results_dir, Date date, const std::vector& node_ids, + mio::VectorRange>> models, const std::string& results_dir, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { - const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); + const auto num_age_groups = (size_t)models[0].property.parameters.get_num_groups(); // allow scalar scaling factor as convenience for 1-group models assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); assert(models.size() == node_ids.size()); @@ -395,7 +395,7 @@ IOResult export_input_data_timeseries( num_days, epidata_filenames)); for (size_t r = 0; r < node_ids.size(); r++) { - extrapolated_data[r][t] = models[r].get_initial_values(); + extrapolated_data[r][t] = models[r].property.get_initial_values(); } } @@ -410,7 +410,7 @@ IOResult export_input_data_timeseries( } #else template -IOResult export_input_data_county_timeseries(mio::VectorRange>, const std::string&, Date, const std::vector&, +IOResult export_input_data_county_timeseries(mio::VectorRange>>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, const mio::regions::de::EpidataFilenames&) { @@ -430,7 +430,7 @@ IOResult export_input_data_county_timeseries(mio::VectorRange>, * @param[in] age_group_names strings specifying age group names */ template -IOResult read_input_data(mio::VectorRange>& model, Date date, const std::vector& node_ids, +IOResult read_input_data(mio::VectorRange>>& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, const mio::regions::de::EpidataFilenames& epidata_filenames) { diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index 94e2741357..213d875001 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -387,7 +387,7 @@ set_confirmed_cases_data(Model& model, const std::vector -IOResult set_confirmed_cases_data(mio::VectorRange>& model, const std::string& path, +IOResult set_confirmed_cases_data(mio::VectorRange>>& model, const std::string& path, std::vector const& vregion, Date date, const std::vector& scaling_factor_inf, const std::vector>& immunity_population) @@ -408,7 +408,7 @@ IOResult set_confirmed_cases_data(mio::VectorRange>& model, cons for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { BOOST_OUTCOME_TRY( - set_confirmed_cases_data(model[region_idx], vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, immunity_population)); + set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, immunity_population)); } return success(); @@ -501,13 +501,13 @@ IOResult set_population_data(Model& model, const std::vector& * @return An IOResult indicating success or failure. */ template -IOResult set_population_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, +IOResult set_population_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, const std::vector>& immunity_population) { BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion)); for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx], num_population[region_idx], vregion[region_idx], immunity_population)); + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], vregion[region_idx], immunity_population)); } return success(); } @@ -633,19 +633,19 @@ IOResult set_vaccination_data(Model& model, const std::vector -IOResult set_vaccination_data(mio::VectorRange>& model, const std::string& path, Date date, +IOResult set_vaccination_data(mio::VectorRange>>& model, const std::string& path, Date date, const std::vector& vregion, int num_days) { // Set vaccination data to 0 for all models for (auto& m : model) { - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - m.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.property.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.property.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.property.parameters.template get>().resize(SimulationDay(num_days + 1)); for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { - for (auto a = AgeGroup(0); a < m.parameters.get_num_groups(); ++a) { - m.parameters.template get>()[{a, d}] = 0.0; - m.parameters.template get>()[{a, d}] = 0.0; - m.parameters.template get>()[{a, d}] = 0.0; + for (auto a = AgeGroup(0); a < m.property.parameters.get_num_groups(); ++a) { + m.property.parameters.template get>()[{a, d}] = 0.0; + m.property.parameters.template get>()[{a, d}] = 0.0; + m.property.parameters.template get>()[{a, d}] = 0.0; } } } @@ -665,9 +665,9 @@ IOResult set_vaccination_data(mio::VectorRange>& model, const st std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { - return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(r)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(r)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(r)); + return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(r)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(r)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(r)); }); if (it != vregion.end()) { auto region_idx = size_t(it - vregion.begin()); @@ -676,7 +676,7 @@ IOResult set_vaccination_data(mio::VectorRange>& model, const st } for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx], vacc_data[region_idx], date, num_days)); + BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vacc_data[region_idx], date, num_days)); } return success(); @@ -726,7 +726,7 @@ IOResult set_divi_data(Model& model, const double num_icu, double scal * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data */ template -IOResult set_divi_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, +IOResult set_divi_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, Date date, double scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. @@ -739,7 +739,7 @@ IOResult set_divi_data(mio::VectorRange>& model, const std::stri BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx], num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); } return success(); @@ -770,11 +770,11 @@ IOResult set_divi_data(mio::VectorRange>& model, const std::stri */ template IOResult export_input_data_timeseries( - mio::VectorRange> models, const std::string& results_dir, Date date, const std::vector& node_ids, + mio::VectorRange>> models, const std::string& results_dir, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) { - const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); + const auto num_age_groups = (size_t)models[0].property.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); assert(models.size() == node_ids.size()); @@ -789,7 +789,7 @@ IOResult export_input_data_timeseries( num_days, immunity_population, epidata_filenames)); for (size_t r = 0; r < node_ids.size(); r++) { - extrapolated_data[r][t] = models[r].get_initial_values(); + extrapolated_data[r][t] = models[r].property.get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. for (size_t age = 0; age < num_age_groups; age++) { @@ -811,7 +811,7 @@ IOResult export_input_data_timeseries( #else template -IOResult export_input_data_timeseries(mio::VectorRange>, const std::string&, Date, const std::vector&, +IOResult export_input_data_timeseries(mio::VectorRange>>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, const std::vector>, const mio::regions::de::EpidataFilenames&) { @@ -838,7 +838,7 @@ IOResult export_input_data_timeseries(mio::VectorRange>, const s * @return An IOResult indicating success or failure. */ template -IOResult read_input_data(mio::VectorRange>& model, Date date, const std::vector& node_ids, +IOResult read_input_data(mio::VectorRange>>& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 55811462df..6bdfb3ed1d 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -362,7 +362,7 @@ IOResult set_confirmed_cases_data(Model& model, const std::vector -IOResult set_confirmed_cases_data(mio::VectorRange>& model, const std::string& path, +IOResult set_confirmed_cases_data(mio::VectorRange>>& model, const std::string& path, std::vector const& vregion, Date date, const std::vector& scaling_factor_inf, bool set_death = false) { @@ -381,7 +381,7 @@ IOResult set_confirmed_cases_data(mio::VectorRange>& model, cons } for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_confirmed_cases_data(model[region_idx], vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, set_death)); + BOOST_OUTCOME_TRY(set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, set_death)); } return success(); } @@ -581,7 +581,7 @@ IOResult set_population_data(Model& model, const std::vector& * @param[in] date Date for which the arrays are initialized. */ template -IOResult set_population_data(mio::VectorRange>& model, const std::string& path, const std::string& path_rki, +IOResult set_population_data(mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, const std::vector& vregion, Date date) { BOOST_OUTCOME_TRY(auto&& vnum_population, read_population_data(path, vregion)); @@ -593,7 +593,7 @@ IOResult set_population_data(mio::VectorRange>& model, const std BOOST_OUTCOME_TRY(compute_confirmed_cases_data_fix_recovered(case_data, vregion, date, vnum_rec, 14.)); for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx], vnum_population[region_idx], vregion[region_idx], vnum_rec[region_idx])); + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, vnum_population[region_idx], vregion[region_idx], vnum_rec[region_idx])); } return success(); } @@ -729,17 +729,17 @@ IOResult set_vaccination_data(Model& model, const std::vector -IOResult set_vaccination_data(mio::VectorRange>& model, const std::string& path, Date date, +IOResult set_vaccination_data(mio::VectorRange>>& model, const std::string& path, Date date, const std::vector& vregion, int num_days) { // Set vaccination data to 0 for all models for (auto& m : model) { - m.parameters.template get>().resize(SimulationDay(num_days + 1)); - m.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.property.parameters.template get>().resize(SimulationDay(num_days + 1)); + m.property.parameters.template get>().resize(SimulationDay(num_days + 1)); for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) { - for (auto a = AgeGroup(0); a < m.parameters.get_num_groups(); ++a) { - m.parameters.template get>()[{a, d}] = 0.0; - m.parameters.template get>()[{a, d}] = 0.0; + for (auto a = AgeGroup(0); a < m.property.parameters.get_num_groups(); ++a) { + m.property.parameters.template get>()[{a, d}] = 0.0; + m.property.parameters.template get>()[{a, d}] = 0.0; } } } @@ -758,9 +758,9 @@ IOResult set_vaccination_data(mio::VectorRange>& model, const st std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { - return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(r)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(r)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(r)); + return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(r)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(r)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(r)); }); if (it != vregion.end()) { auto region_idx = size_t(it - vregion.begin()); @@ -769,7 +769,7 @@ IOResult set_vaccination_data(mio::VectorRange>& model, const st } for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx], vacc_data[region_idx], date, num_days)); + BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vacc_data[region_idx], date, num_days)); } return success(); @@ -819,7 +819,7 @@ IOResult set_divi_data(Model& model, const double num_icu, double scal * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data */ template -IOResult set_divi_data(mio::VectorRange>& model, const std::string& path, const std::vector& vregion, +IOResult set_divi_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, Date date, double scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. @@ -832,7 +832,7 @@ IOResult set_divi_data(mio::VectorRange>& model, const std::stri BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx], num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); } return success(); @@ -858,11 +858,11 @@ IOResult set_divi_data(mio::VectorRange>& model, const std::stri */ template IOResult export_input_data_timeseries( - mio::VectorRange> models, const std::string& results_dir, Date date, const std::vector& node_ids, + mio::VectorRange>> models, const std::string& results_dir, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { - const auto num_age_groups = (size_t)models[0].parameters.get_num_groups(); + const auto num_age_groups = (size_t)models[0].property.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); assert(models.size() == node_ids.size()); @@ -877,7 +877,7 @@ IOResult export_input_data_timeseries( num_days, epidata_filenames)); for (size_t r = 0; r < node_ids.size(); r++) { - extrapolated_data[r][t] = models[r].get_initial_values(); + extrapolated_data[r][t] = models[r].property.get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. for (size_t age = 0; age < num_age_groups; age++) { @@ -898,7 +898,7 @@ IOResult export_input_data_timeseries( } #else template -IOResult export_input_data_county_timeseries(mio::VectorRange>, const std::string&, Date, const std::vector&, +IOResult export_input_data_county_timeseries(mio::VectorRange>>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, const mio::regions::de::EpidataFilenames&) { @@ -909,7 +909,7 @@ IOResult export_input_data_county_timeseries(mio::VectorRange>, #endif //MEMILIO_HAS_HDF5 template -IOResult read_input_data(mio::VectorRange>& model, Date date, const std::vector& node_ids, +IOResult read_input_data(mio::VectorRange>>& model, Date date, const std::vector& node_ids, const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { From d7ce1f1948102b9ce005bf71c291d1aad25ce037 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 4 Nov 2025 22:27:45 +0000 Subject: [PATCH 05/26] fixed bugs --- cpp/memilio/geography/regions.h | 2 + cpp/memilio/io/parameters_io.cpp | 1 + cpp/memilio/io/result_io.h | 4 +- cpp/models/ode_secir/parameters_io.h | 124 ++++++------- cpp/models/ode_secirts/parameters_io.cpp | 2 +- cpp/models/ode_secirts/parameters_io.h | 166 +++++++++--------- cpp/models/ode_secirvvs/parameters_io.cpp | 72 +++----- cpp/models/ode_secirvvs/parameters_io.h | 203 +++++++++++----------- 8 files changed, 280 insertions(+), 294 deletions(-) diff --git a/cpp/memilio/geography/regions.h b/cpp/memilio/geography/regions.h index 4d5a79f12d..c885633191 100644 --- a/cpp/memilio/geography/regions.h +++ b/cpp/memilio/geography/regions.h @@ -114,6 +114,8 @@ struct EpidataFilenames { } + public: + static EpidataFilenames county(std::string& pydata) { EpidataFilenames s(pydata); diff --git a/cpp/memilio/io/parameters_io.cpp b/cpp/memilio/io/parameters_io.cpp index 68dfc02756..e584a3e13a 100644 --- a/cpp/memilio/io/parameters_io.cpp +++ b/cpp/memilio/io/parameters_io.cpp @@ -19,6 +19,7 @@ */ #include "memilio/config.h" +#include "memilio/io/parameters_io.h" #ifdef MEMILIO_HAS_JSONCPP diff --git a/cpp/memilio/io/result_io.h b/cpp/memilio/io/result_io.h index e325100e48..56a7ea7070 100644 --- a/cpp/memilio/io/result_io.h +++ b/cpp/memilio/io/result_io.h @@ -117,7 +117,7 @@ IOResult save_result_with_params(const std::vector> BOOST_OUTCOME_TRY(create_directory(result_dir_run.string())); BOOST_OUTCOME_TRY(save_result(result, county_ids, (int)(size_t)params[0].parameters.get_num_groups(), (result_dir_run / "Result.h5").string())); - BOOST_OUTCOME_TRY(write_graph(create_graph_without_edges>(params, county_ids), + BOOST_OUTCOME_TRY(write_graph(Graph>(county_ids, params), result_dir_run.string(), IOF_OmitDistributions)); return success(); } @@ -212,7 +212,7 @@ IOResult save_results(const std::vector auto ensemble_params_p95 = ensemble_params_percentile(ensemble_params, 0.95); auto make_graph = [&county_ids](auto&& params) { - return create_graph_without_edges>(params, county_ids); + return Graph>(county_ids, params); }; BOOST_OUTCOME_TRY( write_graph(make_graph(ensemble_params_p05), result_dir_p05.string(), IOF_OmitDistributions)); diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 2a75cafe67..51a4b32207 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -195,32 +195,30 @@ IOResult set_confirmed_cases_data(Model& model, std::vector -IOResult set_confirmed_cases_data(mio::VectorRange>>& model, const std::string& path, - std::vector const& region, Date date, - const std::vector& scaling_factor_inf) +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - + // sort case_data into regions and ignore once with no region associated std::vector> vcase_data{model.size()}; for (auto&& entry : case_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { - return r == 0 || get_region_id(entry) == r; + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - vcase_data[region_idx].pushback(entry); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { BOOST_OUTCOME_TRY( - set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf)); + set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf)); } return success(); } @@ -229,7 +227,7 @@ IOResult set_confirmed_cases_data(mio::VectorRange>>& model * @brief Sets population data from census data which has been read into num_population. * @tparam FP floating point data type, e.g., double. * @param[in, out] model Vector of models in which the data is set. There should be one model per region. -* @param[in] num_population Vector of population data. The size should be the same as vregion and model. +* @param[in] num_population Vector of population data. * @param[in] vregion Vector of keys of the regions of interest. */ template @@ -249,13 +247,13 @@ IOResult set_population_data(Model& model, const std::vector& auto num_groups = model.parameters.get_num_groups(); auto data_groups = num_population.size(); - if (data_groups == model_groups) { + if (data_groups == (size_t)num_groups) { for (auto i = AgeGroup(0); i < num_groups; i++) { model.populations.template set_difference_from_group_total( {i, InfectionState::Susceptible}, num_population[(size_t)i]); } } - else if (model_groups == 1 && data_groups >= 1) { + else if ((size_t)num_groups == 1 && data_groups >= 1) { const FP total = std::accumulate(num_population.begin(), num_population.end(), FP(0.0), [](const FP& a, const FP& b) { return evaluate_intermediate(a + b); @@ -280,16 +278,16 @@ IOResult set_population_data(Model& model, const std::vector& * @tparam FP Floating point data type, e.g., double. * @param[in, out] model Vector of models in which the data is set. * @param[in] path Path to RKI file containing population data. -* @param[in] vregion Vector of keys of the regions of interest. */ template -IOResult set_population_data(mio::VectorRange>>& model, const std::string& path, - const std::vector& vregion) +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path) { + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); BOOST_OUTCOME_TRY(const auto&& num_population, read_population_data(path, vregion)); - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], vregion[region_idx])); + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id)); } return success(); } @@ -322,7 +320,7 @@ IOResult set_divi_data(Model& model, const double num_icu, double scal } for (auto i = AgeGroup(0); i < num_groups; i++) { - model.populations[{i, InfectionState::InfectedCriticalNaive}] = + model.populations[{i, InfectionState::InfectedCritical}] = scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; } @@ -333,13 +331,12 @@ IOResult set_divi_data(Model& model, const double num_icu, double scal * @brief sets populations data from DIVI register into Model * @param[in, out] model vector of objects in which the data is set * @param[in] path Path to transformed DIVI file - * @param[in] vregion vector of keys of the regions of interest * @param[in] date Date for which the arrays are initialized * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data */ template -IOResult set_divi_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu) +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + double scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. if (!is_divi_data_available(date)) { @@ -348,10 +345,13 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std date); return success(); } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); } return success(); @@ -359,6 +359,30 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std } //namespace details + +/** + * @brief reads population data from population files for the specified nodes + * @param[in, out] model vector of model in which the data is set + * @param[in] date Date for which the data should be read + * @param[in] scaling_factor_inf factors by which to scale the confirmed cases of rki data + * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + * @param[in] pydata_dir directory of files + * @param[in] age_group_names strings specifying age group names + */ +template +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, double scaling_factor_icu, + const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, + scaling_factor_icu)); + + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, + scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path)); + return success(); +} + #ifdef MEMILIO_HAS_HDF5 /** @@ -366,10 +390,9 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std * The initialisation is applied for a predefined number of days and finally saved in a timeseries for each region. In the end, * we save the files "Results_rki.h5" and "Results_rki_sum.h5" in the results_dir. * Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. -* @param[in] models Vector of models in which the data is set. Copy is made to avoid changing the original model. +* @param[in] model Vector of models in which the data is set. Copy is made to avoid changing the original model. * @param[in] results_dir Path to result files. * @param[in] date Date for which the data should be read. -* @param[in] node_ids Vector of keys of the node_ids of interest. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. * @param[in] num_days Number of days to be simulated/initialized. @@ -377,29 +400,31 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std */ template IOResult export_input_data_timeseries( - mio::VectorRange>> models, const std::string& results_dir, Date date, const std::vector& node_ids, + const mio::VectorRange>> model, const std::string& results_dir, Date date, const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { - const auto num_age_groups = (size_t)models[0].property.parameters.get_num_groups(); + const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); // allow scalar scaling factor as convenience for 1-group models assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); - assert(models.size() == node_ids.size()); + std::vector> extrapolated_data( - node_ids.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); + model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); - BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, + BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, num_days, epidata_filenames)); - for (size_t r = 0; r < node_ids.size(); r++) { - extrapolated_data[r][t] = models[r].property.get_initial_values(); + for (size_t r = 0; r < model.size(); r++) { + extrapolated_data[r][t] = model[r].property.get_initial_values(); } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, node_ids, static_cast(num_age_groups), + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); @@ -410,7 +435,7 @@ IOResult export_input_data_timeseries( } #else template -IOResult export_input_data_county_timeseries(mio::VectorRange>>, const std::string&, Date, const std::vector&, +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, const mio::regions::de::EpidataFilenames&) { @@ -419,31 +444,8 @@ IOResult export_input_data_county_timeseries(mio::VectorRange -IOResult read_input_data(mio::VectorRange>>& model, Date date, const std::vector& node_ids, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, - scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, node_ids)); - return success(); -} - } // namespace osecir + } // namespace mio #endif // MEMILIO_HAS_JSONCPP diff --git a/cpp/models/ode_secirts/parameters_io.cpp b/cpp/models/ode_secirts/parameters_io.cpp index d70e4c4066..77f2bc9b0a 100644 --- a/cpp/models/ode_secirts/parameters_io.cpp +++ b/cpp/models/ode_secirts/parameters_io.cpp @@ -179,7 +179,7 @@ IOResult compute_confirmed_cases_data( try_fix_constraints(num_InfectedSevere[i], tol_error, "InfectedSevere"); try_fix_constraints(num_death[i], tol_error, "Dead"); try_fix_constraints(num_icu[i], tol_error, "InfectedCritical"); - try_fix_constraints(num_timm_i[i], tol_error, "Recently Recovered or Vaccinated"); + try_fix_constraints(num_imm[i], tol_error, "Recently Recovered or Vaccinated"); } return success(); diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index 213d875001..e6965665b5 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -247,8 +247,6 @@ set_confirmed_cases_data(Model& model, const std::vector& model, const std::vector& model, const std::vector& model, const std::vector -IOResult set_confirmed_cases_data(mio::VectorRange>>& model, const std::string& path, - std::vector const& vregion, Date date, - const std::vector& scaling_factor_inf, +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf, const std::vector>& immunity_population) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); @@ -397,18 +392,18 @@ IOResult set_confirmed_cases_data(mio::VectorRange>>& model // sort case_data into regions and ignore once with no region associated std::vector> vcase_data{model.size()}; for (auto&& entry : case_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { - return r == 0 || get_region_id(entry) == r; + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - vcase_data[region_idx].pushback(entry); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { BOOST_OUTCOME_TRY( - set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, immunity_population)); + set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf, immunity_population)); } return success(); @@ -494,20 +489,21 @@ IOResult set_population_data(Model& model, const std::vector& * * @param[in,out] model A vector of models for which population data will be set. * @param[in] path The file path to the population data. - * @param[in] vregion A vector of region identifiers corresponding to the population data. * @param[in] immunity_population A 2D vector where each row represents the immunity distribution for a specific region * across different levels of immunity (e.g., naive, partial, improved). * * @return An IOResult indicating success or failure. */ template -IOResult set_population_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::vector>& immunity_population) { + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion)); - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], vregion[region_idx], immunity_population)); + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id, immunity_population)); } return success(); } @@ -627,14 +623,13 @@ IOResult set_vaccination_data(Model& model, const std::vector -IOResult set_vaccination_data(mio::VectorRange>>& model, const std::string& path, Date date, - const std::vector& vregion, int num_days) +IOResult set_vaccination_data(const mio::VectorRange>>& model, const std::string& path, Date date, + int num_days) { // Set vaccination data to 0 for all models for (auto& m : model) { @@ -660,22 +655,22 @@ IOResult set_vaccination_data(mio::VectorRange>>& model, co } BOOST_OUTCOME_TRY(auto&& vacc_data, read_vaccination_data(path)); - + // Sort case_data into regions and ignore once with no region associated std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { - return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(r)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(r)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(r)); + auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { + return m.id == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(m.id)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(m.id)); }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - vvacc_data[region_idx].pushback(vacc_data_entry); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vvacc_data[region_idx].push_back(vacc_data_entry); } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vacc_data[region_idx], date, num_days)); } @@ -721,13 +716,12 @@ IOResult set_divi_data(Model& model, const double num_icu, double scal * @brief sets populations data from DIVI register into Model * @param[in, out] model vector of objects in which the data is set * @param[in] path Path to transformed DIVI file - * @param[in] vregion vector of keys of the regions of interest * @param[in] date Date for which the arrays are initialized * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data */ template -IOResult set_divi_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu) +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + double scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. if (!is_divi_data_available(date)) { @@ -736,10 +730,13 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std date); return success(); } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); } return success(); @@ -747,6 +744,41 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std } // namespace details +/** + * @brief Reads compartments for geographic units at a specified date from data files. + * + * This function estimates all compartments from available data using the provided model parameters. + * + * @param[in,out] model Vector of models, one per county, to be initialized with data. + * @param[in] date Date for which the data should be read. + * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. + * @param[in] scaling_factor_icu Scaling factor for ICU cases. + * @param[in] pydata_dir Directory containing the input data files. + * @param[in] num_days Number of days to simulate. + * @param[in] immunity_population Matrix containing immunity proportions for each age group and immunity layer. + * + * @return An IOResult indicating success or failure. + */ +template +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, double scaling_factor_icu, + int num_days, const std::vector>& immunity_population, + const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + + BOOST_OUTCOME_TRY( + details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, num_days)); + + // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. + // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, scaling_factor_icu)); + + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, + scaling_factor_inf, immunity_population)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, immunity_population)); + return success(); +} + #ifdef MEMILIO_HAS_HDF5 /** @@ -756,10 +788,9 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std * used to initialize the model with real-world data. The resulting data represents the initialized states of * the model over the specified time range. * - * @param[in] models A vector of models for which the extrapolated data is set. + * @param[in] model A vector of models for which the extrapolated data is set. * @param[in] results_dir Path to the directory where the extrapolated results will be saved in a h5 file. * @param[in] date Date for which the data should be read. - * @param[in] node_ids Vector of keys of the node_ids of interest. * @param[in] scaling_factor_inf A vector of scaling factors applied to confirmed cases. * @param[in] scaling_factor_icu A scaling factor applied to ICU cases. * @param[in] num_days The number of days for which will be extrapolated. @@ -770,26 +801,25 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std */ template IOResult export_input_data_timeseries( - mio::VectorRange>> models, const std::string& results_dir, Date date, const std::vector& node_ids, + const mio::VectorRange>> model, const std::string& results_dir, Date date, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) { - const auto num_age_groups = (size_t)models[0].property.parameters.get_num_groups(); + const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); - assert(models.size() == node_ids.size()); std::vector> extrapolated_data( - models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); + model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, - num_days, immunity_population, epidata_filenames)); + BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, + num_days, immunity_population, epidata_filenames)); - for (size_t r = 0; r < node_ids.size(); r++) { - extrapolated_data[r][t] = models[r].property.get_initial_values(); + for (size_t r = 0; r < model.size(); r++) { + extrapolated_data[r][t] = model[r].property.get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. for (size_t age = 0; age < num_age_groups; age++) { @@ -799,7 +829,10 @@ IOResult export_input_data_timeseries( } } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, node_ids, static_cast(num_age_groups), + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); @@ -811,7 +844,7 @@ IOResult export_input_data_timeseries( #else template -IOResult export_input_data_timeseries(mio::VectorRange>>, const std::string&, Date, const std::vector&, +IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, const std::vector>, const mio::regions::de::EpidataFilenames&) { @@ -821,45 +854,8 @@ IOResult export_input_data_timeseries(mio::VectorRange>>, c #endif //MEMILIO_HAS_HDF5 -/** - * @brief Reads compartments for geographic units at a specified date from data files. - * - * This function estimates all compartments from available data using the provided model parameters. - * - * @param[in,out] model Vector of models, one per county, to be initialized with data. - * @param[in] date Date for which the data should be read. - * @param[in] node_ids Vector of IDs of the units for which data is read. - * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. - * @param[in] scaling_factor_icu Scaling factor for ICU cases. - * @param[in] pydata_dir Directory containing the input data files. - * @param[in] num_days Number of days to simulate. - * @param[in] immunity_population Matrix containing immunity proportions for each age group and immunity layer. - * - * @return An IOResult indicating success or failure. - */ -template -IOResult read_input_data(mio::VectorRange>>& model, Date date, const std::vector& node_ids, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - int num_days, const std::vector>& immunity_population, - const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - - BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, node_ids, num_days)); - - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, - scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, - date, scaling_factor_inf, immunity_population)); - BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, node_ids, - immunity_population)); - return success(); -} - } // namespace osecirts + } // namespace mio #endif // MEMILIO_HAS_JSONCPP diff --git a/cpp/models/ode_secirvvs/parameters_io.cpp b/cpp/models/ode_secirvvs/parameters_io.cpp index 300c6cedd9..59d222c1bb 100644 --- a/cpp/models/ode_secirvvs/parameters_io.cpp +++ b/cpp/models/ode_secirvvs/parameters_io.cpp @@ -134,17 +134,8 @@ IOResult compute_confirmed_cases_data( return success(); } -IOResult compute_confirmed_cases_data_fix_recovered(std::string const& path, std::vector const& vregion, - Date date, std::vector>& vnum_rec, - double delay) -{ - BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - return compute_confirmed_cases_data_fix_recovered(case_data, vregion, date, vnum_rec, delay); -} - -IOResult compute_confirmed_cases_data_fix_recovered(const std::vector& case_data, - std::vector const& vregion, Date date, - std::vector>& vnum_rec, double delay) +IOResult> compute_confirmed_cases_data_fix_recovered( + const std::vector& case_data, const int region, Date date, double delay) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -167,46 +158,37 @@ IOResult compute_confirmed_cases_data_fix_recovered(const std::vector num_rec(num_groups, 0.0); + for (auto&& rki_entry : case_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&rki_entry](auto r) { - return r == 0 || get_region_id(rki_entry) == r; - }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - if (rki_entry.date == offset_date_by_days(date, int(-delay))) { - vnum_rec[region_idx][size_t(rki_entry.age_group)] = rki_entry.num_confirmed; - } + if (rki_entry.date == offset_date_by_days(date, int(-delay))) { + num_rec[size_t(rki_entry.age_group)] = rki_entry.num_confirmed; } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - auto region = vregion[region_idx]; - auto& num_rec = vnum_rec[region_idx]; - - size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size(); - for (size_t i = 0; i < num_groups; i++) { - auto try_fix_constraints = [region, i](double& value, double error, auto str) { - if (value < error) { - // this should probably return a failure - // but the algorithm is not robust enough to avoid large negative - // values and there are tests that rely on it - log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " - "exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - else if (value < 0) { - log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " - "automatically corrected", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); - value = 0.0; - } - }; - try_fix_constraints(num_rec[i], 0, "Recovered"); - } + for (size_t i = 0; i < num_groups; i++) { + auto try_fix_constraints = [region, i](double& value, double error, auto str) { + if (value < error) { + // this should probably return a failure + // but the algorithm is not robust enough to avoid large negative + // values and there are tests that rely on it + log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " + "exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + else if (value < 0) { + log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " + "automatically corrected", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + value = 0.0; + } + }; + try_fix_constraints(num_rec[i], 0, "Recovered"); } - return success(); + return success(num_rec); } } // namespace details diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 6bdfb3ed1d..4096b0011d 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -60,17 +60,13 @@ IOResult compute_confirmed_cases_data( * @param[in] path Path to RKI confirmed cases file. * @param[in] vregion Vector of keys of the region of interest. * @param[in] date Date for which the arrays are initialized. - * @param[in, out] num_rec Output vector for number of people in the compartement recovered. * @param[in] delay Number of days in the past the are used to set recovered compartment. + * @return Vector for number of people in the compartment recovered. * @see mio::read_confirmed_cases_data * @{ */ -IOResult compute_confirmed_cases_data_fix_recovered(const std::vector& rki_data, - std::vector const& vregion, Date date, - std::vector>& vnum_rec, double delay = 14.); -IOResult compute_confirmed_cases_data_fix_recovered(std::string const& path, std::vector const& vregion, - Date date, std::vector>& vnum_rec, - double delay = 14.); +IOResult> compute_confirmed_cases_data_fix_recovered( + const std::vector& case_data, const int region, Date date, double delay = 14.); /**@}*/ /** @@ -191,6 +187,7 @@ IOResult set_confirmed_cases_data(Model& model, const std::vector(num_age_groups, 0.0); num_InfectedSevere = std::vector(num_age_groups, 0.0); num_icu = std::vector(num_age_groups, 0.0); + for (size_t group = 0; group < num_age_groups; group++) { double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; t_Exposed.push_back(static_cast( @@ -233,7 +230,6 @@ IOResult set_confirmed_cases_data(Model& model, const std::vector set_confirmed_cases_data(Model& model, const std::vector(num_age_groups, 0.0); num_InfectedSevere = std::vector(num_age_groups, 0.0); num_icu = std::vector(num_age_groups, 0.0); + for (size_t group = 0; group < num_age_groups; group++) { double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; t_Exposed.push_back(static_cast( @@ -319,33 +316,30 @@ IOResult set_confirmed_cases_data(Model& model, const std::vector(a + b); - }) == 0.0) { - log_warning("No infections for vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region[county]); - } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), + [](const double& a, const double& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning("No infections for vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); } return success(); @@ -362,8 +356,7 @@ IOResult set_confirmed_cases_data(Model& model, const std::vector -IOResult set_confirmed_cases_data(mio::VectorRange>>& model, const std::string& path, - std::vector const& vregion, Date date, +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, Date date, const std::vector& scaling_factor_inf, bool set_death = false) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); @@ -371,17 +364,17 @@ IOResult set_confirmed_cases_data(mio::VectorRange>>& model // sort case_data into regions and ignore once with no region associated std::vector> vcase_data{model.size()}; for (auto&& entry : case_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { - return r == 0 || get_region_id(entry) == r; + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - vcase_data[region_idx].pushback(entry); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], vregion[region_idx], date, scaling_factor_inf, set_death)); + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf, set_death)); } return success(); } @@ -577,23 +570,32 @@ IOResult set_population_data(Model& model, const std::vector& * @param[in, out] model Vector of objects in which the data is set. * @param[in] path Path to population data file. * @param[in] path_rki Path to RKI cases data file. -* @param[in] vregion Vector of keys of the regions of interest. * @param[in] date Date for which the arrays are initialized. */ template -IOResult set_population_data(mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, - const std::vector& vregion, Date date) +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, + Date date) { + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); BOOST_OUTCOME_TRY(auto&& vnum_population, read_population_data(path, vregion)); BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path_rki)); - auto num_age_groups = ConfirmedCasesDataEntry::age_group_names.size(); - std::vector> vnum_rec(model.size(), std::vector(num_age_groups, 0.0)); - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data_fix_recovered(case_data, vregion, date, vnum_rec, 14.)); + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; + }); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); + } + } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, vnum_population[region_idx], vregion[region_idx], vnum_rec[region_idx])); + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(auto&& num_rec, compute_confirmed_cases_data_fix_recovered(case_data[region_idx], model[region_idx].id, date, 14.)); + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, vnum_population[region_idx], model[region_idx].id, num_rec)); } return success(); } @@ -725,12 +727,11 @@ IOResult set_vaccination_data(Model& model, const std::vector -IOResult set_vaccination_data(mio::VectorRange>>& model, const std::string& path, Date date, - const std::vector& vregion, int num_days) +IOResult set_vaccination_data(const mio::VectorRange>>& model, const std::string& path, Date date, + int num_days) { // Set vaccination data to 0 for all models for (auto& m : model) { @@ -757,18 +758,18 @@ IOResult set_vaccination_data(mio::VectorRange>>& model, co // Sort case_data into regions and ignore once with no region associated std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { - auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) { - return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(r)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(r)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(r)); + auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { + return m.id == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(m.id)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(m.id)); }); - if (it != vregion.end()) { - auto region_idx = size_t(it - vregion.begin()); - vvacc_data[region_idx].pushback(vacc_data_entry); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vvacc_data[region_idx].push_back(vacc_data_entry); } } - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vacc_data[region_idx], date, num_days)); } @@ -814,13 +815,12 @@ IOResult set_divi_data(Model& model, const double num_icu, double scal * @brief sets populations data from DIVI register into Model * @param[in, out] model vector of objects in which the data is set * @param[in] path Path to transformed DIVI file - * @param[in] vregion vector of keys of the regions of interest * @param[in] date Date for which the arrays are initialized * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data */ template -IOResult set_divi_data(mio::VectorRange>>& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu) +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + double scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. if (!is_divi_data_available(date)) { @@ -829,10 +829,13 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std date); return success(); } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], vregion[region_idx], scaling_factor_icu)); + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); } return success(); @@ -840,6 +843,27 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std } // namespace details +template +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, double scaling_factor_icu, + int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + + BOOST_OUTCOME_TRY( + details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, num_days)); + + // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. + // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, + scaling_factor_icu)); + + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, + date, scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, + epidata_filenames.case_data_path, date)); + return success(); +} + #ifdef MEMILIO_HAS_HDF5 /** @@ -847,10 +871,9 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std * The initialisation is applied for a predefined number of days and finally saved in a timeseries for each region. In the end, * we save the files "Results_rki.h5" and "Results_rki_sum.h5" in the results_dir. * Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. -* @param[in] models Vector of models in which the data is set. Copy is made to avoid changing the original model. +* @param[in] model Vector of models in which the data is set. Copy is made to avoid changing the original model. * @param[in] results_dir Path to result files. * @param[in] date Date for which the data should be read. -* @param[in] node_ids Vector of keys of the node_ids of interest. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. * @param[in] num_days Number of days to be simulated/initialized. @@ -858,26 +881,25 @@ IOResult set_divi_data(mio::VectorRange>>& model, const std */ template IOResult export_input_data_timeseries( - mio::VectorRange>> models, const std::string& results_dir, Date date, const std::vector& node_ids, + const mio::VectorRange>> model, const std::string& results_dir, Date date, const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { - const auto num_age_groups = (size_t)models[0].property.parameters.get_num_groups(); + const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); - assert(models.size() == node_ids.size()); std::vector> extrapolated_data( - models.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); + model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data(model, date, county, scaling_factor_inf, scaling_factor_icu, + BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, num_days, epidata_filenames)); - for (size_t r = 0; r < node_ids.size(); r++) { - extrapolated_data[r][t] = models[r].property.get_initial_values(); + for (size_t r = 0; r < model.size(); r++) { + extrapolated_data[r][t] = model[r].property.get_initial_values(); // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. // Since we should be independent whether we consider them or not, we add them back here before we save the data. for (size_t age = 0; age < num_age_groups; age++) { @@ -887,7 +909,9 @@ IOResult export_input_data_timeseries( } } } - BOOST_OUTCOME_TRY(save_result(extrapolated_data, node_ids, static_cast(num_age_groups), + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); @@ -898,7 +922,7 @@ IOResult export_input_data_timeseries( } #else template -IOResult export_input_data_county_timeseries(mio::VectorRange>>, const std::string&, Date, const std::vector&, +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, const std::vector&, const double, const int, const mio::regions::de::EpidataFilenames&) { @@ -908,29 +932,8 @@ IOResult export_input_data_county_timeseries(mio::VectorRange -IOResult read_input_data(mio::VectorRange>>& model, Date date, const std::vector& node_ids, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - - BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, node_ids, num_days)); - - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, node_ids, date, - scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, node_ids, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, - epidata_filenames.case_data_path, node_ids, date)); - return success(); -} - - } // namespace osecirvvs + } // namespace mio #endif // MEMILIO_HAS_JSONCPP From c553af3064ea5d2265613b27725f5e327d442720 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 4 Nov 2025 23:27:41 +0000 Subject: [PATCH 06/26] fix graph functions --- cpp/memilio/mobility/graph.h | 41 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index 17212cda15..a02a9ba162 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -152,21 +152,37 @@ class Graph using NodeProperty = NodePropertyT; using EdgeProperty = EdgePropertyT; - Graph(std::vector& node_ids, std::vector& node_properties) + Graph(const std::vector& node_ids, std::vector& node_properties) { for (auto i = size_t(0); i < node_ids.size(); ++i) { add_node(node_ids[i], node_properties[i]); } } + Graph(std::vector& node_properties) + { + for (auto i = size_t(0); i < node_properties.size(); ++i) { + add_node(i, node_properties[i]); + } + } + template - Graph(std::vector& node_ids, Args&&... args) + Graph(const std::vector& node_ids, Args&&... args) { for (int id : node_ids) { add_node(id, std::forward(args)...); } } + template + Graph(const int number_of_nodes, Args&&... args) + { + for (auto id = size_t(0); id < number_of_nodes; ++id) { + add_node(id, std::forward(args)...); + } + } + + Graph() = default; /** * @brief add a node to the graph. property of the node is constructed from arguments. @@ -256,25 +272,24 @@ class Graph std::vector> m_edges; }; -template -void set_test_and_trace_capacity(mio::VectorRange>& nodes) +template +void set_test_and_trace_capacity(const mio::VectorRange>& nodes, double tnt_capacity_factor) { for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { auto tnt_capacity = nodes[node_idx].property.populations.get_total() * tnt_capacity_factor; auto& tnt_value = nodes[node_idx].property.parameters.template get(); - tnt_value = UncertainValue(tnt_capacity); + tnt_value = UncertainValue(tnt_capacity); tnt_value.set_distribution(mio::ParameterDistributionUniform(0.8 * tnt_capacity, 1.2 * tnt_capacity)); } } template -void set_german_holidays(mio::VectorRange>& nodes, const std::vector& node_ids, - const mio::Date& start_date, const mio::Date& end_date) +void set_german_holidays(const mio::VectorRange>& nodes, const mio::Date& start_date, const mio::Date& end_date) { for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { - auto state_id = regions::de::get_state_id(node_id[node_idx]); + auto state_id = regions::de::get_state_id(nodes[node_idx].id); auto holiday_periods = regions::de::get_holidays(state_id, start_date, end_date); auto& contacts = nodes[node_idx].property.parameters.template get(); @@ -288,15 +303,15 @@ void set_german_holidays(mio::VectorRange>& nodes, const std::vector } } -template -void set_uncertainty_on_population(mio::VectorRange>& nodes) +template +void set_uncertainty_on_population(const mio::VectorRange>& nodes) { for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { - for (auto i = mio::AgeGroup(0); i < params.get_num_groups(); i++) { + for (auto i = mio::AgeGroup(0); i < nodes[0].property.parameters.get_num_groups(); i++) { for (auto j = Index(0); j < Model::Compartments::Count; ++j) { auto& compartment_value = nodes[node_idx].property.populations[{i, j}]; compartment_value = - UncertainValue(compartment_value.value()); + UncertainValue(compartment_value.value()); compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), 1.1 * compartment_value.value())); } @@ -342,7 +357,7 @@ IOResult set_edges(const fs::path& mobility_data_file, Graph(num_age_groups, 1.0) : commuting_weights); //commuters - auto working_population = 0.0; + FP working_population = 0.0; for (auto age = AgeGroup(0); age < populations.template size(); ++age) { working_population += populations.get_group_total(age) * commuting_weights[size_t(age)]; } From 511956bb2e71eab56a7a9c14def81ced8966de3f Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Fri, 14 Nov 2025 13:43:14 +0000 Subject: [PATCH 07/26] Adapt documentation for new interfaces --- cpp/memilio/ad/ad.h | 61 ++ cpp/memilio/epidemiology/populations.h | 11 + cpp/memilio/mobility/graph.h | 8 +- cpp/memilio/utils/custom_index_array.h | 9 + cpp/models/ode_secir/parameters_io.cpp | 315 +++++++- cpp/models/ode_secir/parameters_io.h | 465 +++--------- cpp/models/ode_secirts/parameters_io.cpp | 536 +++++++++++++- cpp/models/ode_secirts/parameters_io.h | 719 ++++--------------- cpp/models/ode_secirvvs/parameters_io.cpp | 634 +++++++++++++++- cpp/models/ode_secirvvs/parameters_io.h | 834 ++++------------------ 10 files changed, 1940 insertions(+), 1652 deletions(-) diff --git a/cpp/memilio/ad/ad.h b/cpp/memilio/ad/ad.h index 96c93bcd29..8ea41afc6f 100644 --- a/cpp/memilio/ad/ad.h +++ b/cpp/memilio/ad/ad.h @@ -27,6 +27,67 @@ #include #include +// Extend automatic differentiation (AD) library to support std::round and std::trunc. +namespace ad +{ +namespace internal +{ +using std::round; +template +static inline double round(const ad::internal::active_type& x) +{ + return round(x._value()); +} +template +static inline double round(const ad::internal::binary_intermediate_aa& x) +{ + return round(x._value()); +} +template +static inline double round(const ad::internal::binary_intermediate_ap& x) +{ + return round(x._value()); +} +template +static inline double round(const ad::internal::binary_intermediate_pa& x) +{ + return round(x._value()); +} +template +static inline double round(const ad::internal::unary_intermediate& x) +{ + return round(x._value()); +} + +using std::trunc; +template +static inline double trunc(const ad::internal::active_type& x) +{ + return trunc(x._value()); +} +template +static inline double trunc(const ad::internal::binary_intermediate_aa& x) +{ + return trunc(x._value()); +} +template +static inline double trunc(const ad::internal::binary_intermediate_ap& x) +{ + return trunc(x._value()); +} +template +static inline double trunc(const ad::internal::binary_intermediate_pa& x) +{ + return trunc(x._value()); +} +template +static inline double trunc(const ad::internal::unary_intermediate& x) +{ + return trunc(x._value()); +} +} // namespace internal +} // namespace ad + // Allow std::numeric_limits to work with AD types. template struct std::numeric_limits> : public numeric_limits { diff --git a/cpp/memilio/epidemiology/populations.h b/cpp/memilio/epidemiology/populations.h index 5c0f918633..65a826f54b 100644 --- a/cpp/memilio/epidemiology/populations.h +++ b/cpp/memilio/epidemiology/populations.h @@ -63,6 +63,17 @@ class Populations : public CustomIndexArray, Categories...> { } + explicit Populations(Base&& array) + : Base(std::move(array)) + { + } + + template + Populations convert() const + { + return Populations(Base::convert()); + } + /** * @brief get_num_compartments returns the number of compartments * diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index a02a9ba162..b9df7be042 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -152,8 +152,12 @@ class Graph using NodeProperty = NodePropertyT; using EdgeProperty = EdgePropertyT; + /* add note for same size of parameters + */ Graph(const std::vector& node_ids, std::vector& node_properties) { + assert(node_ids.size() == node_properties.size()); + for (auto i = size_t(0); i < node_ids.size(); ++i) { add_node(node_ids[i], node_properties[i]); } @@ -167,10 +171,10 @@ class Graph } template - Graph(const std::vector& node_ids, Args&&... args) + Graph(const std::vector& node_ids, Args&&... node_args) { for (int id : node_ids) { - add_node(id, std::forward(args)...); + add_node(id, std::forward(node_args)...); } } diff --git a/cpp/memilio/utils/custom_index_array.h b/cpp/memilio/utils/custom_index_array.h index d17d496275..45863e5e2f 100644 --- a/cpp/memilio/utils/custom_index_array.h +++ b/cpp/memilio/utils/custom_index_array.h @@ -342,6 +342,15 @@ class CustomIndexArray } } + template + CustomIndexArray convert() const + { + CustomIndexArray other; + other.resize(m_dimensions); + other.array() = m_y.template cast(); + return other; + } + private: // Random Access Iterator for CustomIndexArray // To Do: As of Eigen 3.4, this is not needed anymore, diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index 08a9841ef7..75c3b4efe8 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -46,15 +46,15 @@ namespace details IOResult compute_confirmed_cases_data( std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf) + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& scaling_factor_inf) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -123,7 +123,7 @@ IOResult compute_confirmed_cases_data( (num_InfectedSymptoms[i] / scaling_factor_inf[i] + num_InfectedSevere[i] / scaling_factor_inf[i] + num_icu[i] / scaling_factor_inf[i] + num_death[i] / scaling_factor_inf[i]); - auto try_fix_constraints = [region, i](double& value, double error, auto str) { + auto try_fix_constraints = [region, i](ScalarType& value, ScalarType error, auto str) { if (value < error) { //this should probably return a failure //but the algorithm is not robust enough to avoid large negative values and there are tests that rely on it @@ -150,8 +150,305 @@ IOResult compute_confirmed_cases_data( return success(); } -} // namespace details +IOResult set_confirmed_cases_data(Model& model, std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf) +{ + const size_t num_age_groups = ConfirmedCasesDataEntry::age_group_names.size(); + // allow single scalar scaling that is broadcast to all age groups + assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); + + // Set scaling factors to match num age groups + std::vector scaling_factor_inf_full; + if (scaling_factor_inf.size() == 1) { + scaling_factor_inf_full.assign(num_age_groups, scaling_factor_inf[0]); + } + else { + scaling_factor_inf_full = scaling_factor_inf; + } + + std::vector t_InfectedNoSymptoms; + std::vector t_Exposed; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; + + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; + std::vector mu_U_D; + + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_rec(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + + const size_t model_groups = (size_t)model.parameters.get_num_groups(); + assert(model_groups == 1 || model_groups == num_age_groups); + for (size_t ag = 0; ag < num_age_groups; ag++) { + // If the model has fewer groups than casedata entries available, + // reuse group 0 parameters for all RKI age groups + const size_t group = (model_groups == num_age_groups) ? ag : 0; + + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + mu_C_R.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf_full)); + + if (model_groups == num_age_groups) { + for (size_t i = 0; i < model_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::Exposed}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptoms}] = + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptoms}] = + num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevere}] = + num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCritical}] = num_icu[i]; + } + model.populations[{AgeGroup(i), InfectionState::Recovered}] = num_rec[i]; + model.populations[{AgeGroup(i), InfectionState::Dead}] = num_death[i]; + } + } + else { + const auto sum_vec = [](const std::vector& v) { + return std::accumulate(v.begin(), v.end(), ScalarType(0.0), [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }); + }; + model.populations[{AgeGroup(0), InfectionState::Exposed}] = sum_vec(num_Exposed); + model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptoms}] = + sum_vec(num_InfectedNoSymptoms); + model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(0), InfectionState::InfectedSymptoms}] = + sum_vec(num_InfectedSymptoms); + model.populations[{AgeGroup(0), InfectionState::InfectedSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(0), InfectionState::InfectedSevere}] = + sum_vec(num_InfectedSevere); + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(0), InfectionState::InfectedCritical}] = sum_vec(num_icu); + } + model.populations[{AgeGroup(0), InfectionState::Dead}] = sum_vec(num_death); + model.populations[{AgeGroup(0), InfectionState::Recovered}] = sum_vec(num_rec); + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning( + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", + date, region); + } + return success(); +} + +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf) +{ + BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); + + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; + }); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); + } + } + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY( + set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf)); + } + return success(); +} + +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region) +{ + if (std::accumulate(num_population.begin(), num_population.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) <= 0) + { + log_warning("No population data available for region " + std::to_string(region) + + ". Population data has not been set."); + return success(); + } + + auto num_groups = model.parameters.get_num_groups(); + auto data_groups = num_population.size(); + + if (data_groups == (size_t)num_groups) { + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations.template set_difference_from_group_total( + {i, InfectionState::Susceptible}, num_population[(size_t)i]); + } + } + else if ((size_t)num_groups == 1 && data_groups >= 1) { + const ScalarType total = std::accumulate(num_population.begin(), num_population.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }); + model.populations.template set_difference_from_group_total( + {AgeGroup(0), InfectionState::Susceptible}, total); + } + + for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { + for (auto j = Index(0); j < InfectionState::Count; ++j) { + if (model.populations[{i, j}] < 0) { + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), + size_t(j), model.populations[{i, j}]); + } + } + } + return success(); +} + +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path) +{ + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(const auto&& num_population, read_population_data(path, vregion)); + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id)); + } + return success(); +} + +IOResult set_divi_data(Model& model, const ScalarType num_icu, ScalarType scaling_factor_icu) +{ + ScalarType sum_mu_I_U = 0; + std::vector mu_I_U; + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + sum_mu_I_U += model.parameters.template get>()[i] * + model.parameters.template get>()[i]; + mu_I_U.push_back(model.parameters.template get>()[i] * + model.parameters.template get>()[i]); + } + + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations[{i, InfectionState::InfectedCritical}] = + scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; + } + + return success(); +} + +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + ScalarType scaling_factor_icu) +{ + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); + } + + return success(); +} + +} //namespace details + +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, + const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, + scaling_factor_icu)); + + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, + scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path)); + return success(); +} + +#ifdef MEMILIO_HAS_HDF5 + +IOResult export_input_data_timeseries( + const mio::VectorRange>> model, const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); + // allow scalar scaling factor as convenience for 1-group models + assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); + + std::vector> extrapolated_data( + model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); + + for (int t = 0; t <= num_days; ++t) { + auto offset_day = offset_date_by_days(date, t); + + BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, epidata_filenames)); + + for (size_t r = 0; r < model.size(); r++) { + extrapolated_data[r][t] = model[r].property.get_initial_values(); + } + } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), + path_join(results_dir, "Results_rki.h5"))); + + auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); + BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), + path_join(results_dir, "Results_rki_sum.h5"))); + + return success(); +} +#else +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, + const std::vector&, const ScalarType, const int, + const mio::regions::de::EpidataFilenames&) +{ + mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); + return success(); +} +#endif // MEMILIO_HAS_HDF5 + } // namespace osecir + } // namespace mio #endif // MEMILIO_HAS_JSONCPP diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 51a4b32207..1820e03c47 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -40,408 +40,161 @@ namespace osecir namespace details { + /** - * @brief reads populations data from RKI. - * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. - * @param[in] region Vector of keys of the region of interest. - * @param[in] date Date at which the data is read. - * @param[in, out] num_* Output vector for number of people in the corresponding compartement. - * @param[in] t_* vector Average time it takes to get from one compartement to another for each age group. - * @param[in] mu_* vector Probabilities to get from one compartement to another for each age group. - * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. - */ + * @brief Reads populations data from rki data. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Key of the region of interest. + * @param[in] date Date at which the data is read. + * @param[in, out] num_* Output vector for number of people in the corresponding compartement. + * @param[in] t_* vector Average time it takes to get from one compartement to another for each age group. + * @param[in] mu_* vector Probabilities to get from one compartement to another for each age group. + * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. + */ IOResult compute_confirmed_cases_data( std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf); + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& scaling_factor_inf); /** - * @brief Sets populations data from already read case data with multiple age groups into a Model with one age group. - * @tparam FP Floating point data type, e.g., double. - * @param[in, out] model Vector of models in which the data is set. - * @param[in] case_data List of confirmed cases data entries. - * @param[in] region Vector of keys of the region of interest. + * @brief Sets populations data from already read case data with multiple age groups into a Model. + * @param[in, out] model Model in which the data is set. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Key of the region of interest. * @param[in] date Date at which the data is read. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. */ -template -IOResult set_confirmed_cases_data(Model& model, std::vector& case_data, - const int region, Date date, const std::vector& scaling_factor_inf) -{ - const size_t num_age_groups = ConfirmedCasesDataEntry::age_group_names.size(); - // allow single scalar scaling that is broadcast to all age groups - assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); - - // Set scaling factors to match num age groups - std::vector scaling_factor_inf_full; - if (scaling_factor_inf.size() == 1) { - scaling_factor_inf_full.assign(num_age_groups, scaling_factor_inf[0]); - } - else { - scaling_factor_inf_full = scaling_factor_inf; - } - - std::vector t_InfectedNoSymptoms; - std::vector t_Exposed; - std::vector t_InfectedSymptoms; - std::vector t_InfectedSevere; - std::vector t_InfectedCritical; - - std::vector mu_C_R; - std::vector mu_I_H; - std::vector mu_H_U; - std::vector mu_U_D; - - std::vector num_InfectedSymptoms(num_age_groups, 0.0); - std::vector num_death(num_age_groups, 0.0); - std::vector num_rec(num_age_groups, 0.0); - std::vector num_Exposed(num_age_groups, 0.0); - std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); - std::vector num_InfectedSevere(num_age_groups, 0.0); - std::vector num_icu(num_age_groups, 0.0); - - const size_t model_groups = (size_t)model.parameters.get_num_groups(); - assert(model_groups == 1 || model_groups == num_age_groups); - for (size_t ag = 0; ag < num_age_groups; ag++) { - // If the model has fewer groups than casedata entries available, - // reuse group 0 parameters for all RKI age groups - const size_t group = (model_groups == num_age_groups) ? ag : 0; - - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedSymptoms.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedSevere.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - - mu_C_R.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_I_H.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_H_U.push_back( - model.parameters.template get>()[(AgeGroup)group]); - } - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf_full)); - - if (model_groups == num_age_groups) { - for (size_t i = 0; i < model_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::Exposed}] = num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptoms}] = - num_InfectedNoSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptoms}] = - num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevere}] = - num_InfectedSevere[i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCritical}] = num_icu[i]; - } - model.populations[{AgeGroup(i), InfectionState::Recovered}] = num_rec[i]; - model.populations[{AgeGroup(i), InfectionState::Dead}] = num_death[i]; - } - } - else { - const auto sum_vec = [](const std::vector& v) { - return std::accumulate(v.begin(), v.end(), FP(0.0), [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }); - }; - model.populations[{AgeGroup(0), InfectionState::Exposed}] = sum_vec(num_Exposed); - model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptoms}] = - sum_vec(num_InfectedNoSymptoms); - model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(0), InfectionState::InfectedSymptoms}] = - sum_vec(num_InfectedSymptoms); - model.populations[{AgeGroup(0), InfectionState::InfectedSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(0), InfectionState::InfectedSevere}] = - sum_vec(num_InfectedSevere); - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(0), InfectionState::InfectedCritical}] = sum_vec(num_icu); - } - model.populations[{AgeGroup(0), InfectionState::Dead}] = sum_vec(num_death); - model.populations[{AgeGroup(0), InfectionState::Recovered}] = sum_vec(num_rec); - } - if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) == 0.0) { - log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region); - } - return success(); -} +IOResult set_confirmed_cases_data(Model& model, std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf); /** - * @brief Sets the infected population for a given model based on confirmed cases data. Here, we - * read the case data from a file. - * @tparam FP Floating point data type, e.g., double. - * @param[in, out] Vector of models for which the confirmed cases data will be set. + * @brief Sets the infected populations for the given models based on confirmed cases data. + * Reads the case data from a file and then calls a subfunction that sets the infected population + * for each model. + * @param[in, out] model VectorRange of Node%s each containing a Model for which the confirmed cases data will be set. * @param[in] path Path to the confirmed cases data file. * @param[in] date Date at which the data is read. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. */ -template -IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, - Date date, const std::vector& scaling_factor_inf) -{ - BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - - // sort case_data into regions and ignore once with no region associated - std::vector> vcase_data{model.size()}; - for (auto&& entry : case_data) { - auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { - return m.id == 0 || get_region_id(entry) == m.id; - }); - if (it != model.end()) { - auto region_idx = size_t(it - model.begin()); - vcase_data[region_idx].push_back(entry); - } - } - - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY( - set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf)); - } - return success(); -} +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf); /** -* @brief Sets population data from census data which has been read into num_population. -* @tparam FP floating point data type, e.g., double. -* @param[in, out] model Vector of models in which the data is set. There should be one model per region. -* @param[in] num_population Vector of population data. -* @param[in] vregion Vector of keys of the regions of interest. -*/ -template -IOResult set_population_data(Model& model, const std::vector& num_population, - const int region) -{ - if (std::accumulate(num_population.begin(), num_population.end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) <= 0) - { - log_warning("No population data available for region " + std::to_string(region) + - ". Population data has not been set."); - return success(); - } - - auto num_groups = model.parameters.get_num_groups(); - auto data_groups = num_population.size(); - - if (data_groups == (size_t)num_groups) { - for (auto i = AgeGroup(0); i < num_groups; i++) { - model.populations.template set_difference_from_group_total( - {i, InfectionState::Susceptible}, num_population[(size_t)i]); - } - } - else if ((size_t)num_groups == 1 && data_groups >= 1) { - const FP total = std::accumulate(num_population.begin(), num_population.end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }); - model.populations.template set_difference_from_group_total( - {AgeGroup(0), InfectionState::Susceptible}, total); - } - - for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { - for (auto j = Index(0); j < InfectionState::Count; ++j) { - if (model.populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model.populations[{i, j}]); - } - } - } - return success(); -} + * @brief Sets population data from census data which has been read into num_population. + * @param[in, out] model Model in which the data is set. + * @param[in] num_population Vector of population data for the region of interest. + * @param[in] region Key of the region of interest. + */ +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region); /** -* @brief Sets population data from census data into a Model. -* @tparam FP Floating point data type, e.g., double. -* @param[in, out] model Vector of models in which the data is set. -* @param[in] path Path to RKI file containing population data. -*/ -template -IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path) -{ - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(const auto&& num_population, read_population_data(path, vregion)); + * @brief Reads population data from a file and sets it for the each given model. + * @param[in, out] model VectorRange of Node%s containing a Model for which the confirmed cases data will be set. + * @param[in] path Path to population data file. + */ +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path); - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id)); - } - return success(); -} +/** + * @brief Sets ICU data into a Model, distributed across age groups. + * @param[in, out] model Model in which the data is set. + * @param[in] num_icu ICU data for the region of interest. + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + */ +IOResult set_divi_data(Model& model, const ScalarType num_icu, ScalarType scaling_factor_icu); /** * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. - * + * * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) * for each region, and sets these values in the model. The ICU cases are distributed across age groups * using the transition probabilities from severe to critical. - * @tparam FP Floating point type (default: double). - * - * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. - * @param[in] num_icu icu data + * + * @param[in, out] model VectorRange of Node%s each containing a Model. + * @param[in] path Path to transformed DIVI file. + * @param[in] date Date at which the data is read. * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. - * - * @return An IOResult indicating success or failure. */ -template -IOResult set_divi_data(Model& model, const double num_icu, double scaling_factor_icu) -{ - FP sum_mu_I_U = 0; - std::vector mu_I_U; - auto num_groups = model.parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - sum_mu_I_U += model.parameters.template get>()[i] * - model.parameters.template get>()[i]; - mu_I_U.push_back(model.parameters.template get>()[i] * - model.parameters.template get>()[i]); - } +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + ScalarType scaling_factor_icu); - for (auto i = AgeGroup(0); i < num_groups; i++) { - model.populations[{i, InfectionState::InfectedCritical}] = - scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; - } +} //namespace details - return success(); -} /** - * @brief sets populations data from DIVI register into Model - * @param[in, out] model vector of objects in which the data is set - * @param[in] path Path to transformed DIVI file - * @param[in] date Date for which the arrays are initialized - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + * @brief Reads compartments for geographic units at a specified date from data files. + * + * This function estimates all compartments from available data using the provided model parameters. + * + * @param[in,out] model VectorRange of Node%s each containing a Model to be initialized with data. + * @param[in] date Date for which the data should be read. + * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. + * @param[in] scaling_factor_icu Scaling factor for ICU cases. + * @param[in] epidata_filenames Object containing the input data file paths. + * + * @return An IOResult indicating success or failure. */ -template -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, - double scaling_factor_icu) -{ - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); - } - - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); - } - - return success(); -} - -} //namespace details - +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, + const mio::regions::de::EpidataFilenames& epidata_filenames); /** - * @brief reads population data from population files for the specified nodes - * @param[in, out] model vector of model in which the data is set - * @param[in] date Date for which the data should be read - * @param[in] scaling_factor_inf factors by which to scale the confirmed cases of rki data - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data - * @param[in] pydata_dir directory of files - * @param[in] age_group_names strings specifying age group names + * @brief Converts input data from one range of models to another with different type. + * + * @tparam FP Floating point type (default: double). + * @param[in] model_from VectorRange of Node%s each containing a Model with the input data. + * @param[in,out] model_to VectorRange of Node%s each containing a Model to be initialized with data. + * + * @return An IOResult indicating success or failure. */ -template -IOResult read_input_data(const mio::VectorRange>>& model, Date date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - const mio::regions::de::EpidataFilenames& epidata_filenames) +template +void convert_input_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to) { - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, - scaling_factor_icu)); + assert(model_from.size() == model_to.size()); + assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()) + // Todo: add conversion of ParameterSet and then re-use code from other model parameters io - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, - scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path)); - return success(); + for (size_t region_idx = 0; region_idx < model_from.size(); ++region_idx) { + // convert populations to mio::UncertainValue + // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work + model_to[region_idx].property.populations = model_to[region_idx].property.populations.convert().convert>(); + } } #ifdef MEMILIO_HAS_HDF5 /** -* @brief Uses the initialisation method, which uses the reported data to set the initial conditions for the model for a given day. -* The initialisation is applied for a predefined number of days and finally saved in a timeseries for each region. In the end, -* we save the files "Results_rki.h5" and "Results_rki_sum.h5" in the results_dir. -* Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. -* @param[in] model Vector of models in which the data is set. Copy is made to avoid changing the original model. -* @param[in] results_dir Path to result files. -* @param[in] date Date for which the data should be read. -* @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. -* @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. -* @param[in] num_days Number of days to be simulated/initialized. -* @param[in] pydata_dir Directory that contains the data files. -*/ -template + * @brief Uses the initialisation method, which uses the reported data to set the initial conditions for the model for a given day. + * + * The initialisation is applied for a predefined number of days and finally saved in a timeseries for each region. In the end, + * we save the files "Results_rki.h5" and "Results_rki_sum.h5" in the results_dir. + * Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. + * + * @param[in] model VectorRange of Node%s each containing a Model in which the data is set. + * @param[in] results_dir Path to result files. + * @param[in] date Date for which the data should be read. + * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. + * @param[in] scaling_factor_icu Scaling factor for ICU cases. + * @param[in] num_days Number of days to be simulated/initialized. + * @param[in] epidata_filenames Object containing the input data file paths. + * + * @return An IOResult indicating success or failure. + */ IOResult export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, - const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); - // allow scalar scaling factor as convenience for 1-group models - assert(scaling_factor_inf.size() == 1 || scaling_factor_inf.size() == num_age_groups); - - std::vector> extrapolated_data( - model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); - - for (int t = 0; t <= num_days; ++t) { - auto offset_day = offset_date_by_days(date, t); - - BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, - num_days, epidata_filenames)); - - for (size_t r = 0; r < model.size(); r++) { - extrapolated_data[r][t] = model[r].property.get_initial_values(); - } - } - - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), - path_join(results_dir, "Results_rki.h5"))); - - auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); - BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), - path_join(results_dir, "Results_rki_sum.h5"))); - - return success(); -} + const mio::VectorRange>> model, const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames); #else -template -IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const double, const int, - const mio::regions::de::EpidataFilenames&) -{ - mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); - return success(); -} +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, + const std::vector&, const ScalarType, const int, + const mio::regions::de::EpidataFilenames&); #endif // MEMILIO_HAS_HDF5 } // namespace osecir diff --git a/cpp/models/ode_secirts/parameters_io.cpp b/cpp/models/ode_secirts/parameters_io.cpp index 77f2bc9b0a..e8a39472ce 100644 --- a/cpp/models/ode_secirts/parameters_io.cpp +++ b/cpp/models/ode_secirts/parameters_io.cpp @@ -55,17 +55,17 @@ namespace details IOResult compute_confirmed_cases_data( const std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_imm, const std::vector& t_Exposed, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_imm, const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, - const std::vector& t_imm_interval_i, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, - const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, - const std::vector& scaling_factor_inf, const size_t layer) + const std::vector& t_imm_interval_i, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, + const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, + const std::vector& scaling_factor_inf, const size_t layer) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -92,9 +92,9 @@ IOResult compute_confirmed_cases_data( auto age = (size_t)entry.age_group; // transition probabilities - double recoveredPerInfectedNoSymptoms = mu_C_R[age]; - double severePerInfectedSymptoms = mu_I_H[age]; - double criticalPerSevere = mu_H_U[age]; + ScalarType recoveredPerInfectedNoSymptoms = mu_C_R[age]; + ScalarType severePerInfectedSymptoms = mu_I_H[age]; + ScalarType criticalPerSevere = mu_H_U[age]; // transition times int timeInfectedNoSymptoms = t_InfectedNoSymptoms[age]; @@ -105,11 +105,11 @@ IOResult compute_confirmed_cases_data( timeInfectedNoSymptoms = static_cast(std::round(timeInfectedNoSymptoms * reduc_t_Infected[age])); timeInfectedSymptoms = static_cast(std::round(timeInfectedSymptoms * reduc_t_Infected[age])); - const double red_fact_exp = reduc_Exposed[age]; + const ScalarType red_fact_exp = reduc_Exposed[age]; - const double red_fact_inf = reduc_InfectedSymptoms[age]; + const ScalarType red_fact_inf = reduc_InfectedSymptoms[age]; - const double red_fact_sev = reduc_icu_death[age]; + const ScalarType red_fact_sev = reduc_icu_death[age]; recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms); severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms; @@ -154,7 +154,7 @@ IOResult compute_confirmed_cases_data( size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size(); for (size_t i = 0; i < num_groups; i++) { - auto try_fix_constraints = [region, i](double& value, double error, auto str) { + auto try_fix_constraints = [region, i](ScalarType& value, ScalarType error, auto str) { if (value < error) { // this should probably return a failure // but the algorithm is not robust enough to avoid large negative @@ -172,7 +172,7 @@ IOResult compute_confirmed_cases_data( } }; - const double tol_error = -1e-8; + const ScalarType tol_error = -1e-8; try_fix_constraints(num_InfectedSymptoms[i], tol_error, "InfectedSymptoms"); try_fix_constraints(num_InfectedNoSymptoms[i], tol_error, "InfectedNoSymptoms"); try_fix_constraints(num_Exposed[i], tol_error, "Exposed"); @@ -185,7 +185,509 @@ IOResult compute_confirmed_cases_data( return success(); } +IOResult +set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, + const std::vector>& immunity_population) +{ + auto num_age_groups = (size_t)model.parameters.get_num_groups(); + assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors + assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups); + + std::vector t_Exposed; + std::vector t_InfectedNoSymptoms; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; + std::vector t_imm_interval_i; + + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; + + std::vector reduc_t_Infected; + std::vector reduc_Exposed; + std::vector reduc_InfectedSymptoms; + std::vector reduc_icu_death; + + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + std::vector num_timm1(num_age_groups, 0.0); + std::vector num_timm2(num_age_groups, 0.0); + + std::vector denom_E(num_age_groups, 0.0); + std::vector denom_I_NS(num_age_groups, 0.0); + std::vector denom_I_Sy(num_age_groups, 0.0); + std::vector denom_I_Sev_Cr(num_age_groups, 0.0); + + // calculate the denominators to split the reported case numbers to the different immunity layers. + for (size_t group = 0; group < num_age_groups; group++) { + denom_E[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model.parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[(AgeGroup)group]); + + denom_I_NS[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model.parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[(AgeGroup)group]); + + denom_I_Sy[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model + .parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model + .parameters.template get>()[(AgeGroup)group]); + + denom_I_Sev_Cr[group] = + 1 / (immunity_population[0][group] + + immunity_population[1][group] * + model.parameters.template get>()[( + AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[( + AgeGroup)group]); + } + + /*----------- Naive immunity -----------*/ + for (size_t group = 0; group < num_age_groups; group++) { + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_imm_interval_i.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + mu_C_R.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back( + model.parameters.template get>()[(AgeGroup)group]); + + reduc_t_Infected.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_Exposed.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_InfectedSymptoms.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_icu_death.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, + reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, + scaling_factor_inf, 0)); + + size_t num_groups = (size_t)model.parameters.get_num_groups(); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = + immunity_population[0][i] * denom_E[i] * num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = + immunity_population[0][i] * denom_I_NS[i] * num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = + immunity_population[0][i] * denom_I_Sy[i] * num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = + immunity_population[0][i] * denom_I_Sev_Cr[i] * num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = + immunity_population[0][i] * denom_I_Sev_Cr[i] * num_icu[i]; + } + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) == 0) { + log_warning( + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", + date, region); + } + + /*----------- PARTIAL Immunity -----------*/ + reduc_Exposed.clear(); + reduc_InfectedSymptoms.clear(); + reduc_icu_death.clear(); + + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + + for (size_t group = 0; group < num_age_groups; group++) { + reduc_Exposed.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_InfectedSymptoms.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_icu_death.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, + reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, + scaling_factor_inf, 1)); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * + denom_I_Sy[i] * num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = + immunity_population[1][i] * + model + .parameters.template get>()[(AgeGroup)i] * + denom_I_Sev_Cr[i] * num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = + immunity_population[1][i] * + model + .parameters.template get>()[(AgeGroup)i] * + denom_I_Sev_Cr[i] * num_icu[i]; + } + // the += is necessary because we already set the previous vaccinated individuals + model.populations[{AgeGroup(i), InfectionState::TemporaryImmunePartialImmunity}] += + immunity_population[1][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_timm1[i]; + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) == 0) { + + log_warning("No infections for partially vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); + } + + /*----------- Improved Immunity -----------*/ + reduc_Exposed.clear(); + reduc_InfectedSymptoms.clear(); + reduc_icu_death.clear(); + + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + + for (size_t group = 0; group < num_age_groups; group++) { + reduc_Exposed.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_InfectedSymptoms.push_back( + model.parameters.template get>()[(AgeGroup)group]); + reduc_icu_death.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm2, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, + reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, + scaling_factor_inf, 2)); + + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] = + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * + denom_I_Sy[i] * num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = + immunity_population[2][i] * + model + .parameters.template get>()[(AgeGroup)i] * + denom_I_Sev_Cr[i] * num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = + immunity_population[2][i] * + model + .parameters.template get>()[(AgeGroup)i] * + denom_I_Sev_Cr[i] * num_icu[i]; + } + + // the += is necessary because we already set the previous vaccinated individuals + model.populations[{AgeGroup(i), InfectionState::TemporaryImmuneImprovedImmunity}] += + immunity_population[2][i] * + model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * + num_timm2[i]; + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) == 0) { + log_warning("No infections for vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); + } + return success(); +} + +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf, + const std::vector>& immunity_population) +{ + BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); + + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; + }); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); + } + } + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY( + set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf, immunity_population)); + } + + return success(); +} + +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region, const std::vector>& immunity_population) +{ + if (std::accumulate(num_population.begin(), num_population.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) <= 0) + { + log_warning("No population data available for region " + std::to_string(region) + + ". Population data has not been set."); + return success(); + } + + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + + ScalarType SN = num_population[size_t(i)] * immunity_population[0][size_t(i)]; + ScalarType SPI = num_population[size_t(i)] * immunity_population[1][size_t(i)]; + ScalarType SII = num_population[size_t(i)] - SN - SPI; + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::max( + 0.0, + SII - + (model.populations[{i, InfectionState::ExposedImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + + model.populations[{i, InfectionState::DeadImprovedImmunity}] + + model.populations[{i, InfectionState::TemporaryImmuneImprovedImmunity}])); + + model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( + 0.0, + SPI - model.populations[{i, InfectionState::ExposedPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - + model.populations[{i, InfectionState::DeadPartialImmunity}] - + model.populations[{i, InfectionState::TemporaryImmunePartialImmunity}]); + + model.populations.template set_difference_from_group_total( + {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); + } + + for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { + for (auto j = Index(0); j < InfectionState::Count; ++j) { + if (model.populations[{i, j}] < 0) { + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), + size_t(j), model.populations[{i, j}]); + } + } + } + + return success(); +} + +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, + const std::vector>& immunity_population) +{ + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion)); + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id, immunity_population)); + } + return success(); +} + +IOResult set_divi_data(Model& model, const ScalarType num_icu, ScalarType scaling_factor_icu) +{ + ScalarType sum_mu_I_U = 0; + std::vector mu_I_U; + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + sum_mu_I_U += model.parameters.template get>()[i] * + model.parameters.template get>()[i]; + mu_I_U.push_back(model.parameters.template get>()[i] * + model.parameters.template get>()[i]); + } + + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations[{i, InfectionState::InfectedCriticalNaive}] = + scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; + } + + return success(); +} + +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + ScalarType scaling_factor_icu) +{ + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); + } + + return success(); +} + } // namespace details + +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, + int num_days, const std::vector>& immunity_population, + const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + + BOOST_OUTCOME_TRY( + details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, num_days)); + + // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. + // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, scaling_factor_icu)); + + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, + scaling_factor_inf, immunity_population)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, immunity_population)); + return success(); +} + +#ifdef MEMILIO_HAS_HDF5 + +IOResult export_input_data_timeseries( + const mio::VectorRange>> model, const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, + const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); + assert(scaling_factor_inf.size() == num_age_groups); + assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); + std::vector> extrapolated_data( + model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); + + for (int t = 0; t <= num_days; ++t) { + auto offset_day = offset_date_by_days(date, t); + + // TODO: empty vaccination data path guard + BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, + num_days, immunity_population, epidata_filenames)); + + for (size_t r = 0; r < model.size(); r++) { + extrapolated_data[r][t] = model[r].property.get_initial_values(); + // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. + // Since we should be independent whether we consider them or not, we add them back here before we save the data. + for (size_t age = 0; age < num_age_groups; age++) { + extrapolated_data[r][t][(size_t)InfectionState::SusceptibleImprovedImmunity + + age * (size_t)InfectionState::Count] += + extrapolated_data[r][t][(size_t)InfectionState::DeadNaive + age * (size_t)InfectionState::Count]; + } + } + } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), + path_join(results_dir, "Results_rki.h5"))); + + auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); + BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), + path_join(results_dir, "Results_rki_sum.h5"))); + + return success(); +} + +#else +IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, + const std::vector&, const ScalarType, const int, + const std::vector>, const mio::regions::de::EpidataFilenames&) +{ + mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); + return success(); +} + +#endif //MEMILIO_HAS_HDF5 + } // namespace osecirts } // namespace mio diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index e6965665b5..53b8ace419 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -47,20 +47,31 @@ namespace osecirts namespace details { +/** + * @brief Reads populations data from rki data. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Key of the region of interest. + * @param[in] date Date at which the data is read. + * @param[in, out] num_* Output vector for number of people in the corresponding compartement. + * @param[in] t_* vector Average time it takes to get from one compartement to another for each age group. + * @param[in] mu_* vector Probabilities to get from one compartement to another for each age group. + * @param[in] reduc_* vector Factors by which to adjust the times and transition rates based on immunity layer. + * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. + * @param[in] layer Specifies the immunity layer: 0 (Naive), 1 (Partial Immunity), 2 (Improved Immunity). + */ IOResult compute_confirmed_cases_data( const std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_imm, const std::vector& t_Exposed, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_imm, const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, - const std::vector& t_imm_interval_i, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, - const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, - const std::vector& scaling_factor_inf, const size_t layer); -/**@}*/ + const std::vector& t_imm_interval_i, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, + const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, + const std::vector& scaling_factor_inf, const size_t layer); /** * @brief Sets the confirmed cases data in the model considering different immunity layers. @@ -68,446 +79,100 @@ IOResult compute_confirmed_cases_data( * This function distributes confirmed case data across infection states for regions and age groups * in the model. It considers different levels of immunity (naive, partial, and improved). * - * @tparam FP Floating point type (default: double). - * - * @param[in,out] model Vector of models, each representing a region, where the compartments are updated. - * @param[in] case_data Vector of confirmed case data entries. - * @param[in] region Vector of region IDs for which the data is processed. - * @param[in] date Date for which the confirmed cases are set in the model. + * @param[in, out] model Model in which the data is set. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Key of the region of interest. + * @param[in] date Date at which the data is read. * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. * @param[in] immunity_population Vector containing the immunity distribution for naive, partial, and improved immunity layers. * * @return An IOResult indicating success or failure. */ -template IOResult -set_confirmed_cases_data(Model& model, const std::vector& case_data, - const int region, Date date, const std::vector& scaling_factor_inf, - const std::vector>& immunity_population) -{ - auto num_age_groups = (size_t)model.parameters.get_num_groups(); - assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors - assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups); - - std::vector t_Exposed; - std::vector t_InfectedNoSymptoms; - std::vector t_InfectedSymptoms; - std::vector t_InfectedSevere; - std::vector t_InfectedCritical; - std::vector t_imm_interval_i; - - std::vector mu_C_R; - std::vector mu_I_H; - std::vector mu_H_U; - - std::vector reduc_t_Infected; - std::vector reduc_Exposed; - std::vector reduc_InfectedSymptoms; - std::vector reduc_icu_death; - - std::vector num_InfectedSymptoms(num_age_groups, 0.0); - std::vector num_death(num_age_groups, 0.0); - std::vector num_Exposed(num_age_groups, 0.0); - std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); - std::vector num_InfectedSevere(num_age_groups, 0.0); - std::vector num_icu(num_age_groups, 0.0); - std::vector num_timm1(num_age_groups, 0.0); - std::vector num_timm2(num_age_groups, 0.0); - - std::vector denom_E(num_age_groups, 0.0); - std::vector denom_I_NS(num_age_groups, 0.0); - std::vector denom_I_Sy(num_age_groups, 0.0); - std::vector denom_I_Sev_Cr(num_age_groups, 0.0); - - // calculate the denominators to split the reported case numbers to the different immunity layers. - for (size_t group = 0; group < num_age_groups; group++) { - denom_E[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model.parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model.parameters.template get>()[(AgeGroup)group]); - - denom_I_NS[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model.parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model.parameters.template get>()[(AgeGroup)group]); - - denom_I_Sy[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model - .parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model - .parameters.template get>()[(AgeGroup)group]); - - denom_I_Sev_Cr[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model.parameters.template get>()[( - AgeGroup)group] + - immunity_population[2][group] * - model.parameters.template get>()[( - AgeGroup)group]); - } - - /*----------- Naive immunity -----------*/ - for (size_t group = 0; group < num_age_groups; group++) { - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedSymptoms.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedSevere.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_imm_interval_i.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - - mu_C_R.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_I_H.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_H_U.push_back( - model.parameters.template get>()[(AgeGroup)group]); - - reduc_t_Infected.push_back( - model.parameters.template get>()[(AgeGroup)group]); - reduc_Exposed.push_back( - model.parameters.template get>()[(AgeGroup)group]); - reduc_InfectedSymptoms.push_back( - model.parameters.template get>()[(AgeGroup)group]); - reduc_icu_death.push_back( - model.parameters.template get>()[(AgeGroup)group]); - } - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, - reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, - scaling_factor_inf, 0)); - - size_t num_groups = (size_t)model.parameters.get_num_groups(); - for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = - immunity_population[0][i] * denom_E[i] * num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = - immunity_population[0][i] * denom_I_NS[i] * num_InfectedNoSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = - immunity_population[0][i] * denom_I_Sy[i] * num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = - immunity_population[0][i] * denom_I_Sev_Cr[i] * num_InfectedSevere[i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = - immunity_population[0][i] * denom_I_Sev_Cr[i] * num_icu[i]; - } - } - if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) == 0) { - log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region); - } - - /*----------- PARTIAL Immunity -----------*/ - reduc_Exposed.clear(); - reduc_InfectedSymptoms.clear(); - reduc_icu_death.clear(); - - num_InfectedSymptoms = std::vector(num_age_groups, 0.0); - num_death = std::vector(num_age_groups, 0.0); - num_Exposed = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); - num_InfectedSevere = std::vector(num_age_groups, 0.0); - num_icu = std::vector(num_age_groups, 0.0); - - for (size_t group = 0; group < num_age_groups; group++) { - reduc_Exposed.push_back( - model.parameters.template get>()[(AgeGroup)group]); - reduc_InfectedSymptoms.push_back( - model.parameters.template get>()[(AgeGroup)group]); - reduc_icu_death.push_back( - model.parameters.template get>()[(AgeGroup)group]); - } - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, - reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, - scaling_factor_inf, 1)); - for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = - immunity_population[1][i] * - model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = - immunity_population[1][i] * - model.parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * - num_InfectedNoSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = - immunity_population[1][i] * - model.parameters.template get>()[(AgeGroup)i] * - denom_I_Sy[i] * num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = - immunity_population[1][i] * - model - .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_InfectedSevere[i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = - immunity_population[1][i] * - model - .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_icu[i]; - } - // the += is necessary because we already set the previous vaccinated individuals - model.populations[{AgeGroup(i), InfectionState::TemporaryImmunePartialImmunity}] += - immunity_population[1][i] * - model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_timm1[i]; - } - if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) == 0) { - - log_warning("No infections for partially vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region); - } - - /*----------- Improved Immunity -----------*/ - reduc_Exposed.clear(); - reduc_InfectedSymptoms.clear(); - reduc_icu_death.clear(); - - num_InfectedSymptoms = std::vector(num_age_groups, 0.0); - num_death = std::vector(num_age_groups, 0.0); - num_Exposed = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); - num_InfectedSevere = std::vector(num_age_groups, 0.0); - num_icu = std::vector(num_age_groups, 0.0); - - for (size_t group = 0; group < num_age_groups; group++) { - reduc_Exposed.push_back( - model.parameters.template get>()[(AgeGroup)group]); - reduc_InfectedSymptoms.push_back( - model.parameters.template get>()[(AgeGroup)group]); - reduc_icu_death.push_back( - model.parameters.template get>()[(AgeGroup)group]); - } - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm2, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, - reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, - scaling_factor_inf, 2)); - - for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = - immunity_population[2][i] * - model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] = - immunity_population[2][i] * - model.parameters.template get>()[(AgeGroup)i] * denom_I_NS[i] * - num_InfectedNoSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = - immunity_population[2][i] * - model.parameters.template get>()[(AgeGroup)i] * - denom_I_Sy[i] * num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = - immunity_population[2][i] * - model - .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_InfectedSevere[i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = - immunity_population[2][i] * - model - .parameters.template get>()[(AgeGroup)i] * - denom_I_Sev_Cr[i] * num_icu[i]; - } - - // the += is necessary because we already set the previous vaccinated individuals - model.populations[{AgeGroup(i), InfectionState::TemporaryImmuneImprovedImmunity}] += - immunity_population[2][i] * - model.parameters.template get>()[(AgeGroup)i] * denom_E[i] * - num_timm2[i]; - } - if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), FP(0.0), - [](const FP& a, const FP& b) { - return evaluate_intermediate(a + b); - }) == 0) { - log_warning("No infections for vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region); - } - return success(); -} +set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, + const std::vector>& immunity_population); /** - * @brief Reads confirmed case data from a file and sets it in the model. + * @brief Sets confirmed case data from a file into the given models. * - * This function reads transformed RKI data from the specified file and distributes the confirmed case data - * across different infection states for regions and age groups in the model. It considers naive, partial, - * and improved immunity layers. - * - * @tparam FP Floating point type (default: double). + * This function reads transformed rki data from the specified file and calls a subfunction that distributes the + * confirmed case data across different infection states for age groups in each model. + * It considers naive, partial, and improved immunity layers. * - * @param[in,out] model Vector of models, each representing a region, where the compartments are updated. - * @param[in] path Path to the file containing case (RKI) data. - * @param[in] date Date for which the confirmed cases are set in the model. + * @param[in, out] model VectorRange of Node%s each containing a Model for which the confirmed cases data will be set. + * @param[in] path Path to the confirmed cases data file. + * @param[in] date Date at which the data is read. * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. * @param[in] immunity_population Vector containing the immunity distribution for naive, partial, and improved immunity layers. * * @return An IOResult indicating success or failure. */ -template -IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, - Date date, const std::vector& scaling_factor_inf, - const std::vector>& immunity_population) -{ - BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - - // sort case_data into regions and ignore once with no region associated - std::vector> vcase_data{model.size()}; - for (auto&& entry : case_data) { - auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { - return m.id == 0 || get_region_id(entry) == m.id; - }); - if (it != model.end()) { - auto region_idx = size_t(it - model.begin()); - vcase_data[region_idx].push_back(entry); - } - } - - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY( - set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf, immunity_population)); - } - - return success(); -} +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf, + const std::vector>& immunity_population); /** - * @brief Sets the population data for the given models based on the provided population distribution and immunity levels. - * - * @tparam FP Floating point type (default: double). - * - * @param[in,out] model A vector of models for which population data will be set. - * @param[in] num_population A 2D vector where each row represents the age group population distribution for a specific region. - * @param[in] vregion A vector of region identifiers corresponding to the population data. + * @brief Sets the population data for the given model based on the provided population distribution and immunity levels. + * @param[in, out] model Model in which the data is set. + * @param[in] num_population Vector of population data for the region of interest. + * @param[in] region Key of the region of interest. * @param[in] immunity_population A 2D vector where each row represents the immunity distribution for a specific region * across different levels of immunity (e.g., naive, partial, improved immunity). * * @return An IOResult indicating success or failure. */ -template -IOResult set_population_data(Model& model, const std::vector& num_population, - const int region, const std::vector>& immunity_population) -{ - if (std::accumulate(num_population.begin(), num_population.end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) <= 0) - { - log_warning("No population data available for region " + std::to_string(region) + - ". Population data has not been set."); - return success(); - } - - auto num_groups = model.parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - - FP SN = num_population[size_t(i)] * immunity_population[0][size_t(i)]; - FP SPI = num_population[size_t(i)] * immunity_population[1][size_t(i)]; - FP SII = num_population[size_t(i)] - SN - SPI; - - model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::max( - 0.0, - FP(SII - - (model.populations[{i, InfectionState::ExposedImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] + - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + - model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + - model.populations[{i, InfectionState::DeadImprovedImmunity}] + - model.populations[{i, InfectionState::TemporaryImmuneImprovedImmunity}]))); - - model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( - 0.0, - SPI - model.populations[{i, InfectionState::ExposedPartialImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - - model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - - model.populations[{i, InfectionState::DeadPartialImmunity}] - - model.populations[{i, InfectionState::TemporaryImmunePartialImmunity}]); - - model.populations.template set_difference_from_group_total( - {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); - } - - for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { - for (auto j = Index(0); j < InfectionState::Count; ++j) { - if (model.populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model.populations[{i, j}]); - } - } - } - - return success(); -} +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region, const std::vector>& immunity_population); /** * @brief Reads population data from a file and sets it for the each given model. - * - * @param[in,out] model A vector of models for which population data will be set. - * @param[in] path The file path to the population data. - * @param[in] immunity_population A 2D vector where each row represents the immunity distribution for a specific region - * across different levels of immunity (e.g., naive, partial, improved). + * @param[in, out] model VectorRange of Node%s containing a Model for which the confirmed cases data will be set. + * @param[in] path Path to population data file. + * @param[in] immunity_population A 2D vector specifying immunity for each age group and immunity layer. * * @return An IOResult indicating success or failure. */ -template -IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, - const std::vector>& immunity_population) -{ - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion)); +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, + const std::vector>& immunity_population); - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id, immunity_population)); - } - return success(); -} +/** + * @brief Sets ICU data into a Model, distributed across age groups. + * @param[in, out] model Model in which the data is set. + * @param[in] num_icu ICU data for the region of interest. + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + */ +IOResult set_divi_data(Model& model, const ScalarType num_icu, ScalarType scaling_factor_icu); + +/** + * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. + * + * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) + * for each region, and sets these values in the model. The ICU cases are distributed across age groups + * using the transition probabilities from severe to critical. + * + * @param[in, out] model VectorRange of Node%s each containing a Model for which the confirmed cases data will be set. + * @param[in] path Path to transformed DIVI file. + * @param[in] date Date at which the data is read. + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + */ +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + ScalarType scaling_factor_icu); +/** + * @brief Sets vaccination data into a Model using provided vaccination (partial, full, and booster) data. + * @tparam FP Floating point type (default: double). + * @param[in, out] model Model in which the data is set. + * @param[in] vacc_data Vector of VaccinationDataEntry objects containing the vaccination data. + * @param[in] date Start date for the simulation. + * @param[in] num_days Number of days for which the simulation is run. + * @param[in] max_date + * @param[in] days_until_effective_n + * @param[in] days_until_effective_pi + * @param[in] days_until_effective_ii + * + * @return An IOResult indicating success or failure. + */ template IOResult set_vaccination_data(Model& model, const VaccinationDataEntry& vacc_data_entry, Date date, int num_days, Date max_date, const int days_until_effective_n, @@ -565,10 +230,8 @@ IOResult set_vaccination_data(Model& model, const VaccinationDataEntry /** * @brief Sets vaccination data for the given models using provided vaccination (partial, full, and booster) data. - * - * + * * @tparam FP Floating point type (default: double). - * * @param[in,out] model A vector of models for which vaccination data will be set. * @param[in] vacc_data A vector of VaccinationDataEntry objects containing the vaccination data. * @param[in] date The starting date for the simulation. @@ -619,12 +282,11 @@ IOResult set_vaccination_data(Model& model, const std::vector @@ -656,7 +318,7 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod BOOST_OUTCOME_TRY(auto&& vacc_data, read_vaccination_data(path)); - // Sort case_data into regions and ignore once with no region associated + // Sort vacc_data into regions and ignore once with no region associated std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { @@ -677,71 +339,6 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod return success(); } -/** - * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. - * - * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) - * for each region, and sets these values in the model. The ICU cases are distributed across age groups - * using the transition probabilities from severe to critical. - * @tparam FP Floating point type (default: double). - * - * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. - * @param[in] num_icu icu data - * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. - * - * @return An IOResult indicating success or failure. - */ -template -IOResult set_divi_data(Model& model, const double num_icu, double scaling_factor_icu) -{ - FP sum_mu_I_U = 0; - std::vector mu_I_U; - auto num_groups = model.parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - sum_mu_I_U += model.parameters.template get>()[i] * - model.parameters.template get>()[i]; - mu_I_U.push_back(model.parameters.template get>()[i] * - model.parameters.template get>()[i]); - } - - for (auto i = AgeGroup(0); i < num_groups; i++) { - model.populations[{i, InfectionState::InfectedCriticalNaive}] = - scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; - } - - return success(); -} - -/** - * @brief sets populations data from DIVI register into Model - * @param[in, out] model vector of objects in which the data is set - * @param[in] path Path to transformed DIVI file - * @param[in] date Date for which the arrays are initialized - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data - */ -template -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, - double scaling_factor_icu) -{ - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); - } - - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); - } - - return success(); -} - } // namespace details /** @@ -749,109 +346,81 @@ IOResult set_divi_data(const mio::VectorRange>>& model, con * * This function estimates all compartments from available data using the provided model parameters. * - * @param[in,out] model Vector of models, one per county, to be initialized with data. + * @param[in,out] model VectorRange of Node%s each containing a Model to be initialized with data. * @param[in] date Date for which the data should be read. * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. * @param[in] scaling_factor_icu Scaling factor for ICU cases. - * @param[in] pydata_dir Directory containing the input data files. * @param[in] num_days Number of days to simulate. * @param[in] immunity_population Matrix containing immunity proportions for each age group and immunity layer. + * @param[in] epidata_filenames Object containing the input data file paths. * * @return An IOResult indicating success or failure. - */ -template -IOResult read_input_data(const mio::VectorRange>>& model, Date date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - int num_days, const std::vector>& immunity_population, - const mio::regions::de::EpidataFilenames& epidata_filenames) -{ + */ +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, + int num_days, const std::vector>& immunity_population, + const mio::regions::de::EpidataFilenames& epidata_filenames); +/** + * @brief Converts input data from one range of models to another with different type. + * + * @tparam FP Floating point type (default: double). + * @param[in] model_from VectorRange of Node%s each containing a Model with the input data. + * @param[in,out] model_to VectorRange of Node%s each containing a Model to be initialized with data. + * @param[in] date Date for which the data should be read. + * @param[in] num_days Number of days to simulate. + * @param[in] epidata_filenames Object containing the input data file paths. + * + * @return An IOResult indicating success or failure. + */ +template +IOResult convert_input_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to, + Date date, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + assert(model_from.size() == model_to.size()); + assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()) + // Todo: add conversion of ParameterSet and then re-use code from all model parameters io + // For now call set_vacination_data with FP to set correct parameters BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, num_days)); - - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, scaling_factor_icu)); + details::set_vaccination_data(model_to, epidata_filenames.vaccination_data_path, date, num_days)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, - scaling_factor_inf, immunity_population)); - BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, immunity_population)); + for (size_t region_idx = 0; region_idx < model_from.size(); ++region_idx) { + // convert populations to mio::UncertainValue + // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work + model_to[region_idx].property.populations = model_to[region_idx].property.populations.convert().convert>(); + } return success(); } #ifdef MEMILIO_HAS_HDF5 /** - * @brief Exports extrapolated real-world data time series for specified regions. - * - * This function generates and exports time series data based on the extrapolation and approximation methods - * used to initialize the model with real-world data. The resulting data represents the initialized states of - * the model over the specified time range. - * - * @param[in] model A vector of models for which the extrapolated data is set. - * @param[in] results_dir Path to the directory where the extrapolated results will be saved in a h5 file. + * @brief Uses the initialisation method, which uses the reported data to set the initial conditions for the model for a given day. + * + * The initialisation is applied for a predefined number of days and finally saved in a timeseries for each region. In the end, + * we save the files "Results_rki.h5" and "Results_rki_sum.h5" in the results_dir. + * Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. + * + * @param[in] model VectorRange of Node%s each containing a Model in which the data is set. + * @param[in] results_dir Path to result files. * @param[in] date Date for which the data should be read. - * @param[in] scaling_factor_inf A vector of scaling factors applied to confirmed cases. - * @param[in] scaling_factor_icu A scaling factor applied to ICU cases. - * @param[in] num_days The number of days for which will be extrapolated. - * @param[in] pydata_dir Directory that contains the data files. - * @param[in] immunity_population A vector of vectors specifying immunity for each age group and immunity layer. - * + * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. + * @param[in] scaling_factor_icu Scaling factor for ICU cases. + * @param[in] num_days Number of days to be simulated/initialized. + * @param[in] immunity_population Matrix containing immunity proportions for each age group and immunity layer. + * @param[in] epidata_filenames Object containing the input data file paths. + * * @return An IOResult indicating success or failure. */ -template IOResult export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, - const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); - assert(scaling_factor_inf.size() == num_age_groups); - assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); - std::vector> extrapolated_data( - model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); - - for (int t = 0; t <= num_days; ++t) { - auto offset_day = offset_date_by_days(date, t); - - // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, - num_days, immunity_population, epidata_filenames)); - - for (size_t r = 0; r < model.size(); r++) { - extrapolated_data[r][t] = model[r].property.get_initial_values(); - // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. - // Since we should be independent whether we consider them or not, we add them back here before we save the data. - for (size_t age = 0; age < num_age_groups; age++) { - extrapolated_data[r][t][(size_t)InfectionState::SusceptibleImprovedImmunity + - age * (size_t)InfectionState::Count] += - extrapolated_data[r][t][(size_t)InfectionState::DeadNaive + age * (size_t)InfectionState::Count]; - } - } - } - - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), - path_join(results_dir, "Results_rki.h5"))); - - auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); - BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), - path_join(results_dir, "Results_rki_sum.h5"))); - - return success(); -} - + const mio::VectorRange>> model, const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, + const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames); #else -template -IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const double, const int, - const std::vector>, const mio::regions::de::EpidataFilenames&) -{ - mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); - return success(); -} - +IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, + const std::vector&, const ScalarType, const int, + const std::vector>, const mio::regions::de::EpidataFilenames&); + #endif //MEMILIO_HAS_HDF5 } // namespace osecirts diff --git a/cpp/models/ode_secirvvs/parameters_io.cpp b/cpp/models/ode_secirvvs/parameters_io.cpp index 59d222c1bb..1995e393ef 100644 --- a/cpp/models/ode_secirvvs/parameters_io.cpp +++ b/cpp/models/ode_secirvvs/parameters_io.cpp @@ -32,15 +32,15 @@ namespace details IOResult compute_confirmed_cases_data( const std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf) + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& scaling_factor_inf) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -104,7 +104,7 @@ IOResult compute_confirmed_cases_data( num_icu[i] / scaling_factor_inf[i]; // TODO: this has to be adapted for scaling_factor_inf != 1 or != ***_icu num_rec[i] -= num_death[i] / scaling_factor_inf[i]; - auto try_fix_constraints = [region, i](double& value, double error, auto str) { + auto try_fix_constraints = [region, i](ScalarType& value, ScalarType error, auto str) { if (value < error) { // this should probably return a failure // but the algorithm is not robust enough to avoid large negative @@ -134,8 +134,8 @@ IOResult compute_confirmed_cases_data( return success(); } -IOResult> compute_confirmed_cases_data_fix_recovered( - const std::vector& case_data, const int region, Date date, double delay) +IOResult> compute_confirmed_cases_data_fix_recovered( + const std::vector& case_data, const int region, Date date, ScalarType delay) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -159,7 +159,7 @@ IOResult> compute_confirmed_cases_data_fix_recovered( } auto num_groups = ConfirmedCasesDataEntry::age_group_names.size(); - std::vector num_rec(num_groups, 0.0); + std::vector num_rec(num_groups, 0.0); for (auto&& rki_entry : case_data) { if (rki_entry.date == offset_date_by_days(date, int(-delay))) { @@ -168,7 +168,7 @@ IOResult> compute_confirmed_cases_data_fix_recovered( } for (size_t i = 0; i < num_groups; i++) { - auto try_fix_constraints = [region, i](double& value, double error, auto str) { + auto try_fix_constraints = [region, i](ScalarType& value, ScalarType error, auto str) { if (value < error) { // this should probably return a failure // but the algorithm is not robust enough to avoid large negative @@ -191,7 +191,617 @@ IOResult> compute_confirmed_cases_data_fix_recovered( return success(num_rec); } +IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, + bool set_death = false) +{ + auto num_age_groups = (size_t)model.parameters.get_num_groups(); + assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors + assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups); + + std::vector t_Exposed; + std::vector t_InfectedNoSymptoms; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; + + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; + + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_rec(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + + /*----------- UNVACCINATED -----------*/ + for (size_t group = 0; group < num_age_groups; group++) { + + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + mu_C_R.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back( + model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back( + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); + + + size_t num_groups = (size_t)model.parameters.get_num_groups(); + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = + num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = + num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = num_icu[i]; + } + model.populations[{AgeGroup(i), InfectionState::SusceptibleImprovedImmunity}] = num_rec[i]; + if (set_death) { + // in set_confirmed_cases_data initilization, deaths are now set to 0. In order to visualize + // the extrapolated real number of deaths, they have to be set here. In the comparison of data + // it has to be paid attention to the fact, the the simulation starts with deaths=0 + // while this method starts with deaths=number of reported deaths so far... + // Additionally, we set the number of reported deaths to DeadNaive since no information on that is + // available here. + // Do only add deaths after substraction. + model.populations[{AgeGroup(i), InfectionState::DeadNaive}] = num_death[i]; + } + } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning( + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", + date, region); + } + + /*----------- PARTIALLY VACCINATED -----------*/ + t_InfectedNoSymptoms.clear(); + t_Exposed.clear(); + t_InfectedSymptoms.clear(); + t_InfectedSevere.clear(); + t_InfectedCritical.clear(); + + mu_C_R.clear(); + mu_I_H.clear(); + mu_H_U.clear(); + + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_rec = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + + for (size_t group = 0; group < num_age_groups; group++) { + ScalarType reduc_t = model.parameters.template get>()[(AgeGroup)group]; + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + ScalarType exp_fac_part_immune = + model.parameters.template get>()[(AgeGroup)group]; + ScalarType inf_fac_part_immune = + model.parameters.template get>()[(AgeGroup)group]; + ScalarType hosp_fac_part_immune = + model + .parameters.template get>()[(AgeGroup)group]; + ScalarType icu_fac_part_immune = + model + .parameters.template get>()[(AgeGroup)group]; + mu_C_R.push_back(( + 1 - inf_fac_part_immune / exp_fac_part_immune * + (1 - model + .parameters.template get>()[(AgeGroup)group]))); + mu_I_H.push_back( + hosp_fac_part_immune / inf_fac_part_immune * + model.parameters.template get>()[(AgeGroup)group]); + // transfer from H to U, D unchanged. + mu_H_U.push_back( + icu_fac_part_immune / hosp_fac_part_immune * + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); + + + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = + num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = + num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = + num_icu[i]; + } + } + // } + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning("No infections for partially vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); + } + + /*----------- FULLY VACCINATED -----------*/ + t_InfectedNoSymptoms.clear(); + t_Exposed.clear(); + t_InfectedSymptoms.clear(); + t_InfectedSevere.clear(); + t_InfectedCritical.clear(); + + mu_C_R.clear(); + mu_I_H.clear(); + mu_H_U.clear(); + + num_InfectedSymptoms = std::vector(num_age_groups, 0.0); + num_death = std::vector(num_age_groups, 0.0); + num_rec = std::vector(num_age_groups, 0.0); + num_Exposed = std::vector(num_age_groups, 0.0); + num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); + num_InfectedSevere = std::vector(num_age_groups, 0.0); + num_icu = std::vector(num_age_groups, 0.0); + + for (size_t group = 0; group < num_age_groups; group++) { + ScalarType reduc_t = model.parameters.template get>()[(AgeGroup)group]; + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group]))); + + ScalarType reduc_immune_exp = + model.parameters.template get>()[(AgeGroup)group]; + ScalarType reduc_immune_inf = + model.parameters.template get>()[(AgeGroup)group]; + ScalarType reduc_immune_hosp = + model.parameters.template get>()[( + AgeGroup)group]; + ScalarType reduc_immune_icu = + model.parameters.template get>()[( + AgeGroup)group]; + mu_C_R.push_back(( + 1 - reduc_immune_inf / reduc_immune_exp * + (1 - model + .parameters.template get>()[(AgeGroup)group]))); + mu_I_H.push_back( + reduc_immune_hosp / reduc_immune_inf * + model.parameters.template get>()[(AgeGroup)group]); + // transfer from H to U, D unchanged. + mu_H_U.push_back( + reduc_immune_icu / reduc_immune_hosp * + model.parameters.template get>()[(AgeGroup)group]); + } + + BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, + num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, + t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, + t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); + + for (size_t i = 0; i < num_groups; i++) { + model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] = + num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = + num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = + num_InfectedSevere[i]; + // Only set the number of ICU patients here, if the date is not available in the data. + if (!is_divi_data_available(date)) { + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = + num_icu[i]; + } + } + + if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) == 0.0) { + log_warning("No infections for vaccinated reported on date {} for region {}. " + "Population data has not been set.", + date, region); + } + + return success(); +} + +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, Date date, + const std::vector& scaling_factor_inf, bool set_death = false) +{ + BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); + + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; + }); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); + } + } + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf, set_death)); + } + return success(); +} + +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region, const std::vector& num_rec) +{ + if (std::accumulate(num_population.begin(), num_population.end(), ScalarType(0.0), + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }) <= 0) + { + log_warning("No population data available for region " + std::to_string(region) + + ". Population data has not been set."); + return success(); + } + + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + + ScalarType S_v = std::min( + model.parameters.template get>()[{i, SimulationDay(0)}] + + num_rec[size_t(i)], + num_population[size_t(i)]); + ScalarType S_pv = std::max( + model.parameters.template get>()[{i, SimulationDay(0)}] - + model.parameters.template get>()[{i, SimulationDay(0)}], + 0.0); // use std::max with 0 + ScalarType S; + if (num_population[size_t(i)] - S_pv - S_v < 0.0) { + log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", + region, size_t(i)); + S = 0.0; + S_v = num_population[size_t(i)] - S_pv; + } + else { + S = num_population[size_t(i)] - S_pv - S_v; + } + + ScalarType denom_E = + 1 / (S + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); + ScalarType denom_C = + 1 / (S + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); + ScalarType denom_I = + 1 / + (S + + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); + ScalarType denom_HU = + 1 / + (S + + S_pv * model + .parameters.template get>()[i] + + S_v * model + .parameters.template get>()[i]); + + model.populations[{i, InfectionState::ExposedNaive}] = + S * model.populations[{i, InfectionState::ExposedNaive}] * denom_E; + model.populations[{i, InfectionState::ExposedPartialImmunity}] = + S_pv * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::ExposedPartialImmunity}] * denom_E; + model.populations[{i, InfectionState::ExposedImprovedImmunity}] = + S_v * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::ExposedImprovedImmunity}] * denom_E; + + model.populations[{i, InfectionState::InfectedNoSymptomsNaive}] = + S * model.populations[{i, InfectionState::InfectedNoSymptomsNaive}] * denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] = + S_pv * model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] * denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] = + S_v * model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] * denom_C; + + model.populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] = + S * model.populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] * denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = + S_pv * model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] * + denom_C; + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = + S_v * model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] * + denom_C; + + model.populations[{i, InfectionState::InfectedSymptomsNaive}] = + S * model.populations[{i, InfectionState::InfectedSymptomsNaive}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] = + S_pv * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] = + S_v * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] * denom_I; + + model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] = + S * model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = + S_pv * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] * denom_I; + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = + S_v * model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] * denom_I; + + model.populations[{i, InfectionState::InfectedSevereNaive}] = + S * model.populations[{i, InfectionState::InfectedSevereNaive}] * denom_HU; + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] = + S_pv * + model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] * denom_HU; + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] = + S_v * + model + .parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] * denom_HU; + + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] = + S_pv * + model.parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] = + S_v * + model + .parameters.template get>()[i] * + model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + model.populations[{i, InfectionState::InfectedCriticalNaive}] = + S * model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = + model.parameters.template get>()[{i, SimulationDay(0)}] + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] - + (model.populations[{i, InfectionState::InfectedSymptomsNaive}] + + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSevereNaive}] + + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] + + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalNaive}] + + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + + model.populations[{i, InfectionState::DeadNaive}] + + model.populations[{i, InfectionState::DeadPartialImmunity}] + + model.populations[{i, InfectionState::DeadImprovedImmunity}]); + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::min( + S_v - model.populations[{i, InfectionState::ExposedImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - + model.populations[{i, InfectionState::DeadImprovedImmunity}], + std::max(0.0, ScalarType(model.populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); + + model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( + 0.0, + S_pv - model.populations[{i, InfectionState::ExposedPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - + model.populations[{i, InfectionState::DeadPartialImmunity}]); + + model.populations.template set_difference_from_group_total( + {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); + } + + for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { + for (auto j = Index(0); j < InfectionState::Count; ++j) { + if (model.populations[{i, j}] < 0) { + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), + size_t(j), model.populations[{i, j}] / num_population[size_t(i)]); + } + } + } + + return success(); +} + +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, + Date date) +{ + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(auto&& vnum_population, read_population_data(path, vregion)); + BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path_rki)); + + // sort case_data into regions and ignore once with no region associated + std::vector> vcase_data{model.size()}; + for (auto&& entry : case_data) { + auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { + return m.id == 0 || get_region_id(entry) == m.id; + }); + if (it != model.end()) { + auto region_idx = size_t(it - model.begin()); + vcase_data[region_idx].push_back(entry); + } + } + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(auto&& num_rec, compute_confirmed_cases_data_fix_recovered(vcase_data[region_idx], model[region_idx].id, date, 14.)); + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, vnum_population[region_idx], model[region_idx].id, num_rec)); + } + return success(); +} + +IOResult set_divi_data(Model& model, const ScalarType num_icu, ScalarType scaling_factor_icu) +{ + ScalarType sum_mu_I_U = 0; + std::vector mu_I_U; + auto num_groups = model.parameters.get_num_groups(); + for (auto i = AgeGroup(0); i < num_groups; i++) { + sum_mu_I_U += model.parameters.template get>()[i] * + model.parameters.template get>()[i]; + mu_I_U.push_back(model.parameters.template get>()[i] * + model.parameters.template get>()[i]); + } + + for (auto i = AgeGroup(0); i < num_groups; i++) { + model.populations[{i, InfectionState::InfectedCriticalNaive}] = + scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; + } + + return success(); +} + +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + ScalarType scaling_factor_icu) +{ + // DIVI dataset will no longer be updated from CW29 2024 on. + if (!is_divi_data_available(date)) { + log_warning("No DIVI data available for date: {}. " + "ICU compartment will be set based on Case data.", + date); + return success(); + } + + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); + + for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { + BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); + } + + return success(); +} + } // namespace details + +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, + int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + + BOOST_OUTCOME_TRY( + details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, num_days)); + + // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. + // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, + scaling_factor_icu)); + + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, + date, scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, + epidata_filenames.case_data_path, date)); + return success(); +} + +#ifdef MEMILIO_HAS_HDF5 + +IOResult export_input_data_timeseries( + const mio::VectorRange>> model, const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames) +{ + const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); + assert(scaling_factor_inf.size() == num_age_groups); + assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); + std::vector> extrapolated_data( + model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); + + for (int t = 0; t <= num_days; ++t) { + auto offset_day = offset_date_by_days(date, t); + + // TODO: empty vaccination data path guard + BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, + num_days, epidata_filenames)); + + for (size_t r = 0; r < model.size(); r++) { + extrapolated_data[r][t] = model[r].property.get_initial_values(); + // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. + // Since we should be independent whether we consider them or not, we add them back here before we save the data. + for (size_t age = 0; age < num_age_groups; age++) { + extrapolated_data[r][t][(size_t)InfectionState::SusceptibleImprovedImmunity + + age * (size_t)InfectionState::Count] += + extrapolated_data[r][t][(size_t)InfectionState::DeadNaive + age * (size_t)InfectionState::Count]; + } + } + } + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), + path_join(results_dir, "Results_rki.h5"))); + + auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); + BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), + path_join(results_dir, "Results_rki_sum.h5"))); + + return success(); +} +#else +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, + const std::vector&, const ScalarType, const int, + const mio::regions::de::EpidataFilenames&) +{ + mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); + return success(); +} + +#endif //MEMILIO_HAS_HDF5 + } // namespace osecirvvs } // namespace mio diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 4096b0011d..4e296a39b3 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -42,572 +42,118 @@ namespace osecirvvs namespace details { +/** + * @brief Reads populations data from rki data. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Key of the region of interest. + * @param[in] date Date at which the data is read. + * @param[in, out] num_* Output vector for number of people in the corresponding compartement. + * @param[in] t_* vector Average time it takes to get from one compartement to another for each age group. + * @param[in] mu_* vector Probabilities to get from one compartement to another for each age group. + * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. + */ IOResult compute_confirmed_cases_data( const std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf); -/**@}*/ + const std::vector& t_InfectedCritical, const std::vector& mu_C_R, + const std::vector& mu_I_H, const std::vector& mu_H_U, + const std::vector& scaling_factor_inf); /** - * @brief Reads confirmed cases data and translates data of day t0-delay to recovered compartment. - * @param[in] path Path to RKI confirmed cases file. - * @param[in] vregion Vector of keys of the region of interest. - * @param[in] date Date for which the arrays are initialized. - * @param[in] delay Number of days in the past the are used to set recovered compartment. - * @return Vector for number of people in the compartment recovered. - * @see mio::read_confirmed_cases_data - * @{ - */ -IOResult> compute_confirmed_cases_data_fix_recovered( - const std::vector& case_data, const int region, Date date, double delay = 14.); -/**@}*/ + * @brief Reads confirmed cases data and translates data of day t0-delay to recovered compartment. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Key of the region of interest. + * @param[in] date Date for which the arrays are initialized. + * @param[in] delay Number of days in the past that are used to set recovered compartment. + * @return Vector for number of people in the compartment recovered. + */ +IOResult> compute_confirmed_cases_data_fix_recovered( + const std::vector& case_data, const int region, Date date, ScalarType delay = 14.); /** - * @brief Sets the confirmed cases data for a vector of models based on input data. - * @param[in, out] model Vector of objects in which the data is set. - * @param[in] case_data Vector of case data. Each inner vector represents a different region. - * @param[in] region Vector of keys of the region of interest. - * @param[in] date Date for which the arrays are initialized. - * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of RKI data. - * @param[in] set_death If true, set the number of deaths. - */ -template -IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, - const int region, Date date, const std::vector& scaling_factor_inf, - bool set_death = false) -{ - auto num_age_groups = (size_t)model.parameters.get_num_groups(); - assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors - assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups); - - std::vector t_Exposed; - std::vector t_InfectedNoSymptoms; - std::vector t_InfectedSymptoms; - std::vector t_InfectedSevere; - std::vector t_InfectedCritical; - - std::vector mu_C_R; - std::vector mu_I_H; - std::vector mu_H_U; - - std::vector num_InfectedSymptoms(num_age_groups, 0.0); - std::vector num_death(num_age_groups, 0.0); - std::vector num_rec(num_age_groups, 0.0); - std::vector num_Exposed(num_age_groups, 0.0); - std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); - std::vector num_InfectedSevere(num_age_groups, 0.0); - std::vector num_icu(num_age_groups, 0.0); - - /*----------- UNVACCINATED -----------*/ - for (size_t group = 0; group < num_age_groups; group++) { - - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedSymptoms.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedSevere.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - - mu_C_R.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_I_H.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_H_U.push_back( - model.parameters.template get>()[(AgeGroup)group]); - } - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); - - - size_t num_groups = (size_t)model.parameters.get_num_groups(); - for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = - num_InfectedNoSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = - num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = - num_InfectedSevere[i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = num_icu[i]; - } - model.populations[{AgeGroup(i), InfectionState::SusceptibleImprovedImmunity}] = num_rec[i]; - if (set_death) { - // in set_confirmed_cases_data initilization, deaths are now set to 0. In order to visualize - // the extrapolated real number of deaths, they have to be set here. In the comparison of data - // it has to be paid attention to the fact, the the simulation starts with deaths=0 - // while this method starts with deaths=number of reported deaths so far... - // Additionally, we set the number of reported deaths to DeadNaive since no information on that is - // available here. - // Do only add deaths after substraction. - model.populations[{AgeGroup(i), InfectionState::DeadNaive}] = num_death[i]; - } - } - if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) == 0.0) { - log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region); - } - - /*----------- PARTIALLY VACCINATED -----------*/ - t_InfectedNoSymptoms.clear(); - t_Exposed.clear(); - t_InfectedSymptoms.clear(); - t_InfectedSevere.clear(); - t_InfectedCritical.clear(); - - mu_C_R.clear(); - mu_I_H.clear(); - mu_H_U.clear(); - - num_InfectedSymptoms = std::vector(num_age_groups, 0.0); - num_death = std::vector(num_age_groups, 0.0); - num_rec = std::vector(num_age_groups, 0.0); - num_Exposed = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); - num_InfectedSevere = std::vector(num_age_groups, 0.0); - num_icu = std::vector(num_age_groups, 0.0); - - for (size_t group = 0; group < num_age_groups; group++) { - double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms.push_back(static_cast(std::round( - model.parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSymptoms.push_back(static_cast(std::round( - model.parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSevere.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - - double exp_fac_part_immune = - model.parameters.template get>()[(AgeGroup)group]; - double inf_fac_part_immune = - model.parameters.template get>()[(AgeGroup)group]; - double hosp_fac_part_immune = - model - .parameters.template get>()[(AgeGroup)group]; - double icu_fac_part_immune = - model - .parameters.template get>()[(AgeGroup)group]; - mu_C_R.push_back(( - 1 - inf_fac_part_immune / exp_fac_part_immune * - (1 - model - .parameters.template get>()[(AgeGroup)group]))); - mu_I_H.push_back( - hosp_fac_part_immune / inf_fac_part_immune * - model.parameters.template get>()[(AgeGroup)group]); - // transfer from H to U, D unchanged. - mu_H_U.push_back( - icu_fac_part_immune / hosp_fac_part_immune * - model.parameters.template get>()[(AgeGroup)group]); - } - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); - - - for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = - num_InfectedNoSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = - num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = - num_InfectedSevere[i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = - num_icu[i]; - } - } - // } - if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) == 0.0) { - log_warning("No infections for partially vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region); - } - - /*----------- FULLY VACCINATED -----------*/ - t_InfectedNoSymptoms.clear(); - t_Exposed.clear(); - t_InfectedSymptoms.clear(); - t_InfectedSevere.clear(); - t_InfectedCritical.clear(); - - mu_C_R.clear(); - mu_I_H.clear(); - mu_H_U.clear(); - - num_InfectedSymptoms = std::vector(num_age_groups, 0.0); - num_death = std::vector(num_age_groups, 0.0); - num_rec = std::vector(num_age_groups, 0.0); - num_Exposed = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms = std::vector(num_age_groups, 0.0); - num_InfectedSevere = std::vector(num_age_groups, 0.0); - num_icu = std::vector(num_age_groups, 0.0); - - for (size_t group = 0; group < num_age_groups; group++) { - double reduc_t = model[0].parameters.template get>()[(AgeGroup)group]; - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedNoSymptoms.push_back(static_cast(std::round( - model.parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSymptoms.push_back(static_cast(std::round( - model.parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSevere.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - t_InfectedCritical.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); - - double reduc_immune_exp = - model.parameters.template get>()[(AgeGroup)group]; - double reduc_immune_inf = - model.parameters.template get>()[(AgeGroup)group]; - double reduc_immune_hosp = - model.parameters.template get>()[( - AgeGroup)group]; - double reduc_immune_icu = - model.parameters.template get>()[( - AgeGroup)group]; - mu_C_R.push_back(( - 1 - reduc_immune_inf / reduc_immune_exp * - (1 - model - .parameters.template get>()[(AgeGroup)group]))); - mu_I_H.push_back( - reduc_immune_hosp / reduc_immune_inf * - model.parameters.template get>()[(AgeGroup)group]); - // transfer from H to U, D unchanged. - mu_H_U.push_back( - reduc_immune_icu / reduc_immune_hosp * - model.parameters.template get>()[(AgeGroup)group]); - } - - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); - - for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] = - num_InfectedNoSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = - num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = - num_InfectedSevere[i]; - // Only set the number of ICU patients here, if the date is not available in the data. - if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = - num_icu[i]; - } - } - - if (std::accumulate(num_InfectedSymptoms.begin(), num_InfectedSymptoms.end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) == 0.0) { - log_warning("No infections for vaccinated reported on date {} for region {}. " - "Population data has not been set.", - date, region); - } + * @brief Sets populations data from already read case data with multiple age groups into a Model. + * @param[in, out] model Model in which the data is set. + * @param[in] case_data Vector of ConfirmedCasesDataEntry%s. + * @param[in] region Key of the region of interest. + * @param[in] date Date at which the data is read. + * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. + * @param[in] set_death If true, set the number of deaths. + */ +IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, + bool set_death = false); - return success(); -} /** - * @brief sets populations data from a transformed RKI cases file into a Model. - * @param[in, out] model vector of objects in which the data is set - * @param[in] path Path to transformed RKI cases file - * @param[in] region vector of keys of the region of interest - * @param[in] date Date for which the arrays are initialized - * @param[in] scaling_factor_inf factors by which to scale the confirmed cases of - * rki data - * @param set_death[in] If true, set the number of deaths. - */ -template -IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, Date date, - const std::vector& scaling_factor_inf, bool set_death = false) -{ - BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - - // sort case_data into regions and ignore once with no region associated - std::vector> vcase_data{model.size()}; - for (auto&& entry : case_data) { - auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { - return m.id == 0 || get_region_id(entry) == m.id; - }); - if (it != model.end()) { - auto region_idx = size_t(it - model.begin()); - vcase_data[region_idx].push_back(entry); - } - } - - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_confirmed_cases_data(model[region_idx].property, vcase_data[region_idx], model[region_idx].id, date, scaling_factor_inf, set_death)); - } - return success(); -} + * @brief Sets the infected populations for the given models based on confirmed cases data. + * Reads the case data from a file and then calls a subfunction that sets the infected population + * for each model. + * @param[in, out] model VectorRange of Node%s containing a Model for which the confirmed cases data will be set. + * @param[in] path Path to the confirmed cases data file. + * @param[in] date Date at which the data is read. + * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. + * @param set_death[in] If true, set the number of deaths. + */ +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, Date date, + const std::vector& scaling_factor_inf, bool set_death = false); /** -* @brief sets population data from census data which has been read into num_population -* @param[in, out] model vector of objects in which the data is set -* @param[in] num_population vector of population data -* @param[in] vregion vector of keys of the regions of interest -* @param[in] date Date for which the arrays are initialized -*/ -template -IOResult set_population_data(Model& model, const std::vector& num_population, - const int region, const std::vector& num_rec) -{ - if (std::accumulate(num_population.begin(), num_population.end(), double(0.0), - [](const double& a, const double& b) { - return evaluate_intermediate(a + b); - }) <= 0) - { - log_warning("No population data available for region " + std::to_string(region) + - ". Population data has not been set."); - return success(); - } - - auto num_groups = model.parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - - double S_v = std::min( - model.parameters.template get>()[{i, SimulationDay(0)}] + - num_rec[size_t(i)], - num_population[size_t(i)]); - double S_pv = std::max( - model.parameters.template get>()[{i, SimulationDay(0)}] - - model.parameters.template get>()[{i, SimulationDay(0)}], - 0.0); // use std::max with 0 - double S; - if (num_population[size_t(i)] - S_pv - S_v < 0.0) { - log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", - region, size_t(i)); - S = 0.0; - S_v = num_population[size_t(i)] - S_pv; - } - else { - S = num_population[size_t(i)] - S_pv - S_v; - } - - double denom_E = - 1 / (S + S_pv * model.parameters.template get>()[i] + - S_v * model.parameters.template get>()[i]); - double denom_C = - 1 / (S + S_pv * model.parameters.template get>()[i] + - S_v * model.parameters.template get>()[i]); - double denom_I = - 1 / - (S + - S_pv * model.parameters.template get>()[i] + - S_v * model.parameters.template get>()[i]); - double denom_HU = - 1 / - (S + - S_pv * model - .parameters.template get>()[i] + - S_v * model - .parameters.template get>()[i]); - - model.populations[{i, InfectionState::ExposedNaive}] = - S * model.populations[{i, InfectionState::ExposedNaive}] * denom_E; - model.populations[{i, InfectionState::ExposedPartialImmunity}] = - S_pv * model.parameters.template get>()[i] * - model.populations[{i, InfectionState::ExposedPartialImmunity}] * denom_E; - model.populations[{i, InfectionState::ExposedImprovedImmunity}] = - S_v * model.parameters.template get>()[i] * - model.populations[{i, InfectionState::ExposedImprovedImmunity}] * denom_E; - - model.populations[{i, InfectionState::InfectedNoSymptomsNaive}] = - S * model.populations[{i, InfectionState::InfectedNoSymptomsNaive}] * denom_C; - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] = - S_pv * model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] * denom_C; - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] = - S_v * model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] * denom_C; - - model.populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] = - S * model.populations[{i, InfectionState::InfectedNoSymptomsNaiveConfirmed}] * denom_C; - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = - S_pv * model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] * - denom_C; - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = - S_v * model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] * - denom_C; - - model.populations[{i, InfectionState::InfectedSymptomsNaive}] = - S * model.populations[{i, InfectionState::InfectedSymptomsNaive}] * denom_I; - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] = - S_pv * model.parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] * denom_I; - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] = - S_v * model.parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] * denom_I; - - model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] = - S * model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] * denom_I; - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = - S_pv * model.parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] * denom_I; - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = - S_v * model.parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] * denom_I; - - model.populations[{i, InfectionState::InfectedSevereNaive}] = - S * model.populations[{i, InfectionState::InfectedSevereNaive}] * denom_HU; - model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] = - S_pv * - model.parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] * denom_HU; - model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] = - S_v * - model - .parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] * denom_HU; - - model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] = - S_pv * - model.parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] = - S_v * - model - .parameters.template get>()[i] * - model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - model.populations[{i, InfectionState::InfectedCriticalNaive}] = - S * model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; - - model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = - model.parameters.template get>()[{i, SimulationDay(0)}] + - model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] - - (model.populations[{i, InfectionState::InfectedSymptomsNaive}] + - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + - model.populations[{i, InfectionState::InfectedSevereNaive}] + - model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] + - model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedCriticalNaive}] + - model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + - model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + - model.populations[{i, InfectionState::DeadNaive}] + - model.populations[{i, InfectionState::DeadPartialImmunity}] + - model.populations[{i, InfectionState::DeadImprovedImmunity}]); - - model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::min( - S_v - model.populations[{i, InfectionState::ExposedImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - - model.populations[{i, InfectionState::DeadImprovedImmunity}], - std::max(0.0, double(model.populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); - - model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( - 0.0, - S_pv - model.populations[{i, InfectionState::ExposedPartialImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - - model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - - model.populations[{i, InfectionState::DeadPartialImmunity}]); - - model.populations.template set_difference_from_group_total( - {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); - } - - for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { - for (auto j = Index(0); j < InfectionState::Count; ++j) { - if (model.populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model.populations[{i, j}] / num_population[size_t(i)]); - } - } - } + * @brief Sets the population data for the given model based on the provided population distribution. + * @param[in, out] model Model in which the data is set. + * @param[in] num_population Vector of population data for the region of interest. + * @param[in] region Key of the region of interest. + * @param[in] date Date for which the arrays are initialized. + */ +IOResult set_population_data(Model& model, const std::vector& num_population, + const int region, const std::vector& num_rec); - return success(); -} +/** + * @brief Reads population data from a file and sets it for the each given model. + * @param[in, out] model VectorRange of Node%s containing a Model for which the confirmed cases data will be set. + * @param[in] path Path to population data file. + * @param[in] path_rki Path to rki cases data file. + * @param[in] date Date for which the arrays are initialized. + */ +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, + Date date); /** -* @brief Sets population data from census data which has been read into num_population. -* @param[in, out] model Vector of objects in which the data is set. -* @param[in] path Path to population data file. -* @param[in] path_rki Path to RKI cases data file. -* @param[in] date Date for which the arrays are initialized. -*/ -template -IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, - Date date) -{ - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(auto&& vnum_population, read_population_data(path, vregion)); - BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path_rki)); - - // sort case_data into regions and ignore once with no region associated - std::vector> vcase_data{model.size()}; - for (auto&& entry : case_data) { - auto it = std::find_if(model.begin(), model.end(), [&entry](auto m) { - return m.id == 0 || get_region_id(entry) == m.id; - }); - if (it != model.end()) { - auto region_idx = size_t(it - model.begin()); - vcase_data[region_idx].push_back(entry); - } - } + * @brief Sets ICU data into a Model, distributed across age groups. + * @param[in, out] model Model in which the data is set. + * @param[in] num_icu ICU data for the region of interest. + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + */ +IOResult set_divi_data(Model& model, const ScalarType num_icu, ScalarType scaling_factor_icu); - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(auto&& num_rec, compute_confirmed_cases_data_fix_recovered(case_data[region_idx], model[region_idx].id, date, 14.)); - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, vnum_population[region_idx], model[region_idx].id, num_rec)); - } - return success(); -} +/** + * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. + * + * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) + * for each region, and sets these values in the model. The ICU cases are distributed across age groups + * using the transition probabilities from severe to critical. + * + * @param[in, out] model VectorRange of Node%s each containing a Model for which the confirmed cases data will be set. + * @param[in] path Path to transformed DIVI file. + * @param[in] date Date at which the data is read. + * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + */ +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, + ScalarType scaling_factor_icu); /** - * @brief Sets vaccination data for models stored in a vector. - * - * @tparam FP Floating point type used in the Model objects. - * @param[in, out] model Vector of Model objects in which the vaccination data is set. + * @brief Sets vaccination data into a Model. + * @tparam FP Floating point type (default: double). + * @param[in, out] model Model in which the data is set. * @param[in] vacc_data Vector of VaccinationDataEntry objects containing the vaccination data. * @param[in] date Start date for the simulation. * @param[in] num_days Number of days for which the simulation is run. + * + * @return An IOResult indicating success or failure. */ template IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, @@ -722,12 +268,13 @@ IOResult set_vaccination_data(Model& model, const std::vector IOResult set_vaccination_data(const mio::VectorRange>>& model, const std::string& path, Date date, @@ -755,7 +302,7 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod } BOOST_OUTCOME_TRY(auto&& vacc_data, read_vaccination_data(path)); - // Sort case_data into regions and ignore once with no region associated + // Sort vacc_data into regions and ignore once with no region associated std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { @@ -776,159 +323,84 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod return success(); } +} // namespace details + /** - * @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups. + * @brief Reads compartments for geographic units at a specified date from data files. * - * This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU) - * for each region, and sets these values in the model. The ICU cases are distributed across age groups - * using the transition probabilities from severe to critical. - * @tparam FP Floating point type (default: double). + * This function estimates all compartments from available data using the provided model parameters. * - * @param[in,out] model Vector of models, each representing a region, where the ICU population is updated. - * @param[in] num_icu icu data - * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. + * @param[in,out] model VectorRange of Node%s each containing a Model to be initialized with data. + * @param[in] date Date for which the data should be read. + * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. + * @param[in] scaling_factor_icu Scaling factor for ICU cases. + * @param[in] num_days Number of days to simulate. + * @param[in] epidata_filenames Object containing the input data file paths. * * @return An IOResult indicating success or failure. */ -template -IOResult set_divi_data(Model& model, const double num_icu, double scaling_factor_icu) -{ - FP sum_mu_I_U = 0; - std::vector mu_I_U; - auto num_groups = model.parameters.get_num_groups(); - for (auto i = AgeGroup(0); i < num_groups; i++) { - sum_mu_I_U += model.parameters.template get>()[i] * - model.parameters.template get>()[i]; - mu_I_U.push_back(model.parameters.template get>()[i] * - model.parameters.template get>()[i]); - } - - for (auto i = AgeGroup(0); i < num_groups; i++) { - model.populations[{i, InfectionState::InfectedCriticalNaive}] = - scaling_factor_icu * num_icu * mu_I_U[(size_t)i] / sum_mu_I_U; - } - - return success(); -} +IOResult read_input_data(const mio::VectorRange>>& model, Date date, + const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, + int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames); /** - * @brief sets populations data from DIVI register into Model - * @param[in, out] model vector of objects in which the data is set - * @param[in] path Path to transformed DIVI file - * @param[in] date Date for which the arrays are initialized - * @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data + * @brief Converts input data from one range of models to another with different type. + * + * @tparam FP Floating point type (default: double). + * @param[in] model_from VectorRange of Node%s each containing a Model with the input data. + * @param[in,out] model_to VectorRange of Node%s each containing a Model to be initialized with data. + * @param[in] date Date for which the data should be read. + * @param[in] num_days Number of days to simulate. + * @param[in] epidata_filenames Object containing the input data file paths. + * + * @return An IOResult indicating success or failure. */ -template -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, - double scaling_factor_icu) +template +IOResult convert_input_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to, + Date date, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { - // DIVI dataset will no longer be updated from CW29 2024 on. - if (!is_divi_data_available(date)) { - log_warning("No DIVI data available for date: {}. " - "ICU compartment will be set based on Case data.", - date); - return success(); - } - - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); - - for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_divi_data(model[region_idx].property, num_icu[region_idx], scaling_factor_icu)); - } - - return success(); -} - -} // namespace details - -template -IOResult read_input_data(const mio::VectorRange>>& model, Date date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, - int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - + assert(model_from.size() == model_to.size()); + assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()) + // Todo: add conversion of ParameterSet and then re-use code from all model parameters io + // For now call set_vacination_data with FP to set correct parameters BOOST_OUTCOME_TRY( - details::set_vaccination_data(model, epidata_filenames.vaccination_data_path, date, num_days)); + details::set_vaccination_data(model_to, epidata_filenames.vaccination_data_path, date, num_days)); - // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. - // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, - scaling_factor_icu)); - - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, - epidata_filenames.case_data_path, date)); + for (size_t region_idx = 0; region_idx < model_from.size(); ++region_idx) { + // convert populations to mio::UncertainValue + // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work + model_to[region_idx].property.populations = model_to[region_idx].property.populations.convert().convert>(); + } return success(); } #ifdef MEMILIO_HAS_HDF5 /** -* @brief Uses the initialisation method, which uses the reported data to set the initial conditions for the model for a given day. -* The initialisation is applied for a predefined number of days and finally saved in a timeseries for each region. In the end, -* we save the files "Results_rki.h5" and "Results_rki_sum.h5" in the results_dir. -* Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. -* @param[in] model Vector of models in which the data is set. Copy is made to avoid changing the original model. -* @param[in] results_dir Path to result files. -* @param[in] date Date for which the data should be read. -* @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. -* @param[in] scaling_factor_icu Factor by which to scale the icu cases of divi data. -* @param[in] num_days Number of days to be simulated/initialized. -* @param[in] pydata_dir Directory that contains the data files. -*/ -template + * @brief Uses the initialisation method, which uses the reported data to set the initial conditions for the model for a given day. + * + * The initialisation is applied for a predefined number of days and finally saved in a timeseries for each region. In the end, + * we save the files "Results_rki.h5" and "Results_rki_sum.h5" in the results_dir. + * Results_rki.h5 contains a time series for each region and Results_rki_sum.h5 contains the sum of all regions. + * + * @param[in] model VectorRange of Node%s each containing a Model in which the data is set. + * @param[in] results_dir Path to result files. + * @param[in] date Date for which the data should be read. + * @param[in] scaling_factor_inf Vector of scaling factors for confirmed cases. + * @param[in] scaling_factor_icu Scaling factor for ICU cases. + * @param[in] num_days Number of days to be simulated/initialized. + * @param[in] epidata_filenames Object containing the input data file paths. + * + * @return An IOResult indicating success or failure. + */ IOResult export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, const double scaling_factor_icu, const int num_days, - const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); - assert(scaling_factor_inf.size() == num_age_groups); - assert(num_age_groups == ConfirmedCasesDataEntry::age_group_names.size()); - std::vector> extrapolated_data( - model.size(), TimeSeries::zero(num_days + 1, (size_t)InfectionState::Count * num_age_groups)); - - for (int t = 0; t <= num_days; ++t) { - auto offset_day = offset_date_by_days(date, t); - - // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, - num_days, epidata_filenames)); - - for (size_t r = 0; r < model.size(); r++) { - extrapolated_data[r][t] = model[r].property.get_initial_values(); - // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment. - // Since we should be independent whether we consider them or not, we add them back here before we save the data. - for (size_t age = 0; age < num_age_groups; age++) { - extrapolated_data[r][t][(size_t)InfectionState::SusceptibleImprovedImmunity + - age * (size_t)InfectionState::Count] += - extrapolated_data[r][t][(size_t)InfectionState::DeadNaive + age * (size_t)InfectionState::Count]; - } - } - } - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); - BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), - path_join(results_dir, "Results_rki.h5"))); - - auto extrapolated_rki_data_sum = sum_nodes(std::vector>>{extrapolated_data}); - BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast(num_age_groups), - path_join(results_dir, "Results_rki_sum.h5"))); - - return success(); -} + const mio::VectorRange>> model, const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames); #else -template -IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const double, const int, - const mio::regions::de::EpidataFilenames&) -{ - mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); - return success(); -} +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, + const std::vector&, const ScalarType, const int, + const mio::regions::de::EpidataFilenames&); #endif //MEMILIO_HAS_HDF5 From d054a5ed17eeba3bac58434c0d61645105ed430f Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Wed, 19 Nov 2025 22:57:56 +0000 Subject: [PATCH 08/26] Fix bugs --- cpp/memilio/epidemiology/populations.h | 12 +- cpp/memilio/geography/regions.cpp | 1 + cpp/memilio/mobility/graph.h | 41 ++- cpp/memilio/utils/custom_index_array.h | 9 +- cpp/models/ode_secir/parameters_io.cpp | 173 +++++---- cpp/models/ode_secir/parameters_io.h | 4 +- cpp/models/ode_secirts/parameters_io.cpp | 267 +++++++------- cpp/models/ode_secirts/parameters_io.h | 93 ++--- cpp/models/ode_secirvvs/parameters_io.cpp | 411 ++++++++++------------ cpp/models/ode_secirvvs/parameters_io.h | 86 ++--- 10 files changed, 554 insertions(+), 543 deletions(-) diff --git a/cpp/memilio/epidemiology/populations.h b/cpp/memilio/epidemiology/populations.h index 65a826f54b..1d3e63ca2f 100644 --- a/cpp/memilio/epidemiology/populations.h +++ b/cpp/memilio/epidemiology/populations.h @@ -26,6 +26,7 @@ #include "memilio/math/eigen.h" #include "memilio/math/math_utils.h" +#include #include namespace mio @@ -68,10 +69,15 @@ class Populations : public CustomIndexArray, Categories...> { } - template - Populations convert() const + /** + * @brief Convert internally stored data to OtherType and save into new Populations. + * @tparam OtherType The type to convert into. + * @return New Populations of OtherType with copy of internal data. + */ + template requires std::convertible_to + Populations convert() const { - return Populations(Base::convert()); + return Populations(Base::template convert()); } /** diff --git a/cpp/memilio/geography/regions.cpp b/cpp/memilio/geography/regions.cpp index 30a223f705..308b34db58 100644 --- a/cpp/memilio/geography/regions.cpp +++ b/cpp/memilio/geography/regions.cpp @@ -33,6 +33,7 @@ namespace de StateId get_state_id(int county) { + // integer division return StateId(county / 1000); } diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index b9df7be042..94b8697265 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -20,7 +20,6 @@ #ifndef GRAPH_H #define GRAPH_H -#include #include "memilio/utils/stl_util.h" #include "memilio/epidemiology/age_group.h" #include "memilio/utils/date.h" @@ -29,6 +28,8 @@ #include "memilio/epidemiology/damping.h" #include "memilio/geography/regions.h" #include +#include +#include #include "boost/filesystem.hpp" @@ -152,8 +153,8 @@ class Graph using NodeProperty = NodePropertyT; using EdgeProperty = EdgePropertyT; - /* add note for same size of parameters - */ + /** add note for same size of parameters + */ Graph(const std::vector& node_ids, std::vector& node_properties) { assert(node_ids.size() == node_properties.size()); @@ -170,7 +171,7 @@ class Graph } } - template + template requires std::constructible_from Graph(const std::vector& node_ids, Args&&... node_args) { for (int id : node_ids) { @@ -178,7 +179,7 @@ class Graph } } - template + template requires std::constructible_from Graph(const int number_of_nodes, Args&&... args) { for (auto id = size_t(0); id < number_of_nodes; ++id) { @@ -191,7 +192,7 @@ class Graph /** * @brief add a node to the graph. property of the node is constructed from arguments. */ - template + template requires std::constructible_from Node& add_node(int id, Args&&... args) { m_nodes.emplace_back(id, std::forward(args)...); @@ -201,7 +202,7 @@ class Graph /** * @brief add an edge to the graph. property of the edge is constructed from arguments. */ - template + template requires std::constructible_from Edge& add_edge(size_t start_node_idx, size_t end_node_idx, Args&&... args) { assert(m_nodes.size() > start_node_idx && m_nodes.size() > end_node_idx); @@ -276,19 +277,34 @@ class Graph std::vector> m_edges; }; +/** + * @brief Set test and trace capacity with uncertainty for the given models. + * + * @param[in, out] nodes VectorRange of Node%s each containing a Model in which the data is set. + * @param[in] tnt_capacity_factor Factor for test and trace capacity. + */ template -void set_test_and_trace_capacity(const mio::VectorRange>& nodes, double tnt_capacity_factor) +void set_test_and_trace_capacity(const mio::VectorRange>& nodes, ScalarType tnt_capacity_factor) { for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { auto tnt_capacity = nodes[node_idx].property.populations.get_total() * tnt_capacity_factor; auto& tnt_value = nodes[node_idx].property.parameters.template get(); - tnt_value = UncertainValue(tnt_capacity); + tnt_value = UncertainValue(tnt_capacity); tnt_value.set_distribution(mio::ParameterDistributionUniform(0.8 * tnt_capacity, 1.2 * tnt_capacity)); } } +/** + * @brief Set german state holidays for the given nodes. + * + * Works for nodes of a graph depicting german counties or states. + * + * @param[in, out] nodes VectorRange of Node%s each containing a Model in which the data is set. + * @param[in] start_date Date at the beginning of the simulation. + * @param[in] end_date Date at the end of the simulation. + */ template void set_german_holidays(const mio::VectorRange>& nodes, const mio::Date& start_date, const mio::Date& end_date) { @@ -307,6 +323,11 @@ void set_german_holidays(const mio::VectorRange>& nodes, const mio:: } } +/** + * @brief Add uncertainty to the population of the given nodes. + * + * @param[in, out] nodes VectorRange of Node%s each containing a Model in which the data is set. + */ template void set_uncertainty_on_population(const mio::VectorRange>& nodes) { @@ -315,7 +336,7 @@ void set_uncertainty_on_population(const mio::VectorRange>& nodes) for (auto j = Index(0); j < Model::Compartments::Count; ++j) { auto& compartment_value = nodes[node_idx].property.populations[{i, j}]; compartment_value = - UncertainValue(compartment_value.value()); + UncertainValue(compartment_value.value()); compartment_value.set_distribution(mio::ParameterDistributionUniform(0.9 * compartment_value.value(), 1.1 * compartment_value.value())); } diff --git a/cpp/memilio/utils/custom_index_array.h b/cpp/memilio/utils/custom_index_array.h index 45863e5e2f..14ac136a88 100644 --- a/cpp/memilio/utils/custom_index_array.h +++ b/cpp/memilio/utils/custom_index_array.h @@ -24,6 +24,8 @@ #include "memilio/utils/index.h" #include "memilio/utils/stl_util.h" +#include + namespace { @@ -342,7 +344,12 @@ class CustomIndexArray } } - template + /** + * @brief Convert internally stored data to OtherType and save into new CustomIndexArray. + * @tparam OtherType The type to convert into. + * @return New CustomIndexArray of OtherType with copy of internal data. + */ + template requires std::convertible_to CustomIndexArray convert() const { CustomIndexArray other; diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index 75c3b4efe8..c25a3e6675 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -44,17 +44,16 @@ namespace osecir namespace details { -IOResult compute_confirmed_cases_data( - std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, - const std::vector& t_InfectedNoSymptoms, - const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf) +IOResult +compute_confirmed_cases_data(std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, + const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, + const std::vector& mu_C_R, const std::vector& mu_I_H, + const std::vector& mu_H_U, const std::vector& scaling_factor_inf) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -70,7 +69,6 @@ IOResult compute_confirmed_cases_data( } auto days_surplus = std::min(get_offset_in_days(max_date, date) - 6, 0); - for (auto&& entry : case_data) { auto date_df = entry.date; @@ -84,12 +82,10 @@ IOResult compute_confirmed_cases_data( num_rec[age] += entry.num_confirmed; } if (date_df == offset_date_by_days(date, days_surplus)) { - num_InfectedNoSymptoms[age] -= - 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + num_InfectedNoSymptoms[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; } if (date_df == offset_date_by_days(date, t_InfectedNoSymptoms[age] + days_surplus)) { - num_InfectedNoSymptoms[age] += - 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; + num_InfectedNoSymptoms[age] += 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; num_Exposed[age] -= 1 / (1 - mu_C_R[age]) * scaling_factor_inf[age] * entry.num_confirmed; } if (date_df == offset_date_by_days(date, t_Exposed[age] + t_InfectedNoSymptoms[age] + days_surplus)) { @@ -110,7 +106,6 @@ IOResult compute_confirmed_cases_data( } } - for (size_t i = 0; i < ConfirmedCasesDataEntry::age_group_names.size(); i++) { // R(t0) = ΣC(t0) − I(t0) − H(t0) − U(t0) − D(t0) // subtract currently infectious/hospitalized/ICU/dead @@ -119,21 +114,20 @@ IOResult compute_confirmed_cases_data( // recovered, we would implicitly assume that the same underreporting applies to the entire // history up to t0, which would be wrong. The scaling factor should reflect underreporting // around t0 only. - num_rec[i] -= - (num_InfectedSymptoms[i] / scaling_factor_inf[i] + num_InfectedSevere[i] / scaling_factor_inf[i] + - num_icu[i] / scaling_factor_inf[i] + num_death[i] / scaling_factor_inf[i]); + num_rec[i] -= (num_InfectedSymptoms[i] / scaling_factor_inf[i] + num_InfectedSevere[i] / scaling_factor_inf[i] + + num_icu[i] / scaling_factor_inf[i] + num_death[i] / scaling_factor_inf[i]); auto try_fix_constraints = [region, i](ScalarType& value, ScalarType error, auto str) { if (value < error) { //this should probably return a failure //but the algorithm is not robust enough to avoid large negative values and there are tests that rely on it - log_error("{:s} for age group {:s} is {:.4f} for region {:d}, exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + log_error("{:s} for age group {:s} is {:.4f} for region {:d}, exceeds expected negative value.", str, + ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } else if (value < 0) { log_info("{:s} for age group {:s} is {:.4f} for region {:d}, automatically corrected", str, - ConfirmedCasesDataEntry::age_group_names[i], value, region); + ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } }; @@ -192,8 +186,8 @@ IOResult set_confirmed_cases_data(Model& model, std::vector( - std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_Exposed.push_back( + static_cast(std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedNoSymptoms.push_back(static_cast( std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedSymptoms.push_back(static_cast( @@ -203,30 +197,24 @@ IOResult set_confirmed_cases_data(Model& model, std::vector( std::round(model.parameters.template get>()[(AgeGroup)group]))); - mu_C_R.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_I_H.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_H_U.push_back( - model.parameters.template get>()[(AgeGroup)group]); + mu_C_R.push_back(model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back(model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back(model.parameters.template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf_full)); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data( + case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, + num_death, num_rec, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, + mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf_full)); if (model_groups == num_age_groups) { for (size_t i = 0; i < model_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::Exposed}] = num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptoms}] = - num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::Exposed}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptoms}] = num_InfectedNoSymptoms[i]; model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptoms}] = - num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevere}] = - num_InfectedSevere[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptoms}] = num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevere}] = num_InfectedSevere[i]; // Only set the number of ICU patients here, if the date is not available in the data. if (!is_divi_data_available(date)) { model.populations[{AgeGroup(i), InfectionState::InfectedCritical}] = num_icu[i]; @@ -241,15 +229,12 @@ IOResult set_confirmed_cases_data(Model& model, std::vector(a + b); }); }; - model.populations[{AgeGroup(0), InfectionState::Exposed}] = sum_vec(num_Exposed); - model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptoms}] = - sum_vec(num_InfectedNoSymptoms); + model.populations[{AgeGroup(0), InfectionState::Exposed}] = sum_vec(num_Exposed); + model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptoms}] = sum_vec(num_InfectedNoSymptoms); model.populations[{AgeGroup(0), InfectionState::InfectedNoSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(0), InfectionState::InfectedSymptoms}] = - sum_vec(num_InfectedSymptoms); - model.populations[{AgeGroup(0), InfectionState::InfectedSymptomsConfirmed}] = 0; - model.populations[{AgeGroup(0), InfectionState::InfectedSevere}] = - sum_vec(num_InfectedSevere); + model.populations[{AgeGroup(0), InfectionState::InfectedSymptoms}] = sum_vec(num_InfectedSymptoms); + model.populations[{AgeGroup(0), InfectionState::InfectedSymptomsConfirmed}] = 0; + model.populations[{AgeGroup(0), InfectionState::InfectedSevere}] = sum_vec(num_InfectedSevere); if (!is_divi_data_available(date)) { model.populations[{AgeGroup(0), InfectionState::InfectedCritical}] = sum_vec(num_icu); } @@ -261,8 +246,8 @@ IOResult set_confirmed_cases_data(Model& model, std::vector(a + b); }) == 0.0) { log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region); + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", date, + region); } return success(); } @@ -271,7 +256,7 @@ IOResult set_confirmed_cases_data(const mio::VectorRange& scaling_factor_inf) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); - + // sort case_data into regions and ignore once with no region associated std::vector> vcase_data{model.size()}; for (auto&& entry : case_data) { @@ -285,8 +270,8 @@ IOResult set_confirmed_cases_data(const mio::VectorRange set_population_data(Model& model, const std::vector(a + b); - }) <= 0) - { + }) <= 0) { log_warning("No population data available for region " + std::to_string(region) + ". Population data has not been set."); return success(); } - auto num_groups = model.parameters.get_num_groups(); - auto data_groups = num_population.size(); + auto num_groups = model.parameters.get_num_groups(); + auto data_groups = num_population.size(); if (data_groups == (size_t)num_groups) { for (auto i = AgeGroup(0); i < num_groups; i++) { - model.populations.template set_difference_from_group_total( - {i, InfectionState::Susceptible}, num_population[(size_t)i]); + model.populations.template set_difference_from_group_total({i, InfectionState::Susceptible}, + num_population[(size_t)i]); } } else if ((size_t)num_groups == 1 && data_groups >= 1) { const ScalarType total = std::accumulate(num_population.begin(), num_population.end(), ScalarType(0.0), - [](const ScalarType& a, const ScalarType& b) { - return evaluate_intermediate(a + b); - }); - model.populations.template set_difference_from_group_total( - {AgeGroup(0), InfectionState::Susceptible}, total); + [](const ScalarType& a, const ScalarType& b) { + return evaluate_intermediate(a + b); + }); + model.populations.template set_difference_from_group_total({AgeGroup(0), InfectionState::Susceptible}, + total); } for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { for (auto j = Index(0); j < InfectionState::Count; ++j) { if (model.populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model.populations[{i, j}]); + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), size_t(j), + model.populations[{i, j}]); } } } @@ -335,12 +319,15 @@ IOResult set_population_data(Model& model, const std::vector set_population_data(const mio::VectorRange>>& model, const std::string& path) { - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(const auto&& num_population, read_population_data(path, vregion)); for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id)); + BOOST_OUTCOME_TRY( + set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id)); } return success(); } @@ -352,9 +339,9 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, auto num_groups = model.parameters.get_num_groups(); for (auto i = AgeGroup(0); i < num_groups; i++) { sum_mu_I_U += model.parameters.template get>()[i] * - model.parameters.template get>()[i]; + model.parameters.template get>()[i]; mu_I_U.push_back(model.parameters.template get>()[i] * - model.parameters.template get>()[i]); + model.parameters.template get>()[i]); } for (auto i = AgeGroup(0); i < num_groups; i++) { @@ -365,7 +352,7 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, return success(); } -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, ScalarType scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. @@ -376,8 +363,10 @@ IOResult set_divi_data(const mio::VectorRange>>& mo return success(); } - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { @@ -393,21 +382,21 @@ IOResult read_input_data(const mio::VectorRange>>& const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, const mio::regions::de::EpidataFilenames& epidata_filenames) { - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, - scaling_factor_icu)); + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, - scaling_factor_inf)); + BOOST_OUTCOME_TRY( + details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, scaling_factor_inf)); BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path)); return success(); } #ifdef MEMILIO_HAS_HDF5 -IOResult export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, int num_days, - const mio::regions::de::EpidataFilenames& epidata_filenames) +IOResult export_input_data_timeseries(const mio::VectorRange>> model, + const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, + ScalarType scaling_factor_icu, int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames) { const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); // allow scalar scaling factor as convenience for 1-group models @@ -419,15 +408,18 @@ IOResult export_input_data_timeseries( for (int t = 0; t <= num_days; ++t) { auto offset_day = offset_date_by_days(date, t); - BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, epidata_filenames)); + BOOST_OUTCOME_TRY( + read_input_data(model, offset_day, scaling_factor_inf, scaling_factor_icu, epidata_filenames)); for (size_t r = 0; r < model.size(); r++) { extrapolated_data[r][t] = model[r].property.get_initial_values(); } } - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); @@ -438,8 +430,9 @@ IOResult export_input_data_timeseries( return success(); } #else -IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const ScalarType, const int, +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, + Date, const std::vector&, const std::vector&, + const ScalarType, const int, const mio::regions::de::EpidataFilenames&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 1820e03c47..16385e2b18 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -158,13 +158,13 @@ template void convert_input_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to) { assert(model_from.size() == model_to.size()); - assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()) + assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()); // Todo: add conversion of ParameterSet and then re-use code from other model parameters io for (size_t region_idx = 0; region_idx < model_from.size(); ++region_idx) { // convert populations to mio::UncertainValue // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_to[region_idx].property.populations.convert().convert>(); + model_to[region_idx].property.populations = model_to[region_idx].property.populations.template convert().template convert>(); } } diff --git a/cpp/models/ode_secirts/parameters_io.cpp b/cpp/models/ode_secirts/parameters_io.cpp index e8a39472ce..57965cdaf5 100644 --- a/cpp/models/ode_secirts/parameters_io.cpp +++ b/cpp/models/ode_secirts/parameters_io.cpp @@ -57,12 +57,11 @@ IOResult compute_confirmed_cases_data( const std::vector& case_data, const int region, Date date, std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_imm, const std::vector& t_Exposed, - const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, - const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, - const std::vector& t_imm_interval_i, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, + std::vector& num_icu, std::vector& num_death, std::vector& num_imm, + const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, + const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, + const std::vector& t_InfectedCritical, const std::vector& t_imm_interval_i, + const std::vector& mu_C_R, const std::vector& mu_I_H, const std::vector& mu_H_U, const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, const std::vector& scaling_factor_inf, const size_t layer) @@ -93,12 +92,12 @@ IOResult compute_confirmed_cases_data( // transition probabilities ScalarType recoveredPerInfectedNoSymptoms = mu_C_R[age]; - ScalarType severePerInfectedSymptoms = mu_I_H[age]; - ScalarType criticalPerSevere = mu_H_U[age]; + ScalarType severePerInfectedSymptoms = mu_I_H[age]; + ScalarType criticalPerSevere = mu_H_U[age]; // transition times int timeInfectedNoSymptoms = t_InfectedNoSymptoms[age]; - int timeInfectedSymptoms = t_InfectedSymptoms[age]; + int timeInfectedSymptoms = t_InfectedSymptoms[age]; // if we select a layer with better immunity (layer > 0), we need to adjust the times and transition rates if (layer > 0) { @@ -142,7 +141,8 @@ IOResult compute_confirmed_cases_data( num_icu[age] += severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed; } - if (entry.date == offset_date_by_days(date, -timeInfectedSymptoms - t_InfectedSevere[age] - t_InfectedCritical[age])) { + if (entry.date == + offset_date_by_days(date, -timeInfectedSymptoms - t_InfectedSevere[age] - t_InfectedCritical[age])) { num_death[age] += entry.num_deaths; num_icu[age] -= severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed; @@ -160,14 +160,14 @@ IOResult compute_confirmed_cases_data( // but the algorithm is not robust enough to avoid large negative // values and there are tests that rely on it log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " - "exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + "exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } else if (value < 0) { log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " - "automatically corrected", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + "automatically corrected", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } }; @@ -185,10 +185,9 @@ IOResult compute_confirmed_cases_data( return success(); } -IOResult -set_confirmed_cases_data(Model& model, const std::vector& case_data, - const int region, Date date, const std::vector& scaling_factor_inf, - const std::vector>& immunity_population) +IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, + const std::vector>& immunity_population) { auto num_age_groups = (size_t)model.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors @@ -228,41 +227,40 @@ set_confirmed_cases_data(Model& model, const std::vector>()[(AgeGroup)group] + - immunity_population[2][group] * - model.parameters.template get>()[(AgeGroup)group]); + immunity_population[1][group] * + model.parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[(AgeGroup)group]); denom_I_NS[group] = 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model.parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model.parameters.template get>()[(AgeGroup)group]); + immunity_population[1][group] * + model.parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[(AgeGroup)group]); denom_I_Sy[group] = - 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model - .parameters.template get>()[(AgeGroup)group] + - immunity_population[2][group] * - model - .parameters.template get>()[(AgeGroup)group]); + 1 / + (immunity_population[0][group] + + immunity_population[1][group] * + model.parameters.template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters.template get>()[(AgeGroup)group]); denom_I_Sev_Cr[group] = 1 / (immunity_population[0][group] + - immunity_population[1][group] * - model.parameters.template get>()[( - AgeGroup)group] + - immunity_population[2][group] * - model.parameters.template get>()[( - AgeGroup)group]); + immunity_population[1][group] * + model.parameters + .template get>()[(AgeGroup)group] + + immunity_population[2][group] * + model.parameters + .template get>()[(AgeGroup)group]); } /*----------- Naive immunity -----------*/ for (size_t group = 0; group < num_age_groups; group++) { - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_Exposed.push_back( + static_cast(std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedNoSymptoms.push_back(static_cast( std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedSymptoms.push_back(static_cast( @@ -274,29 +272,25 @@ set_confirmed_cases_data(Model& model, const std::vector( std::round(model.parameters.template get>()[(AgeGroup)group]))); - mu_C_R.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_I_H.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_H_U.push_back( - model.parameters.template get>()[(AgeGroup)group]); + mu_C_R.push_back(model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back(model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back(model.parameters.template get>()[(AgeGroup)group]); - reduc_t_Infected.push_back( - model.parameters.template get>()[(AgeGroup)group]); + reduc_t_Infected.push_back(model.parameters.template get>()[(AgeGroup)group]); reduc_Exposed.push_back( model.parameters.template get>()[(AgeGroup)group]); reduc_InfectedSymptoms.push_back( model.parameters.template get>()[(AgeGroup)group]); reduc_icu_death.push_back( - model.parameters.template get>()[(AgeGroup)group]); + model.parameters + .template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, - reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, - scaling_factor_inf, 0)); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data( + case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, + num_death, num_timm1, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, + t_imm_interval_i, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, + mu_H_U, scaling_factor_inf, 0)); size_t num_groups = (size_t)model.parameters.get_num_groups(); for (size_t i = 0; i < num_groups; i++) { @@ -321,8 +315,8 @@ set_confirmed_cases_data(Model& model, const std::vector(a + b); }) == 0) { log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region); + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", date, + region); } /*----------- PARTIAL Immunity -----------*/ @@ -343,15 +337,15 @@ set_confirmed_cases_data(Model& model, const std::vector>()[(AgeGroup)group]); reduc_icu_death.push_back( - model.parameters.template get>()[(AgeGroup)group]); + model.parameters + .template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, - reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, - scaling_factor_inf, 1)); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data( + case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, + num_death, num_timm1, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, + t_imm_interval_i, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, + mu_H_U, scaling_factor_inf, 1)); for (size_t i = 0; i < num_groups; i++) { model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = immunity_population[1][i] * @@ -369,15 +363,14 @@ set_confirmed_cases_data(Model& model, const std::vector>()[(AgeGroup)i] * + model.parameters.template get>()[(AgeGroup)i] * denom_I_Sev_Cr[i] * num_InfectedSevere[i]; // Only set the number of ICU patients here, if the date is not available in the data. if (!is_divi_data_available(date)) { model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = immunity_population[1][i] * - model - .parameters.template get>()[(AgeGroup)i] * + model.parameters + .template get>()[(AgeGroup)i] * denom_I_Sev_Cr[i] * num_icu[i]; } // the += is necessary because we already set the previous vaccinated individuals @@ -414,15 +407,15 @@ set_confirmed_cases_data(Model& model, const std::vector>()[(AgeGroup)group]); reduc_icu_death.push_back( - model.parameters.template get>()[(AgeGroup)group]); + model.parameters + .template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm2, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, t_imm_interval_i, reduc_t_Infected, reduc_Exposed, - reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, mu_H_U, - scaling_factor_inf, 2)); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data( + case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, + num_death, num_timm2, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, + t_imm_interval_i, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, + mu_H_U, scaling_factor_inf, 2)); for (size_t i = 0; i < num_groups; i++) { model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = @@ -441,15 +434,14 @@ set_confirmed_cases_data(Model& model, const std::vector>()[(AgeGroup)i] * + model.parameters.template get>()[(AgeGroup)i] * denom_I_Sev_Cr[i] * num_InfectedSevere[i]; // Only set the number of ICU patients here, if the date is not available in the data. if (!is_divi_data_available(date)) { model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = immunity_population[2][i] * - model - .parameters.template get>()[(AgeGroup)i] * + model.parameters + .template get>()[(AgeGroup)i] * denom_I_Sev_Cr[i] * num_icu[i]; } @@ -489,8 +481,9 @@ IOResult set_confirmed_cases_data(const mio::VectorRange set_population_data(Model& model, const std::vector(a + b); - }) <= 0) - { + }) <= 0) { log_warning("No population data available for region " + std::to_string(region) + ". Population data has not been set."); return success(); @@ -516,40 +508,37 @@ IOResult set_population_data(Model& model, const std::vector( - {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = + std::max(0.0, SII - (model.populations[{i, InfectionState::ExposedImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + + model.populations[{i, InfectionState::DeadImprovedImmunity}] + + model.populations[{i, InfectionState::TemporaryImmuneImprovedImmunity}])); + + model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = + std::max(0.0, SPI - model.populations[{i, InfectionState::ExposedPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - + model.populations[{i, InfectionState::DeadPartialImmunity}] - + model.populations[{i, InfectionState::TemporaryImmunePartialImmunity}]); + + model.populations.template set_difference_from_group_total({i, InfectionState::SusceptibleNaive}, + num_population[size_t(i)]); } for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { for (auto j = Index(0); j < InfectionState::Count; ++j) { if (model.populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model.populations[{i, j}]); + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), size_t(j), + model.populations[{i, j}]); } } } @@ -560,12 +549,15 @@ IOResult set_population_data(Model& model, const std::vector set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::vector>& immunity_population) { - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion)); for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], model[region_idx].id, immunity_population)); + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, num_population[region_idx], + model[region_idx].id, immunity_population)); } return success(); } @@ -577,9 +569,9 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, auto num_groups = model.parameters.get_num_groups(); for (auto i = AgeGroup(0); i < num_groups; i++) { sum_mu_I_U += model.parameters.template get>()[i] * - model.parameters.template get>()[i]; + model.parameters.template get>()[i]; mu_I_U.push_back(model.parameters.template get>()[i] * - model.parameters.template get>()[i]); + model.parameters.template get>()[i]); } for (auto i = AgeGroup(0); i < num_groups; i++) { @@ -590,7 +582,7 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, return success(); } -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, ScalarType scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. @@ -601,8 +593,10 @@ IOResult set_divi_data(const mio::VectorRange>>& mo return success(); } - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { @@ -616,7 +610,7 @@ IOResult set_divi_data(const mio::VectorRange>>& mo IOResult read_input_data(const mio::VectorRange>>& model, Date date, const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, - int num_days, const std::vector>& immunity_population, + int num_days, const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) { @@ -627,7 +621,7 @@ IOResult read_input_data(const mio::VectorRange>>& // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, + BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, scaling_factor_inf, immunity_population)); BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, immunity_population)); return success(); @@ -635,10 +629,12 @@ IOResult read_input_data(const mio::VectorRange>>& #ifdef MEMILIO_HAS_HDF5 -IOResult export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, - const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames) +IOResult export_input_data_timeseries(const mio::VectorRange>> model, + const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, + const ScalarType scaling_factor_icu, const int num_days, + const std::vector>& immunity_population, + const mio::regions::de::EpidataFilenames& epidata_filenames) { const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); @@ -650,8 +646,8 @@ IOResult export_input_data_timeseries( auto offset_day = offset_date_by_days(date, t); // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, - num_days, immunity_population, epidata_filenames)); + BOOST_OUTCOME_TRY(read_input_data(model, offset_day, scaling_factor_inf, scaling_factor_icu, num_days, + immunity_population, epidata_filenames)); for (size_t r = 0; r < model.size(); r++) { extrapolated_data[r][t] = model[r].property.get_initial_values(); @@ -665,8 +661,10 @@ IOResult export_input_data_timeseries( } } - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); @@ -678,9 +676,10 @@ IOResult export_input_data_timeseries( } #else -IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const ScalarType, const int, - const std::vector>, const mio::regions::de::EpidataFilenames&) +IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, + const std::vector&, const std::vector&, const ScalarType, + const int, const std::vector>, + const mio::regions::de::EpidataFilenames&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); return success(); diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index 53b8ace419..be129c0685 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -63,12 +63,11 @@ IOResult compute_confirmed_cases_data( const std::vector& case_data, const int region, Date date, std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_imm, const std::vector& t_Exposed, - const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, - const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, - const std::vector& t_imm_interval_i, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, + std::vector& num_icu, std::vector& num_death, std::vector& num_imm, + const std::vector& t_Exposed, const std::vector& t_InfectedNoSymptoms, + const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, + const std::vector& t_InfectedCritical, const std::vector& t_imm_interval_i, + const std::vector& mu_C_R, const std::vector& mu_I_H, const std::vector& mu_H_U, const std::vector& reduc_t_Infected, const std::vector& reduc_Exposed, const std::vector& reduc_InfectedSymptoms, const std::vector& reduc_icu_death, const std::vector& scaling_factor_inf, const size_t layer); @@ -88,10 +87,9 @@ IOResult compute_confirmed_cases_data( * * @return An IOResult indicating success or failure. */ -IOResult -set_confirmed_cases_data(Model& model, const std::vector& case_data, - const int region, Date date, const std::vector& scaling_factor_inf, - const std::vector>& immunity_population); +IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, + const int region, Date date, const std::vector& scaling_factor_inf, + const std::vector>& immunity_population); /** * @brief Sets confirmed case data from a file into the given models. @@ -156,7 +154,7 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, * @param[in] date Date at which the data is read. * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. */ -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, ScalarType scaling_factor_icu); /** @@ -174,14 +172,12 @@ IOResult set_divi_data(const mio::VectorRange>>& mo * @return An IOResult indicating success or failure. */ template -IOResult set_vaccination_data(Model& model, const VaccinationDataEntry& vacc_data_entry, - Date date, int num_days, Date max_date, const int days_until_effective_n, +IOResult set_vaccination_data(Model& model, const VaccinationDataEntry& vacc_data_entry, Date date, + int num_days, Date max_date, const int days_until_effective_n, const int days_until_effective_pi, const int days_until_effective_ii) { - auto num_groups = model.parameters.get_num_groups(); - auto date_df = vacc_data_entry.date; - AgeGroup age = vacc_data_entry.age_group; + AgeGroup age = vacc_data_entry.age_group; // get daily vaccinations for each layer for (size_t d = 0; d < (size_t)num_days + 1; ++d) { @@ -240,8 +236,8 @@ IOResult set_vaccination_data(Model& model, const VaccinationDataEntry * @return An IOResult indicating success or failure. */ template -IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, - Date date, int num_days) +IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, Date date, + int num_days) { auto max_date_entry = std::max_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) { @@ -261,16 +257,17 @@ IOResult set_vaccination_data(Model& model, const std::vector>()[AgeGroup(0)]; - auto days_until_effective_pi = - (int)(double)model.parameters.template get>()[AgeGroup(0)]; - auto days_until_effective_ii = - (int)(double)model.parameters.template get>()[AgeGroup(0)]; + auto days_until_effective_n = static_cast( + static_cast(model.parameters.template get>()[AgeGroup(0)])); + auto days_until_effective_pi = static_cast( + static_cast(model.parameters.template get>()[AgeGroup(0)])); + auto days_until_effective_ii = static_cast( + static_cast(model.parameters.template get>()[AgeGroup(0)])); for (auto&& vacc_data_entry : vacc_data) { - BOOST_OUTCOME_TRY(set_vaccination_data(model, vacc_data_entry, date, num_days, max_date, - days_until_effective_n, days_until_effective_pi, days_until_effective_ii)); + BOOST_OUTCOME_TRY(set_vaccination_data(model, vacc_data_entry, date, num_days, max_date, + days_until_effective_n, days_until_effective_pi, + days_until_effective_ii)); } return success(); } @@ -321,8 +318,9 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod // Sort vacc_data into regions and ignore once with no region associated std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { - auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { - return m.id == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || + auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { + return m.id == 0 || + (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(m.id)) || (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(m.id)); }); @@ -333,9 +331,9 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod } for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vacc_data[region_idx], date, num_days)); + BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vvacc_data[region_idx], date, num_days)); } - + return success(); } @@ -358,7 +356,7 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod */ IOResult read_input_data(const mio::VectorRange>>& model, Date date, const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, - int num_days, const std::vector>& immunity_population, + int num_days, const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames); /** @@ -373,12 +371,14 @@ IOResult read_input_data(const mio::VectorRange>>& * * @return An IOResult indicating success or failure. */ -template -IOResult convert_input_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to, - Date date, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) +template +IOResult convert_input_data_type(const mio::VectorRange>>& model_from, + const mio::VectorRange>>& model_to, Date date, int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames) { assert(model_from.size() == model_to.size()); - assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()) + assert((size_t)model_from[0].property.parameters.get_num_groups() == + (size_t)model_to[0].property.parameters.get_num_groups()); // Todo: add conversion of ParameterSet and then re-use code from all model parameters io // For now call set_vacination_data with FP to set correct parameters BOOST_OUTCOME_TRY( @@ -387,7 +387,9 @@ IOResult convert_input_data_type(const mio::VectorRange // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_to[region_idx].property.populations.convert().convert>(); + model_to[region_idx].property.populations = model_to[region_idx] + .property.populations.template convert() + .template convert>(); } return success(); } @@ -412,15 +414,18 @@ IOResult convert_input_data_type(const mio::VectorRange export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, - const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames); +IOResult export_input_data_timeseries(const mio::VectorRange>> model, + const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, + const ScalarType scaling_factor_icu, const int num_days, + const std::vector>& immunity_population, + const mio::regions::de::EpidataFilenames& epidata_filenames); #else -IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const ScalarType, const int, - const std::vector>, const mio::regions::de::EpidataFilenames&); - +IOResult export_input_data_timeseries(const mio::VectorRange>>, const std::string&, Date, + const std::vector&, const std::vector&, const ScalarType, + const int, const std::vector>, + const mio::regions::de::EpidataFilenames&); + #endif //MEMILIO_HAS_HDF5 } // namespace osecirts diff --git a/cpp/models/ode_secirvvs/parameters_io.cpp b/cpp/models/ode_secirvvs/parameters_io.cpp index 1995e393ef..4795e65f05 100644 --- a/cpp/models/ode_secirvvs/parameters_io.cpp +++ b/cpp/models/ode_secirvvs/parameters_io.cpp @@ -30,17 +30,16 @@ namespace osecirvvs namespace details { -IOResult compute_confirmed_cases_data( - const std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, - const std::vector& t_InfectedNoSymptoms, - const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf) +IOResult +compute_confirmed_cases_data(const std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, + const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, + const std::vector& mu_C_R, const std::vector& mu_I_H, + const std::vector& mu_H_U, const std::vector& scaling_factor_inf) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -64,7 +63,7 @@ IOResult compute_confirmed_cases_data( } for (auto&& entry : case_data) { - + auto age = (size_t)entry.age_group; if (entry.date == offset_date_by_days(date, 0)) { num_InfectedSymptoms[age] += scaling_factor_inf[age] * entry.num_confirmed; @@ -100,9 +99,8 @@ IOResult compute_confirmed_cases_data( // and remove dark figure scaling factor num_rec[i] -= num_InfectedSymptoms[i] / scaling_factor_inf[i]; num_rec[i] -= num_InfectedSevere[i] / scaling_factor_inf[i]; - num_rec[i] -= - num_icu[i] / - scaling_factor_inf[i]; // TODO: this has to be adapted for scaling_factor_inf != 1 or != ***_icu + num_rec[i] -= num_icu[i] / + scaling_factor_inf[i]; // TODO: this has to be adapted for scaling_factor_inf != 1 or != ***_icu num_rec[i] -= num_death[i] / scaling_factor_inf[i]; auto try_fix_constraints = [region, i](ScalarType& value, ScalarType error, auto str) { if (value < error) { @@ -110,14 +108,14 @@ IOResult compute_confirmed_cases_data( // but the algorithm is not robust enough to avoid large negative // values and there are tests that rely on it log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " - "exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + "exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } else if (value < 0) { log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " - "automatically corrected", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + "automatically corrected", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } }; @@ -134,8 +132,9 @@ IOResult compute_confirmed_cases_data( return success(); } -IOResult> compute_confirmed_cases_data_fix_recovered( - const std::vector& case_data, const int region, Date date, ScalarType delay) +IOResult> +compute_confirmed_cases_data_fix_recovered(const std::vector& case_data, const int region, + Date date, ScalarType delay) { auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -174,14 +173,14 @@ IOResult> compute_confirmed_cases_data_fix_recovered( // but the algorithm is not robust enough to avoid large negative // values and there are tests that rely on it log_error("{:s} for age group {:s} is {:.4f} for region {:d}, " - "exceeds expected negative value.", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + "exceeds expected negative value.", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } else if (value < 0) { log_info("{:s} for age group {:s} is {:.4f} for region {:d}, " - "automatically corrected", - str, ConfirmedCasesDataEntry::age_group_names[i], value, region); + "automatically corrected", + str, ConfirmedCasesDataEntry::age_group_names[i], value, region); value = 0.0; } }; @@ -192,8 +191,8 @@ IOResult> compute_confirmed_cases_data_fix_recovered( } IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, - const int region, Date date, const std::vector& scaling_factor_inf, - bool set_death = false) + const int region, Date date, const std::vector& scaling_factor_inf, + bool set_death) { auto num_age_groups = (size_t)model.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors @@ -220,8 +219,8 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec /*----------- UNVACCINATED -----------*/ for (size_t group = 0; group < num_age_groups; group++) { - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_Exposed.push_back( + static_cast(std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedNoSymptoms.push_back(static_cast( std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedSymptoms.push_back(static_cast( @@ -231,31 +230,24 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec t_InfectedCritical.push_back(static_cast( std::round(model.parameters.template get>()[(AgeGroup)group]))); - mu_C_R.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_I_H.push_back( - model.parameters.template get>()[(AgeGroup)group]); - mu_H_U.push_back( - model.parameters.template get>()[(AgeGroup)group]); + mu_C_R.push_back(model.parameters.template get>()[(AgeGroup)group]); + mu_I_H.push_back(model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back(model.parameters.template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); - + BOOST_OUTCOME_TRY(compute_confirmed_cases_data( + case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, + num_death, num_rec, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, + mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); size_t num_groups = (size_t)model.parameters.get_num_groups(); for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = - num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::ExposedNaive}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] = num_InfectedNoSymptoms[i]; model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = - num_InfectedSymptoms[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = - num_InfectedSevere[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] = num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] = num_InfectedSevere[i]; // Only set the number of ICU patients here, if the date is not available in the data. if (!is_divi_data_available(date)) { model.populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] = num_icu[i]; @@ -277,8 +269,8 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec return evaluate_intermediate(a + b); }) == 0.0) { log_warning( - "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", - date, region); + "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.", date, + region); } /*----------- PARTIALLY VACCINATED -----------*/ @@ -302,12 +294,12 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec for (size_t group = 0; group < num_age_groups; group++) { ScalarType reduc_t = model.parameters.template get>()[(AgeGroup)group]; - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_Exposed.push_back( + static_cast(std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedNoSymptoms.push_back(static_cast(std::round( model.parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSymptoms.push_back(static_cast(std::round( - model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group] * reduc_t))); t_InfectedSevere.push_back(static_cast( std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedCritical.push_back(static_cast( @@ -318,44 +310,37 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec ScalarType inf_fac_part_immune = model.parameters.template get>()[(AgeGroup)group]; ScalarType hosp_fac_part_immune = - model - .parameters.template get>()[(AgeGroup)group]; + model.parameters + .template get>()[(AgeGroup)group]; ScalarType icu_fac_part_immune = - model - .parameters.template get>()[(AgeGroup)group]; - mu_C_R.push_back(( - 1 - inf_fac_part_immune / exp_fac_part_immune * - (1 - model - .parameters.template get>()[(AgeGroup)group]))); - mu_I_H.push_back( - hosp_fac_part_immune / inf_fac_part_immune * - model.parameters.template get>()[(AgeGroup)group]); + model.parameters + .template get>()[(AgeGroup)group]; + mu_C_R.push_back( + (1 - + inf_fac_part_immune / exp_fac_part_immune * + (1 - model.parameters.template get>()[(AgeGroup)group]))); + mu_I_H.push_back(hosp_fac_part_immune / inf_fac_part_immune * + model.parameters.template get>()[(AgeGroup)group]); // transfer from H to U, D unchanged. - mu_H_U.push_back( - icu_fac_part_immune / hosp_fac_part_immune * - model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back(icu_fac_part_immune / hosp_fac_part_immune * + model.parameters.template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); - + BOOST_OUTCOME_TRY(compute_confirmed_cases_data( + case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, + num_death, num_rec, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, + mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); for (size_t i = 0; i < num_groups; i++) { - model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = num_Exposed[i]; - model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = - num_InfectedNoSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = num_Exposed[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] = num_InfectedNoSymptoms[i]; model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = - num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] = num_InfectedSymptoms[i]; model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = - num_InfectedSevere[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] = num_InfectedSevere[i]; // Only set the number of ICU patients here, if the date is not available in the data. if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = - num_icu[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] = num_icu[i]; } } // } @@ -389,12 +374,12 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec for (size_t group = 0; group < num_age_groups; group++) { ScalarType reduc_t = model.parameters.template get>()[(AgeGroup)group]; - t_Exposed.push_back(static_cast( - std::round(model.parameters.template get>()[(AgeGroup)group]))); + t_Exposed.push_back( + static_cast(std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedNoSymptoms.push_back(static_cast(std::round( model.parameters.template get>()[(AgeGroup)group] * reduc_t))); - t_InfectedSymptoms.push_back(static_cast(std::round( - model.parameters.template get>()[(AgeGroup)group] * reduc_t))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(AgeGroup)group] * reduc_t))); t_InfectedSevere.push_back(static_cast( std::round(model.parameters.template get>()[(AgeGroup)group]))); t_InfectedCritical.push_back(static_cast( @@ -405,43 +390,38 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec ScalarType reduc_immune_inf = model.parameters.template get>()[(AgeGroup)group]; ScalarType reduc_immune_hosp = - model.parameters.template get>()[( - AgeGroup)group]; + model.parameters + .template get>()[(AgeGroup)group]; ScalarType reduc_immune_icu = - model.parameters.template get>()[( - AgeGroup)group]; - mu_C_R.push_back(( - 1 - reduc_immune_inf / reduc_immune_exp * - (1 - model - .parameters.template get>()[(AgeGroup)group]))); - mu_I_H.push_back( - reduc_immune_hosp / reduc_immune_inf * - model.parameters.template get>()[(AgeGroup)group]); + model.parameters + .template get>()[(AgeGroup)group]; + mu_C_R.push_back( + (1 - + reduc_immune_inf / reduc_immune_exp * + (1 - model.parameters.template get>()[(AgeGroup)group]))); + mu_I_H.push_back(reduc_immune_hosp / reduc_immune_inf * + model.parameters.template get>()[(AgeGroup)group]); // transfer from H to U, D unchanged. - mu_H_U.push_back( - reduc_immune_icu / reduc_immune_hosp * - model.parameters.template get>()[(AgeGroup)group]); + mu_H_U.push_back(reduc_immune_icu / reduc_immune_hosp * + model.parameters.template get>()[(AgeGroup)group]); } - BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, region, date, num_Exposed, num_InfectedNoSymptoms, - num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, - t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, - t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); + BOOST_OUTCOME_TRY(compute_confirmed_cases_data( + case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, + num_death, num_rec, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, + mu_C_R, mu_I_H, mu_H_U, scaling_factor_inf)); for (size_t i = 0; i < num_groups; i++) { model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = num_Exposed[i]; model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] = num_InfectedNoSymptoms[i]; model.populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = - num_InfectedSymptoms[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] = num_InfectedSymptoms[i]; model.populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0; - model.populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = - num_InfectedSevere[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] = num_InfectedSevere[i]; // Only set the number of ICU patients here, if the date is not available in the data. if (!is_divi_data_available(date)) { - model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = - num_icu[i]; + model.populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] = num_icu[i]; } } @@ -457,8 +437,8 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec return success(); } -IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, Date date, - const std::vector& scaling_factor_inf, bool set_death = false) +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf, bool set_death) { BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path)); @@ -475,7 +455,8 @@ IOResult set_confirmed_cases_data(const mio::VectorRange set_population_data(Model& model, const std::vector(a + b); - }) <= 0) - { + }) <= 0) { log_warning("No population data available for region " + std::to_string(region) + ". Population data has not been set."); return success(); } - + auto num_groups = model.parameters.get_num_groups(); for (auto i = AgeGroup(0); i < num_groups; i++) { - ScalarType S_v = std::min( - model.parameters.template get>()[{i, SimulationDay(0)}] + - num_rec[size_t(i)], - num_population[size_t(i)]); - ScalarType S_pv = std::max( - model.parameters.template get>()[{i, SimulationDay(0)}] - - model.parameters.template get>()[{i, SimulationDay(0)}], - 0.0); // use std::max with 0 + ScalarType S_v = + std::min(model.parameters.template get>()[{i, SimulationDay(0)}] + + num_rec[size_t(i)], + num_population[size_t(i)]); + ScalarType S_pv = + std::max(model.parameters.template get>()[{i, SimulationDay(0)}] - + model.parameters.template get>()[{i, SimulationDay(0)}], + 0.0); // use std::max with 0 ScalarType S; if (num_population[size_t(i)] - S_pv - S_v < 0.0) { - log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", - region, size_t(i)); + log_warning("Number of vaccinated persons greater than population in county {}, age group {}.", region, + size_t(i)); S = 0.0; S_v = num_population[size_t(i)] - S_pv; } @@ -517,22 +497,17 @@ IOResult set_population_data(Model& model, const std::vector>()[i] + - S_v * model.parameters.template get>()[i]); + S_v * model.parameters.template get>()[i]); ScalarType denom_C = 1 / (S + S_pv * model.parameters.template get>()[i] + - S_v * model.parameters.template get>()[i]); + S_v * model.parameters.template get>()[i]); ScalarType denom_I = - 1 / - (S + - S_pv * model.parameters.template get>()[i] + - S_v * model.parameters.template get>()[i]); + 1 / (S + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); ScalarType denom_HU = 1 / - (S + - S_pv * model - .parameters.template get>()[i] + - S_v * model - .parameters.template get>()[i]); + (S + S_pv * model.parameters.template get>()[i] + + S_v * model.parameters.template get>()[i]); model.populations[{i, InfectionState::ExposedNaive}] = S * model.populations[{i, InfectionState::ExposedNaive}] * denom_E; @@ -553,11 +528,9 @@ IOResult set_population_data(Model& model, const std::vector set_population_data(Model& model, const std::vector>()[i] * + S_pv * model.parameters.template get>()[i] * model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] * denom_HU; model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] = - S_v * - model - .parameters.template get>()[i] * + S_v * model.parameters.template get>()[i] * model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] * denom_HU; model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] = - S_pv * - model.parameters.template get>()[i] * + S_pv * model.parameters.template get>()[i] * model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] = - S_v * - model - .parameters.template get>()[i] * + S_v * model.parameters.template get>()[i] * model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; model.populations[{i, InfectionState::InfectedCriticalNaive}] = S * model.populations[{i, InfectionState::InfectedCriticalNaive}] * denom_HU; @@ -605,52 +572,51 @@ IOResult set_population_data(Model& model, const std::vector>()[{i, SimulationDay(0)}] + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] - (model.populations[{i, InfectionState::InfectedSymptomsNaive}] + - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + - model.populations[{i, InfectionState::InfectedSevereNaive}] + - model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] + - model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + - model.populations[{i, InfectionState::InfectedCriticalNaive}] + - model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + - model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + - model.populations[{i, InfectionState::DeadNaive}] + - model.populations[{i, InfectionState::DeadPartialImmunity}] + - model.populations[{i, InfectionState::DeadImprovedImmunity}]); - - model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::min( - S_v - model.populations[{i, InfectionState::ExposedImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - - model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - - model.populations[{i, InfectionState::DeadImprovedImmunity}], - std::max(0.0, ScalarType(model.populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); - - model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max( - 0.0, - S_pv - model.populations[{i, InfectionState::ExposedPartialImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - - model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - - model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - - model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - - model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - - model.populations[{i, InfectionState::DeadPartialImmunity}]); - - model.populations.template set_difference_from_group_total( - {i, InfectionState::SusceptibleNaive}, num_population[size_t(i)]); + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedSymptomsNaiveConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] + + model.populations[{i, InfectionState::InfectedSevereNaive}] + + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] + + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalNaive}] + + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] + + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] + + model.populations[{i, InfectionState::DeadNaive}] + + model.populations[{i, InfectionState::DeadPartialImmunity}] + + model.populations[{i, InfectionState::DeadImprovedImmunity}]); + + model.populations[{i, InfectionState::SusceptibleImprovedImmunity}] = + std::min(S_v - model.populations[{i, InfectionState::ExposedImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSevereImprovedImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] - + model.populations[{i, InfectionState::DeadImprovedImmunity}], + std::max(0.0, ScalarType(model.populations[{i, InfectionState::SusceptibleImprovedImmunity}]))); + + model.populations[{i, InfectionState::SusceptiblePartialImmunity}] = + std::max(0.0, S_pv - model.populations[{i, InfectionState::ExposedPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] - + model.populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] - + model.populations[{i, InfectionState::InfectedSeverePartialImmunity}] - + model.populations[{i, InfectionState::InfectedCriticalPartialImmunity}] - + model.populations[{i, InfectionState::DeadPartialImmunity}]); + + model.populations.template set_difference_from_group_total({i, InfectionState::SusceptibleNaive}, + num_population[size_t(i)]); } for (auto i = AgeGroup(0); i < AgeGroup(6); i++) { for (auto j = Index(0); j < InfectionState::Count; ++j) { if (model.populations[{i, j}] < 0) { - log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), - size_t(j), model.populations[{i, j}] / num_population[size_t(i)]); + log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), size_t(j), + model.populations[{i, j}] / num_population[size_t(i)]); } } } @@ -658,11 +624,13 @@ IOResult set_population_data(Model& model, const std::vector set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, - Date date) +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, + const std::string& path_rki, Date date) { - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(auto&& vnum_population, read_population_data(path, vregion)); BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path_rki)); @@ -679,8 +647,10 @@ IOResult set_population_data(const mio::VectorRange } for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(auto&& num_rec, compute_confirmed_cases_data_fix_recovered(vcase_data[region_idx], model[region_idx].id, date, 14.)); - BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, vnum_population[region_idx], model[region_idx].id, num_rec)); + BOOST_OUTCOME_TRY(auto&& num_rec, compute_confirmed_cases_data_fix_recovered(vcase_data[region_idx], + model[region_idx].id, date, 14.)); + BOOST_OUTCOME_TRY(set_population_data(model[region_idx].property, vnum_population[region_idx], + model[region_idx].id, num_rec)); } return success(); } @@ -692,9 +662,9 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, auto num_groups = model.parameters.get_num_groups(); for (auto i = AgeGroup(0); i < num_groups; i++) { sum_mu_I_U += model.parameters.template get>()[i] * - model.parameters.template get>()[i]; + model.parameters.template get>()[i]; mu_I_U.push_back(model.parameters.template get>()[i] * - model.parameters.template get>()[i]); + model.parameters.template get>()[i]); } for (auto i = AgeGroup(0); i < num_groups; i++) { @@ -705,7 +675,7 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, return success(); } -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, ScalarType scaling_factor_icu) { // DIVI dataset will no longer be updated from CW29 2024 on. @@ -716,8 +686,10 @@ IOResult set_divi_data(const mio::VectorRange>>& mo return success(); } - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date)); for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { @@ -739,22 +711,22 @@ IOResult read_input_data(const mio::VectorRange>>& // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType. // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available. - BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, - scaling_factor_icu)); + BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, scaling_factor_icu)); - BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, - date, scaling_factor_inf)); - BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, + BOOST_OUTCOME_TRY( + details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, scaling_factor_inf)); + BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, epidata_filenames.case_data_path, date)); return success(); } #ifdef MEMILIO_HAS_HDF5 -IOResult export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, - const mio::regions::de::EpidataFilenames& epidata_filenames) +IOResult export_input_data_timeseries(const mio::VectorRange>> model, + const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, + const ScalarType scaling_factor_icu, const int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames) { const auto num_age_groups = (size_t)model[0].property.parameters.get_num_groups(); assert(scaling_factor_inf.size() == num_age_groups); @@ -766,8 +738,8 @@ IOResult export_input_data_timeseries( auto offset_day = offset_date_by_days(date, t); // TODO: empty vaccination data path guard - BOOST_OUTCOME_TRY(read_input_data(model, date, scaling_factor_inf, scaling_factor_icu, - num_days, epidata_filenames)); + BOOST_OUTCOME_TRY( + read_input_data(model, offset_day, scaling_factor_inf, scaling_factor_icu, num_days, epidata_filenames)); for (size_t r = 0; r < model.size(); r++) { extrapolated_data[r][t] = model[r].property.get_initial_values(); @@ -780,8 +752,10 @@ IOResult export_input_data_timeseries( } } } - std::vector vregion; - std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { return m.id; }); + std::vector vregion; + std::transform(model.begin(), model.end(), std::back_inserter(vregion), [](const auto& m) { + return m.id; + }); BOOST_OUTCOME_TRY(save_result(extrapolated_data, vregion, static_cast(num_age_groups), path_join(results_dir, "Results_rki.h5"))); @@ -792,8 +766,9 @@ IOResult export_input_data_timeseries( return success(); } #else -IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const ScalarType, const int, +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, + Date, const std::vector&, const std::vector&, + const ScalarType, const int, const mio::regions::de::EpidataFilenames&) { mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data."); diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 4e296a39b3..b29eec9674 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -52,17 +52,16 @@ namespace details * @param[in] mu_* vector Probabilities to get from one compartement to another for each age group. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. */ -IOResult compute_confirmed_cases_data( - const std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, - const std::vector& t_InfectedNoSymptoms, - const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf); +IOResult +compute_confirmed_cases_data(const std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, + const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, + const std::vector& mu_C_R, const std::vector& mu_I_H, + const std::vector& mu_H_U, const std::vector& scaling_factor_inf); /** * @brief Reads confirmed cases data and translates data of day t0-delay to recovered compartment. @@ -72,8 +71,9 @@ IOResult compute_confirmed_cases_data( * @param[in] delay Number of days in the past that are used to set recovered compartment. * @return Vector for number of people in the compartment recovered. */ -IOResult> compute_confirmed_cases_data_fix_recovered( - const std::vector& case_data, const int region, Date date, ScalarType delay = 14.); +IOResult> +compute_confirmed_cases_data_fix_recovered(const std::vector& case_data, const int region, + Date date, ScalarType delay = 14.); /** * @brief Sets populations data from already read case data with multiple age groups into a Model. @@ -85,10 +85,9 @@ IOResult> compute_confirmed_cases_data_fix_recovered( * @param[in] set_death If true, set the number of deaths. */ IOResult set_confirmed_cases_data(Model& model, const std::vector& case_data, - const int region, Date date, const std::vector& scaling_factor_inf, + const int region, Date date, const std::vector& scaling_factor_inf, bool set_death = false); - /** * @brief Sets the infected populations for the given models based on confirmed cases data. * Reads the case data from a file and then calls a subfunction that sets the infected population @@ -99,8 +98,9 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. * @param set_death[in] If true, set the number of deaths. */ -IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, Date date, - const std::vector& scaling_factor_inf, bool set_death = false); +IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, + Date date, const std::vector& scaling_factor_inf, + bool set_death = false); /** * @brief Sets the population data for the given model based on the provided population distribution. @@ -119,8 +119,8 @@ IOResult set_population_data(Model& model, const std::vector set_population_data(const mio::VectorRange>>& model, const std::string& path, const std::string& path_rki, - Date date); +IOResult set_population_data(const mio::VectorRange>>& model, const std::string& path, + const std::string& path_rki, Date date); /** * @brief Sets ICU data into a Model, distributed across age groups. @@ -142,7 +142,7 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, * @param[in] date Date at which the data is read. * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. */ -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, ScalarType scaling_factor_icu); /** @@ -156,8 +156,8 @@ IOResult set_divi_data(const mio::VectorRange>>& mo * @return An IOResult indicating success or failure. */ template -IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, - Date date, int num_days) +IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, Date date, + int num_days) { auto max_date_entry = std::max_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -178,8 +178,6 @@ IOResult set_vaccination_data(Model& model, const std::vector FP -> int auto days_until_effective1 = static_cast( static_cast(model.parameters.template get>()[AgeGroup(0)])); @@ -190,7 +188,7 @@ IOResult set_vaccination_data(Model& model, const std::vector set_vaccination_data(Model& model, const std::vector() will eventually (in the simulation) // transfer the difference (between get() at d and d-1) of // N susceptible individuals to 'Susceptible Partially Vaccinated' state at day d; see secir_vaccinated.h - auto offset_first_date = - offset_date_by_days(date, (int)d - days_until_effective1 + vaccination_distance); + auto offset_first_date = offset_date_by_days(date, (int)d - days_until_effective1 + vaccination_distance); if (max_date >= offset_first_date) { // Option 1: considered offset_first_date is available in input data frame if (date_df == offset_first_date) { @@ -305,8 +302,9 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod // Sort vacc_data into regions and ignore once with no region associated std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { - auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { - return m.id == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || + auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { + return m.id == 0 || + (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(m.id)) || (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(m.id)); }); @@ -317,7 +315,7 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod } for (size_t region_idx = 0; region_idx < model.size(); ++region_idx) { - BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vacc_data[region_idx], date, num_days)); + BOOST_OUTCOME_TRY(set_vaccination_data(model[region_idx].property, vvacc_data[region_idx], date, num_days)); } return success(); @@ -355,12 +353,14 @@ IOResult read_input_data(const mio::VectorRange>>& * * @return An IOResult indicating success or failure. */ -template -IOResult convert_input_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to, - Date date, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) +template +IOResult convert_input_data_type(const mio::VectorRange>>& model_from, + const mio::VectorRange>>& model_to, Date date, int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames) { assert(model_from.size() == model_to.size()); - assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()) + assert((size_t)model_from[0].property.parameters.get_num_groups() == + (size_t)model_to[0].property.parameters.get_num_groups()); // Todo: add conversion of ParameterSet and then re-use code from all model parameters io // For now call set_vacination_data with FP to set correct parameters BOOST_OUTCOME_TRY( @@ -369,7 +369,9 @@ IOResult convert_input_data_type(const mio::VectorRange // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_to[region_idx].property.populations.convert().convert>(); + model_to[region_idx].property.populations = model_to[region_idx] + .property.populations.template convert() + .template convert>(); } return success(); } @@ -393,13 +395,15 @@ IOResult convert_input_data_type(const mio::VectorRange export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, const ScalarType scaling_factor_icu, const int num_days, - const mio::regions::de::EpidataFilenames& epidata_filenames); +IOResult export_input_data_timeseries(const mio::VectorRange>> model, + const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, + const ScalarType scaling_factor_icu, const int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames); #else -IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const ScalarType, const int, +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, + Date, const std::vector&, const std::vector&, + const ScalarType, const int, const mio::regions::de::EpidataFilenames&); #endif //MEMILIO_HAS_HDF5 From 0d2adcfb310847987b4c4092cc50f1ebf641a13d Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 24 Nov 2025 09:29:34 +0000 Subject: [PATCH 09/26] Bindings update --- .../2020_npis_sarscov2_wildtype_germany.py | 16 ++--- ...2021_vaccination_sarscov2_delta_germany.py | 16 ++--- .../simulation/bindings/models/osecir.cpp | 57 ++++++++++-------- .../simulation/bindings/models/osecirvvs.cpp | 60 ++++++++++--------- 4 files changed, 73 insertions(+), 76 deletions(-) diff --git a/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py b/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py index ec122bd9e8..00c3c2af99 100644 --- a/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py +++ b/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py @@ -507,7 +507,7 @@ def senior_awareness(t, min, max): dynamic_npis.base_value = 100000 dynamic_npis.set_threshold(200.0, local_npis) - # school holidays(holiday periods are set per node, see set_nodes) + # school holidays(holiday periods are set per node) contacts.school_holiday_damping = damping_helper( 0, 1.0, 1.0, lvl_holidays, typ_school, [loc_school]) contacts.dampings = dampings @@ -534,17 +534,11 @@ def get_graph(self, end_date): data_dir_Germany, "mobility", "commuter_mobility_2022.txt") pydata_dir = os.path.join(data_dir_Germany, "pydata") - path_population_data = os.path.join(pydata_dir, - "county_current_population.json") - - mio.osecir.set_nodes( + graph = mio.osecir.create_graph_german_county( model.parameters, - mio.Date(self.start_date.year, - self.start_date.month, self.start_date.day), - mio.Date(end_date.year, - end_date.month, end_date.day), pydata_dir, - path_population_data, True, graph, scaling_factor_infected, - scaling_factor_icu, tnt_capacity_factor, 0, False) + mio.Date(self.start_date.year,self.start_date.month, self.start_date.day), + mio.Date(end_date.year, end_date.month, end_date.day), + scaling_factor_infected, scaling_factor_icu, pydata_dir, tnt_capacity_factor) mio.osecir.set_edges( mobility_data_file, graph, len(Location)) diff --git a/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py b/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py index 8a8766d252..68f6d35afa 100644 --- a/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py +++ b/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py @@ -594,7 +594,7 @@ def senior_awareness(t, min, max): params.DynamicNPIsInfectedSymptoms = dynamic_npis - # school holidays (holiday periods are set per node, see set_nodes) + # school holidays (holiday periods are set per node) school_holiday_value = mio.UncertainValue(0.5 * (1.0 + 1.0)) school_holiday_value.set_distribution( mio.ParameterDistributionUniform(1.0, 1.0)) @@ -623,16 +623,10 @@ def get_graph(self, end_date): mobility_data_file = os.path.join( data_dir_Germany, "mobility", "commuter_mobility_2022.txt") pydata_dir = os.path.join(data_dir_Germany, "pydata") - - path_population_data = os.path.join(pydata_dir, - "county_current_population.json") - - osecirvvs.set_nodes( - model.parameters, - self.start_date, - end_date, pydata_dir, - path_population_data, True, graph, scaling_factor_infected, - scaling_factor_icu, tnt_capacity_factor, end_date - self.start_date, False) + + graph = mio.osecir.create_graph_german_county( + model.parameters, self.start_date, end_date, + scaling_factor_infected, scaling_factor_icu, pydata_dir, tnt_capacity_factor) osecirvvs.set_edges( mobility_data_file, graph, len(Location)) diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp index 273da48f2d..3d66c038b7 100644 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp @@ -251,26 +251,6 @@ PYBIND11_MODULE(_simulation_osecir, m) }, py::arg("model")); - // These functions are in general not model dependent, only with the current config - m.def( - "set_nodes", - [](const mio::osecir::Parameters& params, mio::Date start_date, mio::Date end_date, - const std::string& data_dir, const std::string& population_data_path, bool is_node_for_county, - mio::Graph, mio::MobilityParameters>& params_graph, - const std::vector& scaling_factor_inf, double scaling_factor_icu, double tnt_capacity_factor, - int num_days = 0, bool export_time_series = false) { - auto result = mio::set_nodes< - double, // FP - mio::osecir::TestAndTraceCapacity, mio::osecir::ContactPatterns, - mio::osecir::Model, mio::MobilityParameters, mio::osecir::Parameters, - decltype(mio::osecir::read_input_data_county>), decltype(mio::get_node_ids)>( - params, start_date, end_date, data_dir, population_data_path, is_node_for_county, params_graph, - mio::osecir::read_input_data_county>, mio::get_node_ids, scaling_factor_inf, - scaling_factor_icu, tnt_capacity_factor, num_days, export_time_series); - return pymio::check_and_throw(result); - }, - py::return_value_policy::move); - pymio::iterable_enum(m, "ContactLocation") .value("Home", ContactLocation::Home) .value("School", ContactLocation::School) @@ -304,15 +284,40 @@ PYBIND11_MODULE(_simulation_osecir, m) pymio::bind_write_graph>(m); pymio::bind_read_graph>(m); m.def( - "read_input_data_county", - [](std::vector>& model, mio::Date date, const std::vector& county, - const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& dir, - int num_days = 0, bool export_time_series = false) { - auto result = mio::osecir::read_input_data_county>( - model, date, county, scaling_factor_inf, scaling_factor_icu, dir, num_days, export_time_series); + "read_input_data_german_county", + [](mio::Graph, mio::MobilityParameters>& params_graph, mio::Date start_date, + const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path) { + + auto result = mio::osecir::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, + mio::regions::de::EpidataFilenames::county(pydata_path)); return pymio::check_and_throw(result); }, py::return_value_policy::move); + + m.def( + "create_graph_german_county", + [](const mio::osecir::Parameters& params, mio::Date start_date, mio::Date end_date, + const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path, + double tnt_capacity_factor) { + + auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); + + mio::Graph, mio::MobilityParameters> params_graph(node_ids, + mio::osecir::Model::Populations({params.get_num_groups(), mio::osecir::InfectionState::Count}), params); + pymio::check_and_throw(mio::osecir::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, + mio::regions::de::EpidataFilenames::county(pydata_path))); + + mio::set_test_and_trace_capacity, mio::osecir::TestAndTraceCapacity>(params_graph.nodes(), tnt_capacity_factor); + mio::set_german_holidays, mio::osecir::ContactPatterns>(params_graph.nodes(), start_date, end_date); + mio::set_uncertainty_on_population>(params_graph.nodes()); + + return params_graph; + }, + "Creates graph of germany with compartments for geographic units at a specified date from data files.", + py::arg("params"), py::arg("start_date"), py::arg("end_date"), py::arg("scaling_factor_inf"), + py::arg("scaling_factor_icu"), py::arg("pydata_path"), py::arg("tnt_capacity_factor"), + py::return_value_policy::move); + #endif // MEMILIO_HAS_JSONCPP m.def("interpolate_simulation_result", diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp index 8e1e922404..06f18f6095 100755 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp @@ -299,28 +299,6 @@ PYBIND11_MODULE(_simulation_osecirvvs, m) }, py::arg("model")); - // These functions are in general not secirvvs dependent, only with the current config - m.def( - "set_nodes", - [](const mio::osecirvvs::Parameters& params, mio::Date start_date, mio::Date end_date, - const std::string& data_dir, const std::string& population_data_path, bool is_node_for_county, - mio::Graph, mio::MobilityParameters>& params_graph, - const std::vector& scaling_factor_inf, double scaling_factor_icu, double tnt_capacity_factor, - int num_days = 0, bool export_time_series = false) { - auto result = - mio::set_nodes, mio::osecirvvs::ContactPatterns, - mio::osecirvvs::Model, mio::MobilityParameters, - mio::osecirvvs::Parameters, - decltype(mio::osecirvvs::read_input_data_county>), - decltype(mio::get_node_ids)>( - params, start_date, end_date, data_dir, population_data_path, is_node_for_county, params_graph, - mio::osecirvvs::read_input_data_county>, mio::get_node_ids, - scaling_factor_inf, scaling_factor_icu, tnt_capacity_factor, num_days, export_time_series); - return pymio::check_and_throw(result); - }, - py::return_value_policy::move); - m.def( "set_edges", [](const std::string& mobility_data_file, @@ -357,14 +335,40 @@ PYBIND11_MODULE(_simulation_osecirvvs, m) pymio::bind_write_graph>(m); pymio::bind_read_graph>(m); m.def( - "read_input_data_county", - [](std::vector>& model, mio::Date date, const std::vector& county, - const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& dir, - int num_days = 0, bool export_time_series = false) { - auto result = mio::osecirvvs::read_input_data_county>( - model, date, county, scaling_factor_inf, scaling_factor_icu, dir, num_days, export_time_series); + "read_input_data_german_county", + [](mio::Graph, mio::MobilityParameters>& params_graph, mio::Date start_date, + const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path) { + + auto result = mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, + mio::regions::de::EpidataFilenames::county(pydata_path)); return pymio::check_and_throw(result); }, + "Reads compartments for german counties at a specified date from data files." + py::arg("params_graph"), py::arg("start_date"), py::arg("scaling_factor_inf"), py::arg("scaling_factor_icu"), + py::arg("pydata_path"), py::return_value_policy::move); + + m.def( + "create_graph_german_county", + [](const mio::osecirvvs::Parameters& params, mio::Date start_date, mio::Date end_date, + const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path, + double tnt_capacity_factor) { + + auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); + + mio::Graph, mio::MobilityParameters> params_graph(node_ids, + mio::osecirvvs::Model::Populations({params.get_num_groups(), mio::osecirvvs::InfectionState::Count}), params); + pymio::check_and_throw(mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, + mio::regions::de::EpidataFilenames::county(pydata_path))); + + mio::set_test_and_trace_capacity, mio::osecirvvs::TestAndTraceCapacity>(params_graph.nodes(), tnt_capacity_factor); + mio::set_german_holidays, mio::osecirvvs::ContactPatterns>(params_graph.nodes(), start_date, end_date); + mio::set_uncertainty_on_population>(params_graph.nodes()); + + return params_graph; + }, + "Creates graph of germany with compartments for geographic units at a specified date from data files.", + py::arg("params"), py::arg("start_date"), py::arg("end_date"), py::arg("scaling_factor_inf"), + py::arg("scaling_factor_icu"), py::arg("pydata_path"), py::arg("tnt_capacity_factor"), py::return_value_policy::move); #endif // MEMILIO_HAS_JSONCPP From db7d684e0a5b97a6948b3c2ed929d996e41f00ed Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 24 Nov 2025 09:30:37 +0000 Subject: [PATCH 10/26] Update tests with big fixes --- cpp/memilio/mobility/graph.h | 4 +- cpp/models/ode_secirvvs/parameters_io.cpp | 7 +- cpp/models/ode_secirvvs/parameters_io.h | 6 +- ...ses.json => cases_all_county_age_ma7.json} | 0 ...ta.json => county_current_population.json} | 0 ...itical_cases.json => county_divi_ma7.json} | 0 ..._data.json => vacc_county_ageinf_ma7.json} | 0 .../data/Germany/pydata/confirmed_cases.json | 1 - .../data/Germany/pydata/critical_cases.json | 1 - .../data/Germany/pydata/population_data.json | 1 - .../data/Germany/pydata/vaccination_data.json | 4493 ----------------- cpp/tests/test_epi_data_io.cpp | 72 +- cpp/tests/test_graph.cpp | 56 +- cpp/tests/test_odesecir.cpp | 264 +- cpp/tests/test_odesecirts.cpp | 376 +- cpp/tests/test_odesecirvvs.cpp | 450 +- cpp/tests/test_regions.cpp | 40 +- cpp/tests/test_save_parameters.cpp | 265 +- 18 files changed, 572 insertions(+), 5464 deletions(-) rename cpp/tests/data/District/pydata/{confirmed_cases.json => cases_all_county_age_ma7.json} (100%) rename cpp/tests/data/District/pydata/{population_data.json => county_current_population.json} (100%) rename cpp/tests/data/District/pydata/{critical_cases.json => county_divi_ma7.json} (100%) rename cpp/tests/data/District/pydata/{vaccination_data.json => vacc_county_ageinf_ma7.json} (100%) delete mode 100644 cpp/tests/data/Germany/pydata/confirmed_cases.json delete mode 100644 cpp/tests/data/Germany/pydata/critical_cases.json delete mode 100644 cpp/tests/data/Germany/pydata/population_data.json delete mode 100644 cpp/tests/data/Germany/pydata/vaccination_data.json diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index 94b8697265..77985452de 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -153,9 +153,7 @@ class Graph using NodeProperty = NodePropertyT; using EdgeProperty = EdgePropertyT; - /** add note for same size of parameters - */ - Graph(const std::vector& node_ids, std::vector& node_properties) + Graph(const std::vector& node_ids, const std::vector& node_properties) { assert(node_ids.size() == node_properties.size()); diff --git a/cpp/models/ode_secirvvs/parameters_io.cpp b/cpp/models/ode_secirvvs/parameters_io.cpp index 4795e65f05..626f8f1dd2 100644 --- a/cpp/models/ode_secirvvs/parameters_io.cpp +++ b/cpp/models/ode_secirvvs/parameters_io.cpp @@ -703,7 +703,8 @@ IOResult set_divi_data(const mio::VectorRange>>& mo IOResult read_input_data(const mio::VectorRange>>& model, Date date, const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, - int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) + int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames, + bool set_death) { BOOST_OUTCOME_TRY( @@ -714,7 +715,7 @@ IOResult read_input_data(const mio::VectorRange>>& BOOST_OUTCOME_TRY(details::set_divi_data(model, epidata_filenames.divi_data_path, date, scaling_factor_icu)); BOOST_OUTCOME_TRY( - details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, scaling_factor_inf)); + details::set_confirmed_cases_data(model, epidata_filenames.case_data_path, date, scaling_factor_inf, set_death)); BOOST_OUTCOME_TRY(details::set_population_data(model, epidata_filenames.population_data_path, epidata_filenames.case_data_path, date)); return success(); @@ -739,7 +740,7 @@ IOResult export_input_data_timeseries(const mio::VectorRange set_confirmed_cases_data(Model& model, const std::vec * @param[in] path Path to the confirmed cases data file. * @param[in] date Date at which the data is read. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. - * @param set_death[in] If true, set the number of deaths. + * @param[in] set_death If true, set the number of deaths. */ IOResult set_confirmed_cases_data(const mio::VectorRange>>& model, const std::string& path, Date date, const std::vector& scaling_factor_inf, @@ -334,12 +334,14 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod * @param[in] scaling_factor_icu Scaling factor for ICU cases. * @param[in] num_days Number of days to simulate. * @param[in] epidata_filenames Object containing the input data file paths. + * @param[in] set_death If true, set the number of deaths. * * @return An IOResult indicating success or failure. */ IOResult read_input_data(const mio::VectorRange>>& model, Date date, const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, - int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames); + int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames, + bool set_death = false); /** * @brief Converts input data from one range of models to another with different type. diff --git a/cpp/tests/data/District/pydata/confirmed_cases.json b/cpp/tests/data/District/pydata/cases_all_county_age_ma7.json similarity index 100% rename from cpp/tests/data/District/pydata/confirmed_cases.json rename to cpp/tests/data/District/pydata/cases_all_county_age_ma7.json diff --git a/cpp/tests/data/District/pydata/population_data.json b/cpp/tests/data/District/pydata/county_current_population.json similarity index 100% rename from cpp/tests/data/District/pydata/population_data.json rename to cpp/tests/data/District/pydata/county_current_population.json diff --git a/cpp/tests/data/District/pydata/critical_cases.json b/cpp/tests/data/District/pydata/county_divi_ma7.json similarity index 100% rename from cpp/tests/data/District/pydata/critical_cases.json rename to cpp/tests/data/District/pydata/county_divi_ma7.json diff --git a/cpp/tests/data/District/pydata/vaccination_data.json b/cpp/tests/data/District/pydata/vacc_county_ageinf_ma7.json similarity index 100% rename from cpp/tests/data/District/pydata/vaccination_data.json rename to cpp/tests/data/District/pydata/vacc_county_ageinf_ma7.json diff --git a/cpp/tests/data/Germany/pydata/confirmed_cases.json b/cpp/tests/data/Germany/pydata/confirmed_cases.json deleted file mode 100644 index 603ac57cc4..0000000000 --- a/cpp/tests/data/Germany/pydata/confirmed_cases.json +++ /dev/null @@ -1 +0,0 @@ -[{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-01","Confirmed":6.1428571429,"Deaths":0.0,"Recovered":6.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-02","Confirmed":6.4285714286,"Deaths":0.0,"Recovered":6.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-03","Confirmed":6.7142857143,"Deaths":0.0,"Recovered":6.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-04","Confirmed":6.8571428571,"Deaths":0.0,"Recovered":6.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-05","Confirmed":7.0,"Deaths":0.0,"Recovered":7.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-06","Confirmed":7.0,"Deaths":0.0,"Recovered":7.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-07","Confirmed":7.0,"Deaths":0.0,"Recovered":7.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-08","Confirmed":7.0,"Deaths":0.0,"Recovered":7.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-09","Confirmed":7.0,"Deaths":0.0,"Recovered":7.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-10","Confirmed":7.0,"Deaths":0.0,"Recovered":7.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-11","Confirmed":7.0,"Deaths":0.0,"Recovered":7.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-12","Confirmed":7.1428571429,"Deaths":0.0,"Recovered":7.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-13","Confirmed":7.2857142857,"Deaths":0.0,"Recovered":7.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-14","Confirmed":7.4285714286,"Deaths":0.0,"Recovered":7.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-15","Confirmed":7.5714285714,"Deaths":0.0,"Recovered":7.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-16","Confirmed":7.7142857143,"Deaths":0.0,"Recovered":7.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-17","Confirmed":7.8571428571,"Deaths":0.0,"Recovered":7.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-18","Confirmed":8.0,"Deaths":0.0,"Recovered":8.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-19","Confirmed":8.2857142857,"Deaths":0.0,"Recovered":8.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-20","Confirmed":8.5714285714,"Deaths":0.0,"Recovered":8.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-21","Confirmed":9.1428571429,"Deaths":0.0,"Recovered":9.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-22","Confirmed":9.7142857143,"Deaths":0.0,"Recovered":9.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-23","Confirmed":10.4285714286,"Deaths":0.0,"Recovered":10.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-24","Confirmed":11.1428571429,"Deaths":0.0,"Recovered":11.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-25","Confirmed":11.8571428571,"Deaths":0.0,"Recovered":11.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-26","Confirmed":12.2857142857,"Deaths":0.0,"Recovered":12.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-27","Confirmed":12.7142857143,"Deaths":0.0,"Recovered":12.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-28","Confirmed":12.8571428571,"Deaths":0.0,"Recovered":12.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-29","Confirmed":13.0,"Deaths":0.0,"Recovered":13.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-30","Confirmed":13.0,"Deaths":0.0,"Recovered":13.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-10-31","Confirmed":13.0,"Deaths":0.0,"Recovered":13.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-01","Confirmed":13.0,"Deaths":0.0,"Recovered":13.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-02","Confirmed":13.1428571429,"Deaths":0.0,"Recovered":13.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-03","Confirmed":13.2857142857,"Deaths":0.0,"Recovered":13.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-04","Confirmed":13.4285714286,"Deaths":0.0,"Recovered":13.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-05","Confirmed":13.5714285714,"Deaths":0.0,"Recovered":13.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-06","Confirmed":13.7142857143,"Deaths":0.0,"Recovered":13.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-07","Confirmed":13.8571428571,"Deaths":0.0,"Recovered":13.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-08","Confirmed":14.0,"Deaths":0.0,"Recovered":14.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-09","Confirmed":14.0,"Deaths":0.0,"Recovered":14.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-10","Confirmed":14.1428571429,"Deaths":0.0,"Recovered":14.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-11","Confirmed":14.2857142857,"Deaths":0.0,"Recovered":14.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-12","Confirmed":14.4285714286,"Deaths":0.0,"Recovered":14.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-13","Confirmed":14.7142857143,"Deaths":0.0,"Recovered":14.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-14","Confirmed":15.0,"Deaths":0.0,"Recovered":15.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-15","Confirmed":15.2857142857,"Deaths":0.0,"Recovered":15.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-16","Confirmed":15.5714285714,"Deaths":0.0,"Recovered":15.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-17","Confirmed":15.7142857143,"Deaths":0.0,"Recovered":15.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-18","Confirmed":16.0,"Deaths":0.0,"Recovered":16.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-19","Confirmed":16.4285714286,"Deaths":0.0,"Recovered":16.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-20","Confirmed":17.0,"Deaths":0.0,"Recovered":17.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-21","Confirmed":17.7142857143,"Deaths":0.0,"Recovered":17.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-22","Confirmed":18.4285714286,"Deaths":0.0,"Recovered":18.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-23","Confirmed":19.5714285714,"Deaths":0.0,"Recovered":19.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-24","Confirmed":21.0,"Deaths":0.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-25","Confirmed":22.4285714286,"Deaths":0.0,"Recovered":22.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-26","Confirmed":23.8571428571,"Deaths":0.0,"Recovered":23.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-27","Confirmed":25.0,"Deaths":0.0,"Recovered":25.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-28","Confirmed":26.0,"Deaths":0.0,"Recovered":26.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-29","Confirmed":27.1428571429,"Deaths":0.0,"Recovered":27.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-11-30","Confirmed":27.8571428571,"Deaths":0.0,"Recovered":27.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-01","Confirmed":28.2857142857,"Deaths":0.0,"Recovered":28.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-02","Confirmed":28.7142857143,"Deaths":0.0,"Recovered":28.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-03","Confirmed":29.4285714286,"Deaths":0.0,"Recovered":29.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-04","Confirmed":30.1428571429,"Deaths":0.0,"Recovered":30.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-05","Confirmed":31.1428571429,"Deaths":0.0,"Recovered":31.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-06","Confirmed":32.0,"Deaths":0.0,"Recovered":32.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-07","Confirmed":32.8571428571,"Deaths":0.0,"Recovered":32.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-08","Confirmed":33.7142857143,"Deaths":0.0,"Recovered":33.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-09","Confirmed":34.5714285714,"Deaths":0.0,"Recovered":34.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-10","Confirmed":35.0,"Deaths":0.0,"Recovered":35.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-11","Confirmed":35.5714285714,"Deaths":0.0,"Recovered":35.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-12","Confirmed":36.1428571429,"Deaths":0.0,"Recovered":36.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-13","Confirmed":36.8571428571,"Deaths":0.0,"Recovered":36.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-14","Confirmed":38.0,"Deaths":0.0,"Recovered":38.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-15","Confirmed":39.2857142857,"Deaths":0.0,"Recovered":39.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-16","Confirmed":40.4285714286,"Deaths":0.0,"Recovered":40.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-17","Confirmed":41.7142857143,"Deaths":0.0,"Recovered":41.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-18","Confirmed":42.8571428571,"Deaths":0.0,"Recovered":42.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-19","Confirmed":43.8571428571,"Deaths":0.0,"Recovered":43.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-20","Confirmed":44.8571428571,"Deaths":0.0,"Recovered":44.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-21","Confirmed":45.4285714286,"Deaths":0.0,"Recovered":45.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-22","Confirmed":45.8571428571,"Deaths":0.0,"Recovered":45.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-23","Confirmed":46.4285714286,"Deaths":0.0,"Recovered":46.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-24","Confirmed":47.0,"Deaths":0.0,"Recovered":47.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-25","Confirmed":47.8571428571,"Deaths":0.0,"Recovered":47.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-26","Confirmed":48.5714285714,"Deaths":0.0,"Recovered":48.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-27","Confirmed":49.1428571429,"Deaths":0.0,"Recovered":49.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-28","Confirmed":49.7142857143,"Deaths":0.0,"Recovered":49.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-29","Confirmed":50.2857142857,"Deaths":0.0,"Recovered":50.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-30","Confirmed":50.7142857143,"Deaths":0.0,"Recovered":50.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A00-A04","Date":"2020-12-31","Confirmed":51.0,"Deaths":0.0,"Recovered":51.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-01","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-02","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-03","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-04","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-05","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-06","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-07","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-08","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-09","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-10","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-11","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-12","Confirmed":30.0,"Deaths":0.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-13","Confirmed":30.1428571429,"Deaths":0.0,"Recovered":30.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-14","Confirmed":30.4285714286,"Deaths":0.0,"Recovered":30.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-15","Confirmed":30.7142857143,"Deaths":0.0,"Recovered":30.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-16","Confirmed":31.0,"Deaths":0.0,"Recovered":31.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-17","Confirmed":31.2857142857,"Deaths":0.0,"Recovered":31.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-18","Confirmed":31.8571428571,"Deaths":0.0,"Recovered":31.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-19","Confirmed":32.4285714286,"Deaths":0.0,"Recovered":32.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-20","Confirmed":32.8571428571,"Deaths":0.0,"Recovered":32.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-21","Confirmed":33.4285714286,"Deaths":0.0,"Recovered":33.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-22","Confirmed":34.4285714286,"Deaths":0.0,"Recovered":34.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-23","Confirmed":35.4285714286,"Deaths":0.0,"Recovered":35.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-24","Confirmed":36.5714285714,"Deaths":0.0,"Recovered":36.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-25","Confirmed":37.5714285714,"Deaths":0.0,"Recovered":37.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-26","Confirmed":38.5714285714,"Deaths":0.0,"Recovered":38.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-27","Confirmed":39.7142857143,"Deaths":0.0,"Recovered":39.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-28","Confirmed":40.8571428571,"Deaths":0.0,"Recovered":40.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-29","Confirmed":41.8571428571,"Deaths":0.0,"Recovered":41.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-30","Confirmed":43.0,"Deaths":0.0,"Recovered":43.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-10-31","Confirmed":44.4285714286,"Deaths":0.0,"Recovered":44.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-01","Confirmed":45.7142857143,"Deaths":0.0,"Recovered":45.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-02","Confirmed":47.2857142857,"Deaths":0.0,"Recovered":47.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-03","Confirmed":48.7142857143,"Deaths":0.0,"Recovered":48.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-04","Confirmed":49.8571428571,"Deaths":0.0,"Recovered":49.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-05","Confirmed":50.7142857143,"Deaths":0.0,"Recovered":50.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-06","Confirmed":52.0,"Deaths":0.0,"Recovered":52.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-07","Confirmed":53.0,"Deaths":0.0,"Recovered":53.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-08","Confirmed":54.2857142857,"Deaths":0.0,"Recovered":54.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-09","Confirmed":55.4285714286,"Deaths":0.0,"Recovered":55.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-10","Confirmed":57.0,"Deaths":0.0,"Recovered":57.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-11","Confirmed":58.5714285714,"Deaths":0.0,"Recovered":58.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-12","Confirmed":60.2857142857,"Deaths":0.0,"Recovered":60.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-13","Confirmed":61.5714285714,"Deaths":0.0,"Recovered":61.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-14","Confirmed":63.0,"Deaths":0.0,"Recovered":63.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-15","Confirmed":64.2857142857,"Deaths":0.0,"Recovered":64.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-16","Confirmed":65.7142857143,"Deaths":0.0,"Recovered":65.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-17","Confirmed":67.1428571429,"Deaths":0.0,"Recovered":67.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-18","Confirmed":68.5714285714,"Deaths":0.0,"Recovered":68.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-19","Confirmed":70.0,"Deaths":0.0,"Recovered":70.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-20","Confirmed":71.2857142857,"Deaths":0.0,"Recovered":71.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-21","Confirmed":72.4285714286,"Deaths":0.0,"Recovered":72.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-22","Confirmed":73.8571428571,"Deaths":0.0,"Recovered":73.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-23","Confirmed":75.0,"Deaths":0.0,"Recovered":75.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-24","Confirmed":75.8571428571,"Deaths":0.0,"Recovered":75.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-25","Confirmed":77.0,"Deaths":0.0,"Recovered":77.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-26","Confirmed":78.5714285714,"Deaths":0.0,"Recovered":78.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-27","Confirmed":80.2857142857,"Deaths":0.0,"Recovered":80.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-28","Confirmed":82.0,"Deaths":0.0,"Recovered":82.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-29","Confirmed":83.7142857143,"Deaths":0.0,"Recovered":83.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-11-30","Confirmed":85.8571428571,"Deaths":0.0,"Recovered":85.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-01","Confirmed":88.0,"Deaths":0.0,"Recovered":88.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-02","Confirmed":90.1428571429,"Deaths":0.0,"Recovered":90.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-03","Confirmed":91.8571428571,"Deaths":0.0,"Recovered":91.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-04","Confirmed":93.8571428571,"Deaths":0.0,"Recovered":93.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-05","Confirmed":95.8571428571,"Deaths":0.0,"Recovered":95.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-06","Confirmed":97.8571428571,"Deaths":0.0,"Recovered":97.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-07","Confirmed":99.7142857143,"Deaths":0.0,"Recovered":99.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-08","Confirmed":102.1428571429,"Deaths":0.0,"Recovered":102.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-09","Confirmed":105.2857142857,"Deaths":0.0,"Recovered":105.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-10","Confirmed":108.5714285714,"Deaths":0.0,"Recovered":108.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-11","Confirmed":112.1428571429,"Deaths":0.0,"Recovered":112.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-12","Confirmed":116.0,"Deaths":0.0,"Recovered":116.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-13","Confirmed":119.7142857143,"Deaths":0.0,"Recovered":119.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-14","Confirmed":123.7142857143,"Deaths":0.0,"Recovered":123.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-15","Confirmed":127.4285714286,"Deaths":0.0,"Recovered":127.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-16","Confirmed":130.7142857143,"Deaths":0.0,"Recovered":130.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-17","Confirmed":133.8571428571,"Deaths":0.0,"Recovered":133.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-18","Confirmed":136.7142857143,"Deaths":0.0,"Recovered":136.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-19","Confirmed":139.4285714286,"Deaths":0.0,"Recovered":139.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-20","Confirmed":142.1428571429,"Deaths":0.0,"Recovered":142.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-21","Confirmed":144.8571428571,"Deaths":0.0,"Recovered":144.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-22","Confirmed":147.4285714286,"Deaths":0.0,"Recovered":147.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-23","Confirmed":149.4285714286,"Deaths":0.0,"Recovered":149.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-24","Confirmed":151.4285714286,"Deaths":0.0,"Recovered":151.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-25","Confirmed":153.1428571429,"Deaths":0.0,"Recovered":153.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-26","Confirmed":154.5714285714,"Deaths":0.0,"Recovered":154.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-27","Confirmed":155.8571428571,"Deaths":0.0,"Recovered":155.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-28","Confirmed":156.5714285714,"Deaths":0.0,"Recovered":156.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-29","Confirmed":157.1428571429,"Deaths":0.0,"Recovered":157.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-30","Confirmed":157.8571428571,"Deaths":0.0,"Recovered":157.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A05-A14","Date":"2020-12-31","Confirmed":158.8571428571,"Deaths":0.0,"Recovered":158.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-01","Confirmed":157.4285714286,"Deaths":0.0,"Recovered":157.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-02","Confirmed":158.8571428571,"Deaths":0.0,"Recovered":158.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-03","Confirmed":160.0,"Deaths":0.0,"Recovered":160.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-04","Confirmed":161.1428571429,"Deaths":0.0,"Recovered":161.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-05","Confirmed":162.0,"Deaths":0.0,"Recovered":162.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-06","Confirmed":162.8571428571,"Deaths":0.0,"Recovered":162.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-07","Confirmed":164.0,"Deaths":0.0,"Recovered":164.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-08","Confirmed":165.2857142857,"Deaths":0.0,"Recovered":165.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-09","Confirmed":166.7142857143,"Deaths":0.0,"Recovered":166.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-10","Confirmed":168.2857142857,"Deaths":0.0,"Recovered":168.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-11","Confirmed":170.0,"Deaths":0.0,"Recovered":170.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-12","Confirmed":171.7142857143,"Deaths":0.0,"Recovered":171.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-13","Confirmed":173.1428571429,"Deaths":0.0,"Recovered":173.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-14","Confirmed":174.8571428571,"Deaths":0.0,"Recovered":174.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-15","Confirmed":177.0,"Deaths":0.0,"Recovered":177.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-16","Confirmed":179.2857142857,"Deaths":0.0,"Recovered":179.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-17","Confirmed":181.7142857143,"Deaths":0.0,"Recovered":181.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-18","Confirmed":184.4285714286,"Deaths":0.0,"Recovered":184.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-19","Confirmed":187.4285714286,"Deaths":0.0,"Recovered":187.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-20","Confirmed":190.5714285714,"Deaths":0.0,"Recovered":190.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-21","Confirmed":194.1428571429,"Deaths":0.0,"Recovered":194.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-22","Confirmed":197.2857142857,"Deaths":0.0,"Recovered":197.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-23","Confirmed":200.7142857143,"Deaths":0.0,"Recovered":200.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-24","Confirmed":204.7142857143,"Deaths":0.0,"Recovered":204.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-25","Confirmed":208.8571428571,"Deaths":0.0,"Recovered":208.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-26","Confirmed":213.8571428571,"Deaths":0.0,"Recovered":213.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-27","Confirmed":219.0,"Deaths":0.0,"Recovered":219.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-28","Confirmed":223.5714285714,"Deaths":0.0,"Recovered":223.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-29","Confirmed":228.8571428571,"Deaths":0.0,"Recovered":228.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-30","Confirmed":234.5714285714,"Deaths":0.0,"Recovered":234.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-10-31","Confirmed":240.4285714286,"Deaths":0.0,"Recovered":240.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-01","Confirmed":246.2857142857,"Deaths":0.0,"Recovered":246.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-02","Confirmed":252.8571428571,"Deaths":0.0,"Recovered":252.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-03","Confirmed":260.5714285714,"Deaths":0.0,"Recovered":260.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-04","Confirmed":269.1428571429,"Deaths":0.0,"Recovered":269.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-05","Confirmed":277.5714285714,"Deaths":0.0,"Recovered":277.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-06","Confirmed":285.8571428571,"Deaths":0.0,"Recovered":285.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-07","Confirmed":293.4285714286,"Deaths":0.0,"Recovered":293.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-08","Confirmed":301.4285714286,"Deaths":0.0,"Recovered":301.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-09","Confirmed":308.2857142857,"Deaths":0.0,"Recovered":308.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-10","Confirmed":314.7142857143,"Deaths":0.0,"Recovered":314.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-11","Confirmed":321.5714285714,"Deaths":0.0,"Recovered":321.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-12","Confirmed":329.5714285714,"Deaths":0.0,"Recovered":329.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-13","Confirmed":338.5714285714,"Deaths":0.0,"Recovered":338.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-14","Confirmed":348.8571428571,"Deaths":0.0,"Recovered":348.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-15","Confirmed":359.2857142857,"Deaths":0.0,"Recovered":359.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-16","Confirmed":369.8571428571,"Deaths":0.0,"Recovered":369.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-17","Confirmed":381.8571428571,"Deaths":0.0,"Recovered":381.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-18","Confirmed":393.4285714286,"Deaths":0.0,"Recovered":393.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-19","Confirmed":404.4285714286,"Deaths":0.0,"Recovered":404.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-20","Confirmed":415.4285714286,"Deaths":0.0,"Recovered":415.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-21","Confirmed":426.5714285714,"Deaths":0.0,"Recovered":426.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-22","Confirmed":437.1428571429,"Deaths":0.0,"Recovered":437.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-23","Confirmed":448.4285714286,"Deaths":0.0,"Recovered":448.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-24","Confirmed":458.7142857143,"Deaths":0.0,"Recovered":458.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-25","Confirmed":469.2857142857,"Deaths":0.0,"Recovered":469.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-26","Confirmed":479.2857142857,"Deaths":0.0,"Recovered":479.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-27","Confirmed":488.5714285714,"Deaths":0.0,"Recovered":488.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-28","Confirmed":497.0,"Deaths":0.0,"Recovered":497.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-29","Confirmed":505.8571428571,"Deaths":0.0,"Recovered":505.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-11-30","Confirmed":514.7142857143,"Deaths":0.0,"Recovered":514.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-01","Confirmed":523.8571428571,"Deaths":0.0,"Recovered":523.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-02","Confirmed":533.2857142857,"Deaths":0.0,"Recovered":533.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-03","Confirmed":543.5714285714,"Deaths":0.0,"Recovered":543.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-04","Confirmed":555.2857142857,"Deaths":0.0,"Recovered":555.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-05","Confirmed":568.4285714286,"Deaths":0.0,"Recovered":568.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-06","Confirmed":581.7142857143,"Deaths":0.0,"Recovered":581.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-07","Confirmed":595.7142857143,"Deaths":0.0,"Recovered":595.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-08","Confirmed":610.0,"Deaths":0.0,"Recovered":610.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-09","Confirmed":624.8571428571,"Deaths":0.0,"Recovered":624.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-10","Confirmed":640.1428571429,"Deaths":0.0,"Recovered":640.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-11","Confirmed":655.5714285714,"Deaths":0.0,"Recovered":655.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-12","Confirmed":670.1428571429,"Deaths":0.0,"Recovered":670.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-13","Confirmed":686.0,"Deaths":0.0,"Recovered":686.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-14","Confirmed":701.7142857143,"Deaths":0.0,"Recovered":701.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-15","Confirmed":717.1428571429,"Deaths":0.0,"Recovered":717.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-16","Confirmed":732.0,"Deaths":0.0,"Recovered":732.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-17","Confirmed":746.7142857143,"Deaths":0.0,"Recovered":746.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-18","Confirmed":761.1428571429,"Deaths":0.0,"Recovered":761.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-19","Confirmed":774.5714285714,"Deaths":0.0,"Recovered":774.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-20","Confirmed":786.4285714286,"Deaths":0.0,"Recovered":786.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-21","Confirmed":797.4285714286,"Deaths":0.0,"Recovered":797.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-22","Confirmed":809.0,"Deaths":0.0,"Recovered":809.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-23","Confirmed":821.0,"Deaths":0.0,"Recovered":821.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-24","Confirmed":832.2857142857,"Deaths":0.0,"Recovered":832.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-25","Confirmed":842.1428571429,"Deaths":0.0,"Recovered":842.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-26","Confirmed":851.8571428571,"Deaths":0.0,"Recovered":851.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-27","Confirmed":862.1428571429,"Deaths":0.0,"Recovered":862.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-28","Confirmed":872.5714285714,"Deaths":0.0,"Recovered":872.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-29","Confirmed":881.2857142857,"Deaths":0.0,"Recovered":881.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-30","Confirmed":889.0,"Deaths":0.0,"Recovered":889.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A15-A34","Date":"2020-12-31","Confirmed":896.0,"Deaths":0.0,"Recovered":896.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-01","Confirmed":168.1428571429,"Deaths":0.0,"Recovered":168.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-02","Confirmed":168.5714285714,"Deaths":0.0,"Recovered":168.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-03","Confirmed":169.0,"Deaths":0.0,"Recovered":169.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-04","Confirmed":169.2857142857,"Deaths":0.0,"Recovered":169.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-05","Confirmed":169.5714285714,"Deaths":0.0,"Recovered":169.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-06","Confirmed":169.7142857143,"Deaths":0.0,"Recovered":169.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-07","Confirmed":170.1428571429,"Deaths":0.0,"Recovered":170.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-08","Confirmed":170.7142857143,"Deaths":0.0,"Recovered":170.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-09","Confirmed":171.7142857143,"Deaths":0.0,"Recovered":171.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-10","Confirmed":172.8571428571,"Deaths":0.0,"Recovered":172.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-11","Confirmed":174.0,"Deaths":0.0,"Recovered":174.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-12","Confirmed":175.2857142857,"Deaths":0.0,"Recovered":175.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-13","Confirmed":176.7142857143,"Deaths":0.0,"Recovered":176.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-14","Confirmed":178.2857142857,"Deaths":0.0,"Recovered":178.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-15","Confirmed":180.1428571429,"Deaths":0.0,"Recovered":180.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-16","Confirmed":181.8571428571,"Deaths":0.0,"Recovered":181.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-17","Confirmed":183.5714285714,"Deaths":0.0,"Recovered":183.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-18","Confirmed":186.1428571429,"Deaths":0.0,"Recovered":186.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-19","Confirmed":189.0,"Deaths":0.0,"Recovered":189.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-20","Confirmed":192.1428571429,"Deaths":0.0,"Recovered":192.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-21","Confirmed":196.0,"Deaths":0.0,"Recovered":196.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-22","Confirmed":200.1428571429,"Deaths":0.0,"Recovered":200.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-23","Confirmed":204.4285714286,"Deaths":0.0,"Recovered":204.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-24","Confirmed":209.2857142857,"Deaths":0.0,"Recovered":209.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-25","Confirmed":214.1428571429,"Deaths":0.0,"Recovered":214.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-26","Confirmed":220.0,"Deaths":0.0,"Recovered":220.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-27","Confirmed":226.4285714286,"Deaths":0.0,"Recovered":226.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-28","Confirmed":232.1428571429,"Deaths":0.0,"Recovered":232.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-29","Confirmed":238.4285714286,"Deaths":0.0,"Recovered":238.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-30","Confirmed":244.4285714286,"Deaths":0.0,"Recovered":244.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-10-31","Confirmed":250.5714285714,"Deaths":0.0,"Recovered":250.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-01","Confirmed":256.8571428571,"Deaths":0.0,"Recovered":256.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-02","Confirmed":262.8571428571,"Deaths":0.0,"Recovered":262.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-03","Confirmed":268.1428571429,"Deaths":0.0,"Recovered":268.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-04","Confirmed":273.5714285714,"Deaths":0.0,"Recovered":273.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-05","Confirmed":278.8571428571,"Deaths":0.0,"Recovered":278.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-06","Confirmed":284.7142857143,"Deaths":0.0,"Recovered":284.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-07","Confirmed":290.2857142857,"Deaths":0.0,"Recovered":290.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-08","Confirmed":295.5714285714,"Deaths":0.0,"Recovered":295.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-09","Confirmed":301.0,"Deaths":0.0,"Recovered":301.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-10","Confirmed":307.7142857143,"Deaths":0.0,"Recovered":307.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-11","Confirmed":314.8571428571,"Deaths":0.0,"Recovered":314.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-12","Confirmed":321.1428571429,"Deaths":0.0,"Recovered":321.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-13","Confirmed":327.7142857143,"Deaths":0.0,"Recovered":327.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-14","Confirmed":334.2857142857,"Deaths":0.0,"Recovered":334.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-15","Confirmed":341.2857142857,"Deaths":0.0,"Recovered":341.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-16","Confirmed":347.8571428571,"Deaths":0.0,"Recovered":347.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-17","Confirmed":354.0,"Deaths":0.0,"Recovered":354.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-18","Confirmed":361.0,"Deaths":0.0,"Recovered":361.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-19","Confirmed":368.7142857143,"Deaths":0.0,"Recovered":368.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-20","Confirmed":376.4285714286,"Deaths":0.0,"Recovered":376.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-21","Confirmed":384.4285714286,"Deaths":0.0,"Recovered":384.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-22","Confirmed":392.2857142857,"Deaths":0.0,"Recovered":392.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-23","Confirmed":400.8571428571,"Deaths":0.0,"Recovered":400.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-24","Confirmed":409.1428571429,"Deaths":0.0,"Recovered":409.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-25","Confirmed":417.1428571429,"Deaths":0.0,"Recovered":417.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-26","Confirmed":425.1428571429,"Deaths":0.0,"Recovered":425.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-27","Confirmed":433.1428571429,"Deaths":0.0,"Recovered":433.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-28","Confirmed":441.2857142857,"Deaths":0.0,"Recovered":441.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-29","Confirmed":450.1428571429,"Deaths":0.0,"Recovered":450.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-11-30","Confirmed":459.1428571429,"Deaths":0.0,"Recovered":459.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-01","Confirmed":468.5714285714,"Deaths":0.0,"Recovered":468.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-02","Confirmed":477.8571428571,"Deaths":0.0,"Recovered":477.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-03","Confirmed":487.7142857143,"Deaths":0.0,"Recovered":487.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-04","Confirmed":498.8571428571,"Deaths":0.0,"Recovered":498.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-05","Confirmed":511.5714285714,"Deaths":0.0,"Recovered":511.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-06","Confirmed":523.7142857143,"Deaths":0.0,"Recovered":523.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-07","Confirmed":535.7142857143,"Deaths":0.0,"Recovered":535.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-08","Confirmed":548.2857142857,"Deaths":0.0,"Recovered":548.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-09","Confirmed":560.4285714286,"Deaths":0.0,"Recovered":560.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-10","Confirmed":573.4285714286,"Deaths":0.0,"Recovered":573.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-11","Confirmed":585.8571428571,"Deaths":0.0,"Recovered":585.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-12","Confirmed":599.1428571429,"Deaths":0.0,"Recovered":599.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-13","Confirmed":613.2857142857,"Deaths":0.0,"Recovered":613.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-14","Confirmed":628.0,"Deaths":0.0,"Recovered":628.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-15","Confirmed":642.2857142857,"Deaths":0.0,"Recovered":642.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-16","Confirmed":658.1428571429,"Deaths":0.0,"Recovered":658.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-17","Confirmed":672.8571428571,"Deaths":0.0,"Recovered":672.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-18","Confirmed":687.1428571429,"Deaths":0.0,"Recovered":687.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-19","Confirmed":700.0,"Deaths":0.0,"Recovered":700.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-20","Confirmed":712.2857142857,"Deaths":0.0,"Recovered":712.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-21","Confirmed":723.7142857143,"Deaths":0.0,"Recovered":723.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-22","Confirmed":735.2857142857,"Deaths":0.0,"Recovered":735.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-23","Confirmed":745.2857142857,"Deaths":0.0,"Recovered":745.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-24","Confirmed":755.0,"Deaths":0.0,"Recovered":755.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-25","Confirmed":764.4285714286,"Deaths":0.0,"Recovered":764.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-26","Confirmed":772.8571428571,"Deaths":0.0,"Recovered":772.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-27","Confirmed":781.0,"Deaths":0.0,"Recovered":781.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-28","Confirmed":789.7142857143,"Deaths":0.1428571429,"Recovered":789.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-29","Confirmed":798.2857142857,"Deaths":0.2857142857,"Recovered":798.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-30","Confirmed":807.0,"Deaths":0.4285714286,"Recovered":806.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A35-A59","Date":"2020-12-31","Confirmed":815.4285714286,"Deaths":0.5714285714,"Recovered":814.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-01","Confirmed":83.8571428571,"Deaths":7.0,"Recovered":76.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-02","Confirmed":84.1428571429,"Deaths":7.0,"Recovered":77.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-03","Confirmed":84.4285714286,"Deaths":7.0,"Recovered":77.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-04","Confirmed":84.7142857143,"Deaths":7.0,"Recovered":77.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-05","Confirmed":84.8571428571,"Deaths":7.0,"Recovered":77.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-06","Confirmed":85.0,"Deaths":7.0,"Recovered":78.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-07","Confirmed":85.0,"Deaths":7.0,"Recovered":78.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-08","Confirmed":85.0,"Deaths":7.0,"Recovered":78.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-09","Confirmed":85.1428571429,"Deaths":7.0,"Recovered":78.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-10","Confirmed":85.2857142857,"Deaths":7.0,"Recovered":78.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-11","Confirmed":85.4285714286,"Deaths":7.0,"Recovered":78.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-12","Confirmed":85.7142857143,"Deaths":7.0,"Recovered":78.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-13","Confirmed":86.1428571429,"Deaths":7.0,"Recovered":79.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-14","Confirmed":86.5714285714,"Deaths":7.0,"Recovered":79.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-15","Confirmed":87.1428571429,"Deaths":7.0,"Recovered":80.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-16","Confirmed":87.7142857143,"Deaths":7.0,"Recovered":80.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-17","Confirmed":88.4285714286,"Deaths":7.0,"Recovered":81.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-18","Confirmed":89.2857142857,"Deaths":7.0,"Recovered":82.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-19","Confirmed":90.0,"Deaths":7.0,"Recovered":83.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-20","Confirmed":90.5714285714,"Deaths":7.0,"Recovered":83.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-21","Confirmed":91.1428571429,"Deaths":7.0,"Recovered":84.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-22","Confirmed":91.7142857143,"Deaths":7.0,"Recovered":84.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-23","Confirmed":92.1428571429,"Deaths":7.0,"Recovered":85.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-24","Confirmed":92.5714285714,"Deaths":7.0,"Recovered":85.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-25","Confirmed":93.0,"Deaths":7.0,"Recovered":86.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-26","Confirmed":93.4285714286,"Deaths":7.0,"Recovered":86.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-27","Confirmed":93.8571428571,"Deaths":7.0,"Recovered":86.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-28","Confirmed":94.5714285714,"Deaths":7.0,"Recovered":87.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-29","Confirmed":95.5714285714,"Deaths":7.0,"Recovered":88.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-30","Confirmed":96.7142857143,"Deaths":7.0,"Recovered":89.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-10-31","Confirmed":98.0,"Deaths":7.0,"Recovered":91.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-01","Confirmed":99.5714285714,"Deaths":7.0,"Recovered":92.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-02","Confirmed":101.4285714286,"Deaths":7.1428571429,"Recovered":94.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-03","Confirmed":103.4285714286,"Deaths":7.2857142857,"Recovered":96.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-04","Confirmed":105.2857142857,"Deaths":7.4285714286,"Recovered":97.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-05","Confirmed":107.1428571429,"Deaths":7.5714285714,"Recovered":99.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-06","Confirmed":109.1428571429,"Deaths":7.7142857143,"Recovered":101.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-07","Confirmed":111.1428571429,"Deaths":7.8571428571,"Recovered":103.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-08","Confirmed":113.0,"Deaths":8.0,"Recovered":105.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-09","Confirmed":114.8571428571,"Deaths":8.1428571429,"Recovered":106.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-10","Confirmed":116.8571428571,"Deaths":8.2857142857,"Recovered":108.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-11","Confirmed":118.7142857143,"Deaths":8.4285714286,"Recovered":110.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-12","Confirmed":120.5714285714,"Deaths":8.5714285714,"Recovered":112.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-13","Confirmed":122.5714285714,"Deaths":8.7142857143,"Recovered":113.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-14","Confirmed":124.4285714286,"Deaths":8.8571428571,"Recovered":115.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-15","Confirmed":126.0,"Deaths":9.0,"Recovered":117.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-16","Confirmed":127.7142857143,"Deaths":9.0,"Recovered":118.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-17","Confirmed":129.5714285714,"Deaths":9.0,"Recovered":120.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-18","Confirmed":131.5714285714,"Deaths":9.0,"Recovered":122.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-19","Confirmed":133.5714285714,"Deaths":9.0,"Recovered":124.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-20","Confirmed":135.8571428571,"Deaths":9.1428571429,"Recovered":126.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-21","Confirmed":138.1428571429,"Deaths":9.2857142857,"Recovered":128.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-22","Confirmed":140.4285714286,"Deaths":9.4285714286,"Recovered":131.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-23","Confirmed":142.8571428571,"Deaths":9.5714285714,"Recovered":133.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-24","Confirmed":145.0,"Deaths":9.7142857143,"Recovered":135.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-25","Confirmed":147.1428571429,"Deaths":9.8571428571,"Recovered":137.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-26","Confirmed":149.1428571429,"Deaths":10.0,"Recovered":139.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-27","Confirmed":150.8571428571,"Deaths":10.0,"Recovered":140.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-28","Confirmed":152.4285714286,"Deaths":10.0,"Recovered":142.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-29","Confirmed":154.4285714286,"Deaths":10.0,"Recovered":144.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-11-30","Confirmed":156.2857142857,"Deaths":10.0,"Recovered":146.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-01","Confirmed":158.5714285714,"Deaths":10.0,"Recovered":148.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-02","Confirmed":160.8571428571,"Deaths":10.0,"Recovered":150.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-03","Confirmed":163.2857142857,"Deaths":10.0,"Recovered":153.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-04","Confirmed":165.7142857143,"Deaths":10.0,"Recovered":155.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-05","Confirmed":168.4285714286,"Deaths":10.0,"Recovered":158.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-06","Confirmed":170.8571428571,"Deaths":10.0,"Recovered":160.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-07","Confirmed":173.1428571429,"Deaths":10.0,"Recovered":163.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-08","Confirmed":175.4285714286,"Deaths":10.0,"Recovered":165.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-09","Confirmed":178.0,"Deaths":10.1428571429,"Recovered":167.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-10","Confirmed":180.4285714286,"Deaths":10.2857142857,"Recovered":170.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-11","Confirmed":182.5714285714,"Deaths":10.4285714286,"Recovered":172.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-12","Confirmed":184.8571428571,"Deaths":10.5714285714,"Recovered":174.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-13","Confirmed":187.5714285714,"Deaths":10.8571428571,"Recovered":176.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-14","Confirmed":190.4285714286,"Deaths":11.1428571429,"Recovered":179.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-15","Confirmed":192.8571428571,"Deaths":11.4285714286,"Recovered":181.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-16","Confirmed":195.5714285714,"Deaths":11.5714285714,"Recovered":184.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-17","Confirmed":198.5714285714,"Deaths":11.8571428571,"Recovered":186.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-18","Confirmed":202.2857142857,"Deaths":12.1428571429,"Recovered":190.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-19","Confirmed":206.5714285714,"Deaths":12.4285714286,"Recovered":194.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-20","Confirmed":210.8571428571,"Deaths":12.5714285714,"Recovered":198.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-21","Confirmed":215.0,"Deaths":12.8571428571,"Recovered":202.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-22","Confirmed":219.8571428571,"Deaths":13.2857142857,"Recovered":206.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-23","Confirmed":224.2857142857,"Deaths":13.7142857143,"Recovered":210.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-24","Confirmed":228.5714285714,"Deaths":14.0,"Recovered":214.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-25","Confirmed":232.1428571429,"Deaths":14.2857142857,"Recovered":217.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-26","Confirmed":235.5714285714,"Deaths":14.5714285714,"Recovered":221.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-27","Confirmed":239.4285714286,"Deaths":14.8571428571,"Recovered":224.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-28","Confirmed":243.2857142857,"Deaths":15.0,"Recovered":228.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-29","Confirmed":247.0,"Deaths":15.0,"Recovered":232.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-30","Confirmed":251.1428571429,"Deaths":15.0,"Recovered":236.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A60-A79","Date":"2020-12-31","Confirmed":255.4285714286,"Deaths":15.1428571429,"Recovered":240.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-01","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-02","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-03","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-04","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-05","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-06","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-07","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-08","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-09","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-10","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-11","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-12","Confirmed":26.0,"Deaths":5.0,"Recovered":21.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-13","Confirmed":26.1428571429,"Deaths":5.0,"Recovered":21.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-14","Confirmed":26.2857142857,"Deaths":5.0,"Recovered":21.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-15","Confirmed":26.4285714286,"Deaths":5.0,"Recovered":21.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-16","Confirmed":26.8571428571,"Deaths":5.0,"Recovered":21.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-17","Confirmed":27.4285714286,"Deaths":5.1428571429,"Recovered":22.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-18","Confirmed":28.0,"Deaths":5.2857142857,"Recovered":22.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-19","Confirmed":28.5714285714,"Deaths":5.4285714286,"Recovered":23.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-20","Confirmed":29.2857142857,"Deaths":5.5714285714,"Recovered":23.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-21","Confirmed":30.2857142857,"Deaths":5.7142857143,"Recovered":24.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-22","Confirmed":31.4285714286,"Deaths":5.8571428571,"Recovered":25.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-23","Confirmed":32.2857142857,"Deaths":6.0,"Recovered":26.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-24","Confirmed":33.0,"Deaths":6.0,"Recovered":27.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-25","Confirmed":34.0,"Deaths":6.0,"Recovered":28.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-26","Confirmed":35.1428571429,"Deaths":6.0,"Recovered":29.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-27","Confirmed":36.0,"Deaths":6.0,"Recovered":30.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-28","Confirmed":36.5714285714,"Deaths":6.0,"Recovered":30.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-29","Confirmed":37.1428571429,"Deaths":6.1428571429,"Recovered":31.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-30","Confirmed":37.7142857143,"Deaths":6.2857142857,"Recovered":31.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-10-31","Confirmed":38.4285714286,"Deaths":6.4285714286,"Recovered":32.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-01","Confirmed":39.0,"Deaths":6.5714285714,"Recovered":32.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-02","Confirmed":39.4285714286,"Deaths":6.7142857143,"Recovered":32.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-03","Confirmed":40.0,"Deaths":6.8571428571,"Recovered":33.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-04","Confirmed":40.5714285714,"Deaths":7.0,"Recovered":33.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-05","Confirmed":41.1428571429,"Deaths":7.1428571429,"Recovered":34.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-06","Confirmed":41.7142857143,"Deaths":7.2857142857,"Recovered":34.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-07","Confirmed":42.1428571429,"Deaths":7.4285714286,"Recovered":34.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-08","Confirmed":42.4285714286,"Deaths":7.5714285714,"Recovered":34.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-09","Confirmed":42.7142857143,"Deaths":7.7142857143,"Recovered":35.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-10","Confirmed":42.8571428571,"Deaths":7.8571428571,"Recovered":35.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-11","Confirmed":43.0,"Deaths":8.0,"Recovered":35.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-12","Confirmed":43.0,"Deaths":8.0,"Recovered":35.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-13","Confirmed":43.0,"Deaths":8.0,"Recovered":35.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-14","Confirmed":43.1428571429,"Deaths":8.0,"Recovered":35.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-15","Confirmed":43.2857142857,"Deaths":8.0,"Recovered":35.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-16","Confirmed":43.4285714286,"Deaths":8.0,"Recovered":35.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-17","Confirmed":43.7142857143,"Deaths":8.0,"Recovered":35.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-18","Confirmed":44.0,"Deaths":8.0,"Recovered":36.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-19","Confirmed":44.2857142857,"Deaths":8.0,"Recovered":36.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-20","Confirmed":44.5714285714,"Deaths":8.0,"Recovered":36.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-21","Confirmed":44.8571428571,"Deaths":8.0,"Recovered":36.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-22","Confirmed":45.1428571429,"Deaths":8.0,"Recovered":37.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-23","Confirmed":45.7142857143,"Deaths":8.0,"Recovered":37.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-24","Confirmed":46.1428571429,"Deaths":8.0,"Recovered":38.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-25","Confirmed":46.5714285714,"Deaths":8.0,"Recovered":38.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-26","Confirmed":47.2857142857,"Deaths":8.1428571429,"Recovered":39.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-27","Confirmed":48.0,"Deaths":8.2857142857,"Recovered":39.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-28","Confirmed":48.5714285714,"Deaths":8.4285714286,"Recovered":40.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-29","Confirmed":49.1428571429,"Deaths":8.5714285714,"Recovered":40.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-11-30","Confirmed":49.4285714286,"Deaths":8.7142857143,"Recovered":40.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-01","Confirmed":49.8571428571,"Deaths":9.0,"Recovered":40.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-02","Confirmed":50.5714285714,"Deaths":9.4285714286,"Recovered":41.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-03","Confirmed":52.8571428571,"Deaths":10.2857142857,"Recovered":42.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-04","Confirmed":55.8571428571,"Deaths":11.2857142857,"Recovered":44.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-05","Confirmed":59.0,"Deaths":12.2857142857,"Recovered":46.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-06","Confirmed":62.4285714286,"Deaths":13.2857142857,"Recovered":49.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-07","Confirmed":66.1428571429,"Deaths":14.4285714286,"Recovered":51.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-08","Confirmed":69.8571428571,"Deaths":15.5714285714,"Recovered":54.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-09","Confirmed":73.5714285714,"Deaths":16.5714285714,"Recovered":57.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-10","Confirmed":75.5714285714,"Deaths":17.1428571429,"Recovered":58.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-11","Confirmed":77.4285714286,"Deaths":17.8571428571,"Recovered":59.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-12","Confirmed":79.2857142857,"Deaths":18.7142857143,"Recovered":60.5714285714},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-13","Confirmed":80.8571428571,"Deaths":19.5714285714,"Recovered":61.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-14","Confirmed":82.8571428571,"Deaths":20.4285714286,"Recovered":62.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-15","Confirmed":85.2857142857,"Deaths":21.2857142857,"Recovered":64.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-16","Confirmed":87.4285714286,"Deaths":22.1428571429,"Recovered":65.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-17","Confirmed":89.5714285714,"Deaths":22.8571428571,"Recovered":66.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-18","Confirmed":92.1428571429,"Deaths":23.2857142857,"Recovered":68.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-19","Confirmed":94.5714285714,"Deaths":23.5714285714,"Recovered":71.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-20","Confirmed":97.1428571429,"Deaths":23.8571428571,"Recovered":73.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-21","Confirmed":99.4285714286,"Deaths":24.1428571429,"Recovered":75.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-22","Confirmed":103.0,"Deaths":24.5714285714,"Recovered":78.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-23","Confirmed":107.0,"Deaths":25.1428571429,"Recovered":81.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-24","Confirmed":111.1428571429,"Deaths":25.8571428571,"Recovered":85.2857142857},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-25","Confirmed":114.7142857143,"Deaths":26.7142857143,"Recovered":88.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-26","Confirmed":118.5714285714,"Deaths":27.5714285714,"Recovered":91.0},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-27","Confirmed":122.2857142857,"Deaths":28.4285714286,"Recovered":93.8571428571},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-28","Confirmed":126.0,"Deaths":29.2857142857,"Recovered":96.7142857143},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-29","Confirmed":128.0,"Deaths":29.8571428571,"Recovered":98.1428571429},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-30","Confirmed":129.7142857143,"Deaths":30.2857142857,"Recovered":99.4285714286},{"ID_County":1002,"County":"SK Kiel","Age_RKI":"A80+","Date":"2020-12-31","Confirmed":131.1428571429,"Deaths":30.5714285714,"Recovered":100.5714285714}] diff --git a/cpp/tests/data/Germany/pydata/critical_cases.json b/cpp/tests/data/Germany/pydata/critical_cases.json deleted file mode 100644 index 9c361855b1..0000000000 --- a/cpp/tests/data/Germany/pydata/critical_cases.json +++ /dev/null @@ -1 +0,0 @@ -[{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-01"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-02"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-03"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-04"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-05"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-06"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-07"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-08"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-09"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-10"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-11"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-12"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-13"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-14"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-15"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-16"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-17"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-18"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-19"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-20"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-21"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-22"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-23"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-24"},{"County":"SK Kiel","ID_County":1002,"ICU":0.0,"ICU_ventilated":0,"Date":"2020-10-25"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-10-26"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":1,"Date":"2020-10-27"},{"County":"SK Kiel","ID_County":1002,"ICU":2.0,"ICU_ventilated":1,"Date":"2020-10-28"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-10-29"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-10-30"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-10-31"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-11-01"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-11-02"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-11-03"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-11-04"},{"County":"SK Kiel","ID_County":1002,"ICU":2.0,"ICU_ventilated":0,"Date":"2020-11-05"},{"County":"SK Kiel","ID_County":1002,"ICU":3.0,"ICU_ventilated":1,"Date":"2020-11-06"},{"County":"SK Kiel","ID_County":1002,"ICU":3.0,"ICU_ventilated":1,"Date":"2020-11-07"},{"County":"SK Kiel","ID_County":1002,"ICU":3.0,"ICU_ventilated":1,"Date":"2020-11-08"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":2,"Date":"2020-11-09"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":0,"Date":"2020-11-10"},{"County":"SK Kiel","ID_County":1002,"ICU":3.0,"ICU_ventilated":1,"Date":"2020-11-11"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":1,"Date":"2020-11-12"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":1,"Date":"2020-11-13"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":1,"Date":"2020-11-14"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":1,"Date":"2020-11-15"},{"County":"SK Kiel","ID_County":1002,"ICU":2.0,"ICU_ventilated":2,"Date":"2020-11-16"},{"County":"SK Kiel","ID_County":1002,"ICU":1.0,"ICU_ventilated":1,"Date":"2020-11-17"},{"County":"SK Kiel","ID_County":1002,"ICU":2.0,"ICU_ventilated":2,"Date":"2020-11-18"},{"County":"SK Kiel","ID_County":1002,"ICU":3.0,"ICU_ventilated":2,"Date":"2020-11-19"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":3,"Date":"2020-11-20"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":3,"Date":"2020-11-21"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":3,"Date":"2020-11-22"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":4,"Date":"2020-11-23"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":4,"Date":"2020-11-24"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":4,"Date":"2020-11-25"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":4,"Date":"2020-11-26"},{"County":"SK Kiel","ID_County":1002,"ICU":5.0,"ICU_ventilated":5,"Date":"2020-11-27"},{"County":"SK Kiel","ID_County":1002,"ICU":6.0,"ICU_ventilated":5,"Date":"2020-11-28"},{"County":"SK Kiel","ID_County":1002,"ICU":6.0,"ICU_ventilated":6,"Date":"2020-11-29"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":8,"Date":"2020-11-30"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":8,"Date":"2020-12-01"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":7,"Date":"2020-12-02"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":7,"Date":"2020-12-03"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":7,"Date":"2020-12-04"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":7,"Date":"2020-12-05"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":7,"Date":"2020-12-06"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":8,"Date":"2020-12-07"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":8,"Date":"2020-12-08"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":6,"Date":"2020-12-09"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":6,"Date":"2020-12-10"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":6,"Date":"2020-12-11"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":6,"Date":"2020-12-12"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":6,"Date":"2020-12-13"},{"County":"SK Kiel","ID_County":1002,"ICU":6.0,"ICU_ventilated":5,"Date":"2020-12-14"},{"County":"SK Kiel","ID_County":1002,"ICU":6.0,"ICU_ventilated":3,"Date":"2020-12-15"},{"County":"SK Kiel","ID_County":1002,"ICU":6.0,"ICU_ventilated":3,"Date":"2020-12-16"},{"County":"SK Kiel","ID_County":1002,"ICU":5.0,"ICU_ventilated":2,"Date":"2020-12-17"},{"County":"SK Kiel","ID_County":1002,"ICU":3.0,"ICU_ventilated":1,"Date":"2020-12-18"},{"County":"SK Kiel","ID_County":1002,"ICU":4.0,"ICU_ventilated":2,"Date":"2020-12-19"},{"County":"SK Kiel","ID_County":1002,"ICU":5.0,"ICU_ventilated":3,"Date":"2020-12-20"},{"County":"SK Kiel","ID_County":1002,"ICU":5.0,"ICU_ventilated":3,"Date":"2020-12-21"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":5,"Date":"2020-12-22"},{"County":"SK Kiel","ID_County":1002,"ICU":9.0,"ICU_ventilated":6,"Date":"2020-12-23"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":3,"Date":"2020-12-24"},{"County":"SK Kiel","ID_County":1002,"ICU":9.0,"ICU_ventilated":3,"Date":"2020-12-25"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":4,"Date":"2020-12-26"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":5,"Date":"2020-12-27"},{"County":"SK Kiel","ID_County":1002,"ICU":8.0,"ICU_ventilated":5,"Date":"2020-12-28"},{"County":"SK Kiel","ID_County":1002,"ICU":7.0,"ICU_ventilated":5,"Date":"2020-12-29"},{"County":"SK Kiel","ID_County":1002,"ICU":6.0,"ICU_ventilated":3,"Date":"2020-12-30"},{"County":"SK Kiel","ID_County":1002,"ICU":6.0,"ICU_ventilated":4,"Date":"2020-12-31"}] diff --git a/cpp/tests/data/Germany/pydata/population_data.json b/cpp/tests/data/Germany/pydata/population_data.json deleted file mode 100644 index b5a0af9b52..0000000000 --- a/cpp/tests/data/Germany/pydata/population_data.json +++ /dev/null @@ -1 +0,0 @@ -[{"ID_County":1001,"Total":90164,"<3 years":2117,"3-5 years":1974,"6-14 years":6983,"15-17 years":2293,"18-24 years":9341,"25-29 years":7593,"30-39 years":10768,"40-49 years":13666,"50-64 years":16871,"65-74 years":10238,">74 years":8319},{"ID_County":1002,"Total":246794,"<3 years":6389,"3-5 years":5898,"6-14 years":17239,"15-17 years":5955,"18-24 years":27799,"25-29 years":23709,"30-39 years":34048,"40-49 years":37026,"50-64 years":43621,"65-74 years":25460,">74 years":19649},{"ID_County":1003,"Total":216530,"<3 years":5135,"3-5 years":5111,"6-14 years":16362,"15-17 years":5812,"18-24 years":18225,"25-29 years":14676,"30-39 years":25564,"40-49 years":34181,"50-64 years":41669,"65-74 years":27084,">74 years":22712},{"ID_County":1004,"Total":80196,"<3 years":1979,"3-5 years":2012,"6-14 years":6967,"15-17 years":2477,"18-24 years":7015,"25-29 years":4594,"30-39 years":8783,"40-49 years":12981,"50-64 years":15810,"65-74 years":9863,">74 years":7716},{"ID_County":1051,"Total":133193,"<3 years":3073,"3-5 years":3236,"6-14 years":12620,"15-17 years":4797,"18-24 years":10054,"25-29 years":6167,"30-39 years":13367,"40-49 years":21875,"50-64 years":27548,"65-74 years":17147,">74 years":13310},{"ID_County":1053,"Total":198019,"<3 years":4653,"3-5 years":5218,"6-14 years":19092,"15-17 years":6390,"18-24 years":14101,"25-29 years":9003,"30-39 years":21455,"40-49 years":35773,"50-64 years":39804,"65-74 years":23999,">74 years":18532},{"ID_County":1054,"Total":165951,"<3 years":3577,"3-5 years":4098,"6-14 years":15853,"15-17 years":5978,"18-24 years":12999,"25-29 years":7972,"30-39 years":16977,"40-49 years":27731,"50-64 years":33969,"65-74 years":21139,">74 years":15657},{"ID_County":1055,"Total":200539,"<3 years":4014,"3-5 years":4318,"6-14 years":16782,"15-17 years":6107,"18-24 years":13467,"25-29 years":8204,"30-39 years":19875,"40-49 years":33526,"50-64 years":43318,"65-74 years":29247,">74 years":21682},{"ID_County":1056,"Total":316103,"<3 years":7740,"3-5 years":8382,"6-14 years":29358,"15-17 years":9736,"18-24 years":22278,"25-29 years":15100,"30-39 years":35125,"40-49 years":57302,"50-64 years":63304,"65-74 years":39378,">74 years":28401},{"ID_County":1057,"Total":128686,"<3 years":2743,"3-5 years":3040,"6-14 years":11866,"15-17 years":4485,"18-24 years":8688,"25-29 years":4845,"30-39 years":12532,"40-49 years":22678,"50-64 years":27416,"65-74 years":17840,">74 years":12553},{"ID_County":1058,"Total":274098,"<3 years":6477,"3-5 years":7101,"6-14 years":26738,"15-17 years":9562,"18-24 years":20110,"25-29 years":11540,"30-39 years":28416,"40-49 years":49169,"50-64 years":56558,"65-74 years":34073,">74 years":24356},{"ID_County":1059,"Total":201156,"<3 years":4914,"3-5 years":5171,"6-14 years":19716,"15-17 years":7376,"18-24 years":15202,"25-29 years":8484,"30-39 years":20786,"40-49 years":34975,"50-64 years":41158,"65-74 years":25220,">74 years":18153},{"ID_County":1060,"Total":277175,"<3 years":6775,"3-5 years":7372,"6-14 years":26061,"15-17 years":8866,"18-24 years":19892,"25-29 years":13542,"30-39 years":31934,"40-49 years":50486,"50-64 years":56175,"65-74 years":33582,">74 years":22490},{"ID_County":1061,"Total":131013,"<3 years":3011,"3-5 years":3133,"6-14 years":12420,"15-17 years":4590,"18-24 years":10145,"25-29 years":5659,"30-39 years":13183,"40-49 years":24107,"50-64 years":26798,"65-74 years":16149,">74 years":11817},{"ID_County":1062,"Total":244156,"<3 years":6116,"3-5 years":6531,"6-14 years":22954,"15-17 years":7647,"18-24 years":15846,"25-29 years":10560,"30-39 years":26799,"40-49 years":45051,"50-64 years":49523,"65-74 years":30554,">74 years":22576},{"ID_County":2000,"Total":1847253,"<3 years":51690,"3-5 years":49328,"6-14 years":143386,"15-17 years":45718,"18-24 years":149717,"25-29 years":147539,"30-39 years":279506,"40-49 years":303786,"50-64 years":325994,"65-74 years":193169,">74 years":157420},{"ID_County":3101,"Total":249406,"<3 years":6343,"3-5 years":5999,"6-14 years":18091,"15-17 years":6296,"18-24 years":22812,"25-29 years":19822,"30-39 years":33225,"40-49 years":38999,"50-64 years":45282,"65-74 years":28078,">74 years":24458},{"ID_County":3102,"Total":104291,"<3 years":2401,"3-5 years":2611,"6-14 years":8932,"15-17 years":3304,"18-24 years":8223,"25-29 years":5270,"30-39 years":10855,"40-49 years":16304,"50-64 years":21892,"65-74 years":13168,">74 years":11331},{"ID_County":3103,"Total":124371,"<3 years":2944,"3-5 years":2879,"6-14 years":9613,"15-17 years":3450,"18-24 years":10304,"25-29 years":8477,"30-39 years":14703,"40-49 years":19138,"50-64 years":24114,"65-74 years":15512,">74 years":13238},{"ID_County":3151,"Total":176523,"<3 years":4442,"3-5 years":4829,"6-14 years":17708,"15-17 years":6629,"18-24 years":14280,"25-29 years":8414,"30-39 years":19507,"40-49 years":31880,"50-64 years":36892,"65-74 years":17843,">74 years":14099},{"ID_County":3153,"Total":136292,"<3 years":2491,"3-5 years":2720,"6-14 years":10314,"15-17 years":3882,"18-24 years":10408,"25-29 years":6725,"30-39 years":13532,"40-49 years":21610,"50-64 years":28692,"65-74 years":18808,">74 years":17108},{"ID_County":3154,"Total":91297,"<3 years":1852,"3-5 years":2127,"6-14 years":7533,"15-17 years":2940,"18-24 years":6770,"25-29 years":4038,"30-39 years":9577,"40-49 years":15637,"50-64 years":20036,"65-74 years":10824,">74 years":9964},{"ID_County":3155,"Total":132285,"<3 years":2725,"3-5 years":2995,"6-14 years":11308,"15-17 years":4190,"18-24 years":9529,"25-29 years":5867,"30-39 years":13296,"40-49 years":22122,"50-64 years":29089,"65-74 years":15938,">74 years":15226},{"ID_County":3157,"Total":134801,"<3 years":3152,"3-5 years":3486,"6-14 years":13284,"15-17 years":4709,"18-24 years":9816,"25-29 years":5956,"30-39 years":14801,"40-49 years":24239,"50-64 years":27382,"65-74 years":15098,">74 years":12879},{"ID_County":3158,"Total":119622,"<3 years":2524,"3-5 years":2813,"6-14 years":10924,"15-17 years":3992,"18-24 years":8792,"25-29 years":5185,"30-39 years":12173,"40-49 years":21499,"50-64 years":25249,"65-74 years":14752,">74 years":11719},{"ID_County":3159,"Total":326041,"<3 years":7098,"3-5 years":7437,"6-14 years":26774,"15-17 years":9582,"18-24 years":30423,"25-29 years":21705,"30-39 years":35729,"40-49 years":51704,"50-64 years":66095,"65-74 years":36516,">74 years":32980},{"ID_County":3241,"Total":1157115,"<3 years":29435,"3-5 years":29745,"6-14 years":96556,"15-17 years":33282,"18-24 years":89682,"25-29 years":73695,"30-39 years":144908,"40-49 years":191807,"50-64 years":225697,"65-74 years":132938,">74 years":109371},{"ID_County":3251,"Total":217089,"<3 years":4949,"3-5 years":5381,"6-14 years":20431,"15-17 years":7470,"18-24 years":15872,"25-29 years":10011,"30-39 years":23303,"40-49 years":39119,"50-64 years":45733,"65-74 years":24781,">74 years":20039},{"ID_County":3252,"Total":148549,"<3 years":3109,"3-5 years":3296,"6-14 years":12680,"15-17 years":4712,"18-24 years":11077,"25-29 years":7055,"30-39 years":14794,"40-49 years":24614,"50-64 years":31006,"65-74 years":18732,">74 years":17474},{"ID_County":3254,"Total":275817,"<3 years":5937,"3-5 years":6550,"6-14 years":24393,"15-17 years":8916,"18-24 years":23128,"25-29 years":13885,"30-39 years":29535,"40-49 years":46194,"50-64 years":56332,"65-74 years":32458,">74 years":28489},{"ID_County":3255,"Total":70458,"<3 years":1453,"3-5 years":1514,"6-14 years":6150,"15-17 years":2356,"18-24 years":5365,"25-29 years":3311,"30-39 years":6705,"40-49 years":11248,"50-64 years":14996,"65-74 years":8963,">74 years":8397},{"ID_County":3256,"Total":121390,"<3 years":2799,"3-5 years":3014,"6-14 years":11532,"15-17 years":4243,"18-24 years":9674,"25-29 years":5928,"30-39 years":13001,"40-49 years":20956,"50-64 years":25361,"65-74 years":12929,">74 years":11952},{"ID_County":3257,"Total":157820,"<3 years":3268,"3-5 years":3673,"6-14 years":14336,"15-17 years":5295,"18-24 years":11404,"25-29 years":7057,"30-39 years":16026,"40-49 years":27307,"50-64 years":33033,"65-74 years":19314,">74 years":17108},{"ID_County":3351,"Total":179011,"<3 years":4363,"3-5 years":4672,"6-14 years":16785,"15-17 years":6111,"18-24 years":13903,"25-29 years":9011,"30-39 years":18839,"40-49 years":29173,"50-64 years":37104,"65-74 years":21278,">74 years":17772},{"ID_County":3352,"Total":198038,"<3 years":4422,"3-5 years":4659,"6-14 years":18363,"15-17 years":6763,"18-24 years":13808,"25-29 years":8615,"30-39 years":19945,"40-49 years":33095,"50-64 years":42991,"65-74 years":25029,">74 years":20351},{"ID_County":3353,"Total":254431,"<3 years":6154,"3-5 years":6789,"6-14 years":24827,"15-17 years":8447,"18-24 years":16780,"25-29 years":10541,"30-39 years":27369,"40-49 years":47930,"50-64 years":52551,"65-74 years":31468,">74 years":21574},{"ID_County":3354,"Total":48412,"<3 years":924,"3-5 years":1064,"6-14 years":4225,"15-17 years":1607,"18-24 years":3307,"25-29 years":1919,"30-39 years":4555,"40-49 years":7606,"50-64 years":10775,"65-74 years":6715,">74 years":5715},{"ID_County":3355,"Total":184139,"<3 years":4761,"3-5 years":5039,"6-14 years":17759,"15-17 years":6069,"18-24 years":15090,"25-29 years":10535,"30-39 years":22544,"40-49 years":32756,"50-64 years":35415,"65-74 years":19196,">74 years":14975},{"ID_County":3356,"Total":113928,"<3 years":2485,"3-5 years":2764,"6-14 years":11008,"15-17 years":3922,"18-24 years":7841,"25-29 years":4756,"30-39 years":11881,"40-49 years":20866,"50-64 years":24407,"65-74 years":14196,">74 years":9801},{"ID_County":3357,"Total":163782,"<3 years":4011,"3-5 years":4374,"6-14 years":16839,"15-17 years":5984,"18-24 years":13603,"25-29 years":8124,"30-39 years":18097,"40-49 years":28546,"50-64 years":33144,"65-74 years":17184,">74 years":13877},{"ID_County":3358,"Total":140673,"<3 years":3274,"3-5 years":3595,"6-14 years":13368,"15-17 years":5007,"18-24 years":11103,"25-29 years":6851,"30-39 years":14892,"40-49 years":23941,"50-64 years":28547,"65-74 years":16313,">74 years":13783},{"ID_County":3359,"Total":204512,"<3 years":5195,"3-5 years":5394,"6-14 years":20153,"15-17 years":7340,"18-24 years":15647,"25-29 years":10416,"30-39 years":23531,"40-49 years":35376,"50-64 years":41690,"65-74 years":23090,">74 years":16680},{"ID_County":3360,"Total":92389,"<3 years":1896,"3-5 years":2197,"6-14 years":8252,"15-17 years":3079,"18-24 years":6603,"25-29 years":3961,"30-39 years":9530,"40-49 years":15401,"50-64 years":19324,"65-74 years":11723,">74 years":10423},{"ID_County":3361,"Total":137133,"<3 years":3420,"3-5 years":3648,"6-14 years":13377,"15-17 years":4700,"18-24 years":10183,"25-29 years":6662,"30-39 years":14822,"40-49 years":23791,"50-64 years":29067,"65-74 years":15836,">74 years":11627},{"ID_County":3401,"Total":77559,"<3 years":1746,"3-5 years":1900,"6-14 years":6954,"15-17 years":2475,"18-24 years":6289,"25-29 years":4095,"30-39 years":8696,"40-49 years":12635,"50-64 years":16036,"65-74 years":9757,">74 years":6976},{"ID_County":3402,"Total":49913,"<3 years":1262,"3-5 years":1239,"6-14 years":4456,"15-17 years":1628,"18-24 years":4858,"25-29 years":3231,"30-39 years":5671,"40-49 years":7754,"50-64 years":9676,"65-74 years":5352,">74 years":4785},{"ID_County":3403,"Total":169077,"<3 years":4313,"3-5 years":4135,"6-14 years":13400,"15-17 years":4575,"18-24 years":16677,"25-29 years":13085,"30-39 years":22446,"40-49 years":27486,"50-64 years":31912,"65-74 years":17031,">74 years":14018},{"ID_County":3404,"Total":165251,"<3 years":4008,"3-5 years":3847,"6-14 years":12492,"15-17 years":4131,"18-24 years":16885,"25-29 years":13976,"30-39 years":21962,"40-49 years":25443,"50-64 years":29546,"65-74 years":17011,">74 years":15949},{"ID_County":3405,"Total":76089,"<3 years":1552,"3-5 years":1555,"6-14 years":5489,"15-17 years":2137,"18-24 years":7588,"25-29 years":4572,"30-39 years":7179,"40-49 years":11575,"50-64 years":15448,"65-74 years":10552,">74 years":8442},{"ID_County":3451,"Total":124859,"<3 years":2929,"3-5 years":3264,"6-14 years":12588,"15-17 years":4314,"18-24 years":9489,"25-29 years":5669,"30-39 years":13304,"40-49 years":22087,"50-64 years":25632,"65-74 years":14699,">74 years":10884},{"ID_County":3452,"Total":189694,"<3 years":4471,"3-5 years":4848,"6-14 years":19120,"15-17 years":6820,"18-24 years":14766,"25-29 years":8799,"30-39 years":20508,"40-49 years":31869,"50-64 years":40198,"65-74 years":21541,">74 years":16753},{"ID_County":3453,"Total":170682,"<3 years":5132,"3-5 years":5509,"6-14 years":20323,"15-17 years":7015,"18-24 years":15924,"25-29 years":10325,"30-39 years":20478,"40-49 years":28594,"50-64 years":30827,"65-74 years":14131,">74 years":12423},{"ID_County":3454,"Total":326954,"<3 years":8532,"3-5 years":9246,"6-14 years":34339,"15-17 years":12337,"18-24 years":29247,"25-29 years":18849,"30-39 years":38962,"40-49 years":54997,"50-64 years":63285,"65-74 years":31639,">74 years":25522},{"ID_County":3455,"Total":98704,"<3 years":2110,"3-5 years":2200,"6-14 years":9368,"15-17 years":3608,"18-24 years":7254,"25-29 years":3935,"30-39 years":9686,"40-49 years":16944,"50-64 years":20735,"65-74 years":13203,">74 years":9662},{"ID_County":3456,"Total":137162,"<3 years":3664,"3-5 years":3801,"6-14 years":14339,"15-17 years":5182,"18-24 years":11429,"25-29 years":7184,"30-39 years":15178,"40-49 years":23468,"50-64 years":26977,"65-74 years":13704,">74 years":12236},{"ID_County":3457,"Total":170756,"<3 years":4203,"3-5 years":4558,"6-14 years":17414,"15-17 years":6275,"18-24 years":13931,"25-29 years":8796,"30-39 years":19131,"40-49 years":28962,"50-64 years":33993,"65-74 years":18749,">74 years":14743},{"ID_County":3458,"Total":130890,"<3 years":3137,"3-5 years":3360,"6-14 years":13437,"15-17 years":4674,"18-24 years":9432,"25-29 years":5671,"30-39 years":13806,"40-49 years":24823,"50-64 years":27164,"65-74 years":14468,">74 years":10917},{"ID_County":3459,"Total":358080,"<3 years":9029,"3-5 years":9845,"6-14 years":37259,"15-17 years":13079,"18-24 years":29999,"25-29 years":17891,"30-39 years":40113,"40-49 years":61578,"50-64 years":71224,"65-74 years":36090,">74 years":31973},{"ID_County":3460,"Total":142814,"<3 years":4196,"3-5 years":4403,"6-14 years":16369,"15-17 years":5528,"18-24 years":13806,"25-29 years":8977,"30-39 years":17753,"40-49 years":24319,"50-64 years":25900,"65-74 years":11377,">74 years":10186},{"ID_County":3461,"Total":88583,"<3 years":1887,"3-5 years":2126,"6-14 years":8585,"15-17 years":3254,"18-24 years":6991,"25-29 years":3959,"30-39 years":8772,"40-49 years":15376,"50-64 years":18571,"65-74 years":10461,">74 years":8602},{"ID_County":3462,"Total":56926,"<3 years":1293,"3-5 years":1400,"6-14 years":5603,"15-17 years":2023,"18-24 years":4456,"25-29 years":2649,"30-39 years":5905,"40-49 years":9254,"50-64 years":12260,"65-74 years":6702,">74 years":5381},{"ID_County":4011,"Total":567559,"<3 years":13591,"3-5 years":13296,"6-14 years":43041,"15-17 years":15092,"18-24 years":51627,"25-29 years":41738,"30-39 years":71838,"40-49 years":89506,"50-64 years":108938,"65-74 years":65011,">74 years":53882},{"ID_County":4012,"Total":113643,"<3 years":2777,"3-5 years":2965,"6-14 years":9371,"15-17 years":3361,"18-24 years":9768,"25-29 years":7100,"30-39 years":12631,"40-49 years":16909,"50-64 years":23407,"65-74 years":13765,">74 years":11589},{"ID_County":5111,"Total":621877,"<3 years":17722,"3-5 years":16039,"6-14 years":44753,"15-17 years":14384,"18-24 years":43675,"25-29 years":46632,"30-39 years":94564,"40-49 years":103604,"50-64 years":115769,"65-74 years":68202,">74 years":56533},{"ID_County":5112,"Total":498686,"<3 years":12311,"3-5 years":12598,"6-14 years":42340,"15-17 years":15473,"18-24 years":42121,"25-29 years":30289,"30-39 years":60170,"40-49 years":79961,"50-64 years":98349,"65-74 years":54377,">74 years":50697},{"ID_County":5113,"Total":582760,"<3 years":13934,"3-5 years":14295,"6-14 years":45092,"15-17 years":16013,"18-24 years":47110,"25-29 years":37536,"30-39 years":69545,"40-49 years":92761,"50-64 years":118496,"65-74 years":66801,">74 years":61177},{"ID_County":5114,"Total":227417,"<3 years":5438,"3-5 years":5711,"6-14 years":19796,"15-17 years":6707,"18-24 years":17811,"25-29 years":12748,"30-39 years":25444,"40-49 years":38198,"50-64 years":46621,"65-74 years":26681,">74 years":22262},{"ID_County":5116,"Total":261034,"<3 years":6170,"3-5 years":6434,"6-14 years":22290,"15-17 years":8134,"18-24 years":22397,"25-29 years":15578,"30-39 years":29165,"40-49 years":43345,"50-64 years":53982,"65-74 years":28860,">74 years":24679},{"ID_County":5117,"Total":170632,"<3 years":3946,"3-5 years":3966,"6-14 years":13410,"15-17 years":4744,"18-24 years":12411,"25-29 years":8905,"30-39 years":18360,"40-49 years":28155,"50-64 years":36190,"65-74 years":21404,">74 years":19143},{"ID_County":5119,"Total":210764,"<3 years":4593,"3-5 years":4910,"6-14 years":17330,"15-17 years":6245,"18-24 years":17079,"25-29 years":12083,"30-39 years":24109,"40-49 years":34787,"50-64 years":45542,"65-74 years":23241,">74 years":20842},{"ID_County":5120,"Total":111338,"<3 years":2523,"3-5 years":2724,"6-14 years":9553,"15-17 years":3616,"18-24 years":9041,"25-29 years":5526,"30-39 years":12321,"40-49 years":18915,"50-64 years":22894,"65-74 years":13346,">74 years":10879},{"ID_County":5122,"Total":159245,"<3 years":3922,"3-5 years":4188,"6-14 years":14172,"15-17 years":5150,"18-24 years":12524,"25-29 years":8653,"30-39 years":17359,"40-49 years":27627,"50-64 years":31089,"65-74 years":18262,">74 years":16298},{"ID_County":5124,"Total":355100,"<3 years":8952,"3-5 years":9061,"6-14 years":29580,"15-17 years":10939,"18-24 years":29202,"25-29 years":22418,"30-39 years":40653,"40-49 years":58517,"50-64 years":70063,"65-74 years":40623,">74 years":35091},{"ID_County":5154,"Total":312465,"<3 years":7558,"3-5 years":8045,"6-14 years":29747,"15-17 years":11129,"18-24 years":25421,"25-29 years":16424,"30-39 years":33937,"40-49 years":55347,"50-64 years":65676,"65-74 years":32164,">74 years":27018},{"ID_County":5158,"Total":485570,"<3 years":10921,"3-5 years":12148,"6-14 years":42107,"15-17 years":14347,"18-24 years":34484,"25-29 years":22945,"30-39 years":50639,"40-49 years":84986,"50-64 years":101616,"65-74 years":62435,">74 years":48941},{"ID_County":5162,"Total":451730,"<3 years":10955,"3-5 years":11691,"6-14 years":41328,"15-17 years":14056,"18-24 years":32827,"25-29 years":22274,"30-39 years":51047,"40-49 years":79832,"50-64 years":94147,"65-74 years":52294,">74 years":41280},{"ID_County":5166,"Total":298863,"<3 years":6606,"3-5 years":7237,"6-14 years":27814,"15-17 years":10688,"18-24 years":23246,"25-29 years":14022,"30-39 years":31157,"40-49 years":54858,"50-64 years":62617,"65-74 years":33485,">74 years":27132},{"ID_County":5170,"Total":459976,"<3 years":9968,"3-5 years":10594,"6-14 years":39809,"15-17 years":15073,"18-24 years":36517,"25-29 years":22504,"30-39 years":47969,"40-49 years":79612,"50-64 years":101141,"65-74 years":52239,">74 years":44551},{"ID_County":5314,"Total":329673,"<3 years":9952,"3-5 years":9603,"6-14 years":27300,"15-17 years":8593,"18-24 years":29628,"25-29 years":27408,"30-39 years":46673,"40-49 years":52578,"50-64 years":57656,"65-74 years":31376,">74 years":28906},{"ID_County":5315,"Total":1087863,"<3 years":30860,"3-5 years":28495,"6-14 years":84031,"15-17 years":27159,"18-24 years":90745,"25-29 years":89750,"30-39 years":170940,"40-49 years":180991,"50-64 years":191953,"65-74 years":107150,">74 years":85787},{"ID_County":5316,"Total":163729,"<3 years":4006,"3-5 years":4266,"6-14 years":14168,"15-17 years":4815,"18-24 years":12505,"25-29 years":9229,"30-39 years":18836,"40-49 years":28073,"50-64 years":31715,"65-74 years":19433,">74 years":16684},{"ID_County":5334,"Total":557026,"<3 years":13271,"3-5 years":13647,"6-14 years":47322,"15-17 years":16599,"18-24 years":56044,"25-29 years":40749,"30-39 years":65159,"40-49 years":88369,"50-64 years":107021,"65-74 years":58285,">74 years":50559},{"ID_County":5358,"Total":264638,"<3 years":6176,"3-5 years":6717,"6-14 years":24872,"15-17 years":9340,"18-24 years":21724,"25-29 years":13931,"30-39 years":28295,"40-49 years":45098,"50-64 years":56384,"65-74 years":28089,">74 years":24011},{"ID_County":5362,"Total":470615,"<3 years":11588,"3-5 years":12212,"6-14 years":43464,"15-17 years":14873,"18-24 years":36128,"25-29 years":24074,"30-39 years":53075,"40-49 years":82914,"50-64 years":98400,"65-74 years":52841,">74 years":41047},{"ID_County":5366,"Total":193656,"<3 years":4332,"3-5 years":4816,"6-14 years":18509,"15-17 years":6835,"18-24 years":15239,"25-29 years":9567,"30-39 years":20139,"40-49 years":34173,"50-64 years":41893,"65-74 years":20654,">74 years":17498},{"ID_County":5370,"Total":255555,"<3 years":6092,"3-5 years":6467,"6-14 years":24577,"15-17 years":9106,"18-24 years":21149,"25-29 years":12963,"30-39 years":27860,"40-49 years":44546,"50-64 years":54127,"65-74 years":26235,">74 years":22432},{"ID_County":5374,"Total":272057,"<3 years":6707,"3-5 years":7146,"6-14 years":26961,"15-17 years":9802,"18-24 years":22406,"25-29 years":14186,"30-39 years":29122,"40-49 years":45954,"50-64 years":54994,"65-74 years":29230,">74 years":25547},{"ID_County":5378,"Total":283271,"<3 years":6608,"3-5 years":7317,"6-14 years":26763,"15-17 years":9566,"18-24 years":20204,"25-29 years":12347,"30-39 years":28682,"40-49 years":51241,"50-64 years":58308,"65-74 years":34414,">74 years":27820},{"ID_County":5382,"Total":600764,"<3 years":14974,"3-5 years":15984,"6-14 years":58472,"15-17 years":20596,"18-24 years":47097,"25-29 years":30746,"30-39 years":64752,"40-49 years":105724,"50-64 years":124075,"65-74 years":67782,">74 years":50562},{"ID_County":5512,"Total":117565,"<3 years":2647,"3-5 years":2749,"6-14 years":10091,"15-17 years":3693,"18-24 years":9312,"25-29 years":6287,"30-39 years":13370,"40-49 years":19691,"50-64 years":25205,"65-74 years":12702,">74 years":11819},{"ID_County":5513,"Total":259645,"<3 years":6298,"3-5 years":6434,"6-14 years":22023,"15-17 years":8051,"18-24 years":22360,"25-29 years":15177,"30-39 years":30739,"40-49 years":41099,"50-64 years":53285,"65-74 years":27601,">74 years":26577},{"ID_County":5515,"Total":315293,"<3 years":8307,"3-5 years":7540,"6-14 years":23735,"15-17 years":7700,"18-24 years":37369,"25-29 years":31839,"30-39 years":43320,"40-49 years":48195,"50-64 years":53777,"65-74 years":27486,">74 years":26025},{"ID_County":5554,"Total":371339,"<3 years":9963,"3-5 years":10635,"6-14 years":39718,"15-17 years":14678,"18-24 years":33382,"25-29 years":20391,"30-39 years":42504,"40-49 years":65620,"50-64 years":70302,"65-74 years":34648,">74 years":29496},{"ID_County":5558,"Total":220586,"<3 years":5108,"3-5 years":5771,"6-14 years":22861,"15-17 years":8626,"18-24 years":18260,"25-29 years":10703,"30-39 years":23532,"40-49 years":39465,"50-64 years":46132,"65-74 years":21587,">74 years":18540},{"ID_County":5562,"Total":614137,"<3 years":13391,"3-5 years":14184,"6-14 years":53244,"15-17 years":19570,"18-24 years":48361,"25-29 years":31205,"30-39 years":67398,"40-49 years":102599,"50-64 years":133782,"65-74 years":68113,">74 years":62289},{"ID_County":5566,"Total":448220,"<3 years":11233,"3-5 years":12243,"6-14 years":47054,"15-17 years":17367,"18-24 years":38123,"25-29 years":23033,"30-39 years":49189,"40-49 years":79303,"50-64 years":87719,"65-74 years":44684,">74 years":38273},{"ID_County":5570,"Total":277840,"<3 years":6757,"3-5 years":7503,"6-14 years":28607,"15-17 years":9907,"18-24 years":22475,"25-29 years":14120,"30-39 years":30193,"40-49 years":47903,"50-64 years":56248,"65-74 years":28768,">74 years":25359},{"ID_County":5711,"Total":334195,"<3 years":9125,"3-5 years":9100,"6-14 years":28941,"15-17 years":9984,"18-24 years":31062,"25-29 years":24849,"30-39 years":42459,"40-49 years":51606,"50-64 years":59451,"65-74 years":34768,">74 years":32850},{"ID_County":5754,"Total":364938,"<3 years":9533,"3-5 years":10024,"6-14 years":37157,"15-17 years":13232,"18-24 years":30318,"25-29 years":20301,"30-39 years":42493,"40-49 years":63963,"50-64 years":70363,"65-74 years":36429,">74 years":31123},{"ID_County":5758,"Total":250578,"<3 years":6079,"3-5 years":6454,"6-14 years":23250,"15-17 years":8330,"18-24 years":20109,"25-29 years":13136,"30-39 years":27345,"40-49 years":42243,"50-64 years":50254,"65-74 years":26995,">74 years":26383},{"ID_County":5762,"Total":140251,"<3 years":3295,"3-5 years":3617,"6-14 years":13694,"15-17 years":5068,"18-24 years":11815,"25-29 years":7029,"30-39 years":14644,"40-49 years":23050,"50-64 years":28950,"65-74 years":14925,">74 years":14165},{"ID_County":5766,"Total":347514,"<3 years":8782,"3-5 years":9358,"6-14 years":33455,"15-17 years":12263,"18-24 years":28517,"25-29 years":18018,"30-39 years":36046,"40-49 years":56371,"50-64 years":70039,"65-74 years":38197,">74 years":36470},{"ID_County":5770,"Total":310409,"<3 years":7669,"3-5 years":8295,"6-14 years":29804,"15-17 years":10896,"18-24 years":25387,"25-29 years":15774,"30-39 years":33124,"40-49 years":51465,"50-64 years":62491,"65-74 years":33183,">74 years":32322},{"ID_County":5774,"Total":307839,"<3 years":8489,"3-5 years":8790,"6-14 years":30180,"15-17 years":10753,"18-24 years":29996,"25-29 years":21117,"30-39 years":37991,"40-49 years":49966,"50-64 years":58939,"65-74 years":27629,">74 years":23990},{"ID_County":5911,"Total":365587,"<3 years":8133,"3-5 years":8132,"6-14 years":26844,"15-17 years":9099,"18-24 years":31645,"25-29 years":26466,"30-39 years":43169,"40-49 years":57515,"50-64 years":75128,"65-74 years":40800,">74 years":38654},{"ID_County":5913,"Total":588250,"<3 years":14051,"3-5 years":14147,"6-14 years":47838,"15-17 years":16484,"18-24 years":50457,"25-29 years":40319,"30-39 years":74220,"40-49 years":94490,"50-64 years":115445,"65-74 years":64179,">74 years":56619},{"ID_County":5914,"Total":188686,"<3 years":4236,"3-5 years":4374,"6-14 years":16278,"15-17 years":6022,"18-24 years":15246,"25-29 years":10423,"30-39 years":20651,"40-49 years":30500,"50-64 years":38379,"65-74 years":22426,">74 years":20151},{"ID_County":5915,"Total":179916,"<3 years":4458,"3-5 years":4696,"6-14 years":16988,"15-17 years":6208,"18-24 years":15052,"25-29 years":10079,"30-39 years":21454,"40-49 years":28771,"50-64 years":36080,"65-74 years":19069,">74 years":17061},{"ID_County":5916,"Total":156449,"<3 years":3466,"3-5 years":3593,"6-14 years":13411,"15-17 years":4783,"18-24 years":12414,"25-29 years":8462,"30-39 years":18210,"40-49 years":25332,"50-64 years":32327,"65-74 years":17628,">74 years":16823},{"ID_County":5954,"Total":324106,"<3 years":6759,"3-5 years":7259,"6-14 years":26546,"15-17 years":9706,"18-24 years":24467,"25-29 years":16069,"30-39 years":33754,"40-49 years":56118,"50-64 years":70136,"65-74 years":39522,">74 years":33772},{"ID_County":5958,"Total":259777,"<3 years":5737,"3-5 years":6573,"6-14 years":24939,"15-17 years":9435,"18-24 years":21281,"25-29 years":13143,"30-39 years":27783,"40-49 years":44064,"50-64 years":52855,"65-74 years":28177,">74 years":25793},{"ID_County":5962,"Total":410222,"<3 years":9548,"3-5 years":10324,"6-14 years":37856,"15-17 years":14014,"18-24 years":33995,"25-29 years":21863,"30-39 years":44075,"40-49 years":70032,"50-64 years":83769,"65-74 years":46511,">74 years":38234},{"ID_County":5966,"Total":133955,"<3 years":3198,"3-5 years":3563,"6-14 years":13282,"15-17 years":4665,"18-24 years":11503,"25-29 years":7287,"30-39 years":15337,"40-49 years":23627,"50-64 years":26414,"65-74 years":13308,">74 years":11771},{"ID_County":5970,"Total":276944,"<3 years":6419,"3-5 years":6621,"6-14 years":24508,"15-17 years":9239,"18-24 years":24562,"25-29 years":16212,"30-39 years":30350,"40-49 years":45083,"50-64 years":57063,"65-74 years":30419,">74 years":26470},{"ID_County":5974,"Total":301785,"<3 years":7075,"3-5 years":7865,"6-14 years":29095,"15-17 years":10405,"18-24 years":24143,"25-29 years":15584,"30-39 years":33477,"40-49 years":52260,"50-64 years":61527,"65-74 years":32259,">74 years":28095},{"ID_County":5978,"Total":394891,"<3 years":8500,"3-5 years":9354,"6-14 years":35420,"15-17 years":12916,"18-24 years":30668,"25-29 years":19737,"30-39 years":42971,"40-49 years":67312,"50-64 years":84883,"65-74 years":44409,">74 years":38722},{"ID_County":6411,"Total":159878,"<3 years":4628,"3-5 years":4433,"6-14 years":12551,"15-17 years":3779,"18-24 years":16280,"25-29 years":14167,"30-39 years":22269,"40-49 years":24572,"50-64 years":28349,"65-74 years":15015,">74 years":13833},{"ID_County":6412,"Total":763380,"<3 years":24095,"3-5 years":21852,"6-14 years":56803,"15-17 years":17403,"18-24 years":58836,"25-29 years":66265,"30-39 years":132109,"40-49 years":127392,"50-64 years":134170,"65-74 years":68150,">74 years":56304},{"ID_County":6413,"Total":130280,"<3 years":4029,"3-5 years":3987,"6-14 years":11681,"15-17 years":3706,"18-24 years":10631,"25-29 years":9708,"30-39 years":18121,"40-49 years":20955,"50-64 years":24049,"65-74 years":12945,">74 years":10469},{"ID_County":6414,"Total":278474,"<3 years":8397,"3-5 years":7971,"6-14 years":23716,"15-17 years":7259,"18-24 years":20580,"25-29 years":19424,"30-39 years":38689,"40-49 years":45713,"50-64 years":52313,"65-74 years":29248,">74 years":25163},{"ID_County":6431,"Total":270340,"<3 years":6027,"3-5 years":6252,"6-14 years":23549,"15-17 years":8904,"18-24 years":20334,"25-29 years":13783,"30-39 years":29588,"40-49 years":47627,"50-64 years":58483,"65-74 years":30591,">74 years":25202},{"ID_County":6432,"Total":297844,"<3 years":7299,"3-5 years":7735,"6-14 years":27199,"15-17 years":9573,"18-24 years":23076,"25-29 years":15385,"30-39 years":34488,"40-49 years":53606,"50-64 years":63052,"65-74 years":32079,">74 years":24352},{"ID_County":6433,"Total":275726,"<3 years":7487,"3-5 years":7411,"6-14 years":25019,"15-17 years":8410,"18-24 years":21774,"25-29 years":16730,"30-39 years":35030,"40-49 years":47344,"50-64 years":54249,"65-74 years":29607,">74 years":22664},{"ID_County":6434,"Total":236914,"<3 years":6264,"3-5 years":6698,"6-14 years":22348,"15-17 years":7209,"18-24 years":15073,"25-29 years":10728,"30-39 years":26847,"40-49 years":43032,"50-64 years":47545,"65-74 years":28548,">74 years":22621},{"ID_County":6435,"Total":420552,"<3 years":10111,"3-5 years":10740,"6-14 years":37498,"15-17 years":12909,"18-24 years":32724,"25-29 years":22199,"30-39 years":49400,"40-49 years":72548,"50-64 years":88276,"65-74 years":46817,">74 years":37330},{"ID_County":6436,"Total":238558,"<3 years":6470,"3-5 years":7033,"6-14 years":21930,"15-17 years":6775,"18-24 years":15068,"25-29 years":12022,"30-39 years":29978,"40-49 years":43432,"50-64 years":47177,"65-74 years":27774,">74 years":20899},{"ID_County":6437,"Total":96703,"<3 years":2126,"3-5 years":2262,"6-14 years":8583,"15-17 years":3312,"18-24 years":7962,"25-29 years":4860,"30-39 years":10162,"40-49 years":15874,"50-64 years":21261,"65-74 years":10684,">74 years":9617},{"ID_County":6438,"Total":355813,"<3 years":9172,"3-5 years":9544,"6-14 years":31128,"15-17 years":10398,"18-24 years":25563,"25-29 years":19780,"30-39 years":44053,"40-49 years":61462,"50-64 years":73346,"65-74 years":40245,">74 years":31122},{"ID_County":6439,"Total":187160,"<3 years":4221,"3-5 years":4773,"6-14 years":17008,"15-17 years":5878,"18-24 years":13252,"25-29 years":8817,"30-39 years":20219,"40-49 years":33624,"50-64 years":40190,"65-74 years":22302,">74 years":16876},{"ID_County":6440,"Total":308339,"<3 years":7498,"3-5 years":7946,"6-14 years":28460,"15-17 years":10067,"18-24 years":23355,"25-29 years":15795,"30-39 years":35583,"40-49 years":55012,"50-64 years":63681,"65-74 years":33315,">74 years":27626},{"ID_County":6531,"Total":270688,"<3 years":6525,"3-5 years":6517,"6-14 years":22429,"15-17 years":8084,"18-24 years":28291,"25-29 years":19629,"30-39 years":32251,"40-49 years":42773,"50-64 years":53966,"65-74 years":26265,">74 years":23957},{"ID_County":6532,"Total":253319,"<3 years":6138,"3-5 years":6393,"6-14 years":22817,"15-17 years":8748,"18-24 years":20738,"25-29 years":13597,"30-39 years":28184,"40-49 years":42578,"50-64 years":52302,"65-74 years":27682,">74 years":24141},{"ID_County":6533,"Total":171912,"<3 years":4141,"3-5 years":4445,"6-14 years":16117,"15-17 years":5792,"18-24 years":13781,"25-29 years":9122,"30-39 years":19196,"40-49 years":29599,"50-64 years":36115,"65-74 years":17928,">74 years":15675},{"ID_County":6534,"Total":247084,"<3 years":5946,"3-5 years":6219,"6-14 years":21457,"15-17 years":7759,"18-24 years":26309,"25-29 years":17900,"30-39 years":28964,"40-49 years":39077,"50-64 years":47870,"65-74 years":24074,">74 years":21509},{"ID_County":6535,"Total":105643,"<3 years":2151,"3-5 years":2338,"6-14 years":8902,"15-17 years":3503,"18-24 years":8020,"25-29 years":4995,"30-39 years":11147,"40-49 years":17194,"50-64 years":23995,"65-74 years":11459,">74 years":11941},{"ID_County":6611,"Total":202137,"<3 years":5194,"3-5 years":5097,"6-14 years":15738,"15-17 years":5208,"18-24 years":20406,"25-29 years":16335,"30-39 years":25313,"40-49 years":30657,"50-64 years":38005,"65-74 years":20794,">74 years":19390},{"ID_County":6631,"Total":223145,"<3 years":5485,"3-5 years":5771,"6-14 years":21426,"15-17 years":7952,"18-24 years":19142,"25-29 years":12833,"30-39 years":25519,"40-49 years":37077,"50-64 years":43551,"65-74 years":22881,">74 years":21508},{"ID_County":6632,"Total":120719,"<3 years":2667,"3-5 years":3001,"6-14 years":10172,"15-17 years":3759,"18-24 years":9121,"25-29 years":6005,"30-39 years":12747,"40-49 years":19538,"50-64 years":26156,"65-74 years":14127,">74 years":13427},{"ID_County":6633,"Total":236764,"<3 years":4984,"3-5 years":5301,"6-14 years":20294,"15-17 years":7780,"18-24 years":16832,"25-29 years":10602,"30-39 years":24348,"40-49 years":40508,"50-64 years":52269,"65-74 years":29774,">74 years":24071},{"ID_County":6634,"Total":179673,"<3 years":3892,"3-5 years":4151,"6-14 years":15511,"15-17 years":5952,"18-24 years":14132,"25-29 years":8830,"30-39 years":19275,"40-49 years":30485,"50-64 years":39014,"65-74 years":20192,">74 years":18238},{"ID_County":6635,"Total":156406,"<3 years":3491,"3-5 years":3877,"6-14 years":14157,"15-17 years":5342,"18-24 years":12154,"25-29 years":7852,"30-39 years":16444,"40-49 years":26269,"50-64 years":33092,"65-74 years":17346,">74 years":16380},{"ID_County":6636,"Total":100629,"<3 years":2008,"3-5 years":2161,"6-14 years":8152,"15-17 years":3179,"18-24 years":7267,"25-29 years":4764,"30-39 years":9729,"40-49 years":16511,"50-64 years":22580,"65-74 years":12574,">74 years":11704},{"ID_County":7111,"Total":114052,"<3 years":2878,"3-5 years":2682,"6-14 years":8439,"15-17 years":3014,"18-24 years":9720,"25-29 years":8783,"30-39 years":14234,"40-49 years":17165,"50-64 years":22243,"65-74 years":12737,">74 years":12157},{"ID_County":7131,"Total":130086,"<3 years":2672,"3-5 years":2866,"6-14 years":11260,"15-17 years":4366,"18-24 years":10014,"25-29 years":6118,"30-39 years":12802,"40-49 years":22257,"50-64 years":27929,"65-74 years":15705,">74 years":14100},{"ID_County":7132,"Total":128805,"<3 years":3009,"3-5 years":3282,"6-14 years":11710,"15-17 years":4574,"18-24 years":10848,"25-29 years":6611,"30-39 years":13485,"40-49 years":21646,"50-64 years":27015,"65-74 years":14066,">74 years":12558},{"ID_County":7133,"Total":158345,"<3 years":3773,"3-5 years":3862,"6-14 years":13798,"15-17 years":5127,"18-24 years":12317,"25-29 years":8023,"30-39 years":16893,"40-49 years":26583,"50-64 years":34517,"65-74 years":17801,">74 years":15651},{"ID_County":7134,"Total":80951,"<3 years":1719,"3-5 years":1811,"6-14 years":6721,"15-17 years":2580,"18-24 years":6430,"25-29 years":4299,"30-39 years":7900,"40-49 years":12993,"50-64 years":18277,"65-74 years":9197,">74 years":9023},{"ID_County":7135,"Total":61375,"<3 years":1307,"3-5 years":1414,"6-14 years":5425,"15-17 years":2005,"18-24 years":4841,"25-29 years":3044,"30-39 years":6101,"40-49 years":10353,"50-64 years":13066,"65-74 years":7035,">74 years":6782},{"ID_County":7137,"Total":214434,"<3 years":4973,"3-5 years":5201,"6-14 years":19033,"15-17 years":7082,"18-24 years":16796,"25-29 years":11104,"30-39 years":23478,"40-49 years":37020,"50-64 years":46356,"65-74 years":23174,">74 years":20217},{"ID_County":7138,"Total":182811,"<3 years":4211,"3-5 years":4543,"6-14 years":17018,"15-17 years":6430,"18-24 years":14959,"25-29 years":8843,"30-39 years":18838,"40-49 years":30612,"50-64 years":38975,"65-74 years":19992,">74 years":18388},{"ID_County":7140,"Total":103163,"<3 years":2316,"3-5 years":2413,"6-14 years":9375,"15-17 years":3543,"18-24 years":8193,"25-29 years":5277,"30-39 years":11058,"40-49 years":17362,"50-64 years":22560,"65-74 years":10833,">74 years":10232},{"ID_County":7141,"Total":122297,"<3 years":2668,"3-5 years":2853,"6-14 years":10557,"15-17 years":3926,"18-24 years":9437,"25-29 years":6041,"30-39 years":12808,"40-49 years":20532,"50-64 years":27055,"65-74 years":14093,">74 years":12328},{"ID_County":7143,"Total":201904,"<3 years":4837,"3-5 years":5167,"6-14 years":18981,"15-17 years":7081,"18-24 years":16423,"25-29 years":10367,"30-39 years":22481,"40-49 years":35491,"50-64 years":42171,"65-74 years":20727,">74 years":18180},{"ID_County":7211,"Total":111528,"<3 years":2802,"3-5 years":2546,"6-14 years":7621,"15-17 years":2651,"18-24 years":14861,"25-29 years":11194,"30-39 years":14478,"40-49 years":16039,"50-64 years":19164,"65-74 years":9957,">74 years":10213},{"ID_County":7231,"Total":112483,"<3 years":2543,"3-5 years":2687,"6-14 years":9824,"15-17 years":3752,"18-24 years":8884,"25-29 years":5812,"30-39 years":12204,"40-49 years":18898,"50-64 years":24355,"65-74 years":11972,">74 years":11553},{"ID_County":7232,"Total":99058,"<3 years":2440,"3-5 years":2497,"6-14 years":9046,"15-17 years":3621,"18-24 years":8372,"25-29 years":5407,"30-39 years":10443,"40-49 years":16808,"50-64 years":20868,"65-74 years":9759,">74 years":9796},{"ID_County":7233,"Total":60646,"<3 years":1295,"3-5 years":1445,"6-14 years":5496,"15-17 years":2131,"18-24 years":4938,"25-29 years":2889,"30-39 years":6044,"40-49 years":9745,"50-64 years":13165,"65-74 years":6993,">74 years":6504},{"ID_County":7235,"Total":149398,"<3 years":3887,"3-5 years":3892,"6-14 years":13531,"15-17 years":5113,"18-24 years":11425,"25-29 years":7736,"30-39 years":17001,"40-49 years":26817,"50-64 years":31600,"65-74 years":14861,">74 years":13535},{"ID_County":7311,"Total":48762,"<3 years":1241,"3-5 years":1198,"6-14 years":4034,"15-17 years":1519,"18-24 years":3890,"25-29 years":2828,"30-39 years":5639,"40-49 years":7546,"50-64 years":9837,"65-74 years":5948,">74 years":5081},{"ID_County":7312,"Total":100030,"<3 years":2389,"3-5 years":2299,"6-14 years":7249,"15-17 years":2679,"18-24 years":11701,"25-29 years":7989,"30-39 years":11510,"40-49 years":14692,"50-64 years":19490,"65-74 years":10580,">74 years":9454},{"ID_County":7313,"Total":46881,"<3 years":1106,"3-5 years":1138,"6-14 years":3697,"15-17 years":1265,"18-24 years":5070,"25-29 years":3395,"30-39 years":5558,"40-49 years":7738,"50-64 years":8946,"65-74 years":4672,">74 years":4297},{"ID_County":7314,"Total":172253,"<3 years":5001,"3-5 years":4901,"6-14 years":14924,"15-17 years":5148,"18-24 years":14871,"25-29 years":11422,"30-39 years":21791,"40-49 years":27748,"50-64 years":32126,"65-74 years":18268,">74 years":16053},{"ID_County":7315,"Total":218578,"<3 years":5710,"3-5 years":5309,"6-14 years":15140,"15-17 years":5072,"18-24 years":25331,"25-29 years":22657,"30-39 years":31368,"40-49 years":31692,"50-64 years":37558,"65-74 years":20743,">74 years":17997},{"ID_County":7316,"Total":53264,"<3 years":1278,"3-5 years":1318,"6-14 years":4301,"15-17 years":1450,"18-24 years":4171,"25-29 years":2935,"30-39 years":5308,"40-49 years":8673,"50-64 years":11561,"65-74 years":6267,">74 years":6002},{"ID_County":7317,"Total":40231,"<3 years":852,"3-5 years":911,"6-14 years":3061,"15-17 years":1164,"18-24 years":3162,"25-29 years":2001,"30-39 years":3957,"40-49 years":6240,"50-64 years":8809,"65-74 years":4905,">74 years":5167},{"ID_County":7318,"Total":50561,"<3 years":1335,"3-5 years":1301,"6-14 years":4334,"15-17 years":1522,"18-24 years":3772,"25-29 years":2875,"30-39 years":5787,"40-49 years":8378,"50-64 years":10748,"65-74 years":5556,">74 years":4953},{"ID_County":7319,"Total":83542,"<3 years":2143,"3-5 years":2278,"6-14 years":7363,"15-17 years":2583,"18-24 years":7175,"25-29 years":5083,"30-39 years":9805,"40-49 years":13506,"50-64 years":17064,"65-74 years":8754,">74 years":7787},{"ID_County":7320,"Total":34193,"<3 years":732,"3-5 years":748,"6-14 years":2829,"15-17 years":987,"18-24 years":2975,"25-29 years":2186,"30-39 years":3680,"40-49 years":5132,"50-64 years":7347,"65-74 years":3873,">74 years":3703},{"ID_County":7331,"Total":129687,"<3 years":3133,"3-5 years":3256,"6-14 years":12441,"15-17 years":4424,"18-24 years":10405,"25-29 years":6599,"30-39 years":14426,"40-49 years":23021,"50-64 years":29164,"65-74 years":12162,">74 years":10658},{"ID_County":7332,"Total":132671,"<3 years":2764,"3-5 years":2942,"6-14 years":11596,"15-17 years":4272,"18-24 years":9418,"25-29 years":5708,"30-39 years":13138,"40-49 years":23420,"50-64 years":30277,"65-74 years":15906,">74 years":13230},{"ID_County":7333,"Total":75325,"<3 years":1762,"3-5 years":1913,"6-14 years":7152,"15-17 years":2572,"18-24 years":6002,"25-29 years":3657,"30-39 years":8085,"40-49 years":12912,"50-64 years":16821,"65-74 years":7465,">74 years":6982},{"ID_County":7334,"Total":129013,"<3 years":3180,"3-5 years":3436,"6-14 years":11845,"15-17 years":4441,"18-24 years":10936,"25-29 years":7313,"30-39 years":15070,"40-49 years":22449,"50-64 years":27254,"65-74 years":12915,">74 years":10174},{"ID_County":7335,"Total":105979,"<3 years":2447,"3-5 years":2605,"6-14 years":9745,"15-17 years":3641,"18-24 years":8580,"25-29 years":5425,"30-39 years":11224,"40-49 years":17637,"50-64 years":23535,"65-74 years":11155,">74 years":9986},{"ID_County":7336,"Total":70219,"<3 years":1494,"3-5 years":1612,"6-14 years":5747,"15-17 years":2378,"18-24 years":5499,"25-29 years":3452,"30-39 years":7052,"40-49 years":11543,"50-64 years":16310,"65-74 years":7603,">74 years":7531},{"ID_County":7337,"Total":110521,"<3 years":2397,"3-5 years":2596,"6-14 years":9713,"15-17 years":3752,"18-24 years":8401,"25-29 years":5249,"30-39 years":11362,"40-49 years":19424,"50-64 years":24685,"65-74 years":12278,">74 years":10663},{"ID_County":7338,"Total":154609,"<3 years":3463,"3-5 years":3670,"6-14 years":13382,"15-17 years":4871,"18-24 years":11348,"25-29 years":7279,"30-39 years":16280,"40-49 years":27305,"50-64 years":34134,"65-74 years":17975,">74 years":14901},{"ID_County":7339,"Total":211417,"<3 years":5276,"3-5 years":5722,"6-14 years":19796,"15-17 years":6807,"18-24 years":15423,"25-29 years":10688,"30-39 years":24281,"40-49 years":38793,"50-64 years":45746,"65-74 years":22033,">74 years":16853},{"ID_County":7340,"Total":94831,"<3 years":1792,"3-5 years":2005,"6-14 years":7675,"15-17 years":3117,"18-24 years":7334,"25-29 years":4402,"30-39 years":9298,"40-49 years":16216,"50-64 years":21556,"65-74 years":11229,">74 years":10207},{"ID_County":8111,"Total":635911,"<3 years":18264,"3-5 years":16763,"6-14 years":47572,"15-17 years":15811,"18-24 years":57524,"25-29 years":56555,"30-39 years":98766,"40-49 years":97175,"50-64 years":108859,"65-74 years":64529,">74 years":54095},{"ID_County":8115,"Total":392807,"<3 years":10714,"3-5 years":11152,"6-14 years":37389,"15-17 years":13085,"18-24 years":30585,"25-29 years":22359,"30-39 years":48825,"40-49 years":66628,"50-64 years":76042,"65-74 years":43387,">74 years":32640},{"ID_County":8116,"Total":535024,"<3 years":14229,"3-5 years":14735,"6-14 years":49508,"15-17 years":17333,"18-24 years":41624,"25-29 years":30764,"30-39 years":66292,"40-49 years":90987,"50-64 years":103153,"65-74 years":59619,">74 years":46782},{"ID_County":8117,"Total":258145,"<3 years":6258,"3-5 years":6638,"6-14 years":24010,"15-17 years":8710,"18-24 years":21221,"25-29 years":14050,"30-39 years":29032,"40-49 years":42730,"50-64 years":51711,"65-74 years":29189,">74 years":24595},{"ID_County":8118,"Total":545423,"<3 years":14878,"3-5 years":15378,"6-14 years":50805,"15-17 years":17297,"18-24 years":43418,"25-29 years":30821,"30-39 years":69581,"40-49 years":92967,"50-64 years":105368,"65-74 years":58999,">74 years":45911},{"ID_County":8119,"Total":427248,"<3 years":10576,"3-5 years":11522,"6-14 years":40477,"15-17 years":14225,"18-24 years":33657,"25-29 years":22756,"30-39 years":49430,"40-49 years":74079,"50-64 years":84514,"65-74 years":47799,">74 years":38211},{"ID_County":8121,"Total":126592,"<3 years":3457,"3-5 years":3591,"6-14 years":11098,"15-17 years":3719,"18-24 years":10745,"25-29 years":8462,"30-39 years":16811,"40-49 years":18990,"50-64 years":23646,"65-74 years":13941,">74 years":12131},{"ID_County":8125,"Total":344456,"<3 years":8657,"3-5 years":9288,"6-14 years":34300,"15-17 years":12427,"18-24 years":28515,"25-29 years":18796,"30-39 years":41546,"40-49 years":60127,"50-64 years":68606,"65-74 years":34184,">74 years":28012},{"ID_County":8126,"Total":112655,"<3 years":2896,"3-5 years":3056,"6-14 years":11061,"15-17 years":4074,"18-24 years":10000,"25-29 years":6516,"30-39 years":13037,"40-49 years":19036,"50-64 years":22445,"65-74 years":10706,">74 years":9828},{"ID_County":8127,"Total":196761,"<3 years":5159,"3-5 years":5348,"6-14 years":19500,"15-17 years":7402,"18-24 years":16937,"25-29 years":11711,"30-39 years":22886,"40-49 years":32516,"50-64 years":40201,"65-74 years":18322,">74 years":16776},{"ID_County":8128,"Total":132399,"<3 years":2941,"3-5 years":3264,"6-14 years":12215,"15-17 years":4690,"18-24 years":10674,"25-29 years":7078,"30-39 years":14334,"40-49 years":21539,"50-64 years":28144,"65-74 years":14024,">74 years":13497},{"ID_County":8135,"Total":132777,"<3 years":3137,"3-5 years":3389,"6-14 years":12573,"15-17 years":4610,"18-24 years":10779,"25-29 years":7285,"30-39 years":14351,"40-49 years":21332,"50-64 years":26691,"65-74 years":14714,">74 years":13917},{"ID_County":8136,"Total":314025,"<3 years":7924,"3-5 years":8506,"6-14 years":31043,"15-17 years":11539,"18-24 years":26792,"25-29 years":17668,"30-39 years":36650,"40-49 years":50978,"50-64 years":62145,"65-74 years":32238,">74 years":28540},{"ID_County":8211,"Total":55185,"<3 years":1148,"3-5 years":1193,"6-14 years":4185,"15-17 years":1571,"18-24 years":3574,"25-29 years":2669,"30-39 years":5659,"40-49 years":8843,"50-64 years":11700,"65-74 years":7386,">74 years":7259},{"ID_County":8212,"Total":312060,"<3 years":8091,"3-5 years":7599,"6-14 years":22719,"15-17 years":7526,"18-24 years":32348,"25-29 years":27526,"30-39 years":42831,"40-49 years":48884,"50-64 years":55442,"65-74 years":31116,">74 years":27976},{"ID_County":8215,"Total":445101,"<3 years":10769,"3-5 years":11507,"6-14 years":40635,"15-17 years":14667,"18-24 years":35138,"25-29 years":23920,"30-39 years":51449,"40-49 years":77162,"50-64 years":92760,"65-74 years":47388,">74 years":39704},{"ID_County":8216,"Total":231420,"<3 years":5315,"3-5 years":5747,"6-14 years":21139,"15-17 years":7684,"18-24 years":18072,"25-29 years":12388,"30-39 years":25493,"40-49 years":39814,"50-64 years":49123,"65-74 years":24867,">74 years":21778},{"ID_County":8221,"Total":161485,"<3 years":4402,"3-5 years":3953,"6-14 years":10671,"15-17 years":3725,"18-24 years":21074,"25-29 years":18615,"30-39 years":23355,"40-49 years":22865,"50-64 years":26487,"65-74 years":14048,">74 years":12291},{"ID_County":8222,"Total":310658,"<3 years":8256,"3-5 years":7985,"6-14 years":23892,"15-17 years":8400,"18-24 years":29662,"25-29 years":24098,"30-39 years":42664,"40-49 years":48941,"50-64 years":57386,"65-74 years":31940,">74 years":27433},{"ID_County":8225,"Total":143633,"<3 years":3297,"3-5 years":3593,"6-14 years":13488,"15-17 years":5003,"18-24 years":11979,"25-29 years":7548,"30-39 years":15529,"40-49 years":24303,"50-64 years":30576,"65-74 years":15098,">74 years":13220},{"ID_County":8226,"Total":548355,"<3 years":13620,"3-5 years":14280,"6-14 years":48771,"15-17 years":17680,"18-24 years":42310,"25-29 years":30567,"30-39 years":63014,"40-49 years":95511,"50-64 years":112993,"65-74 years":60823,">74 years":48784},{"ID_County":8231,"Total":125957,"<3 years":3340,"3-5 years":3408,"6-14 years":11096,"15-17 years":3855,"18-24 years":10994,"25-29 years":8385,"30-39 years":14997,"40-49 years":18771,"50-64 years":24286,"65-74 years":13825,">74 years":13000},{"ID_County":8235,"Total":159201,"<3 years":3821,"3-5 years":4116,"6-14 years":15959,"15-17 years":5811,"18-24 years":13337,"25-29 years":8171,"30-39 years":17380,"40-49 years":26577,"50-64 years":32805,"65-74 years":16901,">74 years":14325},{"ID_County":8236,"Total":199556,"<3 years":4677,"3-5 years":4970,"6-14 years":19707,"15-17 years":7171,"18-24 years":16189,"25-29 years":9951,"30-39 years":21503,"40-49 years":35037,"50-64 years":40732,"65-74 years":21814,">74 years":17804},{"ID_County":8237,"Total":118243,"<3 years":2918,"3-5 years":3092,"6-14 years":11640,"15-17 years":4431,"18-24 years":10074,"25-29 years":6573,"30-39 years":13169,"40-49 years":19823,"50-64 years":23735,"65-74 years":12133,">74 years":10655},{"ID_County":8311,"Total":231195,"<3 years":6732,"3-5 years":6129,"6-14 years":18006,"15-17 years":5752,"18-24 years":27633,"25-29 years":23158,"30-39 years":32661,"40-49 years":34232,"50-64 years":38810,"65-74 years":19711,">74 years":18373},{"ID_County":8315,"Total":263601,"<3 years":6777,"3-5 years":7103,"6-14 years":25171,"15-17 years":9407,"18-24 years":21122,"25-29 years":13623,"30-39 years":28615,"40-49 years":44976,"50-64 years":54187,"65-74 years":29000,">74 years":23618},{"ID_County":8316,"Total":166408,"<3 years":4199,"3-5 years":4574,"6-14 years":16018,"15-17 years":5768,"18-24 years":13307,"25-29 years":8856,"30-39 years":18497,"40-49 years":28891,"50-64 years":34416,"65-74 years":17520,">74 years":14362},{"ID_County":8317,"Total":430953,"<3 years":11009,"3-5 years":11750,"6-14 years":40781,"15-17 years":14992,"18-24 years":36418,"25-29 years":23690,"30-39 years":47863,"40-49 years":72243,"50-64 years":87847,"65-74 years":43995,">74 years":40367},{"ID_County":8325,"Total":139878,"<3 years":3489,"3-5 years":3798,"6-14 years":13812,"15-17 years":5162,"18-24 years":11641,"25-29 years":7317,"30-39 years":15446,"40-49 years":23345,"50-64 years":27497,"65-74 years":15456,">74 years":12914},{"ID_County":8326,"Total":212506,"<3 years":5156,"3-5 years":5504,"6-14 years":19118,"15-17 years":7039,"18-24 years":18418,"25-29 years":11943,"30-39 years":22803,"40-49 years":33526,"50-64 years":43342,"65-74 years":24095,">74 years":21561},{"ID_County":8327,"Total":140766,"<3 years":3700,"3-5 years":4105,"6-14 years":14113,"15-17 years":4883,"18-24 years":11969,"25-29 years":8389,"30-39 years":16531,"40-49 years":22373,"50-64 years":27518,"65-74 years":14428,">74 years":12756},{"ID_County":8335,"Total":286305,"<3 years":7108,"3-5 years":7408,"6-14 years":25491,"15-17 years":8781,"18-24 years":27063,"25-29 years":17795,"30-39 years":31682,"40-49 years":47539,"50-64 years":55009,"65-74 years":31683,">74 years":26745},{"ID_County":8336,"Total":228736,"<3 years":5887,"3-5 years":6083,"6-14 years":21803,"15-17 years":7986,"18-24 years":18600,"25-29 years":12555,"30-39 years":25612,"40-49 years":39716,"50-64 years":45920,"65-74 years":23913,">74 years":20663},{"ID_County":8337,"Total":171003,"<3 years":4492,"3-5 years":4680,"6-14 years":16885,"15-17 years":6303,"18-24 years":14154,"25-29 years":9090,"30-39 years":18348,"40-49 years":28022,"50-64 years":34668,"65-74 years":18261,">74 years":16100},{"ID_County":8415,"Total":287034,"<3 years":7212,"3-5 years":7679,"6-14 years":27061,"15-17 years":9643,"18-24 years":24530,"25-29 years":16369,"30-39 years":33242,"40-49 years":48184,"50-64 years":56305,"65-74 years":30591,">74 years":26220},{"ID_County":8416,"Total":228678,"<3 years":6040,"3-5 years":6220,"6-14 years":21151,"15-17 years":7409,"18-24 years":25806,"25-29 years":18704,"30-39 years":28114,"40-49 years":36555,"50-64 years":42658,"65-74 years":19685,">74 years":16337},{"ID_County":8417,"Total":189363,"<3 years":4328,"3-5 years":4787,"6-14 years":17143,"15-17 years":6664,"18-24 years":15977,"25-29 years":10127,"30-39 years":20522,"40-49 years":31446,"50-64 years":38957,"65-74 years":20759,">74 years":18652},{"ID_County":8421,"Total":126790,"<3 years":3500,"3-5 years":3311,"6-14 years":10309,"15-17 years":3482,"18-24 years":12571,"25-29 years":10685,"30-39 years":17802,"40-49 years":18883,"50-64 years":22793,"65-74 years":12804,">74 years":10649},{"ID_County":8425,"Total":197076,"<3 years":5196,"3-5 years":5611,"6-14 years":20464,"15-17 years":7350,"18-24 years":17113,"25-29 years":10706,"30-39 years":22825,"40-49 years":33582,"50-64 years":38532,"65-74 years":19245,">74 years":16453},{"ID_County":8426,"Total":201282,"<3 years":5519,"3-5 years":5895,"6-14 years":20698,"15-17 years":7451,"18-24 years":17917,"25-29 years":11726,"30-39 years":23693,"40-49 years":33710,"50-64 years":39274,"65-74 years":18940,">74 years":16459},{"ID_County":8435,"Total":217470,"<3 years":5355,"3-5 years":5567,"6-14 years":19925,"15-17 years":7509,"18-24 years":17373,"25-29 years":11749,"30-39 years":24645,"40-49 years":36214,"50-64 years":43672,"65-74 years":26318,">74 years":19142},{"ID_County":8436,"Total":285424,"<3 years":7549,"3-5 years":7931,"6-14 years":28769,"15-17 years":10399,"18-24 years":25401,"25-29 years":16049,"30-39 years":33379,"40-49 years":47600,"50-64 years":55205,"65-74 years":29060,">74 years":24084},{"ID_County":8437,"Total":130849,"<3 years":3258,"3-5 years":3546,"6-14 years":13244,"15-17 years":5097,"18-24 years":11667,"25-29 years":7250,"30-39 years":14116,"40-49 years":22041,"50-64 years":25930,"65-74 years":13209,">74 years":11491},{"ID_County":9161,"Total":137392,"<3 years":3838,"3-5 years":3884,"6-14 years":11604,"15-17 years":3958,"18-24 years":11523,"25-29 years":10439,"30-39 years":19355,"40-49 years":21240,"50-64 years":25612,"65-74 years":14289,">74 years":11649},{"ID_County":9162,"Total":1484226,"<3 years":44008,"3-5 years":39199,"6-14 years":101005,"15-17 years":30755,"18-24 years":122003,"25-29 years":134016,"30-39 years":248530,"40-49 years":240813,"50-64 years":257111,"65-74 years":153850,">74 years":112936},{"ID_County":9163,"Total":63551,"<3 years":1778,"3-5 years":1736,"6-14 years":5182,"15-17 years":1733,"18-24 years":5386,"25-29 years":4822,"30-39 years":8578,"40-49 years":10056,"50-64 years":11779,"65-74 years":7108,">74 years":5392},{"ID_County":9171,"Total":111516,"<3 years":2711,"3-5 years":2839,"6-14 years":10236,"15-17 years":3772,"18-24 years":8747,"25-29 years":6050,"30-39 years":12378,"40-49 years":18519,"50-64 years":23137,"65-74 years":12387,">74 years":10740},{"ID_County":9172,"Total":105929,"<3 years":2394,"3-5 years":2577,"6-14 years":8887,"15-17 years":3301,"18-24 years":8898,"25-29 years":6370,"30-39 years":11761,"40-49 years":16776,"50-64 years":20698,"65-74 years":13311,">74 years":10958},{"ID_County":9173,"Total":127917,"<3 years":3277,"3-5 years":3465,"6-14 years":12108,"15-17 years":4364,"18-24 years":9811,"25-29 years":6551,"30-39 years":14466,"40-49 years":22270,"50-64 years":25267,"65-74 years":14750,">74 years":11588},{"ID_County":9174,"Total":154899,"<3 years":4205,"3-5 years":4534,"6-14 years":14819,"15-17 years":5204,"18-24 years":12308,"25-29 years":8739,"30-39 years":19800,"40-49 years":28366,"50-64 years":29974,"65-74 years":15479,">74 years":11470},{"ID_County":9175,"Total":143649,"<3 years":4089,"3-5 years":4428,"6-14 years":14736,"15-17 years":4831,"18-24 years":10659,"25-29 years":7237,"30-39 years":17472,"40-49 years":26795,"50-64 years":26789,"65-74 years":15594,">74 years":11020},{"ID_County":9176,"Total":132881,"<3 years":3610,"3-5 years":3855,"6-14 years":13647,"15-17 years":4833,"18-24 years":12042,"25-29 years":7998,"30-39 years":16453,"40-49 years":22573,"50-64 years":25517,"65-74 years":12079,">74 years":10272},{"ID_County":9177,"Total":138182,"<3 years":3830,"3-5 years":4118,"6-14 years":14486,"15-17 years":4936,"18-24 years":11226,"25-29 years":7801,"30-39 years":17758,"40-49 years":26083,"50-64 years":26450,"65-74 years":12032,">74 years":9462},{"ID_County":9178,"Total":180007,"<3 years":5201,"3-5 years":5355,"6-14 years":17633,"15-17 years":5897,"18-24 years":16309,"25-29 years":12180,"30-39 years":24638,"40-49 years":32941,"50-64 years":32622,"65-74 years":15591,">74 years":11641},{"ID_County":9179,"Total":219311,"<3 years":5861,"3-5 years":6014,"6-14 years":20171,"15-17 years":6703,"18-24 years":15947,"25-29 years":11287,"30-39 years":26676,"40-49 years":38204,"50-64 years":42902,"65-74 years":27474,">74 years":18072},{"ID_County":9180,"Total":88424,"<3 years":1960,"3-5 years":2061,"6-14 years":7387,"15-17 years":2879,"18-24 years":6533,"25-29 years":4548,"30-39 years":9406,"40-49 years":14836,"50-64 years":17171,"65-74 years":12095,">74 years":9549},{"ID_County":9181,"Total":120302,"<3 years":3150,"3-5 years":3465,"6-14 years":12718,"15-17 years":4419,"18-24 years":9350,"25-29 years":5989,"30-39 years":13745,"40-49 years":22135,"50-64 years":23677,"65-74 years":12384,">74 years":9269},{"ID_County":9182,"Total":100010,"<3 years":2512,"3-5 years":2638,"6-14 years":8867,"15-17 years":3250,"18-24 years":7554,"25-29 years":5037,"30-39 years":11014,"40-49 years":17526,"50-64 years":19668,"65-74 years":12652,">74 years":9292},{"ID_County":9183,"Total":115872,"<3 years":2914,"3-5 years":3010,"6-14 years":11112,"15-17 years":3992,"18-24 years":9514,"25-29 years":6105,"30-39 years":13349,"40-49 years":19689,"50-64 years":23631,"65-74 years":12173,">74 years":10386},{"ID_County":9184,"Total":350473,"<3 years":10186,"3-5 years":10857,"6-14 years":32692,"15-17 years":10060,"18-24 years":25109,"25-29 years":18960,"30-39 years":44011,"40-49 years":62628,"50-64 years":64883,"65-74 years":42512,">74 years":28575},{"ID_County":9185,"Total":97303,"<3 years":2605,"3-5 years":2654,"6-14 years":9547,"15-17 years":3515,"18-24 years":8156,"25-29 years":5535,"30-39 years":12031,"40-49 years":16523,"50-64 years":19302,"65-74 years":9563,">74 years":7871},{"ID_County":9186,"Total":128227,"<3 years":3327,"3-5 years":3554,"6-14 years":12392,"15-17 years":4514,"18-24 years":10588,"25-29 years":7612,"30-39 years":15605,"40-49 years":22948,"50-64 years":25672,"65-74 years":12431,">74 years":9583},{"ID_County":9187,"Total":261330,"<3 years":6649,"3-5 years":7035,"6-14 years":25474,"15-17 years":9342,"18-24 years":21236,"25-29 years":13478,"30-39 years":29255,"40-49 years":45579,"50-64 years":52425,"65-74 years":28973,">74 years":21883},{"ID_County":9188,"Total":136667,"<3 years":3389,"3-5 years":3987,"6-14 years":13387,"15-17 years":4354,"18-24 years":9159,"25-29 years":5894,"30-39 years":14429,"40-49 years":24530,"50-64 years":27136,"65-74 years":17873,">74 years":12528},{"ID_County":9189,"Total":177319,"<3 years":4286,"3-5 years":4510,"6-14 years":16133,"15-17 years":6162,"18-24 years":14153,"25-29 years":9104,"30-39 years":19269,"40-49 years":29141,"50-64 years":36128,"65-74 years":21119,">74 years":17314},{"ID_County":9190,"Total":135478,"<3 years":3415,"3-5 years":3642,"6-14 years":13247,"15-17 years":4870,"18-24 years":10721,"25-29 years":6965,"30-39 years":14724,"40-49 years":23551,"50-64 years":27141,"65-74 years":15295,">74 years":11908},{"ID_County":9261,"Total":73411,"<3 years":1910,"3-5 years":1801,"6-14 years":5549,"15-17 years":1898,"18-24 years":6306,"25-29 years":4759,"30-39 years":9749,"40-49 years":11568,"50-64 years":14092,"65-74 years":8245,">74 years":7535},{"ID_County":9262,"Total":52803,"<3 years":1091,"3-5 years":1077,"6-14 years":3744,"15-17 years":1254,"18-24 years":6355,"25-29 years":4220,"30-39 years":5850,"40-49 years":7358,"50-64 years":10324,"65-74 years":6077,">74 years":5454},{"ID_County":9263,"Total":47791,"<3 years":1034,"3-5 years":1065,"6-14 years":3384,"15-17 years":1297,"18-24 years":3982,"25-29 years":3318,"30-39 years":5695,"40-49 years":7670,"50-64 years":10173,"65-74 years":5300,">74 years":4873},{"ID_County":9271,"Total":119478,"<3 years":2730,"3-5 years":2964,"6-14 years":10991,"15-17 years":4018,"18-24 years":10108,"25-29 years":6787,"30-39 years":14178,"40-49 years":20190,"50-64 years":25219,"65-74 years":12005,">74 years":10288},{"ID_County":9272,"Total":78362,"<3 years":1618,"3-5 years":1810,"6-14 years":7277,"15-17 years":2789,"18-24 years":6459,"25-29 years":4208,"30-39 years":8713,"40-49 years":13143,"50-64 years":17283,"65-74 years":7797,">74 years":7264},{"ID_County":9273,"Total":123058,"<3 years":3262,"3-5 years":3395,"6-14 years":12116,"15-17 years":4325,"18-24 years":10500,"25-29 years":6969,"30-39 years":15090,"40-49 years":21213,"50-64 years":24622,"65-74 years":11634,">74 years":9933},{"ID_County":9274,"Total":159895,"<3 years":4249,"3-5 years":4488,"6-14 years":15925,"15-17 years":5700,"18-24 years":12971,"25-29 years":8500,"30-39 years":19253,"40-49 years":28852,"50-64 years":32558,"65-74 years":15277,">74 years":12121},{"ID_County":9275,"Total":192656,"<3 years":4408,"3-5 years":4590,"6-14 years":17650,"15-17 years":6623,"18-24 years":15537,"25-29 years":10326,"30-39 years":22113,"40-49 years":32289,"50-64 years":40975,"65-74 years":20543,">74 years":17605},{"ID_County":9276,"Total":77410,"<3 years":1686,"3-5 years":1811,"6-14 years":6804,"15-17 years":2477,"18-24 years":6410,"25-29 years":4137,"30-39 years":8695,"40-49 years":12580,"50-64 years":17350,"65-74 years":8228,">74 years":7234},{"ID_County":9277,"Total":121502,"<3 years":2949,"3-5 years":3059,"6-14 years":11452,"15-17 years":4329,"18-24 years":9805,"25-29 years":6620,"30-39 years":13464,"40-49 years":20185,"50-64 years":24898,"65-74 years":12959,">74 years":11782},{"ID_County":9278,"Total":101120,"<3 years":2510,"3-5 years":2721,"6-14 years":10095,"15-17 years":3543,"18-24 years":8282,"25-29 years":5260,"30-39 years":11858,"40-49 years":17790,"50-64 years":21139,"65-74 years":9744,">74 years":8180},{"ID_County":9279,"Total":96683,"<3 years":2280,"3-5 years":2455,"6-14 years":9129,"15-17 years":3366,"18-24 years":8365,"25-29 years":5484,"30-39 years":11350,"40-49 years":16472,"50-64 years":20164,"65-74 years":9553,">74 years":8064},{"ID_County":9361,"Total":42207,"<3 years":1001,"3-5 years":956,"6-14 years":3329,"15-17 years":1233,"18-24 years":3582,"25-29 years":2748,"30-39 years":4782,"40-49 years":6669,"50-64 years":8673,"65-74 years":4642,">74 years":4594},{"ID_County":9362,"Total":153094,"<3 years":4168,"3-5 years":3773,"6-14 years":10503,"15-17 years":3481,"18-24 years":16632,"25-29 years":14944,"30-39 years":22286,"40-49 years":23327,"50-64 years":26042,"65-74 years":14546,">74 years":13393},{"ID_County":9363,"Total":42743,"<3 years":943,"3-5 years":979,"6-14 years":3516,"15-17 years":1256,"18-24 years":3536,"25-29 years":2647,"30-39 years":4930,"40-49 years":6805,"50-64 years":8583,"65-74 years":4973,">74 years":4575},{"ID_County":9371,"Total":103049,"<3 years":2383,"3-5 years":2454,"6-14 years":9707,"15-17 years":3684,"18-24 years":8761,"25-29 years":5444,"30-39 years":11188,"40-49 years":17766,"50-64 years":21695,"65-74 years":10442,">74 years":9527},{"ID_County":9372,"Total":127998,"<3 years":2969,"3-5 years":3039,"6-14 years":11584,"15-17 years":4395,"18-24 years":10721,"25-29 years":7291,"30-39 years":14830,"40-49 years":21363,"50-64 years":27238,"65-74 years":12949,">74 years":11620},{"ID_County":9373,"Total":134573,"<3 years":3350,"3-5 years":3572,"6-14 years":13237,"15-17 years":5046,"18-24 years":11752,"25-29 years":7453,"30-39 years":15525,"40-49 years":23615,"50-64 years":27405,"65-74 years":12632,">74 years":10987},{"ID_County":9374,"Total":94450,"<3 years":2157,"3-5 years":2349,"6-14 years":8937,"15-17 years":3417,"18-24 years":8112,"25-29 years":5232,"30-39 years":10457,"40-49 years":16282,"50-64 years":19756,"65-74 years":9377,">74 years":8376},{"ID_County":9375,"Total":194070,"<3 years":4918,"3-5 years":5137,"6-14 years":18543,"15-17 years":6661,"18-24 years":15738,"25-29 years":10318,"30-39 years":23294,"40-49 years":34847,"50-64 years":41352,"65-74 years":18690,">74 years":14572},{"ID_County":9376,"Total":147872,"<3 years":3278,"3-5 years":3583,"6-14 years":13493,"15-17 years":4974,"18-24 years":12498,"25-29 years":8085,"30-39 years":17372,"40-49 years":25389,"50-64 years":30660,"65-74 years":14816,">74 years":13723},{"ID_County":9377,"Total":72046,"<3 years":1638,"3-5 years":1572,"6-14 years":6364,"15-17 years":2584,"18-24 years":5883,"25-29 years":3729,"30-39 years":7757,"40-49 years":12100,"50-64 years":15248,"65-74 years":7753,">74 years":7417},{"ID_County":9461,"Total":77373,"<3 years":1960,"3-5 years":1815,"6-14 years":5438,"15-17 years":2026,"18-24 years":8361,"25-29 years":6371,"30-39 years":9526,"40-49 years":11816,"50-64 years":14096,"65-74 years":8027,">74 years":7938},{"ID_County":9462,"Total":74783,"<3 years":1663,"3-5 years":1575,"6-14 years":5139,"15-17 years":1907,"18-24 years":9631,"25-29 years":5795,"30-39 years":8548,"40-49 years":10468,"50-64 years":14427,"65-74 years":8288,">74 years":7341},{"ID_County":9463,"Total":41072,"<3 years":880,"3-5 years":946,"6-14 years":3085,"15-17 years":1135,"18-24 years":3681,"25-29 years":2641,"30-39 years":4313,"40-49 years":6615,"50-64 years":8386,"65-74 years":4735,">74 years":4655},{"ID_County":9464,"Total":45825,"<3 years":999,"3-5 years":974,"6-14 years":3575,"15-17 years":1235,"18-24 years":3716,"25-29 years":2637,"30-39 years":4953,"40-49 years":7125,"50-64 years":9604,"65-74 years":5595,">74 years":5411},{"ID_County":9471,"Total":147163,"<3 years":3695,"3-5 years":3898,"6-14 years":14159,"15-17 years":5241,"18-24 years":12661,"25-29 years":8240,"30-39 years":17562,"40-49 years":26282,"50-64 years":30334,"65-74 years":13675,">74 years":11417},{"ID_County":9472,"Total":103664,"<3 years":2374,"3-5 years":2550,"6-14 years":9394,"15-17 years":3522,"18-24 years":8108,"25-29 years":5195,"30-39 years":11543,"40-49 years":18063,"50-64 years":22093,"65-74 years":11134,">74 years":9687},{"ID_County":9473,"Total":86747,"<3 years":1786,"3-5 years":1986,"6-14 years":7595,"15-17 years":2873,"18-24 years":6964,"25-29 years":4340,"30-39 years":9076,"40-49 years":14995,"50-64 years":18847,"65-74 years":9568,">74 years":8717},{"ID_County":9474,"Total":116203,"<3 years":2771,"3-5 years":3025,"6-14 years":10794,"15-17 years":4009,"18-24 years":9823,"25-29 years":6260,"30-39 years":12937,"40-49 years":20532,"50-64 years":24781,"65-74 years":11615,">74 years":9657},{"ID_County":9475,"Total":94801,"<3 years":1859,"3-5 years":2008,"6-14 years":7960,"15-17 years":3036,"18-24 years":6972,"25-29 years":4164,"30-39 years":9368,"40-49 years":15939,"50-64 years":20546,"65-74 years":11608,">74 years":11340},{"ID_County":9476,"Total":66743,"<3 years":1356,"3-5 years":1346,"6-14 years":5455,"15-17 years":2006,"18-24 years":4992,"25-29 years":3362,"30-39 years":7287,"40-49 years":11542,"50-64 years":14730,"65-74 years":7553,">74 years":7114},{"ID_County":9477,"Total":71566,"<3 years":1464,"3-5 years":1679,"6-14 years":6058,"15-17 years":2276,"18-24 years":5232,"25-29 years":3425,"30-39 years":7799,"40-49 years":12283,"50-64 years":15799,"65-74 years":8002,">74 years":7548},{"ID_County":9478,"Total":66776,"<3 years":1507,"3-5 years":1528,"6-14 years":5624,"15-17 years":2235,"18-24 years":5335,"25-29 years":3466,"30-39 years":7520,"40-49 years":11312,"50-64 years":14276,"65-74 years":7354,">74 years":6619},{"ID_County":9479,"Total":72655,"<3 years":1386,"3-5 years":1471,"6-14 years":5650,"15-17 years":2212,"18-24 years":5159,"25-29 years":3421,"30-39 years":6989,"40-49 years":11845,"50-64 years":16156,"65-74 years":9384,">74 years":8979},{"ID_County":9561,"Total":41798,"<3 years":1016,"3-5 years":1034,"6-14 years":3335,"15-17 years":1269,"18-24 years":3485,"25-29 years":2737,"30-39 years":4803,"40-49 years":6700,"50-64 years":8373,"65-74 years":4537,">74 years":4508},{"ID_County":9562,"Total":112528,"<3 years":2911,"3-5 years":2722,"6-14 years":8981,"15-17 years":2860,"18-24 years":11519,"25-29 years":10577,"30-39 years":15819,"40-49 years":17143,"50-64 years":19415,"65-74 years":10696,">74 years":9886},{"ID_County":9563,"Total":128497,"<3 years":3322,"3-5 years":3153,"6-14 years":10594,"15-17 years":3579,"18-24 years":10426,"25-29 years":8415,"30-39 years":17722,"40-49 years":22261,"50-64 years":25179,"65-74 years":13151,">74 years":10695},{"ID_County":9564,"Total":518370,"<3 years":13618,"3-5 years":13226,"6-14 years":37870,"15-17 years":12754,"18-24 years":43612,"25-29 years":39338,"30-39 years":71870,"40-49 years":80840,"50-64 years":98009,"65-74 years":57670,">74 years":49563},{"ID_County":9565,"Total":40981,"<3 years":946,"3-5 years":1094,"6-14 years":3645,"15-17 years":1376,"18-24 years":3052,"25-29 years":2253,"30-39 years":4668,"40-49 years":7167,"50-64 years":8183,"65-74 years":4789,">74 years":3807},{"ID_County":9571,"Total":184591,"<3 years":4435,"3-5 years":4812,"6-14 years":17993,"15-17 years":6984,"18-24 years":16153,"25-29 years":9977,"30-39 years":20739,"40-49 years":31088,"50-64 years":37837,"65-74 years":17863,">74 years":16713},{"ID_County":9572,"Total":137262,"<3 years":3495,"3-5 years":3638,"6-14 years":12958,"15-17 years":4575,"18-24 years":11019,"25-29 years":7260,"30-39 years":15702,"40-49 years":24075,"50-64 years":29554,"65-74 years":14378,">74 years":10608},{"ID_County":9573,"Total":117853,"<3 years":2818,"3-5 years":2869,"6-14 years":10143,"15-17 years":3700,"18-24 years":8717,"25-29 years":6006,"30-39 years":13047,"40-49 years":20962,"50-64 years":25243,"65-74 years":13946,">74 years":10401},{"ID_County":9574,"Total":170792,"<3 years":3797,"3-5 years":4054,"6-14 years":15073,"15-17 years":5645,"18-24 years":12927,"25-29 years":8286,"30-39 years":18358,"40-49 years":30121,"50-64 years":36233,"65-74 years":20291,">74 years":16009},{"ID_County":9575,"Total":101014,"<3 years":2297,"3-5 years":2552,"6-14 years":9620,"15-17 years":3661,"18-24 years":8554,"25-29 years":5418,"30-39 years":10892,"40-49 years":17227,"50-64 years":21367,"65-74 years":10091,">74 years":9336},{"ID_County":9576,"Total":126749,"<3 years":3020,"3-5 years":3172,"6-14 years":11984,"15-17 years":4590,"18-24 years":10309,"25-29 years":6619,"30-39 years":14087,"40-49 years":22574,"50-64 years":26216,"65-74 years":13624,">74 years":10552},{"ID_County":9577,"Total":94734,"<3 years":2191,"3-5 years":2340,"6-14 years":8946,"15-17 years":3334,"18-24 years":7876,"25-29 years":4931,"30-39 years":10196,"40-49 years":15710,"50-64 years":19867,"65-74 years":10118,">74 years":9222},{"ID_County":9661,"Total":71002,"<3 years":1769,"3-5 years":1879,"6-14 years":5850,"15-17 years":1993,"18-24 years":5585,"25-29 years":4752,"30-39 years":9166,"40-49 years":11642,"50-64 years":14337,"65-74 years":7339,">74 years":6690},{"ID_County":9662,"Total":53426,"<3 years":1350,"3-5 years":1396,"6-14 years":4116,"15-17 years":1483,"18-24 years":4589,"25-29 years":3580,"30-39 years":5929,"40-49 years":7450,"50-64 years":10730,"65-74 years":6339,">74 years":6464},{"ID_County":9663,"Total":127934,"<3 years":2751,"3-5 years":2504,"6-14 years":7499,"15-17 years":2695,"18-24 years":18174,"25-29 years":13865,"30-39 years":15710,"40-49 years":17290,"50-64 years":21871,"65-74 years":12728,">74 years":12848},{"ID_County":9671,"Total":174200,"<3 years":3972,"3-5 years":4275,"6-14 years":15823,"15-17 years":6138,"18-24 years":14057,"25-29 years":9197,"30-39 years":18996,"40-49 years":31288,"50-64 years":36827,"65-74 years":18088,">74 years":15539},{"ID_County":9672,"Total":103235,"<3 years":2228,"3-5 years":2383,"6-14 years":8902,"15-17 years":3491,"18-24 years":8085,"25-29 years":5259,"30-39 years":10701,"40-49 years":16789,"50-64 years":22430,"65-74 years":11632,">74 years":11335},{"ID_County":9673,"Total":79635,"<3 years":1828,"3-5 years":1996,"6-14 years":7398,"15-17 years":2918,"18-24 years":6649,"25-29 years":4137,"30-39 years":8475,"40-49 years":13197,"50-64 years":17150,"65-74 years":8114,">74 years":7772},{"ID_County":9674,"Total":84384,"<3 years":1927,"3-5 years":2015,"6-14 years":7875,"15-17 years":3003,"18-24 years":7190,"25-29 years":4766,"30-39 years":9113,"40-49 years":14441,"50-64 years":18336,"65-74 years":8280,">74 years":7436},{"ID_County":9675,"Total":91155,"<3 years":2034,"3-5 years":2283,"6-14 years":8363,"15-17 years":3359,"18-24 years":7750,"25-29 years":5024,"30-39 years":10274,"40-49 years":15685,"50-64 years":19109,"65-74 years":8934,">74 years":8339},{"ID_County":9676,"Total":128743,"<3 years":3096,"3-5 years":3221,"6-14 years":12308,"15-17 years":4732,"18-24 years":10489,"25-29 years":6784,"30-39 years":14711,"40-49 years":22246,"50-64 years":26480,"65-74 years":13368,">74 years":11306},{"ID_County":9677,"Total":126158,"<3 years":2725,"3-5 years":2923,"6-14 years":11120,"15-17 years":4358,"18-24 years":10430,"25-29 years":6401,"30-39 years":13629,"40-49 years":21596,"50-64 years":27488,"65-74 years":13303,">74 years":12185},{"ID_County":9678,"Total":115445,"<3 years":2658,"3-5 years":2728,"6-14 years":10481,"15-17 years":4174,"18-24 years":9709,"25-29 years":6094,"30-39 years":12104,"40-49 years":19800,"50-64 years":24806,"65-74 years":12295,">74 years":10596},{"ID_County":9679,"Total":162302,"<3 years":4039,"3-5 years":4207,"6-14 years":14651,"15-17 years":5492,"18-24 years":13405,"25-29 years":8951,"30-39 years":18487,"40-49 years":27570,"50-64 years":35447,"65-74 years":16341,">74 years":13712},{"ID_County":9761,"Total":296582,"<3 years":7401,"3-5 years":7377,"6-14 years":22569,"15-17 years":7639,"18-24 years":29076,"25-29 years":22967,"30-39 years":40483,"40-49 years":44267,"50-64 years":53970,"65-74 years":32285,">74 years":28549},{"ID_County":9762,"Total":44398,"<3 years":1045,"3-5 years":1139,"6-14 years":3845,"15-17 years":1340,"18-24 years":3579,"25-29 years":2572,"30-39 years":5011,"40-49 years":6980,"50-64 years":8876,"65-74 years":5138,">74 years":4874},{"ID_County":9763,"Total":69151,"<3 years":1607,"3-5 years":1757,"6-14 years":5471,"15-17 years":1944,"18-24 years":6164,"25-29 years":4830,"30-39 years":8375,"40-49 years":10253,"50-64 years":13421,"65-74 years":8234,">74 years":7094},{"ID_County":9764,"Total":44100,"<3 years":1135,"3-5 years":1144,"6-14 years":3829,"15-17 years":1362,"18-24 years":3652,"25-29 years":2699,"30-39 years":5340,"40-49 years":6822,"50-64 years":8681,"65-74 years":5017,">74 years":4418},{"ID_County":9771,"Total":134655,"<3 years":3320,"3-5 years":3580,"6-14 years":13605,"15-17 years":4915,"18-24 years":10967,"25-29 years":6997,"30-39 years":15719,"40-49 years":24474,"50-64 years":26658,"65-74 years":14020,">74 years":10401},{"ID_County":9772,"Total":253468,"<3 years":6175,"3-5 years":6627,"6-14 years":24513,"15-17 years":9267,"18-24 years":20499,"25-29 years":12947,"30-39 years":28718,"40-49 years":44979,"50-64 years":51160,"65-74 years":27604,">74 years":20978},{"ID_County":9773,"Total":96562,"<3 years":2382,"3-5 years":2539,"6-14 years":9557,"15-17 years":3705,"18-24 years":8467,"25-29 years":5214,"30-39 years":11180,"40-49 years":16412,"50-64 years":19524,"65-74 years":9358,">74 years":8224},{"ID_County":9774,"Total":127027,"<3 years":3245,"3-5 years":3361,"6-14 years":12552,"15-17 years":4600,"18-24 years":11171,"25-29 years":7047,"30-39 years":14857,"40-49 years":21756,"50-64 years":25381,"65-74 years":12661,">74 years":10397},{"ID_County":9775,"Total":175204,"<3 years":4652,"3-5 years":4658,"6-14 years":16440,"15-17 years":5703,"18-24 years":14442,"25-29 years":10909,"30-39 years":21013,"40-49 years":29021,"50-64 years":34855,"65-74 years":18812,">74 years":14699},{"ID_County":9776,"Total":81981,"<3 years":1930,"3-5 years":2131,"6-14 years":7935,"15-17 years":2821,"18-24 years":6350,"25-29 years":4041,"30-39 years":8945,"40-49 years":14104,"50-64 years":15892,"65-74 years":9815,">74 years":8021},{"ID_County":9777,"Total":141182,"<3 years":3526,"3-5 years":3881,"6-14 years":13994,"15-17 years":5168,"18-24 years":11494,"25-29 years":7396,"30-39 years":15786,"40-49 years":23899,"50-64 years":28097,"65-74 years":15316,">74 years":12624},{"ID_County":9778,"Total":145341,"<3 years":3629,"3-5 years":3774,"6-14 years":14619,"15-17 years":5554,"18-24 years":11968,"25-29 years":7519,"30-39 years":16232,"40-49 years":24708,"50-64 years":28402,"65-74 years":15595,">74 years":13340},{"ID_County":9779,"Total":133783,"<3 years":3331,"3-5 years":3536,"6-14 years":13240,"15-17 years":4793,"18-24 years":11221,"25-29 years":7607,"30-39 years":15840,"40-49 years":22531,"50-64 years":26473,"65-74 years":13635,">74 years":11575},{"ID_County":9780,"Total":156008,"<3 years":3599,"3-5 years":3927,"6-14 years":14542,"15-17 years":5414,"18-24 years":12280,"25-29 years":7781,"30-39 years":17205,"40-49 years":26548,"50-64 years":31787,"65-74 years":18768,">74 years":14155},{"ID_County":10041,"Total":328714,"<3 years":7098,"3-5 years":7131,"6-14 years":24634,"15-17 years":9159,"18-24 years":27540,"25-29 years":21277,"30-39 years":36312,"40-49 years":51921,"50-64 years":71996,"65-74 years":37989,">74 years":33658},{"ID_County":10042,"Total":103243,"<3 years":2209,"3-5 years":2363,"6-14 years":8939,"15-17 years":3295,"18-24 years":7707,"25-29 years":5378,"30-39 years":11272,"40-49 years":17693,"50-64 years":23196,"65-74 years":11208,">74 years":9984},{"ID_County":10043,"Total":131408,"<3 years":2501,"3-5 years":2645,"6-14 years":9888,"15-17 years":3881,"18-24 years":10342,"25-29 years":7010,"30-39 years":13210,"40-49 years":22069,"50-64 years":29868,"65-74 years":15991,">74 years":14005},{"ID_County":10044,"Total":194319,"<3 years":3914,"3-5 years":4207,"6-14 years":15251,"15-17 years":6035,"18-24 years":15218,"25-29 years":10159,"30-39 years":20053,"40-49 years":32101,"50-64 years":44658,"65-74 years":22484,">74 years":20237},{"ID_County":10045,"Total":142196,"<3 years":2860,"3-5 years":2940,"6-14 years":10832,"15-17 years":4307,"18-24 years":11146,"25-29 years":7458,"30-39 years":14059,"40-49 years":23455,"50-64 years":32126,"65-74 years":17136,">74 years":15876},{"ID_County":10046,"Total":87007,"<3 years":1701,"3-5 years":1730,"6-14 years":6821,"15-17 years":2824,"18-24 years":6707,"25-29 years":4326,"30-39 years":8818,"40-49 years":14832,"50-64 years":20225,"65-74 years":9851,">74 years":9171},{"ID_County":11000,"Total":3669491,"<3 years":105734,"3-5 years":96690,"6-14 years":266567,"15-17 years":82022,"18-24 years":302501,"25-29 years":293743,"30-39 years":517467,"40-49 years":601507,"50-64 years":696247,"65-74 years":419167,">74 years":287847},{"ID_County":12051,"Total":72184,"<3 years":1618,"3-5 years":1528,"6-14 years":4099,"15-17 years":1106,"18-24 years":5761,"25-29 years":4906,"30-39 years":7621,"40-49 years":10934,"50-64 years":15610,"65-74 years":11085,">74 years":7915},{"ID_County":12052,"Total":99678,"<3 years":2345,"3-5 years":2108,"6-14 years":5928,"15-17 years":1503,"18-24 years":9759,"25-29 years":7657,"30-39 years":10736,"40-49 years":14993,"50-64 years":21748,"65-74 years":13065,">74 years":9836},{"ID_County":12053,"Total":57751,"<3 years":1291,"3-5 years":1294,"6-14 years":3575,"15-17 years":974,"18-24 years":5139,"25-29 years":3922,"30-39 years":6202,"40-49 years":8629,"50-64 years":13562,"65-74 years":7325,">74 years":5839},{"ID_County":12054,"Total":180334,"<3 years":5859,"3-5 years":5384,"6-14 years":12881,"15-17 years":2991,"18-24 years":15959,"25-29 years":15412,"30-39 years":26620,"40-49 years":27527,"50-64 years":32272,"65-74 years":19948,">74 years":15481},{"ID_County":12060,"Total":185244,"<3 years":4457,"3-5 years":4520,"6-14 years":13260,"15-17 years":3391,"18-24 years":12311,"25-29 years":9853,"30-39 years":20637,"40-49 years":33109,"50-64 years":43622,"65-74 years":23847,">74 years":16238},{"ID_County":12061,"Total":170791,"<3 years":4018,"3-5 years":4042,"6-14 years":12393,"15-17 years":3354,"18-24 years":11253,"25-29 years":9134,"30-39 years":18846,"40-49 years":30239,"50-64 years":38215,"65-74 years":22565,">74 years":16731},{"ID_County":12062,"Total":101827,"<3 years":2005,"3-5 years":2094,"6-14 years":6653,"15-17 years":1833,"18-24 years":6786,"25-29 years":5363,"30-39 years":10295,"40-49 years":16866,"50-64 years":24363,"65-74 years":14176,">74 years":11392},{"ID_County":12063,"Total":162996,"<3 years":3888,"3-5 years":3918,"6-14 years":13911,"15-17 years":3824,"18-24 years":11171,"25-29 years":7753,"30-39 years":17286,"40-49 years":30919,"50-64 years":35938,"65-74 years":20497,">74 years":13889},{"ID_County":12064,"Total":195751,"<3 years":4516,"3-5 years":4546,"6-14 years":13746,"15-17 years":3765,"18-24 years":13217,"25-29 years":9855,"30-39 years":21193,"40-49 years":35483,"50-64 years":46912,"65-74 years":23997,">74 years":18522},{"ID_County":12065,"Total":212914,"<3 years":5219,"3-5 years":5381,"6-14 years":17181,"15-17 years":4600,"18-24 years":13702,"25-29 years":10931,"30-39 years":23512,"40-49 years":40189,"50-64 years":47059,"65-74 years":26523,">74 years":18619},{"ID_County":12066,"Total":109371,"<3 years":2216,"3-5 years":2199,"6-14 years":6796,"15-17 years":1841,"18-24 years":7493,"25-29 years":5943,"30-39 years":11073,"40-49 years":17638,"50-64 years":25389,"65-74 years":16418,">74 years":12365},{"ID_County":12067,"Total":178803,"<3 years":3922,"3-5 years":3981,"6-14 years":12065,"15-17 years":3263,"18-24 years":11939,"25-29 years":9183,"30-39 years":18618,"40-49 years":30407,"50-64 years":42803,"65-74 years":24436,">74 years":18185},{"ID_County":12068,"Total":98861,"<3 years":2222,"3-5 years":2159,"6-14 years":6660,"15-17 years":1820,"18-24 years":6930,"25-29 years":5593,"30-39 years":10236,"40-49 years":16692,"50-64 years":24277,"65-74 years":12392,">74 years":9881},{"ID_County":12069,"Total":216566,"<3 years":5116,"3-5 years":5744,"6-14 years":18477,"15-17 years":4729,"18-24 years":13878,"25-29 years":10056,"30-39 years":23554,"40-49 years":40965,"50-64 years":49579,"65-74 years":25741,">74 years":18726},{"ID_County":12070,"Total":76158,"<3 years":1438,"3-5 years":1505,"6-14 years":4842,"15-17 years":1434,"18-24 years":5262,"25-29 years":3771,"30-39 years":6954,"40-49 years":12656,"50-64 years":18698,"65-74 years":10718,">74 years":8880},{"ID_County":12071,"Total":113720,"<3 years":2189,"3-5 years":2351,"6-14 years":7344,"15-17 years":1904,"18-24 years":7338,"25-29 years":5682,"30-39 years":11122,"40-49 years":19696,"50-64 years":28536,"65-74 years":15438,">74 years":12119},{"ID_County":12072,"Total":169997,"<3 years":4089,"3-5 years":4175,"6-14 years":13012,"15-17 years":3549,"18-24 years":11913,"25-29 years":9580,"30-39 years":18925,"40-49 years":31251,"50-64 years":37272,"65-74 years":21058,">74 years":15173},{"ID_County":12073,"Total":118947,"<3 years":2465,"3-5 years":2502,"6-14 years":8024,"15-17 years":2271,"18-24 years":8213,"25-29 years":5818,"30-39 years":11516,"40-49 years":19785,"50-64 years":29792,"65-74 years":16289,">74 years":12271},{"ID_County":13003,"Total":209191,"<3 years":5316,"3-5 years":4606,"6-14 years":12107,"15-17 years":2956,"18-24 years":22825,"25-29 years":19626,"30-39 years":24625,"40-49 years":28800,"50-64 years":40433,"65-74 years":27582,">74 years":20317},{"ID_County":13004,"Total":95653,"<3 years":2463,"3-5 years":2362,"6-14 years":6240,"15-17 years":1576,"18-24 years":7820,"25-29 years":6503,"30-39 years":10873,"40-49 years":13716,"50-64 years":20858,"65-74 years":12828,">74 years":10414},{"ID_County":13071,"Total":258074,"<3 years":6077,"3-5 years":5962,"6-14 years":17690,"15-17 years":4637,"18-24 years":18600,"25-29 years":14583,"30-39 years":27122,"40-49 years":42305,"50-64 years":63257,"65-74 years":31933,">74 years":25909},{"ID_County":13072,"Total":215794,"<3 years":5230,"3-5 years":5329,"6-14 years":16157,"15-17 years":4265,"18-24 years":14232,"25-29 years":11281,"30-39 years":22999,"40-49 years":38368,"50-64 years":52771,"65-74 years":25860,">74 years":19301},{"ID_County":13073,"Total":224702,"<3 years":5328,"3-5 years":5031,"6-14 years":14811,"15-17 years":3889,"18-24 years":16190,"25-29 years":12916,"30-39 years":23344,"40-49 years":36832,"50-64 years":53456,"65-74 years":30110,">74 years":22796},{"ID_County":13074,"Total":157322,"<3 years":3879,"3-5 years":3888,"6-14 years":11948,"15-17 years":3203,"18-24 years":11716,"25-29 years":9506,"30-39 years":17844,"40-49 years":26605,"50-64 years":36108,"65-74 years":18144,">74 years":14480},{"ID_County":13075,"Total":235623,"<3 years":5523,"3-5 years":5466,"6-14 years":15416,"15-17 years":4029,"18-24 years":20755,"25-29 years":15975,"30-39 years":24555,"40-49 years":36273,"50-64 years":55568,"65-74 years":28506,">74 years":23554},{"ID_County":13076,"Total":211779,"<3 years":4833,"3-5 years":4808,"6-14 years":15645,"15-17 years":4158,"18-24 years":14624,"25-29 years":11568,"30-39 years":22695,"40-49 years":37078,"50-64 years":52083,"65-74 years":24601,">74 years":19683},{"ID_County":14511,"Total":246334,"<3 years":5973,"3-5 years":5586,"6-14 years":15094,"15-17 years":3781,"18-24 years":19033,"25-29 years":17040,"30-39 years":27071,"40-49 years":34132,"50-64 years":52267,"65-74 years":36872,">74 years":29485},{"ID_County":14521,"Total":334948,"<3 years":7896,"3-5 years":7916,"6-14 years":23096,"15-17 years":6181,"18-24 years":21442,"25-29 years":18023,"30-39 years":36266,"40-49 years":48455,"50-64 years":82180,"65-74 years":43146,">74 years":40348},{"ID_County":14522,"Total":304099,"<3 years":7056,"3-5 years":6982,"6-14 years":20691,"15-17 years":5432,"18-24 years":21109,"25-29 years":16862,"30-39 years":32329,"40-49 years":46786,"50-64 years":69066,"65-74 years":40884,">74 years":36903},{"ID_County":14523,"Total":225997,"<3 years":4735,"3-5 years":4917,"6-14 years":14834,"15-17 years":3896,"18-24 years":14536,"25-29 years":11811,"30-39 years":23458,"40-49 years":34577,"50-64 years":52593,"65-74 years":33019,">74 years":27618},{"ID_County":14524,"Total":315002,"<3 years":6962,"3-5 years":6932,"6-14 years":20573,"15-17 years":5436,"18-24 years":21505,"25-29 years":17172,"30-39 years":32693,"40-49 years":48364,"50-64 years":71688,"65-74 years":44668,">74 years":39010},{"ID_County":14612,"Total":556780,"<3 years":17983,"3-5 years":15564,"6-14 years":36659,"15-17 years":7795,"18-24 years":57003,"25-29 years":51630,"30-39 years":77122,"40-49 years":76192,"50-64 years":93317,"65-74 years":69011,">74 years":54504},{"ID_County":14625,"Total":299758,"<3 years":7153,"3-5 years":7244,"6-14 years":21385,"15-17 years":5384,"18-24 years":19478,"25-29 years":16295,"30-39 years":32446,"40-49 years":47496,"50-64 years":67949,"65-74 years":40712,">74 years":34213},{"ID_County":14626,"Total":252725,"<3 years":5652,"3-5 years":5806,"6-14 years":17220,"15-17 years":4614,"18-24 years":16317,"25-29 years":12971,"30-39 years":24756,"40-49 years":38703,"50-64 years":58541,"65-74 years":36389,">74 years":31755},{"ID_County":14627,"Total":241717,"<3 years":5787,"3-5 years":5915,"6-14 years":17399,"15-17 years":4317,"18-24 years":15419,"25-29 years":12967,"30-39 years":26271,"40-49 years":38829,"50-64 years":53482,"65-74 years":33344,">74 years":27988},{"ID_County":14628,"Total":245586,"<3 years":6029,"3-5 years":6034,"6-14 years":18023,"15-17 years":4458,"18-24 years":15870,"25-29 years":12757,"30-39 years":27194,"40-49 years":38751,"50-64 years":53764,"65-74 years":34809,">74 years":27898},{"ID_County":14713,"Total":593145,"<3 years":17668,"3-5 years":15211,"6-14 years":37445,"15-17 years":8758,"18-24 years":53824,"25-29 years":53657,"30-39 years":82515,"40-49 years":83817,"50-64 years":105603,"65-74 years":74443,">74 years":60203},{"ID_County":14729,"Total":258139,"<3 years":5995,"3-5 years":6100,"6-14 years":18265,"15-17 years":4709,"18-24 years":16931,"25-29 years":12982,"30-39 years":27855,"40-49 years":43724,"50-64 years":59308,"65-74 years":34562,">74 years":27709},{"ID_County":14730,"Total":197741,"<3 years":4466,"3-5 years":4504,"6-14 years":13913,"15-17 years":3538,"18-24 years":13369,"25-29 years":10913,"30-39 years":21360,"40-49 years":33227,"50-64 years":45874,"65-74 years":25397,">74 years":21181},{"ID_County":15001,"Total":80103,"<3 years":1660,"3-5 years":1632,"6-14 years":4594,"15-17 years":1284,"18-24 years":5495,"25-29 years":4528,"30-39 years":7748,"40-49 years":12295,"50-64 years":18265,"65-74 years":12977,">74 years":9625},{"ID_County":15002,"Total":238762,"<3 years":6376,"3-5 years":5801,"6-14 years":15006,"15-17 years":3737,"18-24 years":23608,"25-29 years":19472,"30-39 years":28617,"40-49 years":33424,"50-64 years":46620,"65-74 years":32161,">74 years":23939},{"ID_County":15003,"Total":237565,"<3 years":6144,"3-5 years":5505,"6-14 years":14342,"15-17 years":3652,"18-24 years":23078,"25-29 years":19067,"30-39 years":27476,"40-49 years":34475,"50-64 years":47831,"65-74 years":31963,">74 years":24033},{"ID_County":15081,"Total":83173,"<3 years":1932,"3-5 years":2031,"6-14 years":6064,"15-17 years":1800,"18-24 years":5966,"25-29 years":4757,"30-39 years":8721,"40-49 years":14381,"50-64 years":19276,"65-74 years":9889,">74 years":8354},{"ID_County":15082,"Total":158486,"<3 years":3188,"3-5 years":3241,"6-14 years":10082,"15-17 years":2736,"18-24 years":11310,"25-29 years":8620,"30-39 years":16204,"40-49 years":25598,"50-64 years":37556,"65-74 years":22342,">74 years":17608},{"ID_County":15083,"Total":170923,"<3 years":3944,"3-5 years":4095,"6-14 years":12196,"15-17 years":3230,"18-24 years":11780,"25-29 years":9490,"30-39 years":19287,"40-49 years":29949,"50-64 years":41150,"65-74 years":19665,">74 years":16136},{"ID_County":15084,"Total":178846,"<3 years":3636,"3-5 years":3662,"6-14 years":11431,"15-17 years":2957,"18-24 years":11863,"25-29 years":9707,"30-39 years":18078,"40-49 years":28939,"50-64 years":42037,"65-74 years":24830,">74 years":21705},{"ID_County":15085,"Total":213310,"<3 years":4370,"3-5 years":4542,"6-14 years":14066,"15-17 years":3788,"18-24 years":14517,"25-29 years":11461,"30-39 years":21726,"40-49 years":34900,"50-64 years":50235,"65-74 years":29711,">74 years":23996},{"ID_County":15086,"Total":89589,"<3 years":1915,"3-5 years":1961,"6-14 years":6088,"15-17 years":1687,"18-24 years":5975,"25-29 years":4702,"30-39 years":9516,"40-49 years":15426,"50-64 years":21504,"65-74 years":11517,">74 years":9297},{"ID_County":15087,"Total":134942,"<3 years":2626,"3-5 years":2693,"6-14 years":8477,"15-17 years":2376,"18-24 years":8518,"25-29 years":6844,"30-39 years":13611,"40-49 years":21316,"50-64 years":33021,"65-74 years":19542,">74 years":15918},{"ID_County":15088,"Total":183815,"<3 years":4205,"3-5 years":4175,"6-14 years":12388,"15-17 years":3281,"18-24 years":12694,"25-29 years":10012,"30-39 years":20220,"40-49 years":30894,"50-64 years":44084,"65-74 years":23646,">74 years":18216},{"ID_County":15089,"Total":189125,"<3 years":3864,"3-5 years":3948,"6-14 years":12091,"15-17 years":3528,"18-24 years":13089,"25-29 years":10096,"30-39 years":18970,"40-49 years":31047,"50-64 years":44159,"65-74 years":26927,">74 years":21406},{"ID_County":15090,"Total":111190,"<3 years":2534,"3-5 years":2429,"6-14 years":7862,"15-17 years":2249,"18-24 years":8342,"25-29 years":6138,"30-39 years":11009,"40-49 years":19032,"50-64 years":26389,"65-74 years":14131,">74 years":11074},{"ID_County":15091,"Total":124953,"<3 years":2555,"3-5 years":2533,"6-14 years":7950,"15-17 years":2183,"18-24 years":8304,"25-29 years":6218,"30-39 years":12324,"40-49 years":20694,"50-64 years":30057,"65-74 years":18188,">74 years":13947},{"ID_County":16051,"Total":213981,"<3 years":5940,"3-5 years":5467,"6-14 years":14207,"15-17 years":3428,"18-24 years":20601,"25-29 years":16673,"30-39 years":26871,"40-49 years":31762,"50-64 years":43804,"65-74 years":25974,">74 years":19254},{"ID_County":16052,"Total":93125,"<3 years":2040,"3-5 years":1867,"6-14 years":5449,"15-17 years":1341,"18-24 years":6951,"25-29 years":5557,"30-39 years":9364,"40-49 years":13929,"50-64 years":22048,"65-74 years":13261,">74 years":11317},{"ID_County":16053,"Total":111343,"<3 years":3254,"3-5 years":2670,"6-14 years":6718,"15-17 years":1591,"18-24 years":14064,"25-29 years":12565,"30-39 years":14443,"40-49 years":14211,"50-64 years":19269,"65-74 years":13285,">74 years":9273},{"ID_County":16054,"Total":36789,"<3 years":667,"3-5 years":652,"6-14 years":2020,"15-17 years":567,"18-24 years":2396,"25-29 years":1864,"30-39 years":3519,"40-49 years":5719,"50-64 years":9448,"65-74 years":5947,">74 years":3989},{"ID_County":16055,"Total":65228,"<3 years":1940,"3-5 years":1746,"6-14 years":4685,"15-17 years":1053,"18-24 years":6373,"25-29 years":5445,"30-39 years":8248,"40-49 years":9414,"50-64 years":12461,"65-74 years":7628,">74 years":6237},{"ID_County":16056,"Total":42250,"<3 years":1060,"3-5 years":1016,"6-14 years":2825,"15-17 years":731,"18-24 years":2885,"25-29 years":2846,"30-39 years":4840,"40-49 years":6560,"50-64 years":8839,"65-74 years":6017,">74 years":4630},{"ID_County":16061,"Total":100006,"<3 years":2606,"3-5 years":2605,"6-14 years":7929,"15-17 years":2178,"18-24 years":7769,"25-29 years":6617,"30-39 years":11962,"40-49 years":15603,"50-64 years":22300,"65-74 years":11705,">74 years":8732},{"ID_County":16062,"Total":83416,"<3 years":1873,"3-5 years":1894,"6-14 years":5658,"15-17 years":1502,"18-24 years":6522,"25-29 years":4966,"30-39 years":8821,"40-49 years":13241,"50-64 years":18752,"65-74 years":11413,">74 years":8775},{"ID_County":16063,"Total":118974,"<3 years":2733,"3-5 years":2600,"6-14 years":8201,"15-17 years":2246,"18-24 years":8331,"25-29 years":6988,"30-39 years":13615,"40-49 years":19261,"50-64 years":28285,"65-74 years":14946,">74 years":11768},{"ID_County":16064,"Total":102232,"<3 years":2446,"3-5 years":2477,"6-14 years":7598,"15-17 years":2180,"18-24 years":7385,"25-29 years":5937,"30-39 years":11328,"40-49 years":16576,"50-64 years":23231,"65-74 years":12751,">74 years":10323},{"ID_County":16065,"Total":74212,"<3 years":1532,"3-5 years":1586,"6-14 years":4947,"15-17 years":1436,"18-24 years":5101,"25-29 years":3968,"30-39 years":7719,"40-49 years":11849,"50-64 years":18121,"65-74 years":10055,">74 years":7898},{"ID_County":16066,"Total":124916,"<3 years":2685,"3-5 years":2649,"6-14 years":7908,"15-17 years":2294,"18-24 years":8867,"25-29 years":7745,"30-39 years":13481,"40-49 years":20148,"50-64 years":29702,"65-74 years":16667,">74 years":12771},{"ID_County":16067,"Total":134908,"<3 years":3163,"3-5 years":3084,"6-14 years":9791,"15-17 years":2553,"18-24 years":9239,"25-29 years":7687,"30-39 years":14922,"40-49 years":22073,"50-64 years":31330,"65-74 years":17599,">74 years":13467},{"ID_County":16068,"Total":69427,"<3 years":1689,"3-5 years":1608,"6-14 years":4837,"15-17 years":1330,"18-24 years":4738,"25-29 years":3907,"30-39 years":8013,"40-49 years":11536,"50-64 years":17187,"65-74 years":8298,">74 years":6285},{"ID_County":16069,"Total":63197,"<3 years":1382,"3-5 years":1405,"6-14 years":4214,"15-17 years":1180,"18-24 years":4567,"25-29 years":4038,"30-39 years":7252,"40-49 years":10210,"50-64 years":15102,"65-74 years":7465,">74 years":6383},{"ID_County":16070,"Total":106249,"<3 years":2490,"3-5 years":2353,"6-14 years":6869,"15-17 years":1808,"18-24 years":8638,"25-29 years":6689,"30-39 years":11567,"40-49 years":16697,"50-64 years":24417,"65-74 years":14021,">74 years":10700},{"ID_County":16071,"Total":82156,"<3 years":2073,"3-5 years":2087,"6-14 years":6202,"15-17 years":1619,"18-24 years":5365,"25-29 years":4680,"30-39 years":9536,"40-49 years":13718,"50-64 years":20098,"65-74 years":9330,">74 years":7448},{"ID_County":16072,"Total":57717,"<3 years":1127,"3-5 years":1165,"6-14 years":3688,"15-17 years":957,"18-24 years":3727,"25-29 years":3153,"30-39 years":6383,"40-49 years":9191,"50-64 years":13943,"65-74 years":7842,">74 years":6541},{"ID_County":16073,"Total":103199,"<3 years":2127,"3-5 years":2092,"6-14 years":6505,"15-17 years":1624,"18-24 years":6771,"25-29 years":5584,"30-39 years":10506,"40-49 years":16350,"50-64 years":24431,"65-74 years":14773,">74 years":12437},{"ID_County":16074,"Total":82950,"<3 years":1857,"3-5 years":1849,"6-14 years":5862,"15-17 years":1504,"18-24 years":5597,"25-29 years":4629,"30-39 years":9109,"40-49 years":13778,"50-64 years":19939,"65-74 years":10766,">74 years":8061},{"ID_County":16075,"Total":80312,"<3 years":1787,"3-5 years":1768,"6-14 years":5504,"15-17 years":1532,"18-24 years":5352,"25-29 years":4527,"30-39 years":8615,"40-49 years":12846,"50-64 years":19216,"65-74 years":10182,">74 years":8983},{"ID_County":16076,"Total":97398,"<3 years":1915,"3-5 years":2019,"6-14 years":6412,"15-17 years":1730,"18-24 years":5848,"25-29 years":4857,"30-39 years":9825,"40-49 years":15777,"50-64 years":23999,"65-74 years":13447,">74 years":11570},{"ID_County":16077,"Total":89393,"<3 years":1707,"3-5 years":1705,"6-14 years":5678,"15-17 years":1515,"18-24 years":5581,"25-29 years":4498,"30-39 years":8867,"40-49 years":14176,"50-64 years":21402,"65-74 years":13249,">74 years":11015}] diff --git a/cpp/tests/data/Germany/pydata/vaccination_data.json b/cpp/tests/data/Germany/pydata/vaccination_data.json deleted file mode 100644 index e8c47d14fb..0000000000 --- a/cpp/tests/data/Germany/pydata/vaccination_data.json +++ /dev/null @@ -1,4493 +0,0 @@ -[ - { - "Date": "2020-11-23", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14372.2949635005, - "Vacc_completed": 1325.3928078641, - "Vacc_refreshed": 234.0214496372, - "Vacc_refreshed_2": 117.0107248186 - }, - { - "Date": "2020-11-24", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14377.1100641854, - "Vacc_completed": 1326.7384263101, - "Vacc_refreshed": 242.1400638609, - "Vacc_refreshed_2": 121.07003193045 - }, - { - "Date": "2020-11-25", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14381.7559278649, - "Vacc_completed": 1329.4413693873, - "Vacc_refreshed": 246.2374710913, - "Vacc_refreshed_2": 123.11873554565 - }, - { - "Date": "2020-11-26", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14385.7162526455, - "Vacc_completed": 1338.1839321545, - "Vacc_refreshed": 252.0149200475, - "Vacc_refreshed_2": 126.00746002375 - }, - { - "Date": "2020-11-27", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14389.4326934411, - "Vacc_completed": 1345.9094675595, - "Vacc_refreshed": 256.9046042339, - "Vacc_refreshed_2": 128.45230211695 - }, - { - "Date": "2020-11-28", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14391.2007554132, - "Vacc_completed": 1348.71606757, - "Vacc_refreshed": 258.1776032516, - "Vacc_refreshed_2": 129.0888016258 - }, - { - "Date": "2020-11-29", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14394.8621297613, - "Vacc_completed": 1354.2416050796, - "Vacc_refreshed": 267.8589065036, - "Vacc_refreshed_2": 133.9294532518 - }, - { - "Date": "2020-11-30", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14398.3456243909, - "Vacc_completed": 1359.868800934, - "Vacc_refreshed": 270.9855298163, - "Vacc_refreshed_2": 135.49276490815 - }, - { - "Date": "2020-12-01", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14398.4645205246, - "Vacc_completed": 1363.0538159145, - "Vacc_refreshed": 275.840425604, - "Vacc_refreshed_2": 137.920212802 - }, - { - "Date": "2020-12-02", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14399.1657319944, - "Vacc_completed": 1365.5993182323, - "Vacc_refreshed": 277.5856365007, - "Vacc_refreshed_2": 138.79281825035 - }, - { - "Date": "2020-12-03", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14402.7230837573, - "Vacc_completed": 1368.6201543223, - "Vacc_refreshed": 286.3361695339, - "Vacc_refreshed_2": 143.16808476695 - }, - { - "Date": "2020-12-04", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14403.1500082752, - "Vacc_completed": 1371.4419603277, - "Vacc_refreshed": 291.9429549926, - "Vacc_refreshed_2": 145.9714774963 - }, - { - "Date": "2020-12-05", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14409.601025491, - "Vacc_completed": 1375.0385110041, - "Vacc_refreshed": 294.4838831323, - "Vacc_refreshed_2": 147.24194156615 - }, - { - "Date": "2020-12-06", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14412.5992098988, - "Vacc_completed": 1379.7282797993, - "Vacc_refreshed": 304.3709721295, - "Vacc_refreshed_2": 152.18548606475 - }, - { - "Date": "2020-12-07", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14412.7379664054, - "Vacc_completed": 1388.4437755617, - "Vacc_refreshed": 310.9469195789, - "Vacc_refreshed_2": 155.47345978945 - }, - { - "Date": "2020-12-08", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14413.0256783966, - "Vacc_completed": 1395.0228908154, - "Vacc_refreshed": 316.1322991564, - "Vacc_refreshed_2": 158.0661495782 - }, - { - "Date": "2020-12-09", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14418.5923400284, - "Vacc_completed": 1395.4421160716, - "Vacc_refreshed": 324.326203234, - "Vacc_refreshed_2": 162.163101617 - }, - { - "Date": "2020-12-10", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14427.1006875636, - "Vacc_completed": 1400.9550416303, - "Vacc_refreshed": 326.1675291407, - "Vacc_refreshed_2": 163.08376457035 - }, - { - "Date": "2020-12-11", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14428.1259159444, - "Vacc_completed": 1401.6589165675, - "Vacc_refreshed": 336.1473853823, - "Vacc_refreshed_2": 168.07369269115 - }, - { - "Date": "2020-12-12", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14429.6710322591, - "Vacc_completed": 1406.4316961423, - "Vacc_refreshed": 338.7341080527, - "Vacc_refreshed_2": 169.36705402635 - }, - { - "Date": "2020-12-13", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14435.5405186058, - "Vacc_completed": 1406.8193757343, - "Vacc_refreshed": 348.5515447081, - "Vacc_refreshed_2": 174.27577235405 - }, - { - "Date": "2020-12-14", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14440.6128511884, - "Vacc_completed": 1406.8790930463, - "Vacc_refreshed": 349.9224707035, - "Vacc_refreshed_2": 174.96123535175 - }, - { - "Date": "2020-12-15", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14448.1553470558, - "Vacc_completed": 1407.8576900416, - "Vacc_refreshed": 354.7521313753, - "Vacc_refreshed_2": 177.37606568765 - }, - { - "Date": "2020-12-16", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14456.4196110425, - "Vacc_completed": 1411.7530351787, - "Vacc_refreshed": 361.5526839017, - "Vacc_refreshed_2": 180.77634195085 - }, - { - "Date": "2020-12-17", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14466.1757833279, - "Vacc_completed": 1412.4941157515, - "Vacc_refreshed": 364.0766791828, - "Vacc_refreshed_2": 182.0383395914 - }, - { - "Date": "2020-12-18", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14472.9152722164, - "Vacc_completed": 1421.7399661156, - "Vacc_refreshed": 371.2418954122, - "Vacc_refreshed_2": 185.6209477061 - }, - { - "Date": "2020-12-19", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14474.3971159945, - "Vacc_completed": 1423.8796012137, - "Vacc_refreshed": 378.3445685688, - "Vacc_refreshed_2": 189.1722842844 - }, - { - "Date": "2020-12-20", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14482.9259977884, - "Vacc_completed": 1428.8212618966, - "Vacc_refreshed": 382.6712538747, - "Vacc_refreshed_2": 191.33562693735 - }, - { - "Date": "2020-12-21", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14491.6837567491, - "Vacc_completed": 1430.1481016913, - "Vacc_refreshed": 392.5489632959, - "Vacc_refreshed_2": 196.27448164795 - }, - { - "Date": "2020-12-22", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14499.5728298642, - "Vacc_completed": 1439.468906008, - "Vacc_refreshed": 397.6649554861, - "Vacc_refreshed_2": 198.83247774305 - }, - { - "Date": "2020-12-23", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14500.4884339857, - "Vacc_completed": 1447.6074532094, - "Vacc_refreshed": 404.4236802991, - "Vacc_refreshed_2": 202.21184014955 - }, - { - "Date": "2020-12-24", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14508.6628209678, - "Vacc_completed": 1449.1955087396, - "Vacc_refreshed": 413.1290507873, - "Vacc_refreshed_2": 206.56452539365 - }, - { - "Date": "2020-12-25", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14509.0177335192, - "Vacc_completed": 1457.0313439789, - "Vacc_refreshed": 418.6984801264, - "Vacc_refreshed_2": 209.3492400632 - }, - { - "Date": "2020-12-26", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14518.7925361684, - "Vacc_completed": 1462.4055060107, - "Vacc_refreshed": 419.6070699812, - "Vacc_refreshed_2": 209.8035349906 - }, - { - "Date": "2020-12-27", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14522.121758092, - "Vacc_completed": 1468.1811367429, - "Vacc_refreshed": 425.9772045183, - "Vacc_refreshed_2": 212.98860225915 - }, - { - "Date": "2020-12-28", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14528.5474917037, - "Vacc_completed": 1473.5164593205, - "Vacc_refreshed": 435.7810319021, - "Vacc_refreshed_2": 217.89051595105 - }, - { - "Date": "2020-12-29", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14536.5601109176, - "Vacc_completed": 1481.2704120463, - "Vacc_refreshed": 438.2410199432, - "Vacc_refreshed_2": 219.1205099716 - }, - { - "Date": "2020-12-30", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14542.1473955627, - "Vacc_completed": 1482.7064631605, - "Vacc_refreshed": 445.3488141502, - "Vacc_refreshed_2": 222.6744070751 - }, - { - "Date": "2020-12-31", - "ID_County": 1002, - "Age_RKI": "0-4", - "Vacc_partially": 14544.5952478081, - "Vacc_completed": 1486.0552178086, - "Vacc_refreshed": 446.1812966093, - "Vacc_refreshed_2": 223.09064830465 - }, - { - "Date": "2020-10-01", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10765.9941189788, - "Vacc_completed": 1603.3500569399, - "Vacc_refreshed": 0, - "Vacc_refreshed_2": 0.0 - }, - { - "Date": "2020-10-02", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10773.3717745702, - "Vacc_completed": 1605.3068408797, - "Vacc_refreshed": 3.6283182226, - "Vacc_refreshed_2": 1.8141591113 - }, - { - "Date": "2020-10-03", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10773.4956401429, - "Vacc_completed": 1610.6119068185, - "Vacc_refreshed": 6.1967396209, - "Vacc_refreshed_2": 3.09836981045 - }, - { - "Date": "2020-10-04", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10774.4184508751, - "Vacc_completed": 1613.016161978, - "Vacc_refreshed": 15.7069691534, - "Vacc_refreshed_2": 7.8534845767 - }, - { - "Date": "2020-10-05", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10780.8073818373, - "Vacc_completed": 1622.1917795654, - "Vacc_refreshed": 20.1697274397, - "Vacc_refreshed_2": 10.08486371985 - }, - { - "Date": "2020-10-06", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10785.5287460006, - "Vacc_completed": 1625.0602525893, - "Vacc_refreshed": 22.4671684217, - "Vacc_refreshed_2": 11.23358421085 - }, - { - "Date": "2020-10-07", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10790.1084610651, - "Vacc_completed": 1627.3787523231, - "Vacc_refreshed": 28.5217462646, - "Vacc_refreshed_2": 14.2608731323 - }, - { - "Date": "2020-10-08", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10796.2300309, - "Vacc_completed": 1630.4363483664, - "Vacc_refreshed": 35.3070676184, - "Vacc_refreshed_2": 17.6535338092 - }, - { - "Date": "2020-10-09", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10801.7222904172, - "Vacc_completed": 1638.725087864, - "Vacc_refreshed": 43.7679344272, - "Vacc_refreshed_2": 21.8839672136 - }, - { - "Date": "2020-10-10", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10804.7724722766, - "Vacc_completed": 1646.4905335365, - "Vacc_refreshed": 44.1718542676, - "Vacc_refreshed_2": 22.0859271338 - }, - { - "Date": "2020-10-11", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10814.3453353804, - "Vacc_completed": 1650.9992837124, - "Vacc_refreshed": 49.5204655539, - "Vacc_refreshed_2": 24.76023277695 - }, - { - "Date": "2020-10-12", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10821.6255112157, - "Vacc_completed": 1656.4335840831, - "Vacc_refreshed": 52.7009855172, - "Vacc_refreshed_2": 26.3504927586 - }, - { - "Date": "2020-10-13", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10830.9379325639, - "Vacc_completed": 1657.186187271, - "Vacc_refreshed": 56.5428649986, - "Vacc_refreshed_2": 28.2714324993 - }, - { - "Date": "2020-10-14", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10838.202902864, - "Vacc_completed": 1662.1470499364, - "Vacc_refreshed": 58.6277824858, - "Vacc_refreshed_2": 29.3138912429 - }, - { - "Date": "2020-10-15", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10840.8786753296, - "Vacc_completed": 1670.6860254071, - "Vacc_refreshed": 58.7593924743, - "Vacc_refreshed_2": 29.37969623715 - }, - { - "Date": "2020-10-16", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10843.7453960183, - "Vacc_completed": 1673.6372365137, - "Vacc_refreshed": 61.8595630166, - "Vacc_refreshed_2": 30.9297815083 - }, - { - "Date": "2020-10-17", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10849.1151892515, - "Vacc_completed": 1675.1066023109, - "Vacc_refreshed": 64.6020615007, - "Vacc_refreshed_2": 32.30103075035 - }, - { - "Date": "2020-10-18", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10850.9329685403, - "Vacc_completed": 1679.1505675366, - "Vacc_refreshed": 72.0237510859, - "Vacc_refreshed_2": 36.01187554295 - }, - { - "Date": "2020-10-19", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10854.4610677614, - "Vacc_completed": 1681.5473018047, - "Vacc_refreshed": 75.0145349272, - "Vacc_refreshed_2": 37.5072674636 - }, - { - "Date": "2020-10-20", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10858.0662824418, - "Vacc_completed": 1688.7179113019, - "Vacc_refreshed": 82.7641475111, - "Vacc_refreshed_2": 41.38207375555 - }, - { - "Date": "2020-10-21", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10867.8357803799, - "Vacc_completed": 1688.741478882, - "Vacc_refreshed": 92.1411476813, - "Vacc_refreshed_2": 46.07057384065 - }, - { - "Date": "2020-10-22", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10877.245759177, - "Vacc_completed": 1696.3354153291, - "Vacc_refreshed": 93.5350586202, - "Vacc_refreshed_2": 46.7675293101 - }, - { - "Date": "2020-10-23", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10878.9277486403, - "Vacc_completed": 1704.5169058825, - "Vacc_refreshed": 99.9257252117, - "Vacc_refreshed_2": 49.96286260585 - }, - { - "Date": "2020-10-24", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10881.5163902637, - "Vacc_completed": 1704.5184844203, - "Vacc_refreshed": 104.0563799981, - "Vacc_refreshed_2": 52.02818999905 - }, - { - "Date": "2020-10-25", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10882.0628121233, - "Vacc_completed": 1710.1811092467, - "Vacc_refreshed": 110.998904559, - "Vacc_refreshed_2": 55.4994522795 - }, - { - "Date": "2020-10-26", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10884.1868939764, - "Vacc_completed": 1711.6669667815, - "Vacc_refreshed": 119.5835613879, - "Vacc_refreshed_2": 59.79178069395 - }, - { - "Date": "2020-10-27", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10890.26315895, - "Vacc_completed": 1712.8219244738, - "Vacc_refreshed": 126.203975023, - "Vacc_refreshed_2": 63.1019875115 - }, - { - "Date": "2020-10-28", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10894.6858788747, - "Vacc_completed": 1721.7467435031, - "Vacc_refreshed": 135.9649739788, - "Vacc_refreshed_2": 67.9824869894 - }, - { - "Date": "2020-10-29", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10897.5575288795, - "Vacc_completed": 1721.7787127468, - "Vacc_refreshed": 145.614673399, - "Vacc_refreshed_2": 72.8073366995 - }, - { - "Date": "2020-10-30", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10903.1231721286, - "Vacc_completed": 1724.7269587992, - "Vacc_refreshed": 149.6717929743, - "Vacc_refreshed_2": 74.83589648715 - }, - { - "Date": "2020-10-31", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10911.1763853993, - "Vacc_completed": 1726.3071857535, - "Vacc_refreshed": 158.0496522084, - "Vacc_refreshed_2": 79.0248261042 - }, - { - "Date": "2020-11-01", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10919.5582023277, - "Vacc_completed": 1727.9236223535, - "Vacc_refreshed": 160.5751263702, - "Vacc_refreshed_2": 80.2875631851 - }, - { - "Date": "2020-11-02", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10920.4962369047, - "Vacc_completed": 1730.7211296321, - "Vacc_refreshed": 162.2038531114, - "Vacc_refreshed_2": 81.1019265557 - }, - { - "Date": "2020-11-03", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10930.0062994591, - "Vacc_completed": 1733.2273616859, - "Vacc_refreshed": 164.6178844659, - "Vacc_refreshed_2": 82.30894223295 - }, - { - "Date": "2020-11-04", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10931.0781786076, - "Vacc_completed": 1743.0639116966, - "Vacc_refreshed": 171.6949336111, - "Vacc_refreshed_2": 85.84746680555 - }, - { - "Date": "2020-11-05", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10936.2371584575, - "Vacc_completed": 1743.4973637943, - "Vacc_refreshed": 173.1954991423, - "Vacc_refreshed_2": 86.59774957115 - }, - { - "Date": "2020-11-06", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10937.1969149599, - "Vacc_completed": 1752.0043206175, - "Vacc_refreshed": 173.4521249531, - "Vacc_refreshed_2": 86.72606247655 - }, - { - "Date": "2020-11-07", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10942.5829785849, - "Vacc_completed": 1758.5438162851, - "Vacc_refreshed": 175.0971428389, - "Vacc_refreshed_2": 87.54857141945 - }, - { - "Date": "2020-11-08", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10945.8458051779, - "Vacc_completed": 1765.593119461, - "Vacc_refreshed": 184.781293552, - "Vacc_refreshed_2": 92.390646776 - }, - { - "Date": "2020-11-09", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10955.2619609788, - "Vacc_completed": 1766.7516696253, - "Vacc_refreshed": 194.3279051811, - "Vacc_refreshed_2": 97.16395259055 - }, - { - "Date": "2020-11-10", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10963.0529992794, - "Vacc_completed": 1774.4096958807, - "Vacc_refreshed": 199.3585168564, - "Vacc_refreshed_2": 99.6792584282 - }, - { - "Date": "2020-11-11", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10963.0740456643, - "Vacc_completed": 1776.7353479155, - "Vacc_refreshed": 200.2783085421, - "Vacc_refreshed_2": 100.13915427105 - }, - { - "Date": "2020-11-12", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10972.7647446192, - "Vacc_completed": 1786.1838226639, - "Vacc_refreshed": 202.522841172, - "Vacc_refreshed_2": 101.261420586 - }, - { - "Date": "2020-11-13", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10972.7950553291, - "Vacc_completed": 1788.5013884886, - "Vacc_refreshed": 205.1107008609, - "Vacc_refreshed_2": 102.55535043045 - }, - { - "Date": "2020-11-14", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10973.1049316279, - "Vacc_completed": 1790.2712267193, - "Vacc_refreshed": 214.0688577867, - "Vacc_refreshed_2": 107.03442889335 - }, - { - "Date": "2020-11-15", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10976.2696576646, - "Vacc_completed": 1797.8582422894, - "Vacc_refreshed": 219.0460187772, - "Vacc_refreshed_2": 109.5230093886 - }, - { - "Date": "2020-11-16", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10984.9161656634, - "Vacc_completed": 1801.5924446935, - "Vacc_refreshed": 227.656626047, - "Vacc_refreshed_2": 113.8283130235 - }, - { - "Date": "2020-11-17", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10994.063273181, - "Vacc_completed": 1802.6817444812, - "Vacc_refreshed": 235.6032823069, - "Vacc_refreshed_2": 117.80164115345 - }, - { - "Date": "2020-11-18", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 10996.8771305673, - "Vacc_completed": 1802.9071097171, - "Vacc_refreshed": 237.7242073629, - "Vacc_refreshed_2": 118.86210368145 - }, - { - "Date": "2020-11-19", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11002.0527900673, - "Vacc_completed": 1809.5395950318, - "Vacc_refreshed": 241.3631599251, - "Vacc_refreshed_2": 120.68157996255 - }, - { - "Date": "2020-11-20", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11007.1528572096, - "Vacc_completed": 1813.9025489723, - "Vacc_refreshed": 245.5305344153, - "Vacc_refreshed_2": 122.76526720765 - }, - { - "Date": "2020-11-21", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11013.1337350258, - "Vacc_completed": 1821.5275057931, - "Vacc_refreshed": 250.3168579858, - "Vacc_refreshed_2": 125.1584289929 - }, - { - "Date": "2020-11-22", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11015.6696905796, - "Vacc_completed": 1822.9598630397, - "Vacc_refreshed": 255.6335351411, - "Vacc_refreshed_2": 127.81676757055 - }, - { - "Date": "2020-11-23", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11023.4754023371, - "Vacc_completed": 1827.2471461973, - "Vacc_refreshed": 265.5951098299, - "Vacc_refreshed_2": 132.79755491495 - }, - { - "Date": "2020-11-24", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11032.8284479669, - "Vacc_completed": 1827.5539031975, - "Vacc_refreshed": 267.3513136054, - "Vacc_refreshed_2": 133.6756568027 - }, - { - "Date": "2020-11-25", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11039.3845078238, - "Vacc_completed": 1828.9970028031, - "Vacc_refreshed": 270.5903250252, - "Vacc_refreshed_2": 135.2951625126 - }, - { - "Date": "2020-11-26", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11039.693720803, - "Vacc_completed": 1836.2049019351, - "Vacc_refreshed": 272.0758803579, - "Vacc_refreshed_2": 136.03794017895 - }, - { - "Date": "2020-11-27", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11047.8242120991, - "Vacc_completed": 1837.1027842122, - "Vacc_refreshed": 275.2277393803, - "Vacc_refreshed_2": 137.61386969015 - }, - { - "Date": "2020-11-28", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11053.900379851, - "Vacc_completed": 1838.273599421, - "Vacc_refreshed": 282.2344875735, - "Vacc_refreshed_2": 141.11724378675 - }, - { - "Date": "2020-11-29", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11059.6633767419, - "Vacc_completed": 1845.0089267377, - "Vacc_refreshed": 284.3140546038, - "Vacc_refreshed_2": 142.1570273019 - }, - { - "Date": "2020-11-30", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11068.9288674107, - "Vacc_completed": 1852.7615624634, - "Vacc_refreshed": 287.0304142153, - "Vacc_refreshed_2": 143.51520710765 - }, - { - "Date": "2020-12-01", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11072.6595101177, - "Vacc_completed": 1857.871819743, - "Vacc_refreshed": 289.2733395979, - "Vacc_refreshed_2": 144.63666979895 - }, - { - "Date": "2020-12-02", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11082.5784142097, - "Vacc_completed": 1865.7647392626, - "Vacc_refreshed": 291.3426551576, - "Vacc_refreshed_2": 145.6713275788 - }, - { - "Date": "2020-12-03", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11089.5185616411, - "Vacc_completed": 1869.3958231852, - "Vacc_refreshed": 299.8179962185, - "Vacc_refreshed_2": 149.90899810925 - }, - { - "Date": "2020-12-04", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11097.3087770941, - "Vacc_completed": 1878.7026117675, - "Vacc_refreshed": 306.1608208876, - "Vacc_refreshed_2": 153.0804104438 - }, - { - "Date": "2020-12-05", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11101.8508357142, - "Vacc_completed": 1879.7270518854, - "Vacc_refreshed": 308.0716738039, - "Vacc_refreshed_2": 154.03583690195 - }, - { - "Date": "2020-12-06", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11103.0915214706, - "Vacc_completed": 1883.5574266434, - "Vacc_refreshed": 311.2801806804, - "Vacc_refreshed_2": 155.6400903402 - }, - { - "Date": "2020-12-07", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11111.9334619087, - "Vacc_completed": 1887.7967037043, - "Vacc_refreshed": 320.2156677375, - "Vacc_refreshed_2": 160.10783386875 - }, - { - "Date": "2020-12-08", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11118.8667730664, - "Vacc_completed": 1896.6793284207, - "Vacc_refreshed": 321.8561637233, - "Vacc_refreshed_2": 160.92808186165 - }, - { - "Date": "2020-12-09", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11123.0290736537, - "Vacc_completed": 1902.1985445903, - "Vacc_refreshed": 328.4656069808, - "Vacc_refreshed_2": 164.2328034904 - }, - { - "Date": "2020-12-10", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11129.3471714321, - "Vacc_completed": 1902.2057666507, - "Vacc_refreshed": 334.8734059386, - "Vacc_refreshed_2": 167.4367029693 - }, - { - "Date": "2020-12-11", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11137.9949570833, - "Vacc_completed": 1907.7915885083, - "Vacc_refreshed": 339.9783670978, - "Vacc_refreshed_2": 169.9891835489 - }, - { - "Date": "2020-12-12", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11139.4617826874, - "Vacc_completed": 1910.6126501167, - "Vacc_refreshed": 342.8472462544, - "Vacc_refreshed_2": 171.4236231272 - }, - { - "Date": "2020-12-13", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11144.4191917936, - "Vacc_completed": 1917.8558172992, - "Vacc_refreshed": 351.3104814196, - "Vacc_refreshed_2": 175.6552407098 - }, - { - "Date": "2020-12-14", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11153.423123173, - "Vacc_completed": 1927.8115362669, - "Vacc_refreshed": 359.1887782128, - "Vacc_refreshed_2": 179.5943891064 - }, - { - "Date": "2020-12-15", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11155.4646855253, - "Vacc_completed": 1931.0938823989, - "Vacc_refreshed": 363.4217582407, - "Vacc_refreshed_2": 181.71087912035 - }, - { - "Date": "2020-12-16", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11164.8755655095, - "Vacc_completed": 1932.0922021433, - "Vacc_refreshed": 369.5881371093, - "Vacc_refreshed_2": 184.79406855465 - }, - { - "Date": "2020-12-17", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11168.2127634861, - "Vacc_completed": 1937.8864562316, - "Vacc_refreshed": 371.2850357688, - "Vacc_refreshed_2": 185.6425178844 - }, - { - "Date": "2020-12-18", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11170.3919325879, - "Vacc_completed": 1943.9625258254, - "Vacc_refreshed": 372.564368772, - "Vacc_refreshed_2": 186.282184386 - }, - { - "Date": "2020-12-19", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11178.2156716034, - "Vacc_completed": 1946.3680545291, - "Vacc_refreshed": 377.1791450411, - "Vacc_refreshed_2": 188.58957252055 - }, - { - "Date": "2020-12-20", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11187.7206334256, - "Vacc_completed": 1950.3408321869, - "Vacc_refreshed": 385.28114877, - "Vacc_refreshed_2": 192.640574385 - }, - { - "Date": "2020-12-21", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11189.2295548943, - "Vacc_completed": 1952.7801877326, - "Vacc_refreshed": 386.4768386941, - "Vacc_refreshed_2": 193.23841934705 - }, - { - "Date": "2020-12-22", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11193.8090943925, - "Vacc_completed": 1960.5337079214, - "Vacc_refreshed": 395.6463777137, - "Vacc_refreshed_2": 197.82318885685 - }, - { - "Date": "2020-12-23", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11198.0758128722, - "Vacc_completed": 1964.4220756604, - "Vacc_refreshed": 404.4005517293, - "Vacc_refreshed_2": 202.20027586465 - }, - { - "Date": "2020-12-24", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11200.1395546734, - "Vacc_completed": 1974.1843879258, - "Vacc_refreshed": 410.4354615606, - "Vacc_refreshed_2": 205.2177307803 - }, - { - "Date": "2020-12-25", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11203.0858861212, - "Vacc_completed": 1978.0710124849, - "Vacc_refreshed": 414.2205337181, - "Vacc_refreshed_2": 207.11026685905 - }, - { - "Date": "2020-12-26", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11203.5521637654, - "Vacc_completed": 1981.3589179628, - "Vacc_refreshed": 419.5840242501, - "Vacc_refreshed_2": 209.79201212505 - }, - { - "Date": "2020-12-27", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11211.6562498266, - "Vacc_completed": 1989.6665585254, - "Vacc_refreshed": 426.6154672823, - "Vacc_refreshed_2": 213.30773364115 - }, - { - "Date": "2020-12-28", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11219.1926870115, - "Vacc_completed": 1996.1459430488, - "Vacc_refreshed": 430.16915603, - "Vacc_refreshed_2": 215.084578015 - }, - { - "Date": "2020-12-29", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11221.4656474699, - "Vacc_completed": 2001.4601213853, - "Vacc_refreshed": 430.8770850788, - "Vacc_refreshed_2": 215.4385425394 - }, - { - "Date": "2020-12-30", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11224.2379660032, - "Vacc_completed": 2006.2961081678, - "Vacc_refreshed": 433.8074021391, - "Vacc_refreshed_2": 216.90370106955 - }, - { - "Date": "2020-12-31", - "ID_County": 1002, - "Age_RKI": "5-14", - "Vacc_partially": 11229.137503588, - "Vacc_completed": 2013.2392255015, - "Vacc_refreshed": 441.1218403265, - "Vacc_refreshed_2": 220.56092016325 - }, - { - "Date": "2020-10-01", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15118.5419446559, - "Vacc_completed": 1046.4766182565, - "Vacc_refreshed": 0, - "Vacc_refreshed_2": 0.0 - }, - { - "Date": "2020-10-02", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15127.0441726861, - "Vacc_completed": 1051.8189573454, - "Vacc_refreshed": 4.7668817312, - "Vacc_refreshed_2": 2.3834408656 - }, - { - "Date": "2020-10-03", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15134.2198668737, - "Vacc_completed": 1051.8898550539, - "Vacc_refreshed": 6.8954841457, - "Vacc_refreshed_2": 3.44774207285 - }, - { - "Date": "2020-10-04", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15138.5012633389, - "Vacc_completed": 1054.1938291422, - "Vacc_refreshed": 12.8850967826, - "Vacc_refreshed_2": 6.4425483913 - }, - { - "Date": "2020-10-05", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15140.019297286, - "Vacc_completed": 1057.2812920036, - "Vacc_refreshed": 15.610006044, - "Vacc_refreshed_2": 7.805003022 - }, - { - "Date": "2020-10-06", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15141.0655653453, - "Vacc_completed": 1061.1873607435, - "Vacc_refreshed": 18.0052067519, - "Vacc_refreshed_2": 9.00260337595 - }, - { - "Date": "2020-10-07", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15146.6047446953, - "Vacc_completed": 1067.3953196211, - "Vacc_refreshed": 27.5155266211, - "Vacc_refreshed_2": 13.75776331055 - }, - { - "Date": "2020-10-08", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15150.2459378898, - "Vacc_completed": 1077.315397207, - "Vacc_refreshed": 28.0742687581, - "Vacc_refreshed_2": 14.03713437905 - }, - { - "Date": "2020-10-09", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15153.3836683973, - "Vacc_completed": 1082.8237823387, - "Vacc_refreshed": 32.6629347887, - "Vacc_refreshed_2": 16.33146739435 - }, - { - "Date": "2020-10-10", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15155.2486658897, - "Vacc_completed": 1087.8721865368, - "Vacc_refreshed": 42.082807235, - "Vacc_refreshed_2": 21.0414036175 - }, - { - "Date": "2020-10-11", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15157.4630323429, - "Vacc_completed": 1090.0916620904, - "Vacc_refreshed": 43.8436800298, - "Vacc_refreshed_2": 21.9218400149 - }, - { - "Date": "2020-10-12", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15158.7941750828, - "Vacc_completed": 1091.8322828475, - "Vacc_refreshed": 44.7371311455, - "Vacc_refreshed_2": 22.36856557275 - }, - { - "Date": "2020-10-13", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15159.4697179186, - "Vacc_completed": 1097.9581123146, - "Vacc_refreshed": 52.5410403094, - "Vacc_refreshed_2": 26.2705201547 - }, - { - "Date": "2020-10-14", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15166.8797207146, - "Vacc_completed": 1103.4838023049, - "Vacc_refreshed": 58.4482610787, - "Vacc_refreshed_2": 29.22413053935 - }, - { - "Date": "2020-10-15", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15171.177591783, - "Vacc_completed": 1107.529236183, - "Vacc_refreshed": 61.868532741, - "Vacc_refreshed_2": 30.9342663705 - }, - { - "Date": "2020-10-16", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15171.3473624207, - "Vacc_completed": 1108.0854442406, - "Vacc_refreshed": 64.122741794, - "Vacc_refreshed_2": 32.061370897 - }, - { - "Date": "2020-10-17", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15176.6656703161, - "Vacc_completed": 1114.7623442184, - "Vacc_refreshed": 73.3909194547, - "Vacc_refreshed_2": 36.69545972735 - }, - { - "Date": "2020-10-18", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15182.6538662202, - "Vacc_completed": 1121.0967139584, - "Vacc_refreshed": 78.4108273222, - "Vacc_refreshed_2": 39.2054136611 - }, - { - "Date": "2020-10-19", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15191.0826029366, - "Vacc_completed": 1124.8733122731, - "Vacc_refreshed": 88.1249123157, - "Vacc_refreshed_2": 44.06245615785 - }, - { - "Date": "2020-10-20", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15195.1567917247, - "Vacc_completed": 1133.1683853487, - "Vacc_refreshed": 94.0586819047, - "Vacc_refreshed_2": 47.02934095235 - }, - { - "Date": "2020-10-21", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15197.6523517992, - "Vacc_completed": 1140.1742056487, - "Vacc_refreshed": 97.7116921077, - "Vacc_refreshed_2": 48.85584605385 - }, - { - "Date": "2020-10-22", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15202.8832794911, - "Vacc_completed": 1140.4207518542, - "Vacc_refreshed": 101.0390519368, - "Vacc_refreshed_2": 50.5195259684 - }, - { - "Date": "2020-10-23", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15209.502983548, - "Vacc_completed": 1144.1138351675, - "Vacc_refreshed": 104.5568369595, - "Vacc_refreshed_2": 52.27841847975 - }, - { - "Date": "2020-10-24", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15218.5591667959, - "Vacc_completed": 1153.0110444013, - "Vacc_refreshed": 111.8121115483, - "Vacc_refreshed_2": 55.90605577415 - }, - { - "Date": "2020-10-25", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15223.6275127037, - "Vacc_completed": 1157.3585549388, - "Vacc_refreshed": 113.9066704897, - "Vacc_refreshed_2": 56.95333524485 - }, - { - "Date": "2020-10-26", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15225.4100349304, - "Vacc_completed": 1162.1581378525, - "Vacc_refreshed": 116.416758139, - "Vacc_refreshed_2": 58.2083790695 - }, - { - "Date": "2020-10-27", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15225.7888080253, - "Vacc_completed": 1166.5300160643, - "Vacc_refreshed": 119.2414894864, - "Vacc_refreshed_2": 59.6207447432 - }, - { - "Date": "2020-10-28", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15235.240974732, - "Vacc_completed": 1171.76423914, - "Vacc_refreshed": 129.0137217302, - "Vacc_refreshed_2": 64.5068608651 - }, - { - "Date": "2020-10-29", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15236.252829019, - "Vacc_completed": 1174.1820893055, - "Vacc_refreshed": 130.8298102316, - "Vacc_refreshed_2": 65.4149051158 - }, - { - "Date": "2020-10-30", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15244.5996289271, - "Vacc_completed": 1181.3457343202, - "Vacc_refreshed": 138.0198133972, - "Vacc_refreshed_2": 69.0099066986 - }, - { - "Date": "2020-10-31", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15247.7688417561, - "Vacc_completed": 1186.4632437534, - "Vacc_refreshed": 147.549469044, - "Vacc_refreshed_2": 73.774734522 - }, - { - "Date": "2020-11-01", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15254.8324409461, - "Vacc_completed": 1196.0640695451, - "Vacc_refreshed": 148.035813332, - "Vacc_refreshed_2": 74.017906666 - }, - { - "Date": "2020-11-02", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15263.9056700401, - "Vacc_completed": 1202.0195228295, - "Vacc_refreshed": 152.9647063671, - "Vacc_refreshed_2": 76.48235318355 - }, - { - "Date": "2020-11-03", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15271.3608079113, - "Vacc_completed": 1205.9189472233, - "Vacc_refreshed": 159.4326071199, - "Vacc_refreshed_2": 79.71630355995 - }, - { - "Date": "2020-11-04", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15274.5391192733, - "Vacc_completed": 1209.5333389579, - "Vacc_refreshed": 165.8197711746, - "Vacc_refreshed_2": 82.9098855873 - }, - { - "Date": "2020-11-05", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15279.9252173752, - "Vacc_completed": 1217.5022918804, - "Vacc_refreshed": 170.1668415009, - "Vacc_refreshed_2": 85.08342075045 - }, - { - "Date": "2020-11-06", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15289.6429605219, - "Vacc_completed": 1218.0921627258, - "Vacc_refreshed": 176.8858359396, - "Vacc_refreshed_2": 88.4429179698 - }, - { - "Date": "2020-11-07", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15297.4452269777, - "Vacc_completed": 1218.4916546179, - "Vacc_refreshed": 177.0224757358, - "Vacc_refreshed_2": 88.5112378679 - }, - { - "Date": "2020-11-08", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15304.6068820067, - "Vacc_completed": 1221.1648349639, - "Vacc_refreshed": 182.8363512803, - "Vacc_refreshed_2": 91.41817564015 - }, - { - "Date": "2020-11-09", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15308.4472782837, - "Vacc_completed": 1221.3254317254, - "Vacc_refreshed": 188.4124431026, - "Vacc_refreshed_2": 94.2062215513 - }, - { - "Date": "2020-11-10", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15313.3535420035, - "Vacc_completed": 1228.797689569, - "Vacc_refreshed": 197.4958413402, - "Vacc_refreshed_2": 98.7479206701 - }, - { - "Date": "2020-11-11", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15319.6989570363, - "Vacc_completed": 1230.5766158569, - "Vacc_refreshed": 207.1280776834, - "Vacc_refreshed_2": 103.5640388417 - }, - { - "Date": "2020-11-12", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15329.2757609065, - "Vacc_completed": 1232.5532561558, - "Vacc_refreshed": 216.6030971785, - "Vacc_refreshed_2": 108.30154858925 - }, - { - "Date": "2020-11-13", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15331.3854251166, - "Vacc_completed": 1240.7858568563, - "Vacc_refreshed": 224.0947128601, - "Vacc_refreshed_2": 112.04735643005 - }, - { - "Date": "2020-11-14", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15335.6254694555, - "Vacc_completed": 1248.7648628072, - "Vacc_refreshed": 228.3914917972, - "Vacc_refreshed_2": 114.1957458986 - }, - { - "Date": "2020-11-15", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15342.4956408139, - "Vacc_completed": 1253.345700271, - "Vacc_refreshed": 237.7873655386, - "Vacc_refreshed_2": 118.8936827693 - }, - { - "Date": "2020-11-16", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15349.2985100866, - "Vacc_completed": 1254.923228178, - "Vacc_refreshed": 243.7398150729, - "Vacc_refreshed_2": 121.86990753645 - }, - { - "Date": "2020-11-17", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15350.0642849231, - "Vacc_completed": 1256.1247258557, - "Vacc_refreshed": 246.0998008594, - "Vacc_refreshed_2": 123.0499004297 - }, - { - "Date": "2020-11-18", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15350.3098206871, - "Vacc_completed": 1258.7673082658, - "Vacc_refreshed": 255.4830156808, - "Vacc_refreshed_2": 127.7415078404 - }, - { - "Date": "2020-11-19", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15350.8477668821, - "Vacc_completed": 1261.8739088788, - "Vacc_refreshed": 262.4150374381, - "Vacc_refreshed_2": 131.20751871905 - }, - { - "Date": "2020-11-20", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15355.0053188609, - "Vacc_completed": 1268.7063064011, - "Vacc_refreshed": 268.0354130392, - "Vacc_refreshed_2": 134.0177065196 - }, - { - "Date": "2020-11-21", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15356.8245202899, - "Vacc_completed": 1275.6335562552, - "Vacc_refreshed": 272.2800844077, - "Vacc_refreshed_2": 136.14004220385 - }, - { - "Date": "2020-11-22", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15357.7799420851, - "Vacc_completed": 1276.6526923528, - "Vacc_refreshed": 272.4509982396, - "Vacc_refreshed_2": 136.2254991198 - }, - { - "Date": "2020-11-23", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15360.090059624, - "Vacc_completed": 1286.3717718947, - "Vacc_refreshed": 276.5108897334, - "Vacc_refreshed_2": 138.2554448667 - }, - { - "Date": "2020-11-24", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15368.9251730685, - "Vacc_completed": 1289.9608638772, - "Vacc_refreshed": 286.1598516049, - "Vacc_refreshed_2": 143.07992580245 - }, - { - "Date": "2020-11-25", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15374.4348532349, - "Vacc_completed": 1292.7431692071, - "Vacc_refreshed": 286.9834989324, - "Vacc_refreshed_2": 143.4917494662 - }, - { - "Date": "2020-11-26", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15375.2266568732, - "Vacc_completed": 1293.6118841564, - "Vacc_refreshed": 287.1997495191, - "Vacc_refreshed_2": 143.59987475955 - }, - { - "Date": "2020-11-27", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15378.8167187789, - "Vacc_completed": 1294.2472234682, - "Vacc_refreshed": 293.7465776915, - "Vacc_refreshed_2": 146.87328884575 - }, - { - "Date": "2020-11-28", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15381.8183566081, - "Vacc_completed": 1296.5074589754, - "Vacc_refreshed": 294.394169978, - "Vacc_refreshed_2": 147.197084989 - }, - { - "Date": "2020-11-29", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15390.3384592829, - "Vacc_completed": 1298.1144038724, - "Vacc_refreshed": 295.3508481166, - "Vacc_refreshed_2": 147.6754240583 - }, - { - "Date": "2020-11-30", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15397.4841102393, - "Vacc_completed": 1301.7744150574, - "Vacc_refreshed": 295.636121459, - "Vacc_refreshed_2": 147.8180607295 - }, - { - "Date": "2020-12-01", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15406.9128765942, - "Vacc_completed": 1306.3546732411, - "Vacc_refreshed": 299.2176949608, - "Vacc_refreshed_2": 149.6088474804 - }, - { - "Date": "2020-12-02", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15412.9312961067, - "Vacc_completed": 1313.4112918553, - "Vacc_refreshed": 304.1283567048, - "Vacc_refreshed_2": 152.0641783524 - }, - { - "Date": "2020-12-03", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15413.8396565369, - "Vacc_completed": 1323.1872711778, - "Vacc_refreshed": 309.3767578057, - "Vacc_refreshed_2": 154.68837890285 - }, - { - "Date": "2020-12-04", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15417.5353933956, - "Vacc_completed": 1332.5570169907, - "Vacc_refreshed": 310.9982936972, - "Vacc_refreshed_2": 155.4991468486 - }, - { - "Date": "2020-12-05", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15418.826072466, - "Vacc_completed": 1333.4298810326, - "Vacc_refreshed": 318.8191964614, - "Vacc_refreshed_2": 159.4095982307 - }, - { - "Date": "2020-12-06", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15428.6081802722, - "Vacc_completed": 1335.4576305614, - "Vacc_refreshed": 322.681425219, - "Vacc_refreshed_2": 161.3407126095 - }, - { - "Date": "2020-12-07", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15434.4342053135, - "Vacc_completed": 1341.8151001107, - "Vacc_refreshed": 328.87826872, - "Vacc_refreshed_2": 164.43913436 - }, - { - "Date": "2020-12-08", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15442.7494739491, - "Vacc_completed": 1342.4758295952, - "Vacc_refreshed": 336.8125605002, - "Vacc_refreshed_2": 168.4062802501 - }, - { - "Date": "2020-12-09", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15451.9615776405, - "Vacc_completed": 1343.8595431355, - "Vacc_refreshed": 340.6379428895, - "Vacc_refreshed_2": 170.31897144475 - }, - { - "Date": "2020-12-10", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15461.0343740586, - "Vacc_completed": 1352.0217149096, - "Vacc_refreshed": 342.4652609374, - "Vacc_refreshed_2": 171.2326304687 - }, - { - "Date": "2020-12-11", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15467.8869999547, - "Vacc_completed": 1353.9994636638, - "Vacc_refreshed": 343.6202751504, - "Vacc_refreshed_2": 171.8101375752 - }, - { - "Date": "2020-12-12", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15474.9129704383, - "Vacc_completed": 1363.3653927841, - "Vacc_refreshed": 345.0578595323, - "Vacc_refreshed_2": 172.52892976615 - }, - { - "Date": "2020-12-13", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15483.483328834, - "Vacc_completed": 1372.0348541584, - "Vacc_refreshed": 348.4131919851, - "Vacc_refreshed_2": 174.20659599255 - }, - { - "Date": "2020-12-14", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15489.3942653446, - "Vacc_completed": 1377.4077406314, - "Vacc_refreshed": 355.6717942515, - "Vacc_refreshed_2": 177.83589712575 - }, - { - "Date": "2020-12-15", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15494.2503612359, - "Vacc_completed": 1377.4290090401, - "Vacc_refreshed": 358.9820312389, - "Vacc_refreshed_2": 179.49101561945 - }, - { - "Date": "2020-12-16", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15495.3394152185, - "Vacc_completed": 1378.0321848221, - "Vacc_refreshed": 364.7453207897, - "Vacc_refreshed_2": 182.37266039485 - }, - { - "Date": "2020-12-17", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15497.7000250685, - "Vacc_completed": 1378.1938721933, - "Vacc_refreshed": 367.9820639836, - "Vacc_refreshed_2": 183.9910319918 - }, - { - "Date": "2020-12-18", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15498.7689863883, - "Vacc_completed": 1381.0445655705, - "Vacc_refreshed": 371.501202086, - "Vacc_refreshed_2": 185.750601043 - }, - { - "Date": "2020-12-19", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15501.5446144083, - "Vacc_completed": 1383.5660020007, - "Vacc_refreshed": 378.7475176563, - "Vacc_refreshed_2": 189.37375882815 - }, - { - "Date": "2020-12-20", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15509.8230148672, - "Vacc_completed": 1390.2361319678, - "Vacc_refreshed": 382.7365149116, - "Vacc_refreshed_2": 191.3682574558 - }, - { - "Date": "2020-12-21", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15516.8607244434, - "Vacc_completed": 1391.5356833196, - "Vacc_refreshed": 387.0287274101, - "Vacc_refreshed_2": 193.51436370505 - }, - { - "Date": "2020-12-22", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15525.4621417067, - "Vacc_completed": 1391.7538408053, - "Vacc_refreshed": 394.832505058, - "Vacc_refreshed_2": 197.416252529 - }, - { - "Date": "2020-12-23", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15530.1412323442, - "Vacc_completed": 1393.5856974411, - "Vacc_refreshed": 402.9766589833, - "Vacc_refreshed_2": 201.48832949165 - }, - { - "Date": "2020-12-24", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15538.5266345599, - "Vacc_completed": 1394.0860887346, - "Vacc_refreshed": 409.427624651, - "Vacc_refreshed_2": 204.7138123255 - }, - { - "Date": "2020-12-25", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15545.1857152555, - "Vacc_completed": 1400.9009375981, - "Vacc_refreshed": 414.8161834543, - "Vacc_refreshed_2": 207.40809172715 - }, - { - "Date": "2020-12-26", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15550.0113840393, - "Vacc_completed": 1405.1190388135, - "Vacc_refreshed": 423.1492506703, - "Vacc_refreshed_2": 211.57462533515 - }, - { - "Date": "2020-12-27", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15557.7502728646, - "Vacc_completed": 1412.7232837907, - "Vacc_refreshed": 429.51858195, - "Vacc_refreshed_2": 214.759290975 - }, - { - "Date": "2020-12-28", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15558.6635273277, - "Vacc_completed": 1416.4367765358, - "Vacc_refreshed": 433.7574702422, - "Vacc_refreshed_2": 216.8787351211 - }, - { - "Date": "2020-12-29", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15567.8923476818, - "Vacc_completed": 1417.419547185, - "Vacc_refreshed": 436.3988331827, - "Vacc_refreshed_2": 218.19941659135 - }, - { - "Date": "2020-12-30", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15572.0110691064, - "Vacc_completed": 1422.1291332179, - "Vacc_refreshed": 444.7065625402, - "Vacc_refreshed_2": 222.3532812701 - }, - { - "Date": "2020-12-31", - "ID_County": 1002, - "Age_RKI": "15-34", - "Vacc_partially": 15580.056372857, - "Vacc_completed": 1429.5241883626, - "Vacc_refreshed": 445.9185645116, - "Vacc_refreshed_2": 222.9592822558 - }, - { - "Date": "2020-10-01", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14604.162091487, - "Vacc_completed": 1396.5367205842, - "Vacc_refreshed": 0, - "Vacc_refreshed_2": 0.0 - }, - { - "Date": "2020-10-02", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14608.6011110978, - "Vacc_completed": 1403.0638750962, - "Vacc_refreshed": 0.4818747518, - "Vacc_refreshed_2": 0.2409373759 - }, - { - "Date": "2020-10-03", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14617.4016613244, - "Vacc_completed": 1412.4617013546, - "Vacc_refreshed": 2.8841327921, - "Vacc_refreshed_2": 1.44206639605 - }, - { - "Date": "2020-10-04", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14626.8147148128, - "Vacc_completed": 1413.5937989207, - "Vacc_refreshed": 4.347225901, - "Vacc_refreshed_2": 2.1736129505 - }, - { - "Date": "2020-10-05", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14636.7930742671, - "Vacc_completed": 1416.5445655325, - "Vacc_refreshed": 10.9126558661, - "Vacc_refreshed_2": 5.45632793305 - }, - { - "Date": "2020-10-06", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14639.261920851, - "Vacc_completed": 1419.7526675766, - "Vacc_refreshed": 12.1285186735, - "Vacc_refreshed_2": 6.06425933675 - }, - { - "Date": "2020-10-07", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14646.6246553828, - "Vacc_completed": 1429.1501916355, - "Vacc_refreshed": 14.2999622979, - "Vacc_refreshed_2": 7.14998114895 - }, - { - "Date": "2020-10-08", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14655.9228453283, - "Vacc_completed": 1433.2061319495, - "Vacc_refreshed": 18.6765331159, - "Vacc_refreshed_2": 9.33826655795 - }, - { - "Date": "2020-10-09", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14656.6905295279, - "Vacc_completed": 1437.4319338048, - "Vacc_refreshed": 19.3435044237, - "Vacc_refreshed_2": 9.67175221185 - }, - { - "Date": "2020-10-10", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14656.8883385186, - "Vacc_completed": 1446.7135497598, - "Vacc_refreshed": 28.359576628, - "Vacc_refreshed_2": 14.179788314 - }, - { - "Date": "2020-10-11", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14660.5634553543, - "Vacc_completed": 1450.9111526521, - "Vacc_refreshed": 38.3056947196, - "Vacc_refreshed_2": 19.1528473598 - }, - { - "Date": "2020-10-12", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14667.0822550267, - "Vacc_completed": 1458.1473384005, - "Vacc_refreshed": 38.8316353015, - "Vacc_refreshed_2": 19.41581765075 - }, - { - "Date": "2020-10-13", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14668.0361388154, - "Vacc_completed": 1464.9440155832, - "Vacc_refreshed": 44.1485629725, - "Vacc_refreshed_2": 22.07428148625 - }, - { - "Date": "2020-10-14", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14669.4679031112, - "Vacc_completed": 1470.1284856322, - "Vacc_refreshed": 47.7639888511, - "Vacc_refreshed_2": 23.88199442555 - }, - { - "Date": "2020-10-15", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14674.2618994679, - "Vacc_completed": 1476.9344530457, - "Vacc_refreshed": 56.361748961, - "Vacc_refreshed_2": 28.1808744805 - }, - { - "Date": "2020-10-16", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14674.3447644481, - "Vacc_completed": 1477.2393580763, - "Vacc_refreshed": 57.2273767339, - "Vacc_refreshed_2": 28.61368836695 - }, - { - "Date": "2020-10-17", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14684.0130216555, - "Vacc_completed": 1484.3234594705, - "Vacc_refreshed": 63.4497732245, - "Vacc_refreshed_2": 31.72488661225 - }, - { - "Date": "2020-10-18", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14691.8154699011, - "Vacc_completed": 1492.8513113216, - "Vacc_refreshed": 71.1720264341, - "Vacc_refreshed_2": 35.58601321705 - }, - { - "Date": "2020-10-19", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14697.5036031252, - "Vacc_completed": 1493.7450842417, - "Vacc_refreshed": 77.3635307257, - "Vacc_refreshed_2": 38.68176536285 - }, - { - "Date": "2020-10-20", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14702.599106658, - "Vacc_completed": 1503.4641107157, - "Vacc_refreshed": 82.0575571669, - "Vacc_refreshed_2": 41.02877858345 - }, - { - "Date": "2020-10-21", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14706.3806325115, - "Vacc_completed": 1509.7236994586, - "Vacc_refreshed": 82.4020129882, - "Vacc_refreshed_2": 41.2010064941 - }, - { - "Date": "2020-10-22", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14711.1723860607, - "Vacc_completed": 1510.3801441147, - "Vacc_refreshed": 89.5249618369, - "Vacc_refreshed_2": 44.76248091845 - }, - { - "Date": "2020-10-23", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14720.0093085987, - "Vacc_completed": 1517.7733661353, - "Vacc_refreshed": 99.2211580734, - "Vacc_refreshed_2": 49.6105790367 - }, - { - "Date": "2020-10-24", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14727.6474505495, - "Vacc_completed": 1519.2060691793, - "Vacc_refreshed": 104.7140344902, - "Vacc_refreshed_2": 52.3570172451 - }, - { - "Date": "2020-10-25", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14737.2025033477, - "Vacc_completed": 1520.8147599339, - "Vacc_refreshed": 111.7829864033, - "Vacc_refreshed_2": 55.89149320165 - }, - { - "Date": "2020-10-26", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14739.5787007901, - "Vacc_completed": 1526.8277919335, - "Vacc_refreshed": 118.2526435067, - "Vacc_refreshed_2": 59.12632175335 - }, - { - "Date": "2020-10-27", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14740.2622466128, - "Vacc_completed": 1533.9654672239, - "Vacc_refreshed": 121.0872593022, - "Vacc_refreshed_2": 60.5436296511 - }, - { - "Date": "2020-10-28", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14749.3105527103, - "Vacc_completed": 1534.5209202615, - "Vacc_refreshed": 130.3683956867, - "Vacc_refreshed_2": 65.18419784335 - }, - { - "Date": "2020-10-29", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14749.4386233429, - "Vacc_completed": 1534.652607589, - "Vacc_refreshed": 131.8609814668, - "Vacc_refreshed_2": 65.9304907334 - }, - { - "Date": "2020-10-30", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14750.7660084012, - "Vacc_completed": 1541.7255942491, - "Vacc_refreshed": 135.0718914562, - "Vacc_refreshed_2": 67.5359457281 - }, - { - "Date": "2020-10-31", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14754.5460710197, - "Vacc_completed": 1550.2608445951, - "Vacc_refreshed": 143.3620456295, - "Vacc_refreshed_2": 71.68102281475 - }, - { - "Date": "2020-11-01", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14759.0944017155, - "Vacc_completed": 1555.0005459425, - "Vacc_refreshed": 149.1268404613, - "Vacc_refreshed_2": 74.56342023065 - }, - { - "Date": "2020-11-02", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14765.0469016605, - "Vacc_completed": 1561.0596836707, - "Vacc_refreshed": 156.632878281, - "Vacc_refreshed_2": 78.3164391405 - }, - { - "Date": "2020-11-03", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14767.8747922121, - "Vacc_completed": 1562.2055298685, - "Vacc_refreshed": 158.7846499619, - "Vacc_refreshed_2": 79.39232498095 - }, - { - "Date": "2020-11-04", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14770.6956031505, - "Vacc_completed": 1564.0912014269, - "Vacc_refreshed": 160.2235512232, - "Vacc_refreshed_2": 80.1117756116 - }, - { - "Date": "2020-11-05", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14771.8405767953, - "Vacc_completed": 1569.1767284097, - "Vacc_refreshed": 163.0960075253, - "Vacc_refreshed_2": 81.54800376265 - }, - { - "Date": "2020-11-06", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14772.2052559189, - "Vacc_completed": 1577.0342160583, - "Vacc_refreshed": 171.338237261, - "Vacc_refreshed_2": 85.6691186305 - }, - { - "Date": "2020-11-07", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14775.8209952029, - "Vacc_completed": 1582.4601331483, - "Vacc_refreshed": 171.7811634642, - "Vacc_refreshed_2": 85.8905817321 - }, - { - "Date": "2020-11-08", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14783.195452278, - "Vacc_completed": 1590.5417141678, - "Vacc_refreshed": 180.3921690168, - "Vacc_refreshed_2": 90.1960845084 - }, - { - "Date": "2020-11-09", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14789.7908493035, - "Vacc_completed": 1599.1828252755, - "Vacc_refreshed": 184.3843375412, - "Vacc_refreshed_2": 92.1921687706 - }, - { - "Date": "2020-11-10", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14799.5061304555, - "Vacc_completed": 1604.6353429891, - "Vacc_refreshed": 186.9160630046, - "Vacc_refreshed_2": 93.4580315023 - }, - { - "Date": "2020-11-11", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14800.1953862328, - "Vacc_completed": 1607.3418569739, - "Vacc_refreshed": 194.8977352638, - "Vacc_refreshed_2": 97.4488676319 - }, - { - "Date": "2020-11-12", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14804.6194220955, - "Vacc_completed": 1610.8601925588, - "Vacc_refreshed": 198.1360514295, - "Vacc_refreshed_2": 99.06802571475 - }, - { - "Date": "2020-11-13", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14807.6135970058, - "Vacc_completed": 1620.4676732545, - "Vacc_refreshed": 199.7756827366, - "Vacc_refreshed_2": 99.8878413683 - }, - { - "Date": "2020-11-14", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14812.6404573806, - "Vacc_completed": 1625.8005590907, - "Vacc_refreshed": 208.9834954342, - "Vacc_refreshed_2": 104.4917477171 - }, - { - "Date": "2020-11-15", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14821.7780993542, - "Vacc_completed": 1634.2191287828, - "Vacc_refreshed": 218.0082295343, - "Vacc_refreshed_2": 109.00411476715 - }, - { - "Date": "2020-11-16", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14826.4757459809, - "Vacc_completed": 1642.5529482935, - "Vacc_refreshed": 225.0524176739, - "Vacc_refreshed_2": 112.52620883695 - }, - { - "Date": "2020-11-17", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14831.5528263871, - "Vacc_completed": 1649.3317542887, - "Vacc_refreshed": 229.0729255762, - "Vacc_refreshed_2": 114.5364627881 - }, - { - "Date": "2020-11-18", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14835.4543265309, - "Vacc_completed": 1656.6375918093, - "Vacc_refreshed": 230.6069957275, - "Vacc_refreshed_2": 115.30349786375 - }, - { - "Date": "2020-11-19", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14843.0829401722, - "Vacc_completed": 1661.236165662, - "Vacc_refreshed": 240.090987042, - "Vacc_refreshed_2": 120.045493521 - }, - { - "Date": "2020-11-20", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14846.441543514, - "Vacc_completed": 1663.7621214807, - "Vacc_refreshed": 242.6005891297, - "Vacc_refreshed_2": 121.30029456485 - }, - { - "Date": "2020-11-21", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14852.8592673291, - "Vacc_completed": 1670.5438763585, - "Vacc_refreshed": 243.1550853514, - "Vacc_refreshed_2": 121.5775426757 - }, - { - "Date": "2020-11-22", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14859.7577792484, - "Vacc_completed": 1671.9654195564, - "Vacc_refreshed": 252.4226950148, - "Vacc_refreshed_2": 126.2113475074 - }, - { - "Date": "2020-11-23", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14860.9361402439, - "Vacc_completed": 1673.0063955744, - "Vacc_refreshed": 254.9337371613, - "Vacc_refreshed_2": 127.46686858065 - }, - { - "Date": "2020-11-24", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14866.4446359141, - "Vacc_completed": 1680.8225588341, - "Vacc_refreshed": 260.3047312661, - "Vacc_refreshed_2": 130.15236563305 - }, - { - "Date": "2020-11-25", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14873.2607186268, - "Vacc_completed": 1689.7385811283, - "Vacc_refreshed": 267.8936320344, - "Vacc_refreshed_2": 133.9468160172 - }, - { - "Date": "2020-11-26", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14880.5922770798, - "Vacc_completed": 1689.9651236491, - "Vacc_refreshed": 275.7764918768, - "Vacc_refreshed_2": 137.8882459384 - }, - { - "Date": "2020-11-27", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14887.440916863, - "Vacc_completed": 1696.5525450807, - "Vacc_refreshed": 283.5225421273, - "Vacc_refreshed_2": 141.76127106365 - }, - { - "Date": "2020-11-28", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14888.0132355705, - "Vacc_completed": 1703.9968022938, - "Vacc_refreshed": 284.1554601622, - "Vacc_refreshed_2": 142.0777300811 - }, - { - "Date": "2020-11-29", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14897.4895745985, - "Vacc_completed": 1707.7124979313, - "Vacc_refreshed": 293.9654633907, - "Vacc_refreshed_2": 146.98273169535 - }, - { - "Date": "2020-11-30", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14900.9132287675, - "Vacc_completed": 1714.1256328363, - "Vacc_refreshed": 300.1498047442, - "Vacc_refreshed_2": 150.0749023721 - }, - { - "Date": "2020-12-01", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14907.9968139113, - "Vacc_completed": 1717.9722882107, - "Vacc_refreshed": 303.8260258963, - "Vacc_refreshed_2": 151.91301294815 - }, - { - "Date": "2020-12-02", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14914.3000727157, - "Vacc_completed": 1723.7459149842, - "Vacc_refreshed": 310.6001358466, - "Vacc_refreshed_2": 155.3000679233 - }, - { - "Date": "2020-12-03", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14915.2709520902, - "Vacc_completed": 1725.3728171833, - "Vacc_refreshed": 311.7419250413, - "Vacc_refreshed_2": 155.87096252065 - }, - { - "Date": "2020-12-04", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14924.9251049714, - "Vacc_completed": 1730.3968331067, - "Vacc_refreshed": 318.9914066325, - "Vacc_refreshed_2": 159.49570331625 - }, - { - "Date": "2020-12-05", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14929.9737051543, - "Vacc_completed": 1735.419819131, - "Vacc_refreshed": 327.2769475594, - "Vacc_refreshed_2": 163.6384737797 - }, - { - "Date": "2020-12-06", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14930.0867908297, - "Vacc_completed": 1735.4531164502, - "Vacc_refreshed": 333.9507530528, - "Vacc_refreshed_2": 166.9753765264 - }, - { - "Date": "2020-12-07", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14930.1585043075, - "Vacc_completed": 1744.7112606784, - "Vacc_refreshed": 337.8096837232, - "Vacc_refreshed_2": 168.9048418616 - }, - { - "Date": "2020-12-08", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14939.2420152133, - "Vacc_completed": 1745.8678859662, - "Vacc_refreshed": 344.4742142552, - "Vacc_refreshed_2": 172.2371071276 - }, - { - "Date": "2020-12-09", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14940.9708787633, - "Vacc_completed": 1748.1937727819, - "Vacc_refreshed": 352.7895987096, - "Vacc_refreshed_2": 176.3947993548 - }, - { - "Date": "2020-12-10", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14950.0282400838, - "Vacc_completed": 1750.2751748343, - "Vacc_refreshed": 354.0652893483, - "Vacc_refreshed_2": 177.03264467415 - }, - { - "Date": "2020-12-11", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14956.5498846765, - "Vacc_completed": 1758.7641351746, - "Vacc_refreshed": 361.0736440858, - "Vacc_refreshed_2": 180.5368220429 - }, - { - "Date": "2020-12-12", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14957.5908121778, - "Vacc_completed": 1763.4528309235, - "Vacc_refreshed": 364.3501912771, - "Vacc_refreshed_2": 182.17509563855 - }, - { - "Date": "2020-12-13", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14960.7281563782, - "Vacc_completed": 1772.006809538, - "Vacc_refreshed": 364.6804469838, - "Vacc_refreshed_2": 182.3402234919 - }, - { - "Date": "2020-12-14", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14969.2457673746, - "Vacc_completed": 1776.5678522654, - "Vacc_refreshed": 374.4882812856, - "Vacc_refreshed_2": 187.2441406428 - }, - { - "Date": "2020-12-15", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14974.8615073088, - "Vacc_completed": 1779.9556763371, - "Vacc_refreshed": 377.4421123342, - "Vacc_refreshed_2": 188.7210561671 - }, - { - "Date": "2020-12-16", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14984.5914886251, - "Vacc_completed": 1782.6146675026, - "Vacc_refreshed": 381.2082916917, - "Vacc_refreshed_2": 190.60414584585 - }, - { - "Date": "2020-12-17", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14987.5876984189, - "Vacc_completed": 1791.1028428437, - "Vacc_refreshed": 385.3294438436, - "Vacc_refreshed_2": 192.6647219218 - }, - { - "Date": "2020-12-18", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14992.58002825, - "Vacc_completed": 1793.9473770292, - "Vacc_refreshed": 388.9073184565, - "Vacc_refreshed_2": 194.45365922825 - }, - { - "Date": "2020-12-19", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14992.8771499871, - "Vacc_completed": 1796.0612762347, - "Vacc_refreshed": 390.0186176392, - "Vacc_refreshed_2": 195.0093088196 - }, - { - "Date": "2020-12-20", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14993.5505864267, - "Vacc_completed": 1798.6017730753, - "Vacc_refreshed": 390.5734438836, - "Vacc_refreshed_2": 195.2867219418 - }, - { - "Date": "2020-12-21", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 14998.158414122, - "Vacc_completed": 1802.0655230464, - "Vacc_refreshed": 391.8649823662, - "Vacc_refreshed_2": 195.9324911831 - }, - { - "Date": "2020-12-22", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15001.4313521872, - "Vacc_completed": 1804.413054883, - "Vacc_refreshed": 395.3533451537, - "Vacc_refreshed_2": 197.67667257685 - }, - { - "Date": "2020-12-23", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15001.7989985243, - "Vacc_completed": 1812.4490035114, - "Vacc_refreshed": 401.8191046925, - "Vacc_refreshed_2": 200.90955234625 - }, - { - "Date": "2020-12-24", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15002.2088852954, - "Vacc_completed": 1814.4865305652, - "Vacc_refreshed": 409.5825438963, - "Vacc_refreshed_2": 204.79127194815 - }, - { - "Date": "2020-12-25", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15008.2705384657, - "Vacc_completed": 1823.0023861142, - "Vacc_refreshed": 411.4567502649, - "Vacc_refreshed_2": 205.72837513245 - }, - { - "Date": "2020-12-26", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15013.4515790087, - "Vacc_completed": 1830.5873803301, - "Vacc_refreshed": 417.6053918266, - "Vacc_refreshed_2": 208.8026959133 - }, - { - "Date": "2020-12-27", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15022.965858679, - "Vacc_completed": 1833.2575088513, - "Vacc_refreshed": 421.7562400513, - "Vacc_refreshed_2": 210.87812002565 - }, - { - "Date": "2020-12-28", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15024.3362350043, - "Vacc_completed": 1839.0848659035, - "Vacc_refreshed": 429.2321579029, - "Vacc_refreshed_2": 214.61607895145 - }, - { - "Date": "2020-12-29", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15025.0436784182, - "Vacc_completed": 1840.7238800201, - "Vacc_refreshed": 434.1256619822, - "Vacc_refreshed_2": 217.0628309911 - }, - { - "Date": "2020-12-30", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15026.1929816575, - "Vacc_completed": 1848.4826094697, - "Vacc_refreshed": 436.1767563509, - "Vacc_refreshed_2": 218.08837817545 - }, - { - "Date": "2020-12-31", - "ID_County": 1002, - "Age_RKI": "35-59", - "Vacc_partially": 15028.1115762872, - "Vacc_completed": 1851.353962867, - "Vacc_refreshed": 439.6190575403, - "Vacc_refreshed_2": 219.80952877015 - }, - { - "Date": "2020-10-01", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12940.2728292563, - "Vacc_completed": 1761.2082450081, - "Vacc_refreshed": 0, - "Vacc_refreshed_2": 0.0 - }, - { - "Date": "2020-10-02", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12944.552426313, - "Vacc_completed": 1763.9916052944, - "Vacc_refreshed": 5.8453121761, - "Vacc_refreshed_2": 2.92265608805 - }, - { - "Date": "2020-10-03", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12946.2293033065, - "Vacc_completed": 1764.8651614651, - "Vacc_refreshed": 11.3614134516, - "Vacc_refreshed_2": 5.6807067258 - }, - { - "Date": "2020-10-04", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12954.4553975676, - "Vacc_completed": 1773.9720915654, - "Vacc_refreshed": 19.8633846559, - "Vacc_refreshed_2": 9.93169232795 - }, - { - "Date": "2020-10-05", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12962.1675537316, - "Vacc_completed": 1776.6871749169, - "Vacc_refreshed": 23.5340750877, - "Vacc_refreshed_2": 11.76703754385 - }, - { - "Date": "2020-10-06", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12970.2114807284, - "Vacc_completed": 1779.4482697767, - "Vacc_refreshed": 32.7047145334, - "Vacc_refreshed_2": 16.3523572667 - }, - { - "Date": "2020-10-07", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12971.1155781651, - "Vacc_completed": 1787.6912361171, - "Vacc_refreshed": 41.3859214133, - "Vacc_refreshed_2": 20.69296070665 - }, - { - "Date": "2020-10-08", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12976.1479148685, - "Vacc_completed": 1796.0609011819, - "Vacc_refreshed": 49.2224218631, - "Vacc_refreshed_2": 24.61121093155 - }, - { - "Date": "2020-10-09", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12985.389251021, - "Vacc_completed": 1806.0439647379, - "Vacc_refreshed": 58.4565372826, - "Vacc_refreshed_2": 29.2282686413 - }, - { - "Date": "2020-10-10", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12987.6528992192, - "Vacc_completed": 1814.2136648594, - "Vacc_refreshed": 68.4133404236, - "Vacc_refreshed_2": 34.2066702118 - }, - { - "Date": "2020-10-11", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12988.8953336446, - "Vacc_completed": 1820.4740554862, - "Vacc_refreshed": 69.4164203636, - "Vacc_refreshed_2": 34.7082101818 - }, - { - "Date": "2020-10-12", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12989.930788247, - "Vacc_completed": 1825.1779692151, - "Vacc_refreshed": 71.594311523, - "Vacc_refreshed_2": 35.7971557615 - }, - { - "Date": "2020-10-13", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12993.9481590439, - "Vacc_completed": 1834.4690603586, - "Vacc_refreshed": 75.4387792504, - "Vacc_refreshed_2": 37.7193896252 - }, - { - "Date": "2020-10-14", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12997.41102572, - "Vacc_completed": 1836.6145856268, - "Vacc_refreshed": 81.7875242048, - "Vacc_refreshed_2": 40.8937621024 - }, - { - "Date": "2020-10-15", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 12999.5337504327, - "Vacc_completed": 1839.9662175544, - "Vacc_refreshed": 87.9455065083, - "Vacc_refreshed_2": 43.97275325415 - }, - { - "Date": "2020-10-16", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13007.2251436977, - "Vacc_completed": 1842.6498922014, - "Vacc_refreshed": 93.1900542901, - "Vacc_refreshed_2": 46.59502714505 - }, - { - "Date": "2020-10-17", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13012.0856312446, - "Vacc_completed": 1844.701996872, - "Vacc_refreshed": 99.712698674, - "Vacc_refreshed_2": 49.856349337 - }, - { - "Date": "2020-10-18", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13021.33252246, - "Vacc_completed": 1849.3061445307, - "Vacc_refreshed": 102.5319545699, - "Vacc_refreshed_2": 51.26597728495 - }, - { - "Date": "2020-10-19", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13027.1500152398, - "Vacc_completed": 1850.8078304213, - "Vacc_refreshed": 105.0259857828, - "Vacc_refreshed_2": 52.5129928914 - }, - { - "Date": "2020-10-20", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13035.650988116, - "Vacc_completed": 1851.8577100095, - "Vacc_refreshed": 110.1445342625, - "Vacc_refreshed_2": 55.07226713125 - }, - { - "Date": "2020-10-21", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13042.2123284129, - "Vacc_completed": 1856.2056162281, - "Vacc_refreshed": 113.6459186876, - "Vacc_refreshed_2": 56.8229593438 - }, - { - "Date": "2020-10-22", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13048.5274669921, - "Vacc_completed": 1856.9596604869, - "Vacc_refreshed": 119.7006093985, - "Vacc_refreshed_2": 59.85030469925 - }, - { - "Date": "2020-10-23", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13056.4261041722, - "Vacc_completed": 1859.9946313318, - "Vacc_refreshed": 128.4930741519, - "Vacc_refreshed_2": 64.24653707595 - }, - { - "Date": "2020-10-24", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13061.2580735831, - "Vacc_completed": 1864.4241013454, - "Vacc_refreshed": 129.4122729818, - "Vacc_refreshed_2": 64.7061364909 - }, - { - "Date": "2020-10-25", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13069.8769575412, - "Vacc_completed": 1870.828968765, - "Vacc_refreshed": 133.5606697443, - "Vacc_refreshed_2": 66.78033487215 - }, - { - "Date": "2020-10-26", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13074.4847352314, - "Vacc_completed": 1873.0576602324, - "Vacc_refreshed": 142.5189975609, - "Vacc_refreshed_2": 71.25949878045 - }, - { - "Date": "2020-10-27", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13077.43910001, - "Vacc_completed": 1881.1763507471, - "Vacc_refreshed": 143.4948395736, - "Vacc_refreshed_2": 71.7474197868 - }, - { - "Date": "2020-10-28", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13082.3470601758, - "Vacc_completed": 1888.5808588713, - "Vacc_refreshed": 149.0381282873, - "Vacc_refreshed_2": 74.51906414365 - }, - { - "Date": "2020-10-29", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13091.0962170402, - "Vacc_completed": 1894.9989493108, - "Vacc_refreshed": 149.7527355276, - "Vacc_refreshed_2": 74.8763677638 - }, - { - "Date": "2020-10-30", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13097.0655225667, - "Vacc_completed": 1904.9660517959, - "Vacc_refreshed": 155.7716165644, - "Vacc_refreshed_2": 77.8858082822 - }, - { - "Date": "2020-10-31", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13105.8431803144, - "Vacc_completed": 1907.1233275333, - "Vacc_refreshed": 162.7399373626, - "Vacc_refreshed_2": 81.3699686813 - }, - { - "Date": "2020-11-01", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13110.9052745957, - "Vacc_completed": 1915.3369502585, - "Vacc_refreshed": 166.1686970271, - "Vacc_refreshed_2": 83.08434851355 - }, - { - "Date": "2020-11-02", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13120.2888484357, - "Vacc_completed": 1924.594235894, - "Vacc_refreshed": 174.1871820852, - "Vacc_refreshed_2": 87.0935910426 - }, - { - "Date": "2020-11-03", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13122.2684309305, - "Vacc_completed": 1926.8954039089, - "Vacc_refreshed": 179.1800373951, - "Vacc_refreshed_2": 89.59001869755 - }, - { - "Date": "2020-11-04", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13129.679389954, - "Vacc_completed": 1929.8687720822, - "Vacc_refreshed": 186.5609898946, - "Vacc_refreshed_2": 93.2804949473 - }, - { - "Date": "2020-11-05", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13136.2121968271, - "Vacc_completed": 1930.5419008182, - "Vacc_refreshed": 190.3285119819, - "Vacc_refreshed_2": 95.16425599095 - }, - { - "Date": "2020-11-06", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13140.8693305096, - "Vacc_completed": 1933.1368513989, - "Vacc_refreshed": 199.5045342081, - "Vacc_refreshed_2": 99.75226710405 - }, - { - "Date": "2020-11-07", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13141.6505152789, - "Vacc_completed": 1938.3539275062, - "Vacc_refreshed": 199.9231054484, - "Vacc_refreshed_2": 99.9615527242 - }, - { - "Date": "2020-11-08", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13146.3819720109, - "Vacc_completed": 1943.0787615053, - "Vacc_refreshed": 203.5617342411, - "Vacc_refreshed_2": 101.78086712055 - }, - { - "Date": "2020-11-09", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13155.5833925737, - "Vacc_completed": 1944.8505615419, - "Vacc_refreshed": 206.5254255239, - "Vacc_refreshed_2": 103.26271276195 - }, - { - "Date": "2020-11-10", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13155.8864321418, - "Vacc_completed": 1946.7574709443, - "Vacc_refreshed": 208.0171497057, - "Vacc_refreshed_2": 104.00857485285 - }, - { - "Date": "2020-11-11", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13160.8319905342, - "Vacc_completed": 1949.6926878806, - "Vacc_refreshed": 213.0797703475, - "Vacc_refreshed_2": 106.53988517375 - }, - { - "Date": "2020-11-12", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13165.109826694, - "Vacc_completed": 1955.2468047197, - "Vacc_refreshed": 222.6760329578, - "Vacc_refreshed_2": 111.3380164789 - }, - { - "Date": "2020-11-13", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13168.7847714036, - "Vacc_completed": 1956.1809363506, - "Vacc_refreshed": 231.6808966253, - "Vacc_refreshed_2": 115.84044831265 - }, - { - "Date": "2020-11-14", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13176.0869758252, - "Vacc_completed": 1960.8024990411, - "Vacc_refreshed": 233.4328765098, - "Vacc_refreshed_2": 116.7164382549 - }, - { - "Date": "2020-11-15", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13180.123104626, - "Vacc_completed": 1969.8047949709, - "Vacc_refreshed": 241.5696524948, - "Vacc_refreshed_2": 120.7848262474 - }, - { - "Date": "2020-11-16", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13184.6423078124, - "Vacc_completed": 1974.8566545144, - "Vacc_refreshed": 250.4550885677, - "Vacc_refreshed_2": 125.22754428385 - }, - { - "Date": "2020-11-17", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13190.9452560841, - "Vacc_completed": 1975.9346724558, - "Vacc_refreshed": 252.799671753, - "Vacc_refreshed_2": 126.3998358765 - }, - { - "Date": "2020-11-18", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13194.9586490897, - "Vacc_completed": 1984.1998929758, - "Vacc_refreshed": 256.8657355625, - "Vacc_refreshed_2": 128.43286778125 - }, - { - "Date": "2020-11-19", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13203.1981501018, - "Vacc_completed": 1992.2264996957, - "Vacc_refreshed": 262.7110996677, - "Vacc_refreshed_2": 131.35554983385 - }, - { - "Date": "2020-11-20", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13210.570704838, - "Vacc_completed": 2000.1284432323, - "Vacc_refreshed": 268.7466273707, - "Vacc_refreshed_2": 134.37331368535 - }, - { - "Date": "2020-11-21", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13217.6966464936, - "Vacc_completed": 2001.108779963, - "Vacc_refreshed": 270.063420564, - "Vacc_refreshed_2": 135.031710282 - }, - { - "Date": "2020-11-22", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13222.8454105611, - "Vacc_completed": 2006.445790007, - "Vacc_refreshed": 272.306211944, - "Vacc_refreshed_2": 136.153105972 - }, - { - "Date": "2020-11-23", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13231.9459038211, - "Vacc_completed": 2014.1245558198, - "Vacc_refreshed": 274.2682102675, - "Vacc_refreshed_2": 137.13410513375 - }, - { - "Date": "2020-11-24", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13234.4430744102, - "Vacc_completed": 2021.01783734, - "Vacc_refreshed": 283.272422859, - "Vacc_refreshed_2": 141.6362114295 - }, - { - "Date": "2020-11-25", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13234.9880313892, - "Vacc_completed": 2021.3278488109, - "Vacc_refreshed": 288.8833613171, - "Vacc_refreshed_2": 144.44168065855 - }, - { - "Date": "2020-11-26", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13244.1020800967, - "Vacc_completed": 2028.5342497408, - "Vacc_refreshed": 295.5476346222, - "Vacc_refreshed_2": 147.7738173111 - }, - { - "Date": "2020-11-27", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13246.2035006005, - "Vacc_completed": 2034.7337820973, - "Vacc_refreshed": 295.8527619766, - "Vacc_refreshed_2": 147.9263809883 - }, - { - "Date": "2020-11-28", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13250.3034672718, - "Vacc_completed": 2040.4526371692, - "Vacc_refreshed": 297.6289642024, - "Vacc_refreshed_2": 148.8144821012 - }, - { - "Date": "2020-11-29", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13258.1309651863, - "Vacc_completed": 2043.9166550693, - "Vacc_refreshed": 307.2590005259, - "Vacc_refreshed_2": 153.62950026295 - }, - { - "Date": "2020-11-30", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13264.00554028, - "Vacc_completed": 2046.5596745193, - "Vacc_refreshed": 309.1250398792, - "Vacc_refreshed_2": 154.5625199396 - }, - { - "Date": "2020-12-01", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13272.4212557374, - "Vacc_completed": 2049.7116443058, - "Vacc_refreshed": 314.0515587013, - "Vacc_refreshed_2": 157.02577935065 - }, - { - "Date": "2020-12-02", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13272.7885616679, - "Vacc_completed": 2051.2982177338, - "Vacc_refreshed": 320.3832182075, - "Vacc_refreshed_2": 160.19160910375 - }, - { - "Date": "2020-12-03", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13274.2264538665, - "Vacc_completed": 2058.2989667129, - "Vacc_refreshed": 323.7063680074, - "Vacc_refreshed_2": 161.8531840037 - }, - { - "Date": "2020-12-04", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13281.9141553951, - "Vacc_completed": 2063.8206751836, - "Vacc_refreshed": 326.9158074422, - "Vacc_refreshed_2": 163.4579037211 - }, - { - "Date": "2020-12-05", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13290.64171309, - "Vacc_completed": 2064.3110765988, - "Vacc_refreshed": 336.7710359746, - "Vacc_refreshed_2": 168.3855179873 - }, - { - "Date": "2020-12-06", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13291.1885069646, - "Vacc_completed": 2072.8766922561, - "Vacc_refreshed": 344.574816718, - "Vacc_refreshed_2": 172.287408359 - }, - { - "Date": "2020-12-07", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13291.7117921559, - "Vacc_completed": 2081.2889195134, - "Vacc_refreshed": 352.6791052892, - "Vacc_refreshed_2": 176.3395526446 - }, - { - "Date": "2020-12-08", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13295.741331211, - "Vacc_completed": 2082.371745109, - "Vacc_refreshed": 358.7062427923, - "Vacc_refreshed_2": 179.35312139615 - }, - { - "Date": "2020-12-09", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13303.8543248793, - "Vacc_completed": 2084.7970217381, - "Vacc_refreshed": 363.3629273081, - "Vacc_refreshed_2": 181.68146365405 - }, - { - "Date": "2020-12-10", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13305.910901253, - "Vacc_completed": 2089.496376583, - "Vacc_refreshed": 364.4184919111, - "Vacc_refreshed_2": 182.20924595555 - }, - { - "Date": "2020-12-11", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13310.1770755649, - "Vacc_completed": 2091.8877772854, - "Vacc_refreshed": 373.8861441424, - "Vacc_refreshed_2": 186.9430720712 - }, - { - "Date": "2020-12-12", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13318.5822731817, - "Vacc_completed": 2100.0656871327, - "Vacc_refreshed": 380.7622590612, - "Vacc_refreshed_2": 190.3811295306 - }, - { - "Date": "2020-12-13", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13326.848015265, - "Vacc_completed": 2103.7807367097, - "Vacc_refreshed": 383.494468406, - "Vacc_refreshed_2": 191.747234203 - }, - { - "Date": "2020-12-14", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13329.8351558424, - "Vacc_completed": 2106.3811743673, - "Vacc_refreshed": 385.7094999088, - "Vacc_refreshed_2": 192.8547499544 - }, - { - "Date": "2020-12-15", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13334.0243800891, - "Vacc_completed": 2110.0143078684, - "Vacc_refreshed": 387.028737638, - "Vacc_refreshed_2": 193.514368819 - }, - { - "Date": "2020-12-16", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13340.0473805148, - "Vacc_completed": 2114.17877764, - "Vacc_refreshed": 390.7872507231, - "Vacc_refreshed_2": 195.39362536155 - }, - { - "Date": "2020-12-17", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13342.4710995253, - "Vacc_completed": 2117.5584807218, - "Vacc_refreshed": 394.4459716696, - "Vacc_refreshed_2": 197.2229858348 - }, - { - "Date": "2020-12-18", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13345.9586603577, - "Vacc_completed": 2124.6343373595, - "Vacc_refreshed": 401.3739608899, - "Vacc_refreshed_2": 200.68698044495 - }, - { - "Date": "2020-12-19", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13354.1694340722, - "Vacc_completed": 2132.584533812, - "Vacc_refreshed": 404.149558168, - "Vacc_refreshed_2": 202.074779084 - }, - { - "Date": "2020-12-20", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13360.0480186273, - "Vacc_completed": 2135.2279773256, - "Vacc_refreshed": 407.0589420913, - "Vacc_refreshed_2": 203.52947104565 - }, - { - "Date": "2020-12-21", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13362.9287822042, - "Vacc_completed": 2135.7661733179, - "Vacc_refreshed": 412.3495727781, - "Vacc_refreshed_2": 206.17478638905 - }, - { - "Date": "2020-12-22", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13365.9702033874, - "Vacc_completed": 2140.0801351424, - "Vacc_refreshed": 414.1173144704, - "Vacc_refreshed_2": 207.0586572352 - }, - { - "Date": "2020-12-23", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13375.8578305813, - "Vacc_completed": 2147.1687721976, - "Vacc_refreshed": 416.1274613074, - "Vacc_refreshed_2": 208.0637306537 - }, - { - "Date": "2020-12-24", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13384.3434411484, - "Vacc_completed": 2149.6360498231, - "Vacc_refreshed": 422.5420941028, - "Vacc_refreshed_2": 211.2710470514 - }, - { - "Date": "2020-12-25", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13384.8386238776, - "Vacc_completed": 2156.2105881723, - "Vacc_refreshed": 428.2913369026, - "Vacc_refreshed_2": 214.1456684513 - }, - { - "Date": "2020-12-26", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13388.7750604929, - "Vacc_completed": 2160.929719286, - "Vacc_refreshed": 437.0909930573, - "Vacc_refreshed_2": 218.54549652865 - }, - { - "Date": "2020-12-27", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13397.0959920005, - "Vacc_completed": 2169.0772334568, - "Vacc_refreshed": 438.0782576038, - "Vacc_refreshed_2": 219.0391288019 - }, - { - "Date": "2020-12-28", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13406.1913483212, - "Vacc_completed": 2172.8397968306, - "Vacc_refreshed": 445.0079409299, - "Vacc_refreshed_2": 222.50397046495 - }, - { - "Date": "2020-12-29", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13410.1064630998, - "Vacc_completed": 2179.4067803849, - "Vacc_refreshed": 453.2550919609, - "Vacc_refreshed_2": 226.62754598045 - }, - { - "Date": "2020-12-30", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13418.2872479216, - "Vacc_completed": 2183.7956163614, - "Vacc_refreshed": 462.0847473084, - "Vacc_refreshed_2": 231.0423736542 - }, - { - "Date": "2020-12-31", - "ID_County": 1002, - "Age_RKI": "60-79", - "Vacc_partially": 13418.7274837683, - "Vacc_completed": 2186.2625889833, - "Vacc_refreshed": 470.3671533805, - "Vacc_refreshed_2": 235.18357669025 - }, - { - "Date": "2020-10-01", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15108.1816487494, - "Vacc_completed": 1951.3500240632, - "Vacc_refreshed": 0, - "Vacc_refreshed_2": 0.0 - }, - { - "Date": "2020-10-02", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15112.0388992614, - "Vacc_completed": 1956.8484422205, - "Vacc_refreshed": 4.7764537598, - "Vacc_refreshed_2": 2.3882268799 - }, - { - "Date": "2020-10-03", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15115.1174991099, - "Vacc_completed": 1961.6166149519, - "Vacc_refreshed": 11.6778924479, - "Vacc_refreshed_2": 5.83894622395 - }, - { - "Date": "2020-10-04", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15121.0352670933, - "Vacc_completed": 1969.039883077, - "Vacc_refreshed": 19.464449507, - "Vacc_refreshed_2": 9.7322247535 - }, - { - "Date": "2020-10-05", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15130.8297777562, - "Vacc_completed": 1970.7344191294, - "Vacc_refreshed": 28.0813773392, - "Vacc_refreshed_2": 14.0406886696 - }, - { - "Date": "2020-10-06", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15139.7963570637, - "Vacc_completed": 1971.420038313, - "Vacc_refreshed": 34.2304461363, - "Vacc_refreshed_2": 17.11522306815 - }, - { - "Date": "2020-10-07", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15149.3578353885, - "Vacc_completed": 1977.7986093705, - "Vacc_refreshed": 42.9385547047, - "Vacc_refreshed_2": 21.46927735235 - }, - { - "Date": "2020-10-08", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15150.8906121637, - "Vacc_completed": 1981.6633590428, - "Vacc_refreshed": 46.0030569507, - "Vacc_refreshed_2": 23.00152847535 - }, - { - "Date": "2020-10-09", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15153.3987479409, - "Vacc_completed": 1986.7151251441, - "Vacc_refreshed": 54.9967129669, - "Vacc_refreshed_2": 27.49835648345 - }, - { - "Date": "2020-10-10", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15155.2112066, - "Vacc_completed": 1993.3668502516, - "Vacc_refreshed": 59.2446234015, - "Vacc_refreshed_2": 29.62231170075 - }, - { - "Date": "2020-10-11", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15157.213160056, - "Vacc_completed": 2000.1282773775, - "Vacc_refreshed": 61.576334937, - "Vacc_refreshed_2": 30.7881674685 - }, - { - "Date": "2020-10-12", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15159.7206353696, - "Vacc_completed": 2000.5786646957, - "Vacc_refreshed": 62.4328961844, - "Vacc_refreshed_2": 31.2164480922 - }, - { - "Date": "2020-10-13", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15165.6048851908, - "Vacc_completed": 2000.600816545, - "Vacc_refreshed": 70.2254449832, - "Vacc_refreshed_2": 35.1127224916 - }, - { - "Date": "2020-10-14", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15175.5401574577, - "Vacc_completed": 2003.6984716795, - "Vacc_refreshed": 80.0202808521, - "Vacc_refreshed_2": 40.01014042605 - }, - { - "Date": "2020-10-15", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15178.2193352397, - "Vacc_completed": 2010.5259174304, - "Vacc_refreshed": 80.5289834705, - "Vacc_refreshed_2": 40.26449173525 - }, - { - "Date": "2020-10-16", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15186.1911779287, - "Vacc_completed": 2020.3094769054, - "Vacc_refreshed": 88.939485925, - "Vacc_refreshed_2": 44.4697429625 - }, - { - "Date": "2020-10-17", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15192.9408650715, - "Vacc_completed": 2027.102138126, - "Vacc_refreshed": 93.403990271, - "Vacc_refreshed_2": 46.7019951355 - }, - { - "Date": "2020-10-18", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15197.2522804828, - "Vacc_completed": 2033.1768424672, - "Vacc_refreshed": 103.3495680716, - "Vacc_refreshed_2": 51.6747840358 - }, - { - "Date": "2020-10-19", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15201.4718571012, - "Vacc_completed": 2041.9289374755, - "Vacc_refreshed": 107.0046191576, - "Vacc_refreshed_2": 53.5023095788 - }, - { - "Date": "2020-10-20", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15203.6899934618, - "Vacc_completed": 2042.5550193085, - "Vacc_refreshed": 108.1692912263, - "Vacc_refreshed_2": 54.08464561315 - }, - { - "Date": "2020-10-21", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15210.5751055, - "Vacc_completed": 2049.1508387429, - "Vacc_refreshed": 115.4885047404, - "Vacc_refreshed_2": 57.7442523702 - }, - { - "Date": "2020-10-22", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15216.3570734734, - "Vacc_completed": 2052.3213561982, - "Vacc_refreshed": 119.2061326333, - "Vacc_refreshed_2": 59.60306631665 - }, - { - "Date": "2020-10-23", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15225.8779749457, - "Vacc_completed": 2057.4663468474, - "Vacc_refreshed": 126.226397743, - "Vacc_refreshed_2": 63.1131988715 - }, - { - "Date": "2020-10-24", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15230.8206176005, - "Vacc_completed": 2064.8586744443, - "Vacc_refreshed": 133.0501812916, - "Vacc_refreshed_2": 66.5250906458 - }, - { - "Date": "2020-10-25", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15231.8828151205, - "Vacc_completed": 2068.2097593649, - "Vacc_refreshed": 142.0174284746, - "Vacc_refreshed_2": 71.0087142373 - }, - { - "Date": "2020-10-26", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15238.2426035555, - "Vacc_completed": 2071.8714182096, - "Vacc_refreshed": 148.7355853512, - "Vacc_refreshed_2": 74.3677926756 - }, - { - "Date": "2020-10-27", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15247.7928253295, - "Vacc_completed": 2078.7188555952, - "Vacc_refreshed": 156.2462830057, - "Vacc_refreshed_2": 78.12314150285 - }, - { - "Date": "2020-10-28", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15257.1929610505, - "Vacc_completed": 2083.6123346127, - "Vacc_refreshed": 163.8060000189, - "Vacc_refreshed_2": 81.90300000945 - }, - { - "Date": "2020-10-29", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15261.4225446127, - "Vacc_completed": 2092.4315663384, - "Vacc_refreshed": 165.098643188, - "Vacc_refreshed_2": 82.549321594 - }, - { - "Date": "2020-10-30", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15264.9230201438, - "Vacc_completed": 2098.3647861992, - "Vacc_refreshed": 173.1581071885, - "Vacc_refreshed_2": 86.57905359425 - }, - { - "Date": "2020-10-31", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15274.2090277291, - "Vacc_completed": 2098.6684198619, - "Vacc_refreshed": 179.3045017397, - "Vacc_refreshed_2": 89.65225086985 - }, - { - "Date": "2020-11-01", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15275.4881156514, - "Vacc_completed": 2104.7296501443, - "Vacc_refreshed": 184.3873991738, - "Vacc_refreshed_2": 92.1936995869 - }, - { - "Date": "2020-11-02", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15277.4296689803, - "Vacc_completed": 2109.0258070133, - "Vacc_refreshed": 190.3361011534, - "Vacc_refreshed_2": 95.1680505767 - }, - { - "Date": "2020-11-03", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15277.7641225132, - "Vacc_completed": 2111.2503398848, - "Vacc_refreshed": 196.3057900505, - "Vacc_refreshed_2": 98.15289502525 - }, - { - "Date": "2020-11-04", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15280.5288668271, - "Vacc_completed": 2120.2846622436, - "Vacc_refreshed": 201.8816019943, - "Vacc_refreshed_2": 100.94080099715 - }, - { - "Date": "2020-11-05", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15286.6794056665, - "Vacc_completed": 2127.5294418815, - "Vacc_refreshed": 205.8247713924, - "Vacc_refreshed_2": 102.9123856962 - }, - { - "Date": "2020-11-06", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15287.919376399, - "Vacc_completed": 2127.7213986428, - "Vacc_refreshed": 207.0848824799, - "Vacc_refreshed_2": 103.54244123995 - }, - { - "Date": "2020-11-07", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15288.8972252423, - "Vacc_completed": 2131.7043154907, - "Vacc_refreshed": 214.6605013946, - "Vacc_refreshed_2": 107.3302506973 - }, - { - "Date": "2020-11-08", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15295.1676694583, - "Vacc_completed": 2141.6853776317, - "Vacc_refreshed": 217.321705385, - "Vacc_refreshed_2": 108.6608526925 - }, - { - "Date": "2020-11-09", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15299.8279320379, - "Vacc_completed": 2150.6081907236, - "Vacc_refreshed": 224.1814306469, - "Vacc_refreshed_2": 112.09071532345 - }, - { - "Date": "2020-11-10", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15299.9502690873, - "Vacc_completed": 2150.8297260642, - "Vacc_refreshed": 224.2857175024, - "Vacc_refreshed_2": 112.1428587512 - }, - { - "Date": "2020-11-11", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15305.4629063272, - "Vacc_completed": 2159.4075137345, - "Vacc_refreshed": 226.4536786248, - "Vacc_refreshed_2": 113.2268393124 - }, - { - "Date": "2020-11-12", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15313.0091699117, - "Vacc_completed": 2160.0885470064, - "Vacc_refreshed": 232.5677391068, - "Vacc_refreshed_2": 116.2838695534 - }, - { - "Date": "2020-11-13", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15316.6742133238, - "Vacc_completed": 2163.6640679748, - "Vacc_refreshed": 242.4458167027, - "Vacc_refreshed_2": 121.22290835135 - }, - { - "Date": "2020-11-14", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15325.7736410299, - "Vacc_completed": 2171.6222500116, - "Vacc_refreshed": 251.5591803171, - "Vacc_refreshed_2": 125.77959015855 - }, - { - "Date": "2020-11-15", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15333.3685319398, - "Vacc_completed": 2174.4162160121, - "Vacc_refreshed": 254.1541702573, - "Vacc_refreshed_2": 127.07708512865 - }, - { - "Date": "2020-11-16", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15337.5758896556, - "Vacc_completed": 2180.7560110181, - "Vacc_refreshed": 255.4491825287, - "Vacc_refreshed_2": 127.72459126435 - }, - { - "Date": "2020-11-17", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15346.8261947795, - "Vacc_completed": 2184.562660479, - "Vacc_refreshed": 256.0794667401, - "Vacc_refreshed_2": 128.03973337005 - }, - { - "Date": "2020-11-18", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15347.5063487999, - "Vacc_completed": 2192.7053918922, - "Vacc_refreshed": 264.8657432896, - "Vacc_refreshed_2": 132.4328716448 - }, - { - "Date": "2020-11-19", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15355.2915215882, - "Vacc_completed": 2197.3639423288, - "Vacc_refreshed": 266.2003474583, - "Vacc_refreshed_2": 133.10017372915 - }, - { - "Date": "2020-11-20", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15357.0291297717, - "Vacc_completed": 2203.5668703416, - "Vacc_refreshed": 266.2591235692, - "Vacc_refreshed_2": 133.1295617846 - }, - { - "Date": "2020-11-21", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15363.7351300479, - "Vacc_completed": 2212.51470716, - "Vacc_refreshed": 268.1554009506, - "Vacc_refreshed_2": 134.0777004753 - }, - { - "Date": "2020-11-22", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15366.2054877706, - "Vacc_completed": 2220.7805776981, - "Vacc_refreshed": 270.2429125628, - "Vacc_refreshed_2": 135.1214562814 - }, - { - "Date": "2020-11-23", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15374.7828886007, - "Vacc_completed": 2223.4779151007, - "Vacc_refreshed": 271.3258668517, - "Vacc_refreshed_2": 135.66293342585 - }, - { - "Date": "2020-11-24", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15375.8644766411, - "Vacc_completed": 2223.902202818, - "Vacc_refreshed": 277.3418287874, - "Vacc_refreshed_2": 138.6709143937 - }, - { - "Date": "2020-11-25", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15384.0103684975, - "Vacc_completed": 2233.2600148125, - "Vacc_refreshed": 286.2795142721, - "Vacc_refreshed_2": 143.13975713605 - }, - { - "Date": "2020-11-26", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15388.2433647335, - "Vacc_completed": 2242.2405085188, - "Vacc_refreshed": 295.9058348626, - "Vacc_refreshed_2": 147.9529174313 - }, - { - "Date": "2020-11-27", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15395.874552707, - "Vacc_completed": 2242.5126967683, - "Vacc_refreshed": 297.0217883024, - "Vacc_refreshed_2": 148.5108941512 - }, - { - "Date": "2020-11-28", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15399.399317417, - "Vacc_completed": 2250.19318626, - "Vacc_refreshed": 297.4497074595, - "Vacc_refreshed_2": 148.72485372975 - }, - { - "Date": "2020-11-29", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15407.4994879004, - "Vacc_completed": 2258.8146667712, - "Vacc_refreshed": 302.8025504676, - "Vacc_refreshed_2": 151.4012752338 - }, - { - "Date": "2020-11-30", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15410.1346998553, - "Vacc_completed": 2259.5361618465, - "Vacc_refreshed": 305.0699464575, - "Vacc_refreshed_2": 152.53497322875 - }, - { - "Date": "2020-12-01", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15415.5662938607, - "Vacc_completed": 2266.2419298528, - "Vacc_refreshed": 306.5583985118, - "Vacc_refreshed_2": 153.2791992559 - }, - { - "Date": "2020-12-02", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15424.362408066, - "Vacc_completed": 2270.6973906417, - "Vacc_refreshed": 307.7300944183, - "Vacc_refreshed_2": 153.86504720915 - }, - { - "Date": "2020-12-03", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15427.4641661532, - "Vacc_completed": 2273.4475287465, - "Vacc_refreshed": 315.9257071161, - "Vacc_refreshed_2": 157.96285355805 - }, - { - "Date": "2020-12-04", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15430.3003374401, - "Vacc_completed": 2280.4953549554, - "Vacc_refreshed": 320.4057109928, - "Vacc_refreshed_2": 160.2028554964 - }, - { - "Date": "2020-12-05", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15434.7161891817, - "Vacc_completed": 2283.6641990131, - "Vacc_refreshed": 329.6425079267, - "Vacc_refreshed_2": 164.82125396335 - }, - { - "Date": "2020-12-06", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15439.6389263804, - "Vacc_completed": 2286.269595866, - "Vacc_refreshed": 336.6032551175, - "Vacc_refreshed_2": 168.30162755875 - }, - { - "Date": "2020-12-07", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15445.607595077, - "Vacc_completed": 2292.1795115763, - "Vacc_refreshed": 339.4752869467, - "Vacc_refreshed_2": 169.73764347335 - }, - { - "Date": "2020-12-08", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15445.7317234732, - "Vacc_completed": 2299.0428376394, - "Vacc_refreshed": 342.2213588852, - "Vacc_refreshed_2": 171.1106794426 - }, - { - "Date": "2020-12-09", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15448.8137925508, - "Vacc_completed": 2303.3104194582, - "Vacc_refreshed": 346.3780017598, - "Vacc_refreshed_2": 173.1890008799 - }, - { - "Date": "2020-12-10", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15449.4812178935, - "Vacc_completed": 2311.9261799324, - "Vacc_refreshed": 351.1765190663, - "Vacc_refreshed_2": 175.58825953315 - }, - { - "Date": "2020-12-11", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15457.9089483618, - "Vacc_completed": 2315.5711542884, - "Vacc_refreshed": 352.532745084, - "Vacc_refreshed_2": 176.266372542 - }, - { - "Date": "2020-12-12", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15457.9943266817, - "Vacc_completed": 2322.1716179078, - "Vacc_refreshed": 355.0774800773, - "Vacc_refreshed_2": 177.53874003865 - }, - { - "Date": "2020-12-13", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15459.7074068986, - "Vacc_completed": 2323.3027059178, - "Vacc_refreshed": 364.5645466744, - "Vacc_refreshed_2": 182.2822733372 - }, - { - "Date": "2020-12-14", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15465.686171573, - "Vacc_completed": 2325.8040208828, - "Vacc_refreshed": 365.9637341301, - "Vacc_refreshed_2": 182.98186706505 - }, - { - "Date": "2020-12-15", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15466.2025927257, - "Vacc_completed": 2332.7537065257, - "Vacc_refreshed": 366.2841969775, - "Vacc_refreshed_2": 183.14209848875 - }, - { - "Date": "2020-12-16", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15471.0643499093, - "Vacc_completed": 2333.7718947218, - "Vacc_refreshed": 370.7174701468, - "Vacc_refreshed_2": 185.3587350734 - }, - { - "Date": "2020-12-17", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15480.1820736709, - "Vacc_completed": 2336.425519339, - "Vacc_refreshed": 378.1719392306, - "Vacc_refreshed_2": 189.0859696153 - }, - { - "Date": "2020-12-18", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15489.2619602904, - "Vacc_completed": 2342.4314320637, - "Vacc_refreshed": 382.1070985379, - "Vacc_refreshed_2": 191.05354926895 - }, - { - "Date": "2020-12-19", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15497.197059921, - "Vacc_completed": 2351.5508059781, - "Vacc_refreshed": 390.0131449372, - "Vacc_refreshed_2": 195.0065724686 - }, - { - "Date": "2020-12-20", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15506.8997820546, - "Vacc_completed": 2354.7951207515, - "Vacc_refreshed": 397.4755552416, - "Vacc_refreshed_2": 198.7377776208 - }, - { - "Date": "2020-12-21", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15514.6356932026, - "Vacc_completed": 2359.4543858263, - "Vacc_refreshed": 405.5265192328, - "Vacc_refreshed_2": 202.7632596164 - }, - { - "Date": "2020-12-22", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15517.1065215082, - "Vacc_completed": 2362.3705119741, - "Vacc_refreshed": 406.2503084488, - "Vacc_refreshed_2": 203.1251542244 - }, - { - "Date": "2020-12-23", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15526.1890623234, - "Vacc_completed": 2369.2123027947, - "Vacc_refreshed": 407.9863557734, - "Vacc_refreshed_2": 203.9931778867 - }, - { - "Date": "2020-12-24", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15529.1257916241, - "Vacc_completed": 2371.0230854052, - "Vacc_refreshed": 415.4330021443, - "Vacc_refreshed_2": 207.71650107215 - }, - { - "Date": "2020-12-25", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15534.1422800755, - "Vacc_completed": 2376.4314141852, - "Vacc_refreshed": 417.8710629027, - "Vacc_refreshed_2": 208.93553145135 - }, - { - "Date": "2020-12-26", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15536.9779956012, - "Vacc_completed": 2380.9412020655, - "Vacc_refreshed": 418.6065556413, - "Vacc_refreshed_2": 209.30327782065 - }, - { - "Date": "2020-12-27", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15542.623117778, - "Vacc_completed": 2383.2295524317, - "Vacc_refreshed": 425.5318613018, - "Vacc_refreshed_2": 212.7659306509 - }, - { - "Date": "2020-12-28", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15545.7349127212, - "Vacc_completed": 2388.7438112703, - "Vacc_refreshed": 435.2708995295, - "Vacc_refreshed_2": 217.63544976475 - }, - { - "Date": "2020-12-29", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15552.7663039717, - "Vacc_completed": 2398.7179519564, - "Vacc_refreshed": 436.7806978293, - "Vacc_refreshed_2": 218.39034891465 - }, - { - "Date": "2020-12-30", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15553.9038494269, - "Vacc_completed": 2401.9470135031, - "Vacc_refreshed": 445.294989416, - "Vacc_refreshed_2": 222.647494708 - }, - { - "Date": "2020-12-31", - "ID_County": 1002, - "Age_RKI": "80-99", - "Vacc_partially": 15563.5219522465, - "Vacc_completed": 2408.3277109489, - "Vacc_refreshed": 449.1868908695, - "Vacc_refreshed_2": 224.59344543475 - } -] \ No newline at end of file diff --git a/cpp/tests/test_epi_data_io.cpp b/cpp/tests/test_epi_data_io.cpp index f29467e775..bbd2884b78 100644 --- a/cpp/tests/test_epi_data_io.cpp +++ b/cpp/tests/test_epi_data_io.cpp @@ -68,7 +68,7 @@ TEST(TestEpiDataIo, read_rki) ASSERT_EQ(rki_data[0].num_confirmed, 1); ASSERT_EQ(rki_data[0].num_deaths, 2); ASSERT_EQ(rki_data[0].num_recovered, 3); - ASSERT_EQ(rki_data[0].county_id, mio::regions::CountyId(1001)); + ASSERT_EQ(rki_data[0].county_id, mio::regions::de::CountyId(1001)); ASSERT_EQ(rki_data[0].state_id, boost::none); ASSERT_EQ(rki_data[1].age_group, mio::AgeGroup(0)); @@ -76,7 +76,7 @@ TEST(TestEpiDataIo, read_rki) ASSERT_EQ(rki_data[1].num_confirmed, 3); ASSERT_EQ(rki_data[1].num_deaths, 4); ASSERT_EQ(rki_data[1].num_recovered, 5); - ASSERT_EQ(rki_data[1].county_id, mio::regions::CountyId(1001)); + ASSERT_EQ(rki_data[1].county_id, mio::regions::de::CountyId(1001)); ASSERT_EQ(rki_data[1].state_id, boost::none); } @@ -141,11 +141,11 @@ TEST(TestEpiDataIo, read_divi) auto& divi_data = r.value(); ASSERT_EQ(divi_data.size(), 2); - ASSERT_EQ(divi_data[0].county_id, mio::regions::CountyId(1001)); + ASSERT_EQ(divi_data[0].county_id, mio::regions::de::CountyId(1001)); ASSERT_EQ(divi_data[0].date, mio::Date(2022, 10, 5)); ASSERT_EQ(divi_data[0].num_icu, 10.0); - ASSERT_EQ(divi_data[1].county_id, mio::regions::CountyId(1002)); + ASSERT_EQ(divi_data[1].county_id, mio::regions::de::CountyId(1002)); ASSERT_EQ(divi_data[1].date, mio::Date(2022, 10, 7)); ASSERT_EQ(divi_data[1].num_icu, 20.0); } @@ -185,14 +185,14 @@ TEST(TestEpiDataIo, read_population) auto& population_data = r.value(); ASSERT_EQ(population_data.size(), 2); - ASSERT_EQ(population_data[0].county_id, mio::regions::CountyId(1001)); + ASSERT_EQ(population_data[0].county_id, mio::regions::de::CountyId(1001)); ASSERT_THAT(population_data[0].population, testing::ElementsAre(testing::DoubleEq(10.0 + 2 * 10.0 / 3), testing::DoubleEq(10.0 / 3 + 10.0), testing::DoubleEq(10.0 + 10.0 + 10.0 + 0.5 * 10.0), testing::DoubleEq(0.5 * 10.0 + 10.0 + 2 * 10.0 / 3), testing::DoubleEq(10.0 / 3 + 10.0 + 0.2 * 10.0), testing::DoubleEq(0.8 * 10.0))); - ASSERT_EQ(population_data[1].county_id, mio::regions::CountyId(1002)); + ASSERT_EQ(population_data[1].county_id, mio::regions::de::CountyId(1002)); ASSERT_THAT(population_data[1].population, testing::ElementsAre(testing::DoubleEq(10.0 + 2 * 20.0 / 3), testing::DoubleEq(20.0 / 3 + 30.0), testing::DoubleEq(40.0 + 50.0 + 60.0 + 0.5 * 70.0), @@ -280,19 +280,19 @@ TEST(TestEpiDataIo, read_divi_data) ASSERT_EQ(divi_data.size(), 4); - ASSERT_EQ(divi_data[0].district_id, mio::regions::DistrictId(1234)); + ASSERT_EQ(divi_data[0].district_id, mio::regions::de::DistrictId(1234)); ASSERT_EQ(divi_data[0].date, mio::Date(2022, 04, 24)); ASSERT_EQ(divi_data[0].num_icu, 0.5437); - ASSERT_EQ(divi_data[1].district_id, mio::regions::DistrictId(1234)); + ASSERT_EQ(divi_data[1].district_id, mio::regions::de::DistrictId(1234)); ASSERT_EQ(divi_data[1].date, mio::Date(2022, 04, 25)); ASSERT_EQ(divi_data[1].num_icu, 0.64532); - ASSERT_EQ(divi_data[2].district_id, mio::regions::DistrictId(1235)); + ASSERT_EQ(divi_data[2].district_id, mio::regions::de::DistrictId(1235)); ASSERT_EQ(divi_data[2].date, mio::Date(2022, 04, 24)); ASSERT_EQ(divi_data[2].num_icu, 0.3574); - ASSERT_EQ(divi_data[3].district_id, mio::regions::DistrictId(1235)); + ASSERT_EQ(divi_data[3].district_id, mio::regions::de::DistrictId(1235)); ASSERT_EQ(divi_data[3].date, mio::Date(2022, 04, 25)); ASSERT_EQ(divi_data[3].num_icu, 0.35437); } @@ -335,7 +335,7 @@ TEST(TestEpiDataIo, read_confirmed_cases_data) ASSERT_EQ(case_data[0].num_confirmed, 1); ASSERT_EQ(case_data[0].num_deaths, 0); ASSERT_EQ(case_data[0].num_recovered, 0); - ASSERT_EQ(case_data[0].district_id, mio::regions::DistrictId(1234)); + ASSERT_EQ(case_data[0].district_id, mio::regions::de::DistrictId(1234)); ASSERT_EQ(case_data[0].county_id, boost::none); ASSERT_EQ(case_data[0].state_id, boost::none); @@ -344,7 +344,7 @@ TEST(TestEpiDataIo, read_confirmed_cases_data) ASSERT_EQ(case_data[1].num_confirmed, 20); ASSERT_EQ(case_data[1].num_deaths, 1); ASSERT_EQ(case_data[1].num_recovered, 5); - ASSERT_EQ(case_data[1].district_id, mio::regions::DistrictId(1234)); + ASSERT_EQ(case_data[1].district_id, mio::regions::de::DistrictId(1234)); ASSERT_EQ(case_data[1].county_id, boost::none); ASSERT_EQ(case_data[1].state_id, boost::none); @@ -353,7 +353,7 @@ TEST(TestEpiDataIo, read_confirmed_cases_data) ASSERT_EQ(case_data[2].num_confirmed, 15); ASSERT_EQ(case_data[2].num_deaths, 3); ASSERT_EQ(case_data[2].num_recovered, 2); - ASSERT_EQ(case_data[2].district_id, mio::regions::DistrictId(1235)); + ASSERT_EQ(case_data[2].district_id, mio::regions::de::DistrictId(1235)); ASSERT_EQ(case_data[2].county_id, boost::none); ASSERT_EQ(case_data[2].state_id, boost::none); } @@ -394,8 +394,8 @@ TEST(TestEpiDataIO, read_vaccination_data) ASSERT_EQ(vacc_data[0].date, mio::Date(2022, 4, 12)); ASSERT_EQ(vacc_data[0].age_group, mio::AgeGroup(0)); - ASSERT_EQ(vacc_data[0].county_id, mio::regions::CountyId(1001)); - ASSERT_EQ(vacc_data[0].district_id, mio::regions::DistrictId(1234)); + ASSERT_EQ(vacc_data[0].county_id, mio::regions::de::CountyId(1001)); + ASSERT_EQ(vacc_data[0].district_id, mio::regions::de::DistrictId(1234)); ASSERT_EQ(vacc_data[0].num_vaccinations_partial, 0.0); ASSERT_EQ(vacc_data[0].num_vaccinations_completed, 5.0); ASSERT_EQ(vacc_data[0].num_vaccinations_refreshed_first, 2.0); @@ -404,49 +404,13 @@ TEST(TestEpiDataIO, read_vaccination_data) ASSERT_EQ(vacc_data[1].date, mio::Date(2022, 4, 15)); ASSERT_EQ(vacc_data[1].age_group, mio::AgeGroup(2)); ASSERT_EQ(vacc_data[1].county_id, boost::none); - ASSERT_EQ(vacc_data[1].district_id, mio::regions::DistrictId(1235)); + ASSERT_EQ(vacc_data[1].district_id, mio::regions::de::DistrictId(1235)); ASSERT_EQ(vacc_data[1].num_vaccinations_partial, 1.0); ASSERT_EQ(vacc_data[1].num_vaccinations_completed, 1.0); ASSERT_EQ(vacc_data[1].num_vaccinations_refreshed_first, 4.0); ASSERT_EQ(vacc_data[1].num_vaccinations_refreshed_additional, 3.0); } -TEST(TestEpiData, set_vaccination_data) -{ - auto num_age_groups = 1; - auto num_days = 9; - - std::vector county_ids = {1001}; - mio::osecirts::Model model(num_age_groups); - model.parameters.set>(1); - model.parameters.set>(2); - model.parameters.set>(1); - std::vector> model_vector{model}; - - auto f = mio::osecirts::details::set_vaccination_data(model_vector, - mio::path_join(TEST_DATA_DIR, "vaccination_test.json"), - mio::Date(2022, 4, 15), county_ids, num_days); - - auto expected_values_PI = - (Eigen::ArrayXd(num_age_groups * (num_days + 1)) << 7, 10, 20, 15, 10, 5, 2, 15, 8, 0).finished(); - - auto expected_values_II = - (Eigen::ArrayXd(num_age_groups * (num_days + 1)) << 2, 4, 5, 5, 7, 8, 9, 9, 10, 12).finished(); - - auto expected_values_B = - (Eigen::ArrayXd(num_age_groups * (num_days + 1)) << 5, 7, 9, 11, 13, 9, 7, 5, 5, 0).finished(); - - ASSERT_THAT( - print_wrap(model_vector[0].parameters.template get>().array()), - MatrixNear(print_wrap(expected_values_PI), 1e-8, 1e-8)); - ASSERT_THAT( - print_wrap(model_vector[0].parameters.template get>().array()), - MatrixNear(print_wrap(expected_values_II), 1e-8, 1e-8)); - ASSERT_THAT( - print_wrap(model_vector[0].parameters.template get>().array()), - MatrixNear(print_wrap(expected_values_B), 1e-8, 1e-8)); -} - TEST(TestEpiData, vaccination_data) { auto js = Json::Value(Json::arrayValue); @@ -474,7 +438,7 @@ TEST(TestEpiData, vaccination_data) EXPECT_EQ(vacc_data[0].date, mio::Date(2021, 12, 1)); EXPECT_EQ(vacc_data[0].age_group, mio::AgeGroup(1)); - EXPECT_EQ(vacc_data[0].county_id, mio::regions::CountyId(1011)); + EXPECT_EQ(vacc_data[0].county_id, mio::regions::de::CountyId(1011)); EXPECT_EQ(vacc_data[0].num_vaccinations_completed, 23.05); EXPECT_EQ(vacc_data[0].num_vaccinations_partial, 2.0); EXPECT_EQ(vacc_data[0].num_vaccinations_refreshed_first, 6.2); @@ -482,7 +446,7 @@ TEST(TestEpiData, vaccination_data) EXPECT_EQ(vacc_data[1].date, mio::Date(2021, 12, 2)); EXPECT_EQ(vacc_data[1].age_group, mio::AgeGroup(5)); - EXPECT_EQ(vacc_data[1].county_id, mio::regions::CountyId(1012)); + EXPECT_EQ(vacc_data[1].county_id, mio::regions::de::CountyId(1012)); EXPECT_EQ(vacc_data[1].num_vaccinations_completed, 12.0); EXPECT_EQ(vacc_data[1].num_vaccinations_partial, 14.0); EXPECT_EQ(vacc_data[1].num_vaccinations_refreshed_first, 6.2); diff --git a/cpp/tests/test_graph.cpp b/cpp/tests/test_graph.cpp index 65bdb71c42..025aa38d6f 100644 --- a/cpp/tests/test_graph.cpp +++ b/cpp/tests/test_graph.cpp @@ -146,7 +146,7 @@ TEST(TestGraph, graph_without_edges) std::vector models = {MockModel(), MockModel()}; std::vector ids = {1, 2}; - auto g = mio::create_graph_without_edges(models, ids); + mio::Graph g(ids, models); EXPECT_EQ(g.edges().size(), 0); EXPECT_EQ(g.nodes().size(), 2); @@ -159,60 +159,6 @@ TEST(TestGraph, graph_without_edges) EXPECT_FALSE(model_type_false); } -TEST(TestGraph, set_nodes_secir) -{ - - mio::osecir::Parameters params(1); - mio::Graph, mio::MobilityParameters> params_graph; - const auto& read_function_nodes = mock_read_function>; - const auto& node_id_function = mock_node_function; - - const fs::path& dir = " "; - - auto result = - mio::set_nodes, mio::osecir::ContactPatterns, - mio::osecir::Model, mio::MobilityParameters, mio::osecir::Parameters, - decltype(read_function_nodes), decltype(node_id_function)>( - params, mio::Date(2020, 5, 10), mio::Date(2020, 5, 11), dir, " ", false, params_graph, read_function_nodes, - node_id_function, std::vector(size_t(1), 1.0), 1.0, 0.01); - - EXPECT_EQ(params_graph.nodes().size(), 2); - EXPECT_EQ(params_graph.nodes()[0].id, 1001); - EXPECT_EQ(params_graph.nodes()[1].id, 1002); - auto model_type_true1 = std::is_same>::value; - EXPECT_TRUE(model_type_true1); - auto model_type_true2 = std::is_same>::value; - EXPECT_TRUE(model_type_true2); -} - -TEST(TestGraph, set_nodes_secirvvs) -{ - - mio::osecirvvs::Parameters params(1); - mio::Graph, mio::MobilityParameters> params_graph; - const auto& read_function_nodes = mock_read_function>; - const auto& node_id_function = mock_node_function; - - const fs::path& dir = " "; - - auto result = - mio::set_nodes, mio::osecirvvs::ContactPatterns, - mio::osecirvvs::Model, mio::MobilityParameters, - mio::osecirvvs::Parameters, decltype(read_function_nodes), decltype(node_id_function)>( - params, mio::Date(2020, 5, 10), mio::Date(2020, 5, 11), dir, " ", false, params_graph, read_function_nodes, - node_id_function, std::vector(size_t(1), 1.0), 1.0, 0.01); - - EXPECT_EQ(params_graph.nodes().size(), 2); - EXPECT_EQ(params_graph.nodes()[0].id, 1001); - EXPECT_EQ(params_graph.nodes()[1].id, 1002); - auto model_type_true1 = - std::is_same>::value; - EXPECT_TRUE(model_type_true1); - auto model_type_true2 = - std::is_same>::value; - EXPECT_TRUE(model_type_true2); -} - TEST(TestGraph, set_edges) { mio::osecir::Model model(6); diff --git a/cpp/tests/test_odesecir.cpp b/cpp/tests/test_odesecir.cpp index 24533cc68d..5f3fba97a2 100755 --- a/cpp/tests/test_odesecir.cpp +++ b/cpp/tests/test_odesecir.cpp @@ -32,9 +32,12 @@ #include "memilio/geography/regions.h" #include +#include #include +using ModelT = mio::osecir::Model; + TEST(TestOdeSecir, compareWithPreviousRun) { /* @@ -50,7 +53,7 @@ TEST(TestOdeSecir, compareWithPreviousRun) double nb_total_t0 = 10000, nb_exp_t0 = 100, nb_inf_t0 = 50, nb_car_t0 = 50, nb_hosp_t0 = 20, nb_icu_t0 = 10, nb_rec_t0 = 10, nb_dead_t0 = 0; - mio::osecir::Model model(1); + ModelT model(1); model.parameters.set>(60); model.parameters.set>(0.2); @@ -96,7 +99,7 @@ TEST(TestOdeSecir, compareWithPreviousRun) integrator->set_rel_tolerance(1e-3); integrator->set_abs_tolerance(1e-1); mio::TimeSeries secihurd = - mio::simulate>(t0, tmax, dt, model, std::move(integrator)); + mio::simulate(t0, tmax, dt, model, std::move(integrator)); auto compare = load_test_data_csv("secihurd-compare.csv"); @@ -116,7 +119,7 @@ TEST(TestOdeSecir, simulateDefault) double tmax = 1; double dt = 0.1; - mio::osecir::Model model(1); + ModelT model(1); mio::TimeSeries result = mio::simulate(t0, tmax, dt, model); EXPECT_NEAR(result.get_last_time(), tmax, 1e-10); @@ -132,7 +135,7 @@ TEST(TestOdeSecir, checkPopulationConservation) double nb_total_t0 = 10000; - mio::osecir::Model model(1); + ModelT model(1); model.parameters.get>() = 35; @@ -190,7 +193,7 @@ TEST(TestOdeSecir, testParamConstructors) double icu_cap = 4444; double start_day = 30, seasonality = 0.3; - mio::osecir::Model model(1); + ModelT model(1); model.parameters.set>(icu_cap); @@ -226,7 +229,7 @@ TEST(TestOdeSecir, testParamConstructors) contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, cont_freq)); contact_matrix[0].add_damping(0.7, mio::SimulationTime(30.)); - mio::osecir::Model model2{model}; // copy constructor + ModelT model2{model}; // copy constructor EXPECT_EQ(model.parameters.get>(), model2.parameters.get>()); @@ -283,7 +286,7 @@ TEST(TestOdeSecir, testParamConstructors) EXPECT_EQ(model.parameters.get>().get_cont_freq_mat(), model2.parameters.get>().get_cont_freq_mat()); - mio::osecir::Model model3 = std::move(model2); // move constructor + ModelT model3 = std::move(model2); // move constructor EXPECT_EQ(model.parameters.get>(), model3.parameters.get>()); @@ -339,7 +342,7 @@ TEST(TestOdeSecir, testParamConstructors) EXPECT_EQ(model.parameters.get>().get_cont_freq_mat(), model3.parameters.get>().get_cont_freq_mat()); - mio::osecir::Model model4 = model3; // copy assignment constructor + ModelT model4 = model3; // copy assignment constructor EXPECT_EQ(model4.parameters.get>(), model3.parameters.get>()); @@ -395,7 +398,7 @@ TEST(TestOdeSecir, testParamConstructors) EXPECT_EQ(model4.parameters.get>().get_cont_freq_mat(), model3.parameters.get>().get_cont_freq_mat()); - mio::osecir::Model model5 = std::move(model4); // move assignment constructor + ModelT model5 = std::move(model4); // move assignment constructor EXPECT_EQ(model5.parameters.get>(), model3.parameters.get>()); @@ -462,7 +465,7 @@ TEST(TestOdeSecir, testSettersAndGetters) vec.push_back(val); } - mio::osecir::Model model(1); + ModelT model(1); EXPECT_EQ(model.parameters.get>()[(mio::AgeGroup)0].get_distribution().get(), nullptr); @@ -585,7 +588,7 @@ TEST(TestOdeSecir, testSettersAndGetters) TEST(TestOdeSecir, population_zero_no_nan) { // initialize simple model with total population 0 - mio::osecir::Model model(1); + ModelT model(1); model.populations.set_total(0.0); // call the get_flows function @@ -616,7 +619,7 @@ TEST(TestOdeSecir, testDamping) double nb_total_t0 = 1000, nb_inf_t0 = 10; // default model run to be compared against - mio::osecir::Model model_a(1); + ModelT model_a(1); model_a.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_a.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, nb_total_t0); @@ -630,7 +633,7 @@ TEST(TestOdeSecir, testDamping) std::make_unique>()); // reduced transmission - mio::osecir::Model model_b{model_a}; + ModelT model_b{model_a}; model_b.populations.set_total(nb_total_t0); model_b.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_b.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, @@ -644,7 +647,7 @@ TEST(TestOdeSecir, testDamping) EXPECT_EQ(2 * result_b[1].get_last_value()[0], result_a[1].get_last_value()[0]); // no transmission - mio::osecir::Model model_c{model_a}; + ModelT model_c{model_a}; model_c.populations.set_total(nb_total_t0); model_c.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_c.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, @@ -658,7 +661,7 @@ TEST(TestOdeSecir, testDamping) EXPECT_EQ(result_c[1].get_last_value()[0], 0.0); // increased transmission to a factor of two (by +1) - mio::osecir::Model model_d{model_a}; + ModelT model_d{model_a}; model_d.populations.set_total(nb_total_t0); model_d.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = nb_inf_t0; model_d.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, @@ -685,7 +688,7 @@ TEST(TestOdeSecir, testModelConstraints) double nb_total_t0 = 1000000, nb_exp_t0 = 10000, nb_inf_t0 = 5000, nb_car_t0 = 500, nb_hosp_t0 = 20, nb_icu_t0 = 0, nb_rec_t0 = 10, nb_dead_t0 = 0; - mio::osecir::Model model(1); + ModelT model(1); model.parameters.get>()[(mio::AgeGroup)0] = 2.6; model.parameters.get>()[(mio::AgeGroup)0] = 2.6; @@ -771,7 +774,7 @@ TEST(TestOdeSecir, testAndTraceCapacity) double nb_total_t0 = 10000, nb_exp_t0 = 100, nb_inf_t0 = 50, nb_car_t0 = 50; - mio::osecir::Model model(1); + ModelT model(1); auto& params = model.parameters; params.get>()[(mio::AgeGroup)0] = 3.2; @@ -818,7 +821,7 @@ TEST(TestOdeSecir, testAndTraceCapacity) TEST(TestOdeSecir, getInfectionsRelative) { size_t num_groups = 3; - mio::osecir::Model model((int)num_groups); + ModelT model((int)num_groups); model.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedSymptoms}] = 100.0; model.populations.set_difference_from_group_total( {mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, 10'000.0); @@ -837,7 +840,7 @@ TEST(TestOdeSecir, getInfectionsRelative) TEST(TestOdeSecir, get_reproduction_number) { const size_t num_groups = 3; - mio::osecir::Model model((int)num_groups); + ModelT model((int)num_groups); mio::ContactMatrixGroup& contact_matrix = model.parameters.get>(); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(3, 3, 10)); @@ -1006,7 +1009,7 @@ TEST(Secir, get_mobility_factors) { auto beta = 0.25; auto max_beta = 0.5; - auto model = mio::osecir::Model(1); + auto model = ModelT(1); model.parameters.get>().array() = 3.; model.parameters.get>().array() = 2.; model.parameters.get>().array() = 0.1; @@ -1038,7 +1041,7 @@ TEST(Secir, get_mobility_factors) TEST(TestOdeSecir, test_commuters) { - auto model = mio::osecir::Model(2); + auto model = ModelT(2); auto mobility_factor = 0.1; auto non_detection_factor = 0.4; model.parameters.get_start_commuter_detection() = 0.0; @@ -1072,7 +1075,7 @@ TEST(TestOdeSecir, test_commuters) TEST(TestOdeSecir, check_constraints_parameters) { - auto model = mio::osecir::Model(1); + auto model = ModelT(1); EXPECT_EQ(model.parameters.check_constraints(), 0); mio::set_log_level(mio::LogLevel::off); @@ -1150,7 +1153,7 @@ TEST(TestOdeSecir, check_constraints_parameters) TEST(TestOdeSecir, apply_constraints_parameters) { - auto model = mio::osecir::Model(1); + auto model = ModelT(1); auto indx_agegroup = mio::AgeGroup(0); const double tol_times = 1e-1; @@ -1242,7 +1245,7 @@ class ModelTestOdeSecir : public testing::Test , num_age_groups(6) { } - mio::osecir::Model model; + ModelT model; size_t num_age_groups; protected: @@ -1274,24 +1277,22 @@ class ModelTestOdeSecir : public testing::Test // Initialize model with data frrom external reported data. Check if the model is initialized correctly. TEST_F(ModelTestOdeSecir, read_input_data) { - auto model1 = std::vector>{model}; - auto model2 = std::vector>{model}; - auto model3 = std::vector>{model}; - - auto read_result1 = mio::osecir::read_input_data_county(model1, {2020, 12, 01}, {1002}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_GERMANY_PYDATA_DIR, 10); - - auto read_result2 = - mio::osecir::read_input_data(model2, {2020, 12, 01}, {1002}, std::vector(size_t(num_age_groups), 1.0), - 1.0, TEST_GERMANY_PYDATA_DIR, 10); - - auto read_result_district = - mio::osecir::read_input_data(model3, {2020, 12, 01}, {1002}, std::vector(size_t(num_age_groups), 1.0), - 1.0, mio::path_join(TEST_DATA_DIR, "District", "pydata"), 10); + auto model1 = std::vector>{mio::Node(1002, model)}; + auto model2 = std::vector>{mio::Node(1002, model)}; + + auto pydata_germany_path = std::string(TEST_GERMANY_PYDATA_DIR); + auto read_result1 = + mio::osecir::read_input_data(mio::make_range(model1.begin(), model1.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, + mio::regions::de::EpidataFilenames::county(pydata_germany_path)); + + auto pydata_district_path = mio::path_join(TEST_DATA_DIR, "District", "pydata"); + auto read_result_district = + mio::osecir::read_input_data(mio::make_range(model2.begin(), model2.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, + mio::regions::de::EpidataFilenames::county(pydata_district_path)); EXPECT_THAT(read_result1, IsSuccess()); - EXPECT_THAT(read_result2, IsSuccess()); EXPECT_THAT(read_result_district, IsSuccess()); // values were generated by the tested function; can only check stability of the implementation, not correctness @@ -1303,11 +1304,9 @@ TEST_F(ModelTestOdeSecir, read_input_data) 10.5181, 3.2967, 0, 3.28571, 0, 0.657143, 1.33333, 38.3, 7.57143) .finished(); - EXPECT_THAT(print_wrap(model1[0].populations.array().cast()), - MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); - EXPECT_THAT(print_wrap(model2[0].populations.array().cast()), + EXPECT_THAT(print_wrap(model1[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); - EXPECT_THAT(print_wrap(model3[0].populations.array().cast()), + EXPECT_THAT(print_wrap(model2[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); } @@ -1317,15 +1316,14 @@ TEST_F(ModelTestOdeSecir, export_time_series_init) TempFileRegister temp_file_register; auto tmp_results_dir = temp_file_register.get_unique_path(); EXPECT_THAT(mio::create_directory(tmp_results_dir), IsSuccess()); - const auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); + auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); // Test exporting time series - std::vector> models{model}; - EXPECT_THAT(mio::osecir::export_input_data_county_timeseries( - models, tmp_results_dir, {1002}, {2020, 12, 01}, std::vector(size_t(num_age_groups), 1.0), - 1.0, 2, mio::path_join(pydata_dir_Germany, "county_divi_ma7.json"), - mio::path_join(pydata_dir_Germany, "cases_all_county_age_ma7.json"), - mio::path_join(pydata_dir_Germany, "county_current_population.json")), + std::vector> models{mio::Node(1002, model)}; + EXPECT_THAT(mio::osecir::export_input_data_timeseries( + mio::make_range(models.begin(), models.end()), tmp_results_dir, {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 2, + mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); auto data_extrapolated = mio::read_result(mio::path_join(tmp_results_dir, "Results_rki.h5")); @@ -1347,15 +1345,14 @@ TEST_F(ModelTestOdeSecir, export_time_series_init_old_date) TempFileRegister temp_file_register; auto tmp_results_dir = temp_file_register.get_unique_path(); EXPECT_THAT(mio::create_directory(tmp_results_dir), IsSuccess()); - const auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); + auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); // Test exporting time series - std::vector> models{model}; - EXPECT_THAT(mio::osecir::export_input_data_county_timeseries( - models, tmp_results_dir, {1002}, {1000, 12, 01}, std::vector(size_t(num_age_groups), 1.0), - 1.0, 0, mio::path_join(pydata_dir_Germany, "county_divi_ma7.json"), - mio::path_join(pydata_dir_Germany, "cases_all_county_age_ma7.json"), - mio::path_join(pydata_dir_Germany, "county_current_population.json")), + std::vector> models{mio::Node(1002, model)}; + EXPECT_THAT(mio::osecir::export_input_data_timeseries( + mio::make_range(models.begin(), models.end()), tmp_results_dir, {1000, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 2, + mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); auto data_extrapolated = mio::read_result(mio::path_join(tmp_results_dir, "Results_rki.h5")); @@ -1382,12 +1379,12 @@ TEST_F(ModelTestOdeSecir, export_time_series_init_old_date) TEST_F(ModelTestOdeSecir, model_initialization) { // Vector assignment necessary as read_input_data_county changes model - auto model_vector = std::vector>{model}; - const auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); + auto model_vector = std::vector>{mio::Node(1002, model)}; + auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); - EXPECT_THAT(mio::osecir::read_input_data_county(model_vector, {2020, 12, 01}, {1002}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - pydata_dir_Germany, 2, false), + EXPECT_THAT(mio::osecir::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, + mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); // Values from data/export_time_series_init_osecir.h5, for reading in comparison @@ -1400,7 +1397,7 @@ TEST_F(ModelTestOdeSecir, model_initialization) 10.5181, 3.2967, 0, 3.28571, 0, 0.657143, 1.33333, 38.3, 7.57143) .finished(); - EXPECT_THAT(print_wrap(model_vector[0].populations.array().cast()), + EXPECT_THAT(print_wrap(model_vector[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); } @@ -1409,12 +1406,12 @@ TEST_F(ModelTestOdeSecir, model_initialization_old_date) { mio::set_log_level(mio::LogLevel::off); // Vector assignment necessary as read_input_data_county changes model - auto model_vector = std::vector>{model}; - const auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); + auto model_vector = std::vector>{mio::Node(1002, model)}; + auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); - EXPECT_THAT(mio::osecir::read_input_data_county(model_vector, {1000, 12, 01}, {1002}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - pydata_dir_Germany, 0, false), + EXPECT_THAT(mio::osecir::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {1000, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, + mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); // if we enter an old date, the model only should be initialized with the population data. @@ -1431,7 +1428,7 @@ TEST_F(ModelTestOdeSecir, model_initialization_old_date) population_data[0][5], 0, 0, 0, 0, 0, 0, 0, 0, 0) .finished(); - auto results_extrapolated = model_vector[0].populations.array().cast(); + auto results_extrapolated = model_vector[0].property.populations.array().cast(); for (size_t i = 0; i < num_age_groups; i++) { EXPECT_EQ(results_extrapolated(i * Eigen::Index(mio::osecir::InfectionState::Count)), population_data[0][i]); @@ -1444,14 +1441,17 @@ TEST_F(ModelTestOdeSecir, model_initialization_old_date) TEST(TestOdeSecir, set_divi_data_invalid_dates) { mio::set_log_level(mio::LogLevel::off); - auto model = mio::osecir::Model(1); + auto model = ModelT(1); model.populations.array().setConstant(1); - auto model_vector = std::vector>{model}; + auto model_vector = std::vector>{mio::Node(1001, model)}; // Test with date before DIVI dataset was available. - EXPECT_THAT(mio::osecir::details::set_divi_data(model_vector, "", {1001}, {2019, 12, 01}, 1.0), IsSuccess()); + EXPECT_THAT(mio::osecir::details::set_divi_data(mio::make_range(model_vector.begin(), model_vector.end()), + "", {2019, 12, 01}, 1.0), + IsSuccess()); + // Assure that populations is the same as before. - EXPECT_THAT(print_wrap(model_vector[0].populations.array().cast()), + EXPECT_THAT(print_wrap(model_vector[0].property.populations.array().cast()), MatrixNear(print_wrap(model.populations.array().cast()), 1e-10, 1e-10)); mio::set_log_level(mio::LogLevel::warn); @@ -1462,10 +1462,9 @@ TEST(TestOdeSecir, set_divi_data_empty_data) // Create an empty DIVI data vector std::vector empty_data; std::vector regions = {0, 1}; - std::vector num_icu(regions.size(), 0.0); mio::Date date(2020, 4, 1); - auto result = mio::compute_divi_data(empty_data, regions, date, num_icu); + auto result = mio::compute_divi_data(empty_data, regions, date); // Expect failure due to empty DIVI data EXPECT_FALSE(result); @@ -1475,13 +1474,16 @@ TEST(TestOdeSecir, set_divi_data_empty_data) TEST_F(ModelTestOdeSecir, set_confirmed_cases_data_with_ICU) { + auto model_test = ModelT{model}; + model_test.populations.array().setConstant(1); + // set params for (auto age_group = mio::AgeGroup(0); age_group < (mio::AgeGroup)num_age_groups; age_group++) { - model.parameters.get>()[age_group] = 1.0; - model.parameters.get>()[age_group] = 1.0; - model.parameters.get>()[age_group] = 1.0; - model.parameters.get>()[age_group] = 1.0; - model.parameters.get>()[age_group] = 1.0; + model_test.parameters.get>()[age_group] = 1.0; + model_test.parameters.get>()[age_group] = 1.0; + model_test.parameters.get>()[age_group] = 1.0; + model_test.parameters.get>()[age_group] = 1.0; + model_test.parameters.get>()[age_group] = 1.0; } // read case data @@ -1502,10 +1504,9 @@ TEST_F(ModelTestOdeSecir, set_confirmed_cases_data_with_ICU) auto mid_day = case_data[(size_t)case_data.size() / 2].date; // calculate ICU values using set_confirmed_cases_data - auto model_vector = std::vector>{model}; - auto scaling_factor_inf = std::vector(size_t(model.parameters.get_num_groups()), 1.0); + auto scaling_factor_inf = std::vector(size_t(model_test.parameters.get_num_groups()), 1.0); EXPECT_THAT( - mio::osecir::details::set_confirmed_cases_data(model_vector, case_data, {1002}, mid_day, scaling_factor_inf), + mio::osecir::details::set_confirmed_cases_data(model_test, case_data, 1002, mid_day, scaling_factor_inf), IsSuccess()); // Since, TimeInfectedCritical is 1, the number of ICU cases is the difference of confirmed cases between two days, which is 1. @@ -1513,7 +1514,7 @@ TEST_F(ModelTestOdeSecir, set_confirmed_cases_data_with_ICU) for (size_t i = 0; i < num_age_groups; ++i) { const auto expected_value = (i == 2) ? 1.0 : 0.0; const auto actual_value = - model_vector[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}].value(); + model_test.populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}].value(); EXPECT_NEAR(actual_value, expected_value, 1e-10); } } @@ -1536,20 +1537,20 @@ TEST(TestOdeSecirIO, read_input_data_county_aggregates_one_group) { // Set up two models with different number of age groups. const size_t num_age_groups = 6; - std::vector> models6{mio::osecir::Model((int)num_age_groups)}; - std::vector> models1{mio::osecir::Model(1)}; + std::vector> models6{mio::Node(1002, (int)num_age_groups)}; + std::vector> models1{mio::Node(1002, 1)}; // Relevant parameters for model with 6 age groups for (auto i = mio::AgeGroup(0); i < (mio::AgeGroup)num_age_groups; ++i) { - models6[0].parameters.get>()[i] = 0.2; - models6[0].parameters.get>()[i] = 0.25; + models6[0].property.parameters.get>()[i] = 0.2; + models6[0].property.parameters.get>()[i] = 0.25; } // Relevant parameters for model with 1 age group - models1[0].parameters.get>()[mio::AgeGroup(0)] = 0.2; - models1[0].parameters.get>()[mio::AgeGroup(0)] = 0.25; + models1[0].property.parameters.get>()[mio::AgeGroup(0)] = 0.2; + models1[0].property.parameters.get>()[mio::AgeGroup(0)] = 0.25; - const auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); + auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); const std::vector counties{1002}; const auto date = mio::Date(2020, 12, 1); @@ -1557,14 +1558,16 @@ TEST(TestOdeSecirIO, read_input_data_county_aggregates_one_group) std::vector scale1{1.0}; // Initialize both models - ASSERT_THAT(mio::osecir::read_input_data_county(models6, date, counties, scale6, 1.0, pydata_dir_Germany), + ASSERT_THAT(mio::osecir::read_input_data(mio::make_range(models6.begin(), models6.end()), date, scale6, 1.0, + mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); - ASSERT_THAT(mio::osecir::read_input_data_county(models1, date, counties, scale1, 1.0, pydata_dir_Germany), + ASSERT_THAT(mio::osecir::read_input_data(mio::make_range(models1.begin(), models1.end()), date, scale1, 1.0, + mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); // Aggreagate the results from the model with 6 age groups and compare with the model with 1 age group - const auto& m6 = models6[0]; - const auto& m1 = models1[0]; + const auto& m6 = models6[0].property; + const auto& m1 = models1[0].property; const double tol = 1e-10; for (int s = 0; s < (int)mio::osecir::InfectionState::Count; ++s) { double sum6 = 0.0; @@ -1584,32 +1587,32 @@ TEST(TestOdeSecirIO, set_population_data_single_age_group) const size_t num_age_groups = 6; // Create two models: one with 6 age groups, one with 1 age group - std::vector> models6{mio::osecir::Model((int)num_age_groups)}; - std::vector> models1{mio::osecir::Model(1)}; + ModelT models6{(int)num_age_groups}; + ModelT models1{1}; // Test population data with 6 different values for age groups - std::vector> population_data6 = {{10000.0, 20000.0, 30000.0, 25000.0, 15000.0, 8000.0}}; - std::vector> population_data1 = {{108000.0}}; // sum of all age groups - std::vector regions = {1002}; + std::vector population_data6 = {10000.0, 20000.0, 30000.0, 25000.0, 15000.0, 8000.0}; + std::vector population_data1 = {108000.0}; // sum of all age groups + const int region = 1002; // Set population data for both models - EXPECT_THAT(mio::osecir::details::set_population_data(models6, population_data6, regions), IsSuccess()); - EXPECT_THAT(mio::osecir::details::set_population_data(models1, population_data1, regions), IsSuccess()); + EXPECT_THAT(mio::osecir::details::set_population_data(models6, population_data6, region), IsSuccess()); + EXPECT_THAT(mio::osecir::details::set_population_data(models1, population_data1, region), IsSuccess()); // Sum all compartments across age groups in 6-group model and compare 1-group model const double tol = 1e-10; for (int s = 0; s < (int)mio::osecir::InfectionState::Count; ++s) { double sum6 = 0.0; for (size_t ag = 0; ag < num_age_groups; ++ag) { - sum6 += models6[0].populations[{mio::AgeGroup(ag), (mio::osecir::InfectionState)s}].value(); + sum6 += models6.populations[{mio::AgeGroup(ag), (mio::osecir::InfectionState)s}].value(); } - double val1 = models1[0].populations[{mio::AgeGroup(0), (mio::osecir::InfectionState)s}].value(); + double val1 = models1.populations[{mio::AgeGroup(0), (mio::osecir::InfectionState)s}].value(); EXPECT_NEAR(sum6, val1, tol); } // Total population should also match - EXPECT_NEAR(models6[0].populations.get_total(), models1[0].populations.get_total(), tol); + EXPECT_NEAR(models6.populations.get_total(), models1.populations.get_total(), tol); } TEST(TestOdeSecirIO, set_confirmed_cases_data_single_age_group) @@ -1617,8 +1620,8 @@ TEST(TestOdeSecirIO, set_confirmed_cases_data_single_age_group) const size_t num_age_groups = 6; // Create two models: one with 6 age groups, one with 1 age group - std::vector> models6{mio::osecir::Model((int)num_age_groups)}; - std::vector> models1{mio::osecir::Model(1)}; + ModelT models6{(int)num_age_groups}; + ModelT models1{1}; // Create case data for all 6 age groups over multiple days (current day + 6 days back) std::vector case_data; @@ -1626,7 +1629,7 @@ TEST(TestOdeSecirIO, set_confirmed_cases_data_single_age_group) for (int day_offset = -6; day_offset <= 0; ++day_offset) { mio::Date current_date = mio::offset_date_by_days(mio::Date(2020, 12, 1), day_offset); - for (int age_group = 0; age_group < 6; ++age_group) { + for (int age_group = 0; age_group < (int)num_age_groups; ++age_group) { double base_confirmed = 80.0 + age_group * 8.0 + (day_offset + 6) * 5.0; double base_recovered = 40.0 + age_group * 4.0 + (day_offset + 6) * 3.0; double base_deaths = 3.0 + age_group * 0.5 + (day_offset + 6) * 0.5; @@ -1637,20 +1640,20 @@ TEST(TestOdeSecirIO, set_confirmed_cases_data_single_age_group) current_date, mio::AgeGroup(age_group), {}, - mio::regions::CountyId(1002), + mio::regions::de::CountyId(1002), {}}; case_data.push_back(entry); } } - std::vector regions = {1002}; + const int region = 1002; std::vector scaling_factors = {1.0}; // Set confirmed cases data for both models - EXPECT_THAT(mio::osecir::details::set_confirmed_cases_data(models6, case_data, regions, mio::Date(2020, 12, 1), + EXPECT_THAT(mio::osecir::details::set_confirmed_cases_data(models6, case_data, region, mio::Date(2020, 12, 1), scaling_factors), IsSuccess()); - EXPECT_THAT(mio::osecir::details::set_confirmed_cases_data(models1, case_data, regions, mio::Date(2020, 12, 1), + EXPECT_THAT(mio::osecir::details::set_confirmed_cases_data(models1, case_data, region, mio::Date(2020, 12, 1), scaling_factors), IsSuccess()); @@ -1658,43 +1661,48 @@ TEST(TestOdeSecirIO, set_confirmed_cases_data_single_age_group) for (int s = 0; s < (int)mio::osecir::InfectionState::Count; ++s) { double sum6 = 0.0; for (size_t ag = 0; ag < num_age_groups; ++ag) { - sum6 += models6[0].populations[{mio::AgeGroup(ag), (mio::osecir::InfectionState)s}].value(); + sum6 += models6.populations[{mio::AgeGroup(ag), (mio::osecir::InfectionState)s}].value(); } - double val1 = models1[0].populations[{mio::AgeGroup(0), (mio::osecir::InfectionState)s}].value(); + double val1 = models1.populations[{mio::AgeGroup(0), (mio::osecir::InfectionState)s}].value(); EXPECT_NEAR(sum6, val1, 1e-10); } // Total population - EXPECT_NEAR(models6[0].populations.get_total(), models1[0].populations.get_total(), 1e-10); + EXPECT_NEAR(models6.populations.get_total(), models1.populations.get_total(), 1e-10); } TEST(TestOdeSecirIO, set_divi_data_single_age_group) { + const size_t num_age_groups = 6; + // Create models with 6 age groups and 1 age group - std::vector> models_6_groups{mio::osecir::Model(6)}; - std::vector> models_1_group{mio::osecir::Model(1)}; + ModelT models6{(int)num_age_groups}; + ModelT models1{1}; // Set relevant parameters for all age groups - for (int i = 0; i < 6; i++) { - models_6_groups[0].parameters.get>()[mio::AgeGroup(i)] = 0.2; - models_6_groups[0].parameters.get>()[mio::AgeGroup(i)] = 0.25; + for (int i = 0; i < (int)num_age_groups; i++) { + models6.parameters.get>()[mio::AgeGroup(i)] = 0.2; + models6.parameters.get>()[mio::AgeGroup(i)] = 0.25; } // Set relevant parameters for 1 age group model - models_1_group[0].parameters.get>()[mio::AgeGroup(0)] = 0.2; - models_1_group[0].parameters.get>()[mio::AgeGroup(0)] = 0.25; + models1.parameters.get>()[mio::AgeGroup(0)] = 0.2; + models1.parameters.get>()[mio::AgeGroup(0)] = 0.25; // Apply DIVI data to both models - std::vector regions = {1002}; + const int region = 1002; double scaling_factor_icu = 1.0; mio::Date date(2020, 12, 1); std::string divi_data_path = mio::path_join(TEST_DATA_DIR, "Germany", "pydata", "county_divi_ma7.json"); + + auto num_icu = read_divi_data(divi_data_path, {region}, date).value(); + auto result_6_groups = - mio::osecir::details::set_divi_data(models_6_groups, divi_data_path, regions, date, scaling_factor_icu); + mio::osecir::details::set_divi_data(models6, num_icu[0], scaling_factor_icu); auto result_1_group = - mio::osecir::details::set_divi_data(models_1_group, divi_data_path, regions, date, scaling_factor_icu); + mio::osecir::details::set_divi_data(models1, num_icu[0], scaling_factor_icu); EXPECT_THAT(result_6_groups, IsSuccess()); EXPECT_THAT(result_1_group, IsSuccess()); @@ -1703,10 +1711,10 @@ TEST(TestOdeSecirIO, set_divi_data_single_age_group) double total_icu_6_groups_after = 0.0; for (int i = 0; i < 6; i++) { total_icu_6_groups_after += - models_6_groups[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}].value(); + models6.populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}].value(); } double icu_1_group_after = - models_1_group[0].populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedCritical}].value(); + models1.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedCritical}].value(); EXPECT_NEAR(total_icu_6_groups_after, icu_1_group_after, 1e-10); } diff --git a/cpp/tests/test_odesecirts.cpp b/cpp/tests/test_odesecirts.cpp index 4bf0d0e1a8..f0be75b0d8 100755 --- a/cpp/tests/test_odesecirts.cpp +++ b/cpp/tests/test_odesecirts.cpp @@ -50,9 +50,11 @@ #include #include -const mio::osecirts::Model& osecirts_testing_model() +using ModelT = mio::osecirts::Model; + +const ModelT& osecirts_testing_model() { - static mio::osecirts::Model model(1); + static ModelT model(1); model.populations.array().setConstant(1); auto nb_groups = model.parameters.get_num_groups(); @@ -153,7 +155,7 @@ TEST(TestOdeSECIRTS, Simulation) EXPECT_EQ(sim.get_result().get_last_value(), expected_result); } -using FlowSim = mio::osecirts::Simulation>>; +using FlowSim = mio::osecirts::Simulation>; TEST(TestOdeSECIRTS, FlowSimulation) { @@ -182,7 +184,7 @@ TEST(TestOdeSECIRTS, simulateDefault) double tmax = 1; double dt = 0.1; - mio::osecirts::Model model(1); + ModelT model(1); model.populations.set_total(10); model.populations.set_difference_from_total({(mio::AgeGroup)0, mio::osecirts::InfectionState::SusceptibleNaive}, 10); @@ -192,7 +194,7 @@ TEST(TestOdeSECIRTS, simulateDefault) model.parameters.get>().array().setConstant(0); model.parameters.get>().resize(mio::SimulationDay(size_t(1000))); model.parameters.get>().array().setConstant(0); - auto result = mio::simulate>(t0, tmax, dt, model); + auto result = mio::simulate(t0, tmax, dt, model); EXPECT_NEAR(result.get_last_time(), tmax, 1e-10); } @@ -201,7 +203,7 @@ TEST(TestOdeSECIRTS, simulateDefault) TEST(TestOdeSECIRTS, population_zero_no_nan) { // initialize simple model with total population 0 - mio::osecirts::Model model(1); + ModelT model(1); model.populations.set_total(0.0); model.parameters.get>().resize(mio::SimulationDay(size_t(1000))); @@ -230,7 +232,7 @@ TEST(TestOdeSECIRTS, overflow_vaccinations) const double dt = 1; // init simple model - mio::osecirts::Model model(1); + ModelT model(1); model.populations[{mio::AgeGroup(0), mio::osecirts::InfectionState::SusceptibleNaive}] = 10.; model.populations[{mio::AgeGroup(0), mio::osecirts::InfectionState::SusceptiblePartialImmunity}] = 10.; model.populations[{mio::AgeGroup(0), mio::osecirts::InfectionState::SusceptibleImprovedImmunity}] = 10.; @@ -258,7 +260,7 @@ TEST(TestOdeSECIRTS, overflow_vaccinations) } // simulate one step with explicit Euler - auto result = mio::simulate_flows>(t0, tmax, dt, model, std::make_unique>()); + auto result = mio::simulate_flows(t0, tmax, dt, model, std::make_unique>()); // get the flow indices for each type of vaccination and also the indices of the susceptible compartments auto flow_indx_partial_vaccination = @@ -286,10 +288,10 @@ TEST(TestOdeSECIRTS, overflow_vaccinations) TEST(TestOdeSECIRTS, smooth_vaccination_rate) { - const ScalarType tmax = 2.; + const double tmax = 2.; // init simple model - mio::osecirts::Model model(1); + ModelT model(1); auto& daily_vaccinations = model.parameters.get>(); daily_vaccinations.resize(mio::SimulationDay(static_cast(tmax + 1))); @@ -372,7 +374,7 @@ void array_assign_uniform_distribution(mio::CustomIndexArray::Populations& populations, +void set_synthetic_population_data(ModelT::Populations& populations, bool set_invalid_initial_value) { for (mio::AgeGroup i = 0; i < mio::get(populations.size()); i++) { @@ -433,7 +435,7 @@ void set_synthetic_population_data(mio::osecirts::Model::Populations& po } } -void set_demographic_parameters(mio::osecirts::Model::ParameterSet& parameters, bool set_invalid_initial_value) +void set_demographic_parameters(ModelT::ParameterSet& parameters, bool set_invalid_initial_value) { assign_uniform_distribution(parameters.get>(), 20, 50, set_invalid_initial_value); @@ -447,7 +449,7 @@ void set_demographic_parameters(mio::osecirts::Model::ParameterSet& para parameters.get>().array().setConstant(3); } -void set_contact_parameters(mio::osecirts::Model::ParameterSet& parameters, bool set_invalid_initial_value) +void set_contact_parameters(ModelT::ParameterSet& parameters, bool set_invalid_initial_value) { auto& contacts = parameters.get>(); auto& contact_matrix = contacts.get_cont_freq_mat(); @@ -467,7 +469,7 @@ void set_contact_parameters(mio::osecirts::Model::ParameterSet& paramete parameters.get_end_dynamic_npis() = 10.0; //required for dynamic NPIs to have effect in this model } -void set_covid_parameters(mio::osecirts::Model::ParameterSet& params, bool set_invalid_initial_value) +void set_covid_parameters(ModelT::ParameterSet& params, bool set_invalid_initial_value) { //times const double timeExposedMin = 2.67; @@ -587,10 +589,10 @@ void set_covid_parameters(mio::osecirts::Model::ParameterSet& params, bo namespace { -mio::osecirts::Model make_model(int num_age_groups, bool set_invalid_initial_value = false) +ModelT make_model(int num_age_groups, bool set_invalid_initial_value = false) { assert(num_age_groups <= 6 && "Provide more values in functions above to test more age groups."); - mio::osecirts::Model model(num_age_groups); + ModelT model(num_age_groups); set_covid_parameters(model.parameters, set_invalid_initial_value); set_synthetic_population_data(model.populations, set_invalid_initial_value); set_demographic_parameters(model.parameters, set_invalid_initial_value); @@ -604,7 +606,7 @@ TEST(TestOdeSECIRTS, draw_sample_graph) { mio::log_thread_local_rng_seeds(mio::LogLevel::warn); - mio::Graph, mio::MobilityParameters> graph; + mio::Graph> graph; auto num_age_groups = 6; //create model with invalid initials so the test fails if no sampling is done @@ -711,44 +713,90 @@ TEST(TestOdeSECIRTS, checkPopulationConservation) TEST(TestOdeSECIRTS, read_confirmed_cases) { auto num_age_groups = 6; //reading data requires RKI data age groups - auto model = std::vector>({make_model(num_age_groups)}); - const std::vector region{1002}; + ModelT model = make_model(num_age_groups); + const int region = 1002; auto path = mio::path_join(TEST_DATA_DIR, "Germany/pydata/cases_all_county_age_ma7.json"); - std::vector> num_InfectedSymptoms(1); - std::vector> num_death(1); - std::vector> num_timm(1); - std::vector> num_Exposed(1); - std::vector> num_InfectedNoSymptoms(1); - std::vector> num_InfectedSevere(1); - std::vector> num_icu(1); - - num_InfectedSymptoms[0] = std::vector(num_age_groups, 0.0); - num_death[0] = std::vector(num_age_groups, 0.0); - num_timm[0] = std::vector(num_age_groups, 0.0); - num_Exposed[0] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[0] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[0] = std::vector(num_age_groups, 0.0); - num_icu[0] = std::vector(num_age_groups, 0.0); - - ASSERT_THAT(mio::osecirts::details::read_confirmed_cases_data( - path, region, {2020, 12, 01}, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, - num_InfectedSevere, num_icu, num_death, num_timm, model, + std::vector t_Exposed; + std::vector t_InfectedNoSymptoms; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; + std::vector t_imm_interval_i; + + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; + + std::vector reduc_t_Infected; + std::vector reduc_Exposed; + std::vector reduc_InfectedSymptoms; + std::vector reduc_icu_death; + + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_rec(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + std::vector num_timm(num_age_groups, 0.0); + + for (int group = 0; group < num_age_groups; group++) { + t_Exposed.push_back( + static_cast(std::round(model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast( + std::round(model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast( + std::round(model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast( + std::round(model.parameters.template get>()[(mio::AgeGroup)group]))); + t_imm_interval_i.push_back(static_cast( + std::round(model.parameters.template get>()[(mio::AgeGroup)group]))); + + mu_C_R.push_back(model.parameters.template get>()[(mio::AgeGroup)group]); + mu_I_H.push_back(model.parameters.template get>()[(mio::AgeGroup)group]); + mu_H_U.push_back(model.parameters.template get>()[(mio::AgeGroup)group]); + + reduc_t_Infected.push_back(model.parameters.template get>()[(mio::AgeGroup)group]); + reduc_Exposed.push_back( + model.parameters.template get>()[(mio::AgeGroup)group]); + reduc_InfectedSymptoms.push_back( + model.parameters.template get>()[(mio::AgeGroup)group]); + reduc_icu_death.push_back( + model.parameters + .template get>()[(mio::AgeGroup)group]); + } + + auto case_data = + mio::read_confirmed_cases_data(path).value(); + + ASSERT_THAT(mio::osecirts::details::compute_confirmed_cases_data( + case_data, region, {2020, 12, 01}, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, + num_InfectedSevere, num_icu, num_death, num_timm, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, + t_InfectedSevere, t_InfectedCritical, t_imm_interval_i, mu_C_R, mu_I_H, mu_H_U, reduc_t_Infected, + reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, std::vector(size_t(num_age_groups), 1.0), 0), IsSuccess()); // read again with invalid date - ASSERT_THAT(mio::osecirts::details::read_confirmed_cases_data( - path, region, {3020, 12, 01}, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, - num_InfectedSevere, num_icu, num_death, num_timm, model, + ASSERT_THAT(mio::osecirts::details::compute_confirmed_cases_data( + case_data, region, {3020, 12, 01}, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, + num_InfectedSevere, num_icu, num_death, num_timm, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, + t_InfectedSevere, t_InfectedCritical, t_imm_interval_i, mu_C_R, mu_I_H, mu_H_U, reduc_t_Infected, + reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, std::vector(size_t(num_age_groups), 1.0), 0), IsFailure(mio::StatusCode::OutOfRange)); // call the compute function with empty case data const std::vector empty_case_data; ASSERT_THAT(mio::osecirts::details::compute_confirmed_cases_data( - empty_case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, - num_icu, num_death, num_timm, region, {2020, 12, 01}, model, + empty_case_data, region, {2020, 12, 01}, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, + num_InfectedSevere, num_icu, num_death, num_timm, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, + t_InfectedSevere, t_InfectedCritical, t_imm_interval_i, mu_C_R, mu_I_H, mu_H_U, reduc_t_Infected, + reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, std::vector(size_t(num_age_groups), 1.0), 0), IsFailure(mio::StatusCode::InvalidValue)); } @@ -756,14 +804,16 @@ TEST(TestOdeSECIRTS, read_confirmed_cases) TEST(TestOdeSECIRTS, set_divi_data_invalid_dates) { mio::set_log_level(mio::LogLevel::off); - auto model = mio::osecirts::Model(1); + auto model = ModelT(1); model.populations.array().setConstant(1); - auto model_vector = std::vector>{model}; + auto model_vector = std::vector>{mio::Node(1001, model)}; // Test with date before DIVI dataset was available. - EXPECT_THAT(mio::osecirts::details::set_divi_data(model_vector, "", {1001}, {2019, 12, 01}, 1.0), IsSuccess()); + EXPECT_THAT(mio::osecirts::details::set_divi_data(mio::make_range(model_vector.begin(), model_vector.end()), + "", {2019, 12, 01}, 1.0), + IsSuccess()); // Assure that populations is the same as before. - EXPECT_THAT(print_wrap(model_vector[0].populations.array().cast()), + EXPECT_THAT(print_wrap(model_vector[0].property.populations.array().cast()), MatrixNear(print_wrap(model.populations.array().cast()), 1e-10, 1e-10)); mio::set_log_level(mio::LogLevel::warn); } @@ -771,7 +821,7 @@ TEST(TestOdeSECIRTS, set_divi_data_invalid_dates) TEST(TestOdeSECIRTS, set_confirmed_cases_data_with_ICU) { const auto num_age_groups = 6; - auto model = mio::osecirts::Model(num_age_groups); + auto model = ModelT(num_age_groups); model.populations.array().setConstant(1); const std::vector> immunity_population = {{0.04, 0.04, 0.075, 0.08, 0.035, 0.01}, @@ -805,10 +855,9 @@ TEST(TestOdeSECIRTS, set_confirmed_cases_data_with_ICU) auto mid_day = case_data[(size_t)case_data.size() / 2].date; // calculate ICU values using set_confirmed_cases_data - auto model_vector = std::vector>{model}; auto scaling_factor_inf = std::vector(size_t(model.parameters.get_num_groups()), 1.0); - EXPECT_THAT(mio::osecirts::details::set_confirmed_cases_data(model_vector, case_data, {1002}, mid_day, + EXPECT_THAT(mio::osecirts::details::set_confirmed_cases_data(model, case_data, 1002, mid_day, scaling_factor_inf, immunity_population), IsSuccess()); @@ -818,20 +867,17 @@ TEST(TestOdeSECIRTS, set_confirmed_cases_data_with_ICU) const auto expected_value = (i == 2) ? 1.0 : 0.0; auto actual_value_naive = - model_vector[0] - .populations[{mio::AgeGroup(i), mio::osecirts::InfectionState::InfectedCriticalNaive}] + model.populations[{mio::AgeGroup(i), mio::osecirts::InfectionState::InfectedCriticalNaive}] .value(); EXPECT_NEAR(actual_value_naive, expected_value * immunity_population[0][i], 1e-10); auto actual_value_pi = - model_vector[0] - .populations[{mio::AgeGroup(i), mio::osecirts::InfectionState::InfectedCriticalPartialImmunity}] + model.populations[{mio::AgeGroup(i), mio::osecirts::InfectionState::InfectedCriticalPartialImmunity}] .value(); EXPECT_NEAR(actual_value_pi, expected_value * immunity_population[1][i], 1e-10); auto actual_value_ii = - model_vector[0] - .populations[{mio::AgeGroup(i), mio::osecirts::InfectionState::InfectedCriticalImprovedImmunity}] + model.populations[{mio::AgeGroup(i), mio::osecirts::InfectionState::InfectedCriticalImprovedImmunity}] .value(); EXPECT_NEAR(actual_value_ii, expected_value * immunity_population[2][i], 1e-10); } @@ -840,28 +886,27 @@ TEST(TestOdeSECIRTS, set_confirmed_cases_data_with_ICU) TEST(TestOdeSECIRTS, read_data) { auto num_age_groups = 6; //reading data requires RKI data age groups - auto model1 = std::vector>({make_model(num_age_groups)}); - auto model2 = std::vector>({make_model(num_age_groups)}); - auto model3 = std::vector>({make_model(num_age_groups)}); + auto model = make_model(num_age_groups); + auto model1 = std::vector>{mio::Node(1002, model)}; + auto model2 = std::vector>{mio::Node(1002, model)}; const std::vector> immunity_population = {{0.04, 0.04, 0.075, 0.08, 0.035, 0.01}, {0.61, 0.61, 0.62, 0.62, 0.58, 0.41}, {0.35, 0.35, 0.305, 0.3, 0.385, 0.58}}; - auto read_result1 = mio::osecirts::read_input_data_county(model1, {2020, 12, 01}, {1002}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_GERMANY_PYDATA_DIR, 10, immunity_population); - - auto read_result2 = - mio::osecirts::read_input_data(model2, {2020, 12, 01}, {1002}, std::vector(size_t(num_age_groups), 1.0), - 1.0, TEST_GERMANY_PYDATA_DIR, 10, immunity_population); - - auto read_result_district = - mio::osecirts::read_input_data(model3, {2020, 12, 01}, {1002}, std::vector(size_t(num_age_groups), 1.0), - 1.0, mio::path_join(TEST_DATA_DIR, "District/pydata"), 10, immunity_population); + auto pydata_germany_path = std::string(TEST_GERMANY_PYDATA_DIR); + auto read_result1 = + mio::osecirts::read_input_data(mio::make_range(model1.begin(), model1.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 10, immunity_population, + mio::regions::de::EpidataFilenames::county(pydata_germany_path)); + + auto pydata_district_path = mio::path_join(TEST_DATA_DIR, "District", "pydata"); + auto read_result_district = + mio::osecirts::read_input_data(mio::make_range(model2.begin(), model2.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 10, immunity_population, + mio::regions::de::EpidataFilenames::county(pydata_district_path)); ASSERT_THAT(read_result1, IsSuccess()); - ASSERT_THAT(read_result2, IsSuccess()); ASSERT_THAT(read_result_district, IsSuccess()); // values were generated by the tested function; can only check stability of the implementation, not correctness @@ -881,118 +926,86 @@ TEST(TestOdeSECIRTS, read_data) 0.530478, 0.155246) .finished(); - ASSERT_THAT(print_wrap(model1[0].populations.array().cast()), - MatrixNear(print_wrap(model2[0].populations.array().cast()), 1e-5, 1e-5)); + ASSERT_THAT(print_wrap(model1[0].property.populations.array().cast()), + MatrixNear(print_wrap(model2[0].property.populations.array().cast()), 1e-5, 1e-5)); - ASSERT_THAT(print_wrap(model1[0].populations.array().cast()), - MatrixNear(print_wrap(model3[0].populations.array().cast()), 1e-5, 1e-5)); - ASSERT_THAT(print_wrap(model1[0].populations.array().cast()), - MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); - ASSERT_THAT(print_wrap(model2[0].populations.array().cast()), + ASSERT_THAT(print_wrap(model1[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); - ASSERT_THAT(print_wrap(model3[0].populations.array().cast()), + ASSERT_THAT(print_wrap(model2[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); // some more tests which are actually not necessary but can help if the previous tests fails or needs to get changed - for (mio::AgeGroup i = 0; i < model1[0].parameters.get_num_groups(); i++) { - EXPECT_GE(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaive}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaive}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaive}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaive}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaive}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaive}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunity}]), - 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunity}]), - 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunity}]), + for (mio::AgeGroup i = 0; i < model1[0].property.parameters.get_num_groups(); i++) { + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaive}]), 0); + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaive}]), 0); + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaive}]), 0); + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaive}]), 0); + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunity}]), + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunity}]), + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunity}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunity}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunity}]), + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunity}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunity}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunity}]), + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::TemporaryImmunePartialImmunity}]), 0); + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::TemporaryImmunePartialImmunity}]), 0); + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::TemporaryImmuneImprovedImmunity}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunity}]), - 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirts::InfectionState::TemporaryImmunePartialImmunity}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirts::InfectionState::TemporaryImmuneImprovedImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::TemporaryImmuneImprovedImmunity}]), 0); // currently dead and confirmed after commuting compartments are initialized as zero - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), - 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaiveConfirmed}]), 0); + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaiveConfirmed}]), 0); + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsNaiveConfirmed}]), 0); EXPECT_EQ( double( - model1[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), + model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( double( - model2[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), + model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( - double( - model3[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), + double(model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( - double(model1[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), - 0); - EXPECT_EQ( - double(model2[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), - 0); - EXPECT_EQ( - double(model3[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), - 0); - EXPECT_EQ( - double( - model1[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), - 0); - EXPECT_EQ( - double( - model2[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), + double(model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( double( - model3[0].populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), + model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), 0); EXPECT_EQ( double( - model1[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), + model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), 0); EXPECT_EQ( double( - model2[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), + model1[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), 0); EXPECT_EQ( double( - model3[0].populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), + model2[0].property.populations[{i, mio::osecirts::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirts::InfectionState::DeadNaive}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirts::InfectionState::DeadNaive}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirts::InfectionState::DeadNaive}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirts::InfectionState::DeadPartialImmunity}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirts::InfectionState::DeadPartialImmunity}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirts::InfectionState::DeadPartialImmunity}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirts::InfectionState::DeadImprovedImmunity}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirts::InfectionState::DeadImprovedImmunity}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirts::InfectionState::DeadImprovedImmunity}]), 0); + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::DeadNaive}]), 0); + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::DeadNaive}]), 0); + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::DeadPartialImmunity}]), 0); + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::DeadPartialImmunity}]), 0); + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirts::InfectionState::DeadImprovedImmunity}]), 0); + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirts::InfectionState::DeadImprovedImmunity}]), 0); } } @@ -1003,20 +1016,18 @@ TEST(TestOdeSECIRTS, export_time_series_init) ASSERT_THAT(mio::create_directory(tmp_results_dir), IsSuccess()); auto num_age_groups = 6; // Data to be read requires RKI confirmed cases data age groups - auto model = make_model(num_age_groups); + std::vector> model{mio::Node(0, make_model(num_age_groups))}; const std::vector> immunity_population = {{0.04, 0.04, 0.075, 0.08, 0.035, 0.01}, {0.61, 0.61, 0.62, 0.62, 0.58, 0.41}, {0.35, 0.35, 0.305, 0.3, 0.385, 0.58}}; + std::string pydata_test_dir = TEST_DATA_DIR; // Test exporting time series - ASSERT_THAT(mio::osecirts::export_input_data_county_timeseries( - std::vector>{model}, tmp_results_dir, {0}, {2020, 12, 01}, - std::vector(size_t(num_age_groups), 1.0), 1.0, 2, - mio::path_join(TEST_DATA_DIR, "county_divi_ma7.json"), - mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), - mio::path_join(TEST_DATA_DIR, "county_current_population.json"), immunity_population, - mio::path_join(TEST_DATA_DIR, "vacc_county_ageinf_ma7.json")), + ASSERT_THAT(mio::osecirts::export_input_data_timeseries( + mio::make_range(model.begin(), model.end()), tmp_results_dir, {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 2, immunity_population, + mio::regions::de::EpidataFilenames::county(pydata_test_dir)), IsSuccess()); auto data_extrapolated = mio::read_result(mio::path_join(tmp_results_dir, "Results_rki.h5")); @@ -1035,17 +1046,16 @@ TEST(TestOdeSECIRTS, export_time_series_init) TEST(TestOdeSECIRTS, model_initialization) { auto num_age_groups = 6; // Data to be read requires RKI confirmed cases data age groups - auto model = make_model(num_age_groups); - // Vector assignment necessary as read_input_data_county changes model - auto model_vector = std::vector>{model}; + std::vector> model_vector{mio::Node(0, make_model(num_age_groups))}; const std::vector> immunity_population = {{0.04, 0.04, 0.075, 0.08, 0.035, 0.01}, {0.61, 0.61, 0.62, 0.62, 0.58, 0.41}, {0.35, 0.35, 0.305, 0.3, 0.385, 0.58}}; - ASSERT_THAT(mio::osecirts::read_input_data_county(model_vector, {2020, 12, 01}, {0}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_DATA_DIR, 2, immunity_population, false), + std::string pydata_test_dir = TEST_DATA_DIR; + ASSERT_THAT(mio::osecirts::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 2, immunity_population, + mio::regions::de::EpidataFilenames::county(pydata_test_dir)), IsSuccess()); // Values from data/export_time_series_init_osecirts.h5, for reading in comparison @@ -1066,7 +1076,7 @@ TEST(TestOdeSECIRTS, model_initialization) 0.146922, 4.75954, 3.5, 4, 3.58574e+06, 0, 0, 0, 0.530478, 0.155246) .finished(); - ASSERT_THAT(print_wrap(model_vector[0].populations.array().cast()), + ASSERT_THAT(print_wrap(model_vector[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); } @@ -1074,11 +1084,11 @@ TEST(TestOdeSECIRTS, set_vaccination_data_not_avail) { const auto num_age_groups = 2; const auto num_days = 5; - mio::osecirts::Model model(num_age_groups); - std::vector> model_vector = {model}; + ModelT model(num_age_groups); + std::vector> model_vector{mio::Node(1001, model)}; // Setup initial non-zero vaccination data - auto& params = model_vector[0].parameters; + auto& params = model_vector[0].property.parameters; params.get>().resize(mio::SimulationDay(num_days + 1)); params.get>().resize(mio::SimulationDay(num_days + 1)); params.get>().resize(mio::SimulationDay(num_days + 1)); @@ -1097,11 +1107,11 @@ TEST(TestOdeSECIRTS, set_vaccination_data_not_avail) // Call set_vaccination_data with an unavailable date mio::Date unavailable_date(2019, 1, 1); // Date before vaccinations started - std::vector region = {1001}; std::string any_path = "dummy_vacc_path.json"; auto result = - mio::osecirts::details::set_vaccination_data(model_vector, any_path, unavailable_date, region, num_days); + mio::osecirts::details::set_vaccination_data(mio::make_range(model_vector.begin(), model_vector.end()), + any_path, unavailable_date, num_days); ASSERT_THAT(result, IsSuccess()); @@ -1125,9 +1135,24 @@ TEST(TestOdeSECIRTS, set_vaccination_data_min_date_not_avail) // create model const auto num_age_groups = 1; const auto num_days = 5; - mio::osecirts::Model model(num_age_groups); - std::vector> model_vector = {model}; - auto& params = model_vector[0].parameters; + ModelT model(num_age_groups); + auto& params = model.parameters; + + params.template get>()[mio::AgeGroup(0)] = 1; + params.template get>()[mio::AgeGroup(0)] = 1; + params.template get>()[mio::AgeGroup(0)] = 1; + + // Set vaccination data to 0 for all models + params.template get>().resize(mio::SimulationDay(num_days + 1)); + params.template get>().resize(mio::SimulationDay(num_days + 1)); + params.template get>().resize(mio::SimulationDay(num_days + 1)); + for (auto d = mio::SimulationDay(0); d < mio::SimulationDay(num_days + 1); ++d) { + for (auto a = mio::AgeGroup(0); a < params.get_num_groups(); ++a) { + params.template get>()[{a, d}] = 0.0; + params.template get>()[{a, d}] = 0.0; + params.template get>()[{a, d}] = 0.0; + } + } // create simple vaccination data std::vector vacc_data = { @@ -1135,9 +1160,8 @@ TEST(TestOdeSECIRTS, set_vaccination_data_min_date_not_avail) // simulation date before vaccination data mio::Date earlier_date(2021, 1, 1); - std::vector region = {0}; - auto result = mio::osecirts::details::set_vaccination_data(model_vector, vacc_data, earlier_date, region, num_days); + auto result = mio::osecirts::details::set_vaccination_data(model, vacc_data, earlier_date, num_days); ASSERT_THAT(result, IsSuccess()); // check that vaccinations are set to zero for all days and age groups @@ -1163,19 +1187,19 @@ TEST(TestOdeSECIRTS, parameter_percentiles) //build small graph auto model = make_model(5); - auto graph = mio::Graph, mio::MobilityParameters>(); + auto graph = mio::Graph>(); graph.add_node(0, model); //sample a few times - auto sampled_graphs = std::vector, mio::MobilityParameters>>(); + auto sampled_graphs = std::vector>>(); std::generate_n(std::back_inserter(sampled_graphs), 10, [&graph]() { return mio::osecirts::draw_sample(graph); }); //extract nodes from graph - auto sampled_nodes = std::vector>>(); + auto sampled_nodes = std::vector>(); std::transform(sampled_graphs.begin(), sampled_graphs.end(), std::back_inserter(sampled_nodes), [](auto&& g) { - auto models = std::vector>(); + auto models = std::vector(); std::transform(g.nodes().begin(), g.nodes().end(), std::back_inserter(models), [](auto&& n) { return n.property; }); @@ -1189,7 +1213,7 @@ TEST(TestOdeSECIRTS, parameter_percentiles) auto p = double(percentile_params.get>()[mio::AgeGroup(2)]); auto samples = std::vector(); std::transform(sampled_nodes.begin(), sampled_nodes.end(), std::back_inserter(samples), - [](const std::vector>& nodes) { + [](const std::vector& nodes) { return nodes[0].parameters.get>()[mio::AgeGroup(2)]; }); @@ -1199,7 +1223,7 @@ TEST(TestOdeSECIRTS, parameter_percentiles) p = double(percentile_params.get>()[mio::AgeGroup(2)]); samples = std::vector(); std::transform(sampled_nodes.begin(), sampled_nodes.end(), std::back_inserter(samples), - [](const std::vector>& nodes) { + [](const std::vector& nodes) { return nodes[0].parameters.get>()[mio::AgeGroup(2)]; }); std::nth_element(samples.begin(), samples.begin() + 6, samples.end()); @@ -1315,7 +1339,7 @@ TEST(TestOdeSECIRTS, test_commuters) TEST(TestOdeSECIRTS, check_constraints_parameters) { - auto model = mio::osecirts::Model(1); + auto model = ModelT(1); ASSERT_EQ(model.parameters.check_constraints(), 0); mio::set_log_level(mio::LogLevel::off); @@ -1454,7 +1478,7 @@ TEST(TestOdeSECIRTS, check_constraints_parameters) TEST(TestOdeSECIRTS, apply_constraints_parameters) { const double tol_times = 1e-1; - auto model = mio::osecirts::Model(1); + auto model = ModelT(1); auto indx_agegroup = mio::AgeGroup(0); EXPECT_EQ(model.parameters.apply_constraints(), 0); @@ -1598,7 +1622,7 @@ TEST(TestOdeSECIRTS, apply_constraints_parameters) TEST(TestOdeSECIRTS, apply_variant_function) { - auto model = mio::osecirts::Model(1); + auto model = ModelT(1); model.parameters.set>(0.2); model.parameters.set>(0); diff --git a/cpp/tests/test_odesecirvvs.cpp b/cpp/tests/test_odesecirvvs.cpp index 838b15ed2b..eb2e858bed 100755 --- a/cpp/tests/test_odesecirvvs.cpp +++ b/cpp/tests/test_odesecirvvs.cpp @@ -51,13 +51,15 @@ #include #include +using ModelT = mio::osecirvvs::Model; + TEST(TestOdeSECIRVVS, simulateDefault) { double t0 = 0; double tmax = 1; double dt = 0.1; - mio::osecirvvs::Model model(1); + ModelT model(1); model.populations.set_total(10); model.populations.set_difference_from_total({(mio::AgeGroup)0, mio::osecirvvs::InfectionState::SusceptibleNaive}, 10); @@ -75,7 +77,7 @@ TEST(TestOdeSECIRVVS, reduceToSecirAndCompareWithPreviousRun) // double t0 = 0; // double tmax = 50; - mio::osecirvvs::Model model(1); + ModelT model(1); double nb_total_t0 = 10000, nb_exp_t0 = 100, nb_inf_t0 = 50, nb_car_t0 = 50, nb_hosp_t0 = 20, nb_icu_t0 = 10, nb_rec_t0 = 10; @@ -204,7 +206,7 @@ void array_assign_uniform_distribution(mio::CustomIndexArray::Populations& populations, +void set_synthetic_population_data(ModelT::Populations& populations, bool set_invalid_initial_value) { for (mio::AgeGroup i = 0; i < mio::get(populations.size()); i++) { @@ -266,7 +268,7 @@ void set_synthetic_population_data(mio::osecirvvs::Model::Populations& p } } -void set_demographic_parameters(mio::osecirvvs::Model::ParameterSet& parameters, bool set_invalid_initial_value) +void set_demographic_parameters(ModelT::ParameterSet& parameters, bool set_invalid_initial_value) { assign_uniform_distribution(parameters.get>(), 20, 50, set_invalid_initial_value); @@ -276,7 +278,7 @@ void set_demographic_parameters(mio::osecirvvs::Model::ParameterSet& par parameters.get>().array().setConstant(3); } -void set_contact_parameters(mio::osecirvvs::Model::ParameterSet& parameters, bool set_invalid_initial_value) +void set_contact_parameters(ModelT::ParameterSet& parameters, bool set_invalid_initial_value) { auto& contacts = parameters.get>(); auto& contact_matrix = contacts.get_cont_freq_mat(); @@ -297,7 +299,7 @@ void set_contact_parameters(mio::osecirvvs::Model::ParameterSet& paramet parameters.template get>() = 7; } -void set_covid_parameters(mio::osecirvvs::Model::ParameterSet& params, bool set_invalid_initial_value) +void set_covid_parameters(ModelT::ParameterSet& params, bool set_invalid_initial_value) { //times const double timeExposedMin = 2.67; @@ -415,10 +417,10 @@ void set_covid_parameters(mio::osecirvvs::Model::ParameterSet& params, b set_invalid_initial_value); } -mio::osecirvvs::Model make_model(int num_age_groups, bool set_invalid_initial_value = false) +ModelT make_model(int num_age_groups, bool set_invalid_initial_value = false) { assert(num_age_groups <= 6 && "Provide more values in functions above to test more age groups."); - mio::osecirvvs::Model model(num_age_groups); + ModelT model(num_age_groups); set_covid_parameters(model.parameters, set_invalid_initial_value); set_synthetic_population_data(model.populations, set_invalid_initial_value); set_demographic_parameters(model.parameters, set_invalid_initial_value); @@ -431,7 +433,7 @@ TEST(TestOdeSECIRVVS, draw_sample) { mio::log_thread_local_rng_seeds(mio::LogLevel::warn); - mio::Graph, mio::MobilityParameters> graph; + mio::Graph> graph; auto num_age_groups = 6; //create model with invalid initials so the test fails if no sampling is done @@ -513,58 +515,53 @@ TEST(TestOdeSECIRVVS, checkPopulationConservation) TEST(TestOdeSECIRVVS, read_confirmed_cases) { auto num_age_groups = 6; //reading data requires RKI data age groups - auto model = std::vector>({make_model(num_age_groups)}); - std::vector region{1002}; + ModelT model = make_model(num_age_groups); + const int region = 1002; auto path = mio::path_join(TEST_DATA_DIR, "Germany/pydata/cases_all_county_age_ma7.json"); - std::vector> t_Exposed(1); - std::vector> t_InfectedNoSymptoms(1); - std::vector> t_InfectedSymptoms(1); - std::vector> t_InfectedSevere(1); - std::vector> t_InfectedCritical(1); - - std::vector> mu_C_R(1); - std::vector> mu_I_H(1); - std::vector> mu_H_U(1); - - std::vector> num_InfectedSymptoms(1); - std::vector> num_death(1); - std::vector> num_rec(1); - std::vector> num_Exposed(1); - std::vector> num_InfectedNoSymptoms(1); - std::vector> num_InfectedSevere(1); - std::vector> num_icu(1); - - num_InfectedSymptoms[0] = std::vector(num_age_groups, 0.0); - num_death[0] = std::vector(num_age_groups, 0.0); - num_rec[0] = std::vector(num_age_groups, 0.0); - num_Exposed[0] = std::vector(num_age_groups, 0.0); - num_InfectedNoSymptoms[0] = std::vector(num_age_groups, 0.0); - num_InfectedSevere[0] = std::vector(num_age_groups, 0.0); - num_icu[0] = std::vector(num_age_groups, 0.0); + std::vector t_Exposed; + std::vector t_InfectedNoSymptoms; + std::vector t_InfectedSymptoms; + std::vector t_InfectedSevere; + std::vector t_InfectedCritical; + + std::vector mu_C_R; + std::vector mu_I_H; + std::vector mu_H_U; + + std::vector num_InfectedSymptoms(num_age_groups, 0.0); + std::vector num_death(num_age_groups, 0.0); + std::vector num_rec(num_age_groups, 0.0); + std::vector num_Exposed(num_age_groups, 0.0); + std::vector num_InfectedNoSymptoms(num_age_groups, 0.0); + std::vector num_InfectedSevere(num_age_groups, 0.0); + std::vector num_icu(num_age_groups, 0.0); + for (size_t group = 0; group < static_cast(num_age_groups); group++) { - t_Exposed[0].push_back(static_cast( - std::round(model[0].parameters.template get>()[(mio::AgeGroup)group]))); - t_InfectedNoSymptoms[0].push_back(static_cast(std::round( - model[0].parameters.template get>()[(mio::AgeGroup)group]))); - t_InfectedSymptoms[0].push_back(static_cast(std::round( - model[0].parameters.template get>()[(mio::AgeGroup)group]))); - t_InfectedSevere[0].push_back(static_cast(std::round( - model[0].parameters.template get>()[(mio::AgeGroup)group]))); - t_InfectedCritical[0].push_back(static_cast(std::round( - model[0].parameters.template get>()[(mio::AgeGroup)group]))); - - mu_C_R[0].push_back(model[0].parameters.template get>()[( + t_Exposed.push_back(static_cast( + std::round(model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedNoSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedSymptoms.push_back(static_cast(std::round( + model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedSevere.push_back(static_cast(std::round( + model.parameters.template get>()[(mio::AgeGroup)group]))); + t_InfectedCritical.push_back(static_cast(std::round( + model.parameters.template get>()[(mio::AgeGroup)group]))); + + mu_C_R.push_back(model.parameters.template get>()[( mio::AgeGroup)group]); - mu_I_H[0].push_back( - model[0] - .parameters.template get>()[(mio::AgeGroup)group]); - mu_H_U[0].push_back( - model[0].parameters.template get>()[(mio::AgeGroup)group]); + mu_I_H.push_back( + model.parameters.template get>()[(mio::AgeGroup)group]); + mu_H_U.push_back( + model.parameters.template get>()[(mio::AgeGroup)group]); } - auto read = mio::osecirvvs::details::read_confirmed_cases_data( - path, region, {2020, 12, 01}, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, + auto case_data = + mio::read_confirmed_cases_data(path).value(); + + auto read = mio::osecirvvs::details::compute_confirmed_cases_data( + case_data, region, {2020, 12, 01}, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_rec, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, mu_C_R, mu_I_H, mu_H_U, std::vector(size_t(num_age_groups), 1.0)); @@ -574,14 +571,17 @@ TEST(TestOdeSECIRVVS, read_confirmed_cases) TEST(TestOdeSECIRVVS, set_divi_data_invalid_dates) { mio::set_log_level(mio::LogLevel::off); - auto model = mio::osecirvvs::Model(1); + auto model = ModelT(1); model.populations.array().setConstant(1); - auto model_vector = std::vector>{model}; + auto model_vector = std::vector>{mio::Node(1001, model)}; // Test with date before DIVI dataset was available. - EXPECT_THAT(mio::osecirvvs::details::set_divi_data(model_vector, "", {1001}, {2019, 12, 01}, 1.0), IsSuccess()); + EXPECT_THAT(mio::osecirvvs::details::set_divi_data(mio::make_range(model_vector.begin(), model_vector.end()), + "", {2019, 12, 01}, 1.0), + IsSuccess()); + // Assure that populations is the same as before. - EXPECT_THAT(print_wrap(model_vector[0].populations.array().cast()), + EXPECT_THAT(print_wrap(model_vector[0].property.populations.array().cast()), MatrixNear(print_wrap(model.populations.array().cast()), 1e-10, 1e-10)); mio::set_log_level(mio::LogLevel::warn); @@ -590,7 +590,7 @@ TEST(TestOdeSECIRVVS, set_divi_data_invalid_dates) TEST(TestOdeSECIRVVS, set_confirmed_cases_data_with_ICU) { const auto num_age_groups = 6; - auto model = mio::osecirvvs::Model(num_age_groups); + auto model = ModelT(num_age_groups); model.populations.array().setConstant(1); // set params @@ -620,10 +620,9 @@ TEST(TestOdeSECIRVVS, set_confirmed_cases_data_with_ICU) auto mid_day = case_data[(size_t)case_data.size() / 2].date; // calculate ICU values using set_confirmed_cases_data - auto model_vector = std::vector>{model}; auto scaling_factor_inf = std::vector(size_t(model.parameters.get_num_groups()), 1.0); EXPECT_THAT( - mio::osecirvvs::details::set_confirmed_cases_data(model_vector, case_data, {1002}, mid_day, scaling_factor_inf), + mio::osecirvvs::details::set_confirmed_cases_data(model, case_data, 1002, mid_day, scaling_factor_inf), IsSuccess()); // Since, TimeInfectedCritical is 1, the number of ICU cases is the difference of confirmed cases between two days, which is 1. @@ -632,19 +631,19 @@ TEST(TestOdeSECIRVVS, set_confirmed_cases_data_with_ICU) const auto expected_value = (i == 2) ? 1.0 : 0.0; auto actual_value_naive = - model_vector[0] + model .populations[{mio::AgeGroup(i), mio::osecirvvs::InfectionState::InfectedCriticalNaive}] .value(); EXPECT_NEAR(actual_value_naive, expected_value, 1e-10); auto actual_value_pi = - model_vector[0] + model .populations[{mio::AgeGroup(i), mio::osecirvvs::InfectionState::InfectedCriticalPartialImmunity}] .value(); EXPECT_NEAR(actual_value_pi, expected_value, 1e-10); auto actual_value_ii = - model_vector[0] + model .populations[{mio::AgeGroup(i), mio::osecirvvs::InfectionState::InfectedCriticalImprovedImmunity}] .value(); EXPECT_NEAR(actual_value_ii, expected_value, 1e-10); @@ -654,25 +653,23 @@ TEST(TestOdeSECIRVVS, set_confirmed_cases_data_with_ICU) TEST(TestOdeSECIRVVS, read_data) { auto num_age_groups = 6; //reading data requires RKI data age groups - auto model1 = std::vector>({make_model(num_age_groups)}); - auto model2 = std::vector>({make_model(num_age_groups)}); - auto model3 = std::vector>({make_model(num_age_groups)}); - - const auto pydata_dir_District = mio::path_join(TEST_DATA_DIR, "District", "pydata"); - - auto read_result1 = mio::osecirvvs::read_input_data_county(model1, {2020, 12, 01}, {1002}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_GERMANY_PYDATA_DIR, 30); - - auto read_result2 = mio::osecirvvs::read_input_data(model2, {2020, 12, 01}, {1002}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_GERMANY_PYDATA_DIR, 30); - - auto read_result_district = mio::osecirvvs::read_input_data( - model3, {2020, 12, 01}, {1002}, std::vector(size_t(num_age_groups), 1.0), 1.0, pydata_dir_District, 30); + auto model = make_model(num_age_groups); + auto model1 = std::vector>{mio::Node(1002, model)}; + auto model2 = std::vector>{mio::Node(1002, model)}; + + auto pydata_germany_path = std::string(TEST_GERMANY_PYDATA_DIR); + auto read_result1 = + mio::osecirvvs::read_input_data(mio::make_range(model1.begin(), model1.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 30, + mio::regions::de::EpidataFilenames::county(pydata_germany_path)); + + auto pydata_district_path = mio::path_join(TEST_DATA_DIR, "District", "pydata"); + auto read_result_district = + mio::osecirvvs::read_input_data(mio::make_range(model2.begin(), model2.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 30, + mio::regions::de::EpidataFilenames::county(pydata_district_path)); ASSERT_THAT(read_result1, IsSuccess()); - ASSERT_THAT(read_result2, IsSuccess()); ASSERT_THAT(read_result_district, IsSuccess()); // values were generated by the tested function; can only check stability of the implementation, not correctness @@ -692,122 +689,84 @@ TEST(TestOdeSECIRVVS, read_data) 0.00442784, 4.67895, 0.00764769, 0.0729502, 2253.25, 0, 0, 0) .finished(); - ASSERT_THAT(print_wrap(model1[0].populations.array().cast()), - MatrixNear(print_wrap(model2[0].populations.array().cast()), 1e-5, 1e-5)); + ASSERT_THAT(print_wrap(model1[0].property.populations.array().cast()), + MatrixNear(print_wrap(model2[0].property.populations.array().cast()), 1e-5, 1e-5)); - ASSERT_THAT(print_wrap(model1[0].populations.array().cast()), - MatrixNear(print_wrap(model3[0].populations.array().cast()), 1e-5, 1e-5)); - - ASSERT_THAT(print_wrap(model1[0].populations.array().cast()), - MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); - ASSERT_THAT(print_wrap(model2[0].populations.array().cast()), + ASSERT_THAT(print_wrap(model1[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); - ASSERT_THAT(print_wrap(model3[0].populations.array().cast()), + ASSERT_THAT(print_wrap(model2[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); // some more tests which are actually not necessary but can help if the previous tests fails or needs to get changed - for (mio::AgeGroup i = 0; i < model1[0].parameters.get_num_groups(); i++) { - EXPECT_GE(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaive}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaive}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaive}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaive}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaive}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaive}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunity}]), - 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunity}]), + for (mio::AgeGroup i = 0; i < model1[0].property.parameters.get_num_groups(); i++) { + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaive}]), 0); + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaive}]), 0); + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaive}]), 0); + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaive}]), 0); + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunity}]), + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunity}]), 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunity}]), - 0); - EXPECT_GE( - double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunity}]), 0); EXPECT_GE( - double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunity}]), 0); + double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunity}]), 0); EXPECT_GE( - double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunity}]), 0); - EXPECT_GE(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunity}]), + double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunity}]), 0); + EXPECT_GE(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunity}]), 0); - EXPECT_GE(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunity}]), - 0); - EXPECT_GE(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunity}]), + EXPECT_GE(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunity}]), 0); // currently dead and confirmed after commuting compartments are initialized as zero - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), - 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaiveConfirmed}]), + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaiveConfirmed}]), + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaiveConfirmed}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsNaiveConfirmed}]), - 0); - EXPECT_EQ( - double( - model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), - 0); - EXPECT_EQ( - double( - model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), - 0); EXPECT_EQ( double( - model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), + model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( double( - model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), + model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( double( - model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), + model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( double( - model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), + model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsPartialImmunityConfirmed}]), 0); EXPECT_EQ( double(model1[0] - .populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), + .property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), 0); EXPECT_EQ( double(model2[0] - .populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), - 0); - EXPECT_EQ( - double(model3[0] - .populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), - 0); - EXPECT_EQ( - double( - model1[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), + .property.populations[{i, mio::osecirvvs::InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}]), 0); EXPECT_EQ( double( - model2[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), + model1[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), 0); EXPECT_EQ( double( - model3[0].populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), + model2[0].property.populations[{i, mio::osecirvvs::InfectionState::InfectedSymptomsImprovedImmunityConfirmed}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::DeadNaive}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::DeadNaive}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::DeadNaive}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::DeadPartialImmunity}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::DeadPartialImmunity}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::DeadPartialImmunity}]), 0); - EXPECT_EQ(double(model1[0].populations[{i, mio::osecirvvs::InfectionState::DeadImprovedImmunity}]), 0); - EXPECT_EQ(double(model2[0].populations[{i, mio::osecirvvs::InfectionState::DeadImprovedImmunity}]), 0); - EXPECT_EQ(double(model3[0].populations[{i, mio::osecirvvs::InfectionState::DeadImprovedImmunity}]), 0); + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::DeadNaive}]), 0); + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::DeadNaive}]), 0); + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::DeadPartialImmunity}]), 0); + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::DeadPartialImmunity}]), 0); + EXPECT_EQ(double(model1[0].property.populations[{i, mio::osecirvvs::InfectionState::DeadImprovedImmunity}]), 0); + EXPECT_EQ(double(model2[0].property.populations[{i, mio::osecirvvs::InfectionState::DeadImprovedImmunity}]), 0); } } @@ -818,16 +777,14 @@ TEST(TestOdeSECIRVVS, export_time_series_init) ASSERT_THAT(mio::create_directory(tmp_results_dir), IsSuccess()); auto num_age_groups = 6; // Data to be read requires RKI confirmed cases data age groups - auto model = make_model(num_age_groups); + std::vector> model{mio::Node(0, make_model(num_age_groups))}; + std::string pydata_test_dir = TEST_DATA_DIR; // Test exporting time series - ASSERT_THAT(mio::osecirvvs::export_input_data_county_timeseries( - std::vector>{model}, tmp_results_dir, {0}, {2020, 12, 01}, - std::vector(size_t(num_age_groups), 1.0), 1.0, 2, - mio::path_join(TEST_DATA_DIR, "county_divi_ma7.json"), - mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), - mio::path_join(TEST_DATA_DIR, "county_current_population.json"), - mio::path_join(TEST_DATA_DIR, "vacc_county_ageinf_ma7.json")), + ASSERT_THAT(mio::osecirvvs::export_input_data_timeseries( + mio::make_range(model.begin(), model.end()), tmp_results_dir, {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 2, + mio::regions::de::EpidataFilenames::county(pydata_test_dir)), IsSuccess()); auto data_extrapolated = mio::read_result(mio::path_join(tmp_results_dir, "Results_rki.h5")); @@ -850,22 +807,20 @@ TEST(TestOdeSECIRVVS, export_time_series_init_old_date) ASSERT_THAT(mio::create_directory(tmp_results_dir), IsSuccess()); auto num_age_groups = 6; // Data to be read requires RKI confirmed cases data age groups - auto model = make_model(num_age_groups); + std::vector> model{mio::Node(0, make_model(num_age_groups))}; // set vaccinations to zero - model.parameters.get>().array().setConstant(0); - model.parameters.get>().array().setConstant(0); + model[0].property.parameters.get>().array().setConstant(0); + model[0].property.parameters.get>().array().setConstant(0); // set all compartments to zero - model.populations.array().setConstant(0.0); + model[0].property.populations.array().setConstant(0.0); + std::string pydata_test_dir = TEST_DATA_DIR; // Test exporting time series - ASSERT_THAT(mio::osecirvvs::export_input_data_county_timeseries( - std::vector>{model}, tmp_results_dir, {0}, {20, 12, 01}, - std::vector(size_t(num_age_groups), 1.0), 1.0, 0, - mio::path_join(TEST_DATA_DIR, "county_divi_ma7.json"), - mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), - mio::path_join(TEST_DATA_DIR, "county_current_population.json"), - mio::path_join(TEST_DATA_DIR, "vacc_county_ageinf_ma7.json")), + ASSERT_THAT(mio::osecirvvs::export_input_data_timeseries( + mio::make_range(model.begin(), model.end()), tmp_results_dir, {1000, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 2, + mio::regions::de::EpidataFilenames::county(pydata_test_dir)), IsSuccess()); auto data_extrapolated = mio::read_result(mio::path_join(tmp_results_dir, "Results_rki.h5")); @@ -893,13 +848,12 @@ TEST(TestOdeSECIRVVS, export_time_series_init_old_date) TEST(TestOdeSECIRVVS, model_initialization) { auto num_age_groups = 6; // Data to be read requires RKI confirmed cases data age groups - auto model = make_model(num_age_groups); - // Vector assignment necessary as read_input_data_county changes model - auto model_vector = std::vector>{model}; + std::vector> model_vector{mio::Node(0, make_model(num_age_groups))}; - ASSERT_THAT(mio::osecirvvs::read_input_data_county(model_vector, {2020, 12, 01}, {0}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_GERMANY_PYDATA_DIR, 30, false), + std::string pydata_germany_dir = TEST_GERMANY_PYDATA_DIR; + ASSERT_THAT(mio::osecirvvs::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 30, + mio::regions::de::EpidataFilenames::county(pydata_germany_dir)), IsSuccess()); // Values from data/export_time_series_init_osecirvvs.h5, for reading in comparison @@ -921,7 +875,7 @@ TEST(TestOdeSECIRVVS, model_initialization) 9.64602e-06, 4.75937, 1.66604e-05, 0.000158922, 2253.23, 0, 0, 0) .finished(); - ASSERT_THAT(print_wrap(model_vector[0].populations.array().cast()), + ASSERT_THAT(print_wrap(model_vector[0].property.populations.array().cast()), MatrixNear(print_wrap(expected_values), 1e-5, 1e-5)); } @@ -929,55 +883,18 @@ TEST(TestOdeSECIRVVS, model_initialization_old_date) { mio::set_log_level(mio::LogLevel::off); constexpr auto num_age_groups = 6; // Data to be read requires RKI confirmed cases data age groups - auto model = make_model(num_age_groups); - // set vaccinations to zero - model.parameters.get>().array().setConstant(0); - model.parameters.get>().array().setConstant(0); - // set all compartments to zero - model.populations.array().setConstant(0.0); - - auto model_vector = std::vector>{model}; - - ASSERT_THAT(mio::osecirvvs::read_input_data(model_vector, {100, 12, 01}, {0}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_GERMANY_PYDATA_DIR, 0, false), - IsSuccess()); - - // if we enter an old date, the model only should be initialized with the population data. - // read population data - std::string path = mio::path_join(TEST_DATA_DIR, "county_current_population.json"); - const std::vector region{0}; - auto population_data = mio::read_population_data(path, region).value(); - - // So, the expected values are the population data in the susceptible compartments and zeros in the other compartments. - for (auto i = 0; i < num_age_groups; i++) { - EXPECT_NEAR( - model_vector[0].populations.array().cast()(i * Eigen::Index(mio::osecirvvs::InfectionState::Count)), - population_data[0][i], 1e-5); - } - - // sum of all compartments should be equal to the population - EXPECT_NEAR(model_vector[0].populations.array().cast().sum(), - std::accumulate(population_data[0].begin(), population_data[0].end(), 0.0), 1e-5); - mio::set_log_level(mio::LogLevel::warn); -} + std::vector> model_vector{mio::Node(0, make_model(num_age_groups))}; -TEST(TestOdeSECIRVVS, model_initialization_old_date_county) -{ - mio::set_log_level(mio::LogLevel::off); - constexpr auto num_age_groups = 6; // Data to be read requires RKI confirmed cases data age groups - auto model = make_model(num_age_groups); // set vaccinations to zero - model.parameters.get>().array().setConstant(0); - model.parameters.get>().array().setConstant(0); + model_vector[0].property.parameters.get>().array().setConstant(0); + model_vector[0].property.parameters.get>().array().setConstant(0); // set all compartments to zero - model.populations.array().setConstant(0.0); - - auto model_vector = std::vector>{model}; + model_vector[0].property.populations.array().setConstant(0.0); - ASSERT_THAT(mio::osecirvvs::read_input_data_county(model_vector, {100, 12, 01}, {0}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - TEST_GERMANY_PYDATA_DIR, 0, false), + std::string pydata_germany_dir = TEST_GERMANY_PYDATA_DIR; + ASSERT_THAT(mio::osecirvvs::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {1000, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, 30, + mio::regions::de::EpidataFilenames::county(pydata_germany_dir)), IsSuccess()); // if we enter an old date, the model only should be initialized with the population data. @@ -989,12 +906,12 @@ TEST(TestOdeSECIRVVS, model_initialization_old_date_county) // So, the expected values are the population data in the susceptible compartments and zeros in the other compartments. for (auto i = 0; i < num_age_groups; i++) { EXPECT_NEAR( - model_vector[0].populations.array().cast()(i * Eigen::Index(mio::osecirvvs::InfectionState::Count)), + model_vector[0].property.populations.array().cast()(i * Eigen::Index(mio::osecirvvs::InfectionState::Count)), population_data[0][i], 1e-5); } // sum of all compartments should be equal to the population - EXPECT_NEAR(model_vector[0].populations.array().cast().sum(), + EXPECT_NEAR(model_vector[0].property.populations.array().cast().sum(), std::accumulate(population_data[0].begin(), population_data[0].end(), 0.0), 1e-5); mio::set_log_level(mio::LogLevel::warn); } @@ -1013,29 +930,29 @@ TEST(TestOdeSECIRVVS, set_population_data_overflow_vacc) model.parameters .template get>()[{mio::AgeGroup(0), mio::SimulationDay(0)}] = 1e7; - auto model_vector = std::vector>{model}; + std::vector> model_vector{mio::Node(1002, model)}; std::string path_pop_data = mio::path_join(TEST_DATA_DIR, "county_current_population.json"); - const std::vector region{0}; + const std::vector region{1002}; auto population_data = mio::read_population_data(path_pop_data, region).value(); // we choose the date so that no case data is available ASSERT_THAT(mio::osecirvvs::details::set_population_data( - model_vector, path_pop_data, mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), {0}, - {1000, 12, 01}), + mio::make_range(model_vector.begin(), model_vector.end()), path_pop_data, + mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), {1000, 12, 01}), IsSuccess()); EXPECT_NEAR( - double(model_vector[0].populations[{mio::AgeGroup(0), mio::osecirvvs::InfectionState::SusceptibleNaive}]), 0.0, + double(model_vector[0].property.populations[{mio::AgeGroup(0), mio::osecirvvs::InfectionState::SusceptibleNaive}]), 0.0, 1e-10); - EXPECT_NEAR(double(model_vector[0].populations[{mio::AgeGroup(0), + EXPECT_NEAR(double(model_vector[0].property.populations[{mio::AgeGroup(0), mio::osecirvvs::InfectionState::SusceptiblePartialImmunity}]), 1, 1e-10); - EXPECT_NEAR(double(model_vector[0].populations[{mio::AgeGroup(0), + EXPECT_NEAR(double(model_vector[0].property.populations[{mio::AgeGroup(0), mio::osecirvvs::InfectionState::SusceptibleImprovedImmunity}]), population_data[0][0] - 1, 1e-10); - EXPECT_NEAR(model_vector[0].populations.get_group_total(mio::AgeGroup(0)), population_data[0][0], 1e-9); + EXPECT_NEAR(model_vector[0].property.populations.get_group_total(mio::AgeGroup(0)), population_data[0][0], 1e-9); } TEST(TestOdeSECIRVVS, set_population_data_no_data_avail) @@ -1053,19 +970,17 @@ TEST(TestOdeSECIRVVS, set_population_data_no_data_avail) model.parameters .template get>()[{mio::AgeGroup(0), mio::SimulationDay(0)}] = 0; - auto model_vector = std::vector>{model}; + std::vector> model_vector{mio::Node(200, model)}; std::string path_pop_data = mio::path_join(TEST_DATA_DIR, "county_current_population.json"); - const std::vector region{0}; - auto population_data = mio::read_population_data(path_pop_data, region).value(); // we choose the date so that no case data is available ASSERT_THAT(mio::osecirvvs::details::set_population_data( - model_vector, path_pop_data, mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), {200}, - {1000, 12, 01}), - IsSuccess()); + mio::make_range(model_vector.begin(), model_vector.end()), path_pop_data, + mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), {1000, 12, 01}), + IsFailure(mio::StatusCode::InvalidValue)); - EXPECT_NEAR(model.populations.get_total(), 0.0, 1e-10); + EXPECT_NEAR(model_vector[0].property.populations.get_total(), 0.0, 1e-10); } TEST(TestOdeSECIRVVS, run_simulation) @@ -1088,11 +1003,11 @@ TEST(TestOdeSECIRVVS, set_vaccination_data_not_avail) { const auto num_age_groups = 2; const auto num_days = 5; - mio::osecirvvs::Model model(num_age_groups); - std::vector> model_vector = {model}; + ModelT model(num_age_groups); + std::vector> model_vector{mio::Node(1001, model)}; // Setup initial non-zero vaccination data - auto& params = model_vector[0].parameters; + auto& params = model_vector[0].property.parameters; params.get>().resize(mio::SimulationDay(num_days + 1)); params.get>().resize(mio::SimulationDay(num_days + 1)); @@ -1108,10 +1023,10 @@ TEST(TestOdeSECIRVVS, set_vaccination_data_not_avail) // Call set_vaccination_data with an unavailable date mio::Date unavailable_date(2019, 1, 1); // Date before vaccinations started - std::vector region = {1001}; std::string any_path = "dummy_vacc_path.json"; auto result = - mio::osecirvvs::details::set_vaccination_data(model_vector, any_path, unavailable_date, region, num_days); + mio::osecirvvs::details::set_vaccination_data(mio::make_range(model_vector.begin(), model_vector.end()), + any_path, unavailable_date, num_days); ASSERT_THAT(result, IsSuccess()); @@ -1133,23 +1048,32 @@ TEST(TestOdeSECIRVVS, set_vaccination_data_min_date_not_avail) // create model const auto num_age_groups = 1; const auto num_days = 5; - mio::osecirvvs::Model model(num_age_groups); - std::vector> model_vector = {model}; - auto& params = model_vector[0].parameters; + ModelT model(num_age_groups); + + auto& params = model.parameters; params.template get>()[mio::AgeGroup(0)] = 1; params.template get>()[mio::AgeGroup(0)] = 1; params.template get>()[mio::AgeGroup(0)] = 1; + // Set vaccination data to 0 for all models + params.template get>().resize(mio::SimulationDay(num_days + 1)); + params.template get>().resize(mio::SimulationDay(num_days + 1)); + for (auto d = mio::SimulationDay(0); d < mio::SimulationDay(num_days + 1); ++d) { + for (auto a = mio::AgeGroup(0); a < params.get_num_groups(); ++a) { + params.template get>()[{a, d}] = 0.0; + params.template get>()[{a, d}] = 0.0; + } + } + // create simple vaccination data std::vector vacc_data = { mio::VaccinationDataEntry{10.0, 5.0, 0.0, 0.0, mio::Date(2021, 1, 15), mio::AgeGroup(0), {}, {}, {}}}; // simulation date before vaccination data mio::Date earlier_date(2021, 1, 1); - std::vector region = {0}; auto result = - mio::osecirvvs::details::set_vaccination_data(model_vector, vacc_data, earlier_date, region, num_days); + mio::osecirvvs::details::set_vaccination_data(model, vacc_data, earlier_date, num_days); ASSERT_THAT(result, IsSuccess()); // check that vaccinations are set to zero for all days and age groups @@ -1173,19 +1097,19 @@ TEST(TestOdeSECIRVVS, parameter_percentiles) //build small graph auto model = make_model(5); - auto graph = mio::Graph, mio::MobilityParameters>(); + auto graph = mio::Graph>(); graph.add_node(0, model); //sample a few times - auto sampled_graphs = std::vector, mio::MobilityParameters>>(); + auto sampled_graphs = std::vector>>(); std::generate_n(std::back_inserter(sampled_graphs), 10, [&graph]() { return mio::osecirvvs::draw_sample(graph, true); }); //extract nodes from graph - auto sampled_nodes = std::vector>>(); + auto sampled_nodes = std::vector>(); std::transform(sampled_graphs.begin(), sampled_graphs.end(), std::back_inserter(sampled_nodes), [](auto&& g) { - auto models = std::vector>(); + auto models = std::vector(); std::transform(g.nodes().begin(), g.nodes().end(), std::back_inserter(models), [](auto&& n) { return n.property; }); @@ -1200,7 +1124,7 @@ TEST(TestOdeSECIRVVS, parameter_percentiles) auto samples = std::vector(); std::transform( sampled_nodes.begin(), sampled_nodes.end(), std::back_inserter(samples), - [](const std::vector>& nodes) { + [](const std::vector& nodes) { return nodes[0].parameters.get>()[mio::AgeGroup(2)]; }); @@ -1210,7 +1134,7 @@ TEST(TestOdeSECIRVVS, parameter_percentiles) p = double(percentile_params.get>()[mio::AgeGroup(2)]); samples = std::vector(); std::transform(sampled_nodes.begin(), sampled_nodes.end(), std::back_inserter(samples), - [](const std::vector>& nodes) { + [](const std::vector& nodes) { return nodes[0].parameters.get>()[mio::AgeGroup(2)]; }); std::nth_element(samples.begin(), samples.begin() + 6, samples.end()); @@ -1334,7 +1258,7 @@ TEST(TestOdeSECIRVVS, test_commuters) TEST(TestOdeSECIRVVS, population_zero_no_nan) { // initialize simple model with total population 0 - mio::osecirvvs::Model model(1); + ModelT model(1); model.populations.set_total(0.0); // call the get_flows function @@ -1351,7 +1275,7 @@ TEST(TestOdeSECIRVVS, population_zero_no_nan) TEST(TestOdeSECIRVVS, check_constraints_parameters) { - auto model = mio::osecirvvs::Model(1); + auto model = ModelT(1); EXPECT_EQ(model.parameters.check_constraints(), 0); mio::set_log_level(mio::LogLevel::off); @@ -1479,7 +1403,7 @@ TEST(TestOdeSECIRVVS, check_constraints_parameters) TEST(TestOdeSECIRVVS, apply_constraints_parameters) { const double tol_times = 1e-1; - auto model = mio::osecirvvs::Model(1); + auto model = ModelT(1); auto indx_agegroup = mio::AgeGroup(0); EXPECT_EQ(model.parameters.apply_constraints(), 0); @@ -1612,7 +1536,7 @@ TEST(TestOdeSECIRVVS, apply_constraints_parameters) TEST(TestOdeSECIRVVS, apply_variant_function) { - auto model = mio::osecirvvs::Model(1); + auto model = ModelT(1); model.parameters.set>(0.2); model.parameters.set>(0); diff --git a/cpp/tests/test_regions.cpp b/cpp/tests/test_regions.cpp index ec58b9d45a..ffcbf5b7d1 100644 --- a/cpp/tests/test_regions.cpp +++ b/cpp/tests/test_regions.cpp @@ -23,67 +23,67 @@ TEST(TestRegions, get_holidays) { - auto s1 = mio::regions::get_holidays(mio::regions::StateId(1), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s1 = mio::regions::de::get_holidays(mio::regions::de::StateId(1), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s1.size(), 1); ASSERT_EQ(s1[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 18))); - auto s2 = mio::regions::get_holidays(mio::regions::StateId(2), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s2 = mio::regions::de::get_holidays(mio::regions::de::StateId(2), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s2.size(), 1); ASSERT_EQ(s2[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 17))); - auto s4 = mio::regions::get_holidays(mio::regions::StateId(4), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s4 = mio::regions::de::get_holidays(mio::regions::de::StateId(4), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s4.size(), 1); ASSERT_EQ(s4[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s5 = mio::regions::get_holidays(mio::regions::StateId(5), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s5 = mio::regions::de::get_holidays(mio::regions::de::StateId(5), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s5.size(), 1); ASSERT_EQ(s5[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s6 = mio::regions::get_holidays(mio::regions::StateId(6), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s6 = mio::regions::de::get_holidays(mio::regions::de::StateId(6), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s6.size(), 1); ASSERT_EQ(s6[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 18))); - auto s7 = mio::regions::get_holidays(mio::regions::StateId(7), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s7 = mio::regions::de::get_holidays(mio::regions::de::StateId(7), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s7.size(), 1); ASSERT_EQ(s7[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 24))); - auto s8 = mio::regions::get_holidays(mio::regions::StateId(8), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s8 = mio::regions::de::get_holidays(mio::regions::de::StateId(8), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s8.size(), 1); ASSERT_EQ(s8[0], std::make_pair(mio::Date(2020, 10, 26), mio::Date(2020, 10, 31))); - auto s9 = mio::regions::get_holidays(mio::regions::StateId(9), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s9 = mio::regions::de::get_holidays(mio::regions::de::StateId(9), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s9.size(), 1); ASSERT_EQ(s9[0], std::make_pair(mio::Date(2020, 10, 31), mio::Date(2020, 11, 7))); - auto s10 = mio::regions::get_holidays(mio::regions::StateId(10), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s10 = mio::regions::de::get_holidays(mio::regions::de::StateId(10), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s10.size(), 1); ASSERT_EQ(s10[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 24))); - auto s11 = mio::regions::get_holidays(mio::regions::StateId(11), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s11 = mio::regions::de::get_holidays(mio::regions::de::StateId(11), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s11.size(), 1); ASSERT_EQ(s11[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s12 = mio::regions::get_holidays(mio::regions::StateId(12), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s12 = mio::regions::de::get_holidays(mio::regions::de::StateId(12), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s12.size(), 1); ASSERT_EQ(s12[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s13 = mio::regions::get_holidays(mio::regions::StateId(13), mio::Date(2020, 10, 1), mio::Date(2020, 11, 15)); + auto s13 = mio::regions::de::get_holidays(mio::regions::de::StateId(13), mio::Date(2020, 10, 1), mio::Date(2020, 11, 15)); ASSERT_EQ(s13.size(), 1); ASSERT_EQ(s13[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 11))); - auto s14 = mio::regions::get_holidays(mio::regions::StateId(14), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s14 = mio::regions::de::get_holidays(mio::regions::de::StateId(14), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s14.size(), 1); ASSERT_EQ(s14[0], std::make_pair(mio::Date(2020, 10, 19), mio::Date(2020, 11, 1))); - auto s15 = mio::regions::get_holidays(mio::regions::StateId(15), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s15 = mio::regions::de::get_holidays(mio::regions::de::StateId(15), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s15.size(), 1); ASSERT_EQ(s15[0], std::make_pair(mio::Date(2020, 10, 19), mio::Date(2020, 10, 25))); - auto s16 = mio::regions::get_holidays(mio::regions::StateId(16), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s16 = mio::regions::de::get_holidays(mio::regions::de::StateId(16), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s16.size(), 1); ASSERT_EQ(s16[0], std::make_pair(mio::Date(2020, 10, 17), mio::Date(2020, 10, 31))); - auto s3 = mio::regions::get_holidays(mio::regions::StateId(3), mio::Date(2020, 7, 30), mio::Date(2020, 12, 31)); + auto s3 = mio::regions::de::get_holidays(mio::regions::de::StateId(3), mio::Date(2020, 7, 30), mio::Date(2020, 12, 31)); ASSERT_EQ(s3.size(), 3); ASSERT_EQ(s3[0], std::make_pair(mio::Date(2020, 7, 16), mio::Date(2020, 8, 27))); ASSERT_EQ(s3[1], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 24))); @@ -92,8 +92,8 @@ TEST(TestRegions, get_holidays) TEST(TestRegions, get_state_id) { - ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(1001))), mio::regions::StateId(1)); - ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(2000))), mio::regions::StateId(2)); - ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(5970))), mio::regions::StateId(5)); - ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(9161))), mio::regions::StateId(9)); + ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(1001))), mio::regions::de::StateId(1)); + ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(2000))), mio::regions::de::StateId(2)); + ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(5970))), mio::regions::de::StateId(5)); + ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(9161))), mio::regions::de::StateId(9)); } diff --git a/cpp/tests/test_save_parameters.cpp b/cpp/tests/test_save_parameters.cpp index e08324a9ed..ba98b13546 100644 --- a/cpp/tests/test_save_parameters.cpp +++ b/cpp/tests/test_save_parameters.cpp @@ -255,7 +255,7 @@ TEST(TestSaveParameters, read_graph_without_edges) std::vector> models = {model, model}; std::vector ids = {0, 1}; auto graph_no_edges = - mio::create_graph_without_edges, mio::MobilityParameters>(models, ids); + mio::Graph, mio::MobilityParameters>(ids, models); auto write_status = mio::write_graph(graph_no_edges, tmp_results_dir); ASSERT_THAT(print_wrap(write_status), IsSuccess()); @@ -625,269 +625,6 @@ TEST(TestSaveParameters, json_graphs_write_read_compare) } } -TEST(TestSaveParameters, ReadPopulationDataRKIAges) -{ - std::vector> model(1, {6}); - model[0].apply_constraints(); - std::vector scaling_factor_inf(6, 1.0); - double scaling_factor_icu = 1.0; - mio::Date date(2020, 12, 10); - - std::string path = TEST_DATA_DIR; - - for (auto group = mio::AgeGroup(0); group < mio::AgeGroup(6); group++) { - model[0].parameters.get>()[group] = - 0.1 * ((size_t)group + 1); - model[0].parameters.get>()[group] = 0.11 * ((size_t)group + 1); - model[0].parameters.get>()[group] = 0.12 * ((size_t)group + 1); - } - - auto read_result = mio::osecir::read_input_data_germany(model, date, scaling_factor_inf, scaling_factor_icu, path); - ASSERT_THAT(print_wrap(read_result), IsSuccess()); - - std::vector sus = {3444279.56, 7666866.07, 18801541.51, 29518513.27, 16321649.37, 6072737.25}; - std::vector exp = {433.015, 1771.61, 8856.33, 14757.62, 7222.86, 6626.07}; - std::vector car = {434.444, 1772.14, 8724.49, 14386.90, 6995.14, 6307.14}; - std::vector inf = {375.429, 1393.43, 6007.14, 8438.71, 3377.57, 2421.57}; - std::vector hosp = {39.9614, 303.191, 1934.84, 3621.2, 1793.39, 1557.03}; - std::vector icu = {47.6813, 190.725, 429.132, 762.901, 1192.03, 1716.53}; - std::vector rec = {23135.58, 77174.17, 389914.56, 472390.20, 164273.23, 72435.15}; - std::vector death = {2, 4, 48, 1137.86, 8174.14, 18528.9}; - - for (size_t i = 0; i < 6; i++) { - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Susceptible}]), sus[i], 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Exposed}]), exp[i], 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedNoSymptoms}]), car[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSymptoms}]), inf[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSevere}]), hosp[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}]), icu[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Recovered}]), rec[i], 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Dead}]), death[i], 1e-1); - } - - EXPECT_NEAR(model[0].populations.get_total(), 83166695, 1e-6); -} - -TEST(TestSaveParameters, ReadPopulationDataStateAllAges) -{ - std::vector> model(1, {6}); - model[0].apply_constraints(); - std::vector scaling_factor_inf(6, 1.0); - double scaling_factor_icu = 1.0; - mio::Date date(2020, 12, 10); - - std::vector state = {1}; - - std::string path = TEST_DATA_DIR; - - for (auto group = mio::AgeGroup(0); group < mio::AgeGroup(6); group++) { - model[0].parameters.get>()[group] = - 0.1 * ((size_t)group + 1); - model[0].parameters.get>()[group] = 0.11 * ((size_t)group + 1); - model[0].parameters.get>()[group] = 0.12 * ((size_t)group + 1); - } - - auto read_result = - mio::osecir::read_input_data_state(model, date, state, scaling_factor_inf, scaling_factor_icu, path); - ASSERT_THAT(print_wrap(read_result), IsSuccess()); - - std::vector sus = {116699.98, 283936.40, 622935.07, 1042390.64, 606622.90, 213104.13}; - std::vector exp = {8.57143, 30.5357, 149.388, 228.809, 87.1429, 99.2857}; - std::vector car = {7.77778, 26.0714, 143.061, 217.143, 84.8571, 92.1429}; - std::vector inf = {7.00000, 18.7143, 97.7143, 122.000, 40.8571, 36.1429}; - std::vector hosp = {0.707143, 3.92857, 30.6429, 50.5371, 20.35, 19.9886}; - std::vector icu = {0.274725, 1.0989, 2.47253, 4.3956, 6.86813, 9.89011}; - std::vector rec = {385.36, 1192.59, 5328.66, 6331.18, 2109.05, 778.53}; - std::vector death = {0, 0, 0, 16.2857, 99.5714, 198.286}; - - for (size_t i = 0; i < 6; i++) { - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Susceptible}]), sus[i], 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Exposed}]), exp[i], 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedNoSymptoms}]), car[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSymptoms}]), inf[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSevere}]), hosp[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}]), icu[i], - 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Recovered}]), rec[i], 1e-1); - EXPECT_NEAR((model[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Dead}]), death[i], 1e-1); - } - - EXPECT_NEAR(model[0].populations.get_total(), 2903777, 1e-6); -} - -TEST(TestSaveParameters, ReadPopulationDataCountyAllAges) -{ - - std::vector> model1(1, {6}); - model1[0].apply_constraints(); - std::vector> model2(1, {6}); - model2[0].apply_constraints(); - std::vector> model3(1, {6}); - model3[0].apply_constraints(); - std::vector scaling_factor_inf(6, 1.0); - double scaling_factor_icu = 1.0; - mio::Date date(2020, 12, 10); - - std::vector county = {1002}; - - for (auto group = mio::AgeGroup(0); group < mio::AgeGroup(6); group++) { - model1[0].parameters.get>()[group] = - 0.1 * ((size_t)group + 1); - model1[0].parameters.get>()[group] = 0.11 * ((size_t)group + 1); - model1[0].parameters.get>()[group] = 0.12 * ((size_t)group + 1); - model2[0].parameters.get>()[group] = - 0.1 * ((size_t)group + 1); - model2[0].parameters.get>()[group] = 0.11 * ((size_t)group + 1); - model2[0].parameters.get>()[group] = 0.12 * ((size_t)group + 1); - model3[0].parameters.get>()[group] = - 0.1 * ((size_t)group + 1); - model3[0].parameters.get>()[group] = 0.11 * ((size_t)group + 1); - model3[0].parameters.get>()[group] = 0.12 * ((size_t)group + 1); - } - - auto read_result1 = mio::osecir::read_input_data_county(model1, date, county, scaling_factor_inf, - scaling_factor_icu, TEST_GERMANY_PYDATA_DIR); - auto read_result2 = mio::osecir::read_input_data(model2, date, county, scaling_factor_inf, scaling_factor_icu, - TEST_GERMANY_PYDATA_DIR); - auto read_result_district = mio::osecir::read_input_data( - model3, date, county, scaling_factor_inf, scaling_factor_icu, mio::path_join(TEST_DATA_DIR, "District/pydata")); - ASSERT_THAT(print_wrap(read_result1), IsSuccess()); - ASSERT_THAT(print_wrap(read_result2), IsSuccess()); - ASSERT_THAT(print_wrap(read_result_district), IsSuccess()); - - std::vector sus = {10284.66, 19086.96, 73805.00, 82515.81, 43739.68, 15633.34}; - std::vector exp = {0.571429, 4.82143, 20.8163, 22.1429, 4.57143, 4.64286}; - std::vector car = {0.557143, 4.46429, 22.0408, 20.7143, 4.28571, 4.64286}; - std::vector inf = {0.42857, 3.285714, 15.2857, 13.0000, 2.42857, 2.00000}; - std::vector hosp = {0.0942857, 0.691429, 4.90286, 5.34286, 1.41429, 2.45143}; - std::vector icu = {0.0769231, 0.307692, 0.692308, 1.23077, 1.92308, 2.76923}; - std::vector rec = {34.47, 104.47, 618.26, 552.43, 165.83, 54.93}; - std::vector death = {0, 0, 0, 0, 10, 14.4286}; - - for (size_t i = 0; i < 6; i++) { - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Susceptible}]), sus[i], - 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Susceptible}]), sus[i], - 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Susceptible}]), sus[i], - 1e-1); - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Exposed}]), exp[i], 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Exposed}]), exp[i], 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Exposed}]), exp[i], 1e-1); - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedNoSymptoms}]), - car[i], 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedNoSymptoms}]), - car[i], 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedNoSymptoms}]), - car[i], 1e-1); - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSymptoms}]), inf[i], - 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSymptoms}]), inf[i], - 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSymptoms}]), inf[i], - 1e-1); - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSevere}]), hosp[i], - 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSevere}]), hosp[i], - 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedSevere}]), hosp[i], - 1e-1); - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}]), icu[i], - 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}]), icu[i], - 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::InfectedCritical}]), icu[i], - 1e-1); - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Recovered}]), rec[i], 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Recovered}]), rec[i], 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Recovered}]), rec[i], 1e-1); - EXPECT_NEAR((model1[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Dead}]), death[i], 1e-1); - EXPECT_NEAR((model2[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Dead}]), death[i], 1e-1); - EXPECT_NEAR((model3[0].populations[{mio::AgeGroup(i), mio::osecir::InfectionState::Dead}]), death[i], 1e-1); - } - - EXPECT_NEAR(model1[0].populations.get_total(), 246793, 1e-6); - EXPECT_NEAR(model2[0].populations.get_total(), 246793, 1e-6); - EXPECT_NEAR(model3[0].populations.get_total(), 246793, 1e-6); -} - -TEST(TestSaveParameters, ExtrapolateRKI) -{ - std::vector> model{mio::osecir::Model(6)}; - - model[0].apply_constraints(); - std::vector scaling_factor_inf(6, 1.0); - double scaling_factor_icu = 1.0; - mio::Date date(2020, 12, 10); - - std::vector county = {1002}; - - for (auto group = mio::AgeGroup(0); group < mio::AgeGroup(6); group++) { - model[0].parameters.get>()[group] = - 0.1 * ((size_t)group + 1); - model[0].parameters.get>()[group] = 0.11 * ((size_t)group + 1); - model[0].parameters.get>()[group] = 0.12 * ((size_t)group + 1); - } - - TempFileRegister file_register; - auto results_dir = file_register.get_unique_path("ExtrapolateRKI-%%%%-%%%%"); - boost::filesystem::create_directory(results_dir); - auto extrapolate_result = mio::osecir::export_input_data_county_timeseries( - model, results_dir, county, date, scaling_factor_inf, scaling_factor_icu, 1, - mio::path_join(TEST_DATA_DIR, "county_divi_ma7.json"), - mio::path_join(TEST_DATA_DIR, "cases_all_county_age_ma7.json"), - mio::path_join(TEST_DATA_DIR, "county_current_population.json")); - ASSERT_THAT(print_wrap(extrapolate_result), IsSuccess()); - - auto read_result = mio::read_result(mio::path_join(results_dir, "Results_rki.h5")); - ASSERT_THAT(print_wrap(read_result), IsSuccess()); - auto& file_results = read_result.value(); - auto results = file_results[0].get_groups(); - - std::vector sus = {10284.66, 19086.96, 73805.00, 82515.81, 43739.68, 15633.34}; - std::vector exp = {0.571429, 4.82143, 20.8163, 22.1429, 4.57143, 4.64286}; - std::vector car = {0.557143, 4.46429, 22.0408, 20.7143, 4.28571, 4.64286}; - std::vector inf = {0.428571, 3.28571, 15.2857, 13.0000, 2.42857, 2.00000}; - std::vector hosp = {0.0942857, 0.691429, 4.90286, 5.34286, 1.41429, 2.45143}; - std::vector icu = {0.0769231, 0.307692, 0.692308, 1.23077, 1.92308, 2.76923}; - std::vector rec = {34.47, 104.47, 618.26, 552.43, 165.83, 54.93}; - std::vector death = {0, 0, 0, 0, 10, 14.4286}; - - for (size_t i = 0; i < 6; i++) { - EXPECT_NEAR(results[0]((size_t)mio::osecir::InfectionState::Susceptible + - (size_t)mio::osecir::InfectionState::Count * i), - sus[i], 1e-1); - EXPECT_NEAR( - results[0]((size_t)mio::osecir::InfectionState::Exposed + (size_t)mio::osecir::InfectionState::Count * i), - exp[i], 1e-1); - EXPECT_NEAR(results[0]((size_t)mio::osecir::InfectionState::InfectedNoSymptoms + - (size_t)mio::osecir::InfectionState::Count * i), - car[i], 1e-1); - EXPECT_NEAR(results[0]((size_t)mio::osecir::InfectionState::InfectedSymptoms + - (size_t)mio::osecir::InfectionState::Count * i), - inf[i], 1e-1); - EXPECT_NEAR(results[0]((size_t)mio::osecir::InfectionState::InfectedSevere + - (size_t)mio::osecir::InfectionState::Count * i), - hosp[i], 1e-1); - EXPECT_NEAR(results[0]((size_t)mio::osecir::InfectionState::InfectedCritical + - (size_t)mio::osecir::InfectionState::Count * i), - icu[i], 1e-1); - EXPECT_NEAR( - results[0]((size_t)mio::osecir::InfectionState::Recovered + (size_t)mio::osecir::InfectionState::Count * i), - rec[i], 1e-1); - EXPECT_NEAR( - results[0]((size_t)mio::osecir::InfectionState::Dead + (size_t)mio::osecir::InfectionState::Count * i), - death[i], 1e-1); - } -} - TEST(TestSaveParameters, json_write_read_parameters_secirvvs) { mio::osecirvvs::Model model(2); From 0e0c23aea0215beb90e474d0ea514b483b4f009e Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 24 Nov 2025 13:54:05 +0000 Subject: [PATCH 11/26] Fix osecirts tests --- cpp/memilio/mobility/graph.h | 2 +- cpp/models/ode_secirts/parameters_io.cpp | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index 77985452de..854063015c 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -180,7 +180,7 @@ class Graph template requires std::constructible_from Graph(const int number_of_nodes, Args&&... args) { - for (auto id = size_t(0); id < number_of_nodes; ++id) { + for (int id = 0; id < number_of_nodes; ++id) { add_node(id, std::forward(args)...); } } diff --git a/cpp/models/ode_secirts/parameters_io.cpp b/cpp/models/ode_secirts/parameters_io.cpp index 57965cdaf5..949777822f 100644 --- a/cpp/models/ode_secirts/parameters_io.cpp +++ b/cpp/models/ode_secirts/parameters_io.cpp @@ -289,8 +289,8 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec BOOST_OUTCOME_TRY(compute_confirmed_cases_data( case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, - t_imm_interval_i, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, - mu_H_U, scaling_factor_inf, 0)); + t_imm_interval_i, mu_C_R, mu_I_H, mu_H_U, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, + reduc_icu_death, scaling_factor_inf, 0)); size_t num_groups = (size_t)model.parameters.get_num_groups(); for (size_t i = 0; i < num_groups; i++) { @@ -344,8 +344,9 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec BOOST_OUTCOME_TRY(compute_confirmed_cases_data( case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm1, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, - t_imm_interval_i, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, - mu_H_U, scaling_factor_inf, 1)); + t_imm_interval_i, mu_C_R, mu_I_H, mu_H_U, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, + reduc_icu_death, scaling_factor_inf, 1)); + for (size_t i = 0; i < num_groups; i++) { model.populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] = immunity_population[1][i] * @@ -414,8 +415,8 @@ IOResult set_confirmed_cases_data(Model& model, const std::vec BOOST_OUTCOME_TRY(compute_confirmed_cases_data( case_data, region, date, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms, num_InfectedSevere, num_icu, num_death, num_timm2, t_Exposed, t_InfectedNoSymptoms, t_InfectedSymptoms, t_InfectedSevere, t_InfectedCritical, - t_imm_interval_i, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, reduc_icu_death, mu_C_R, mu_I_H, - mu_H_U, scaling_factor_inf, 2)); + t_imm_interval_i, mu_C_R, mu_I_H, mu_H_U, reduc_t_Infected, reduc_Exposed, reduc_InfectedSymptoms, + reduc_icu_death, scaling_factor_inf, 2)); for (size_t i = 0; i < num_groups; i++) { model.populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] = From 3b3c6288ff6664349b508519298684eb56123a40 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:12:21 +0000 Subject: [PATCH 12/26] Change test data of export time series --- ...rt_time_series_initialization_osecirvvs.h5 | Bin 9120 -> 9120 bytes cpp/tests/test_odesecirvvs.cpp | 3 +-- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/tests/data/export_time_series_initialization_osecirvvs.h5 b/cpp/tests/data/export_time_series_initialization_osecirvvs.h5 index 9d4ac4d8edbe65d644b354e997ab151a62592c47..ec4924dcdaf7cc6442c23b7408ffe2bffb489261 100644 GIT binary patch literal 9120 zcmeHL2~-nT7oGr0RIIEDf^33-AmGZPyopK@0wS_%R2HoWR0E1EVx>f^3KcP6rKq(6 zE`Wdq!PJUEK}D@>qHKboMG92V3guT8O`(~2GmU5X&*|wo?SFnI=j6`Z_sw_jci)|v zHxp}T%bGfQ=451aqtg)?ME;Lm{7-~!DYL~M{1_ki!FFhvjlpb&lz4}RjQ$Wr74s`# z{E|2~7bX)KLE`+l#ZE(>P7v?WamTp*zp8*8bNQN4!Rs*9c$ePA`V23IIktoMqa8l* z7cEu)+DVHE{jt9MZ~beDH7?^X<}rTS|8@l=`xo!a7_5JAb#4JX-_d<`a8T%u`IudR z*@c*0gxSTIU4kHPK_Q#AkDQ11J$`+-u6D8=?P2`Bsg3n5j+5+TJdbhv=L*n}iQ?K~ zg`;6lG#X9pz{-jcR`n0Of;NiPo`Ecyf-DkYfC(es(KDr_r2ZhFV|>yy{v>f^{D~<( zQp8wB!G@uF0SK~NJn#?wi~EWWR||ZFu@k}72o%T0X=B4FN@L>;vEf|hv2pnG;0Kkl zahBL{_4KiE_;q9`J2sAi4L_YRHjZjkv$VgpAbva_=&3;-KTdg3ZfzYU-fvH^A-~}qDA(tbQOOJZOK1@K}h6hAi5dUS~fZ(&u z2zn{(4vU$n4E>GsI_LV=OoMqy&>{*QJ1uoMh7ce7M6kTp?k%M*wRgAGDk3jHzE*YX z@^ljiP%0n#K$g^p*{ch;iA=dbj%BQpbKeQ_OUBPo&-5efs^BxKdzKNpa$n@O7r7(o zt+*|7tg4hCkIaFKJ;@H#y0|t|TC_QHA>O#iamCB&gOs{#HbnP$zCI6i%~sap9;kH$ z_4KkT7O4;Wv_hKn_j!QF4QHH%E!4WM|K?U!LYlAZ<$WFWo7ylR)#k5jEZb>l(&WVk z&h9GEudg~iw`!pR%mb0w@+%~eOUZh$KXL78{(&?M|$pjzZ7-OZp%D$ z&Jy}%w^oM2kbjl}@|(X^riCN<4kF2K!z^9~_Uq+wj{{Q5JZ2k>Oix zpAY@<$GWmK?4!ZQURCyaPr_k7lDaIGRqskA=@P01${(`jKzzowA0{Xz0`v}l|GmDb zrO;2SaNDJ(!-4T6dGnQY68c3%pA_vcF;zW9t!w8q&j*3u5xS&A4?ni@%La?9lmh&o z<-$0EO&2+$y?oGd=Q^`CX*bMAGX86sxS$l0E@sHO$D4)-UH7G(Yzzz;=!O<{zqKL? zc^rKdZSR{o!g!LrELK*@N=0J6nqrlux&jwa;%P264W|MKUBB$tjML|4gD4Bv^<-T~ z7x>7^^zlKPY)W8@Pcd=JU^XuKZedhpf8>p`vuU1Pi+v33T-58$= zF8H#niycBC9+B8i_@*+*y5x3b3p6JY>-83SU!%5-<|t}bXE1F<+<8{1)}#yg7PC{?moaYiwZLrxA1BIIU&C zc#^s*JGX~ua)|YM+x3*hG!K1B{L7V}^Sj~+UAe+AZgW*3VCI`zk#+6)b>P`Dz-#C5B-W)AY znWrB5>Uq2#@jXbmWLEh=!+$8>hn;UV6+|dcg8XlEvzDAK%?7HabNA@KmVy3{0xLFo zY$ygNX9lZVL~q3W8gLxJHoclTt%W3AJgx4R%tT#?^Fnq+Rqdsr4`)C0*5;@}|AyQ9 zg0q;^@57m4u|D}cLRSj^WA2SRZzy&3an#qWI#1H&ey(!)wj6LpKKc&gDh1;jM<4y( zqqz_~_ZUofkn_a+AL@D>cJKmO*O|hhp5Z7R$aC7YEj8mBg0f9ZeyI}@-^B(I9o{Q} zBISJjRG-wN%`t&IGU;|2+NTF7bqN-x@DpnZU6G%y3D*kD0Wsfc-XiO&E>dqTvAYh! zgIhHwZ>QE}CiHLcIldP5;rwsw&GLH;U_Ni&elg!)B#lN6)3y$Yrb540!~(y9S5lO^ z@_yDChxz25 zGIw5)QU)rmwyG9Y+b|AiHwk%7L|(WqWX@-7vaXv`{1wR8d*9iTRMFr>RKB1qy-uhJ z`9nEtWohS>U>=YU+X;yaktKiktlo-#qfz*ba=wx-JxaJ=-VOOg0u`C`MgfRnU)@gD z<(D>~(0aQJWCr2Fx^kEa2XCcNKgU%~ yt{q-gstft=tJ})beXP8HhTwcNtb^Q)^H9X${ delta 3435 zcmZYBc{G&m8wc>2O4bb7#!|9GhGdPzecwi8$-b|RJ&{nhHyRR3Bs&R-Y?UQjs*xlj zBqbFUkyIojiIm@Xy#4e3p1-bh?(>}UdA`^6T<5;L|MLFoI%a0yXXm|fxUiI($Xaz4 z3Lb5UDh~g2%urjSBa1SH_d}YgT;rK*|6ny0C!uKgx2Nu&Dg2O03VW}=v zXndXs!G~)po>qo1rG`i}F80ePkl2EjI0sMDt!3cd?hLXdCwcWuUAMy9s4=M!u6(vv zgFLPv<}i8AdE*rjb@$tsTfzD8mghLzsP1XNuIfHZ$*2Lw9{3rb*>uEs7v%(==$~NN zW+sok%H;P#v}{}T^K=gM`drE5if(Cm%`!nGyLlgEdYxUD5%vd`{uFpoVI~R#I?M#b zPMTr1FS5h-EfRw06UA}Zf`2>Y=oQ+|wH{zL@vO{vgO|lnnELBLvWGj^=$+~<6<7?6 zSeT3Or5EAN{Bzd5J<;GUY!;k?2 z&2(^70dpmv$pF%tZH(U{w>8OG+l04w-;+dNlpFRmUTQ@YeI1OHvvk=BGZth8<|ht7 zjeZkbS_&^3Nnv?$Dn}ZQJsZH|xt%auQ%LcJGW{KBULv{sS{Vsu^S4JB`08Rd&jg)) z<&h;Y*HU@unS>Q6#cSn={mcTmNq2)mMo+Kj0eokXJd$zrL3Tah#v|{?$+# zGC%cibLDo#Y}(>H-g){Yv^29X+Ob&<_H-+K8M&Z`*(TmP4r(C5WsRY6V}*zbQJ+*RKhv#~EaZf;2- zAz3r32(4ZYc4Snr?!2~Uo8_;Iie>avxa$5kqLM9ejh^Kc5X%MQsb`p0Z2@A_KlJU7 z1C^46u0Kgd;5(nYKv?~nO?UhI9zDw-?X=q+P0HL}h_kHx`;`~_QT%%=nJOJk_`yi} zF}c_U>e{tW+7_!L6`@TYG_n%R4A^5unexVLdGrHUm<`O3{D?b?k)tYH5zrL)Jz;_6 zHakafVk1>q>gToq&Q<4TiPwcVnY-Q$`S=vp+hvnW-48^HWTO zq8G8APScXDbs08RMOt-lu@`z;9$Ra@&j67{r)+M}04%-{@L`BTf#Y7fT+P(I$Y;y_ zSdLFBP^*(UTWtC;W^3%Ztl++KyEWT0xuw@S3>)6Uui$F1 zH)^}Cl`H?t0O75=&`p{BG=>Be{(}LMxg6T|Dz5APf7kH75QT}%VPFH z+0AB1pWgiB^XP7PQHw+Nq&@Zzt8eKT=}q;SgHF;@WHr z=cd&Vt7yVl`U7d$>QFRoAmE05q@M7)wAuz^G&JD%#(9whBib!hrkahg;W)I%AQmsp ziNZ*(mCcpefJsJ{wWsGj`2OVR+*kE?(64vgx=%VC#J32sC-3b9>DhE0jm!dUIJBmW zLg@^f@u9`2pAKGVhZ8&b7t4OMm|A_8zfKW$%F9!gwQM2#8{AYM)IfBP`Quq?GSF1J z{ggG%1G90e1>lB!GYn(dj@C> zbO&r>d1^ic9YB}!UP20BExT=QiQ2&}f~zL)^EI2(4e9h*hRyENm%xivUWg++xDNM;t!L7lHt&R^?^(V^J@LY9h9#!XOZujWo?!L1 zfG7v=k7Q^$bsA$f4Z;28Z_X2to&V(bSGTgkaxOF8$7c-4#1Izy7&cv%t2R$fQ$Ul^ z=n*%Yb}$s1+rv7&W_xIH*tq=UQEl$4KL`m*UdXWGZhgqKINJU3k_tgr2ohDvHQlOY z7*zO$yqF?@f~7{BwgvG*mE%z|Mcd3Vo3Wq6d1Fag#N&7R65lK@tj>FvOQ=&@JyTQq zGF0fv%ZdUY8NQrm?@X}=Nzt@IA)zQrT`b3nj zl4PM}!3VvZe^oeEtl9D`8x#VM$RgDU#Ro%8e6TI}{+&Pzb`Zl@*!E2+yi) zzXDPop7LN5_zJd8KqB2@9lB-4a$@V}Hn1zgeU^#340_XXdTh08wlk(w)m59gFkAS< zJ5MCTbtScpDu(XGg+vO>2*68SUJ@MB2=f1N6+Yb{h}M7XYyYyu2WM_&`VKw977j5% zJ*Q>2r9?d1tLBwYSWbTk(X5<-4eXpDm*t>VEfRvyH^ESrVGW$KWTcZ zi|e7JNKs-3FEyTMMOc>rI z0!iu~XDZ@(cldXtE(P`6(Qr;pbcE#RylGX!R5*^~>|(XB;6`I@4R*rvmJr@lY8Bd< zfPtltJ{AFcJ z(TUy_Vf3jE7m=Vv2i3Oh^s;}X;Gn>KJ84t1EP!eLUjhfS#!8WRaye%NOX`vbrF33n!8HYQ?Db?glfWH^vt zPBFKDY@~s3a$LabnVCb!olMXwj=IUpWW|X)fUqQ7p%B9aUxQ)CRhwWIla0&oS&()1 aDW6xW6kND; Date: Mon, 24 Nov 2025 15:18:18 +0000 Subject: [PATCH 13/26] fix bindings --- .../memilio/simulation/bindings/simulation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp index a98012dce8..22ef15ac14 100755 --- a/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp @@ -117,13 +117,13 @@ PYBIND11_MODULE(_simulation, m) m.def( "get_state_id_de", [](int county) { - return int(mio::regions::get_state_id(int(mio::regions::CountyId(county)))); + return int(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(county)))); }, py::arg("county_id")); m.def( "get_holidays_de", [](int state, mio::Date start_date, mio::Date end_date) { - auto h = mio::regions::get_holidays(mio::regions::StateId(state), start_date, end_date); + auto h = mio::regions::de::get_holidays(mio::regions::de::StateId(state), start_date, end_date); return std::vector>(h.begin(), h.end()); }, py::arg("state_id"), py::arg("start_date") = mio::Date(std::numeric_limits::min(), 1, 1), From bfe89f29aae4aa225cadc6ad3b19cdb2b6f63152 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:29:35 +0000 Subject: [PATCH 14/26] Const string --- cpp/memilio/geography/regions.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/memilio/geography/regions.h b/cpp/memilio/geography/regions.h index c885633191..bfc8d1edb6 100644 --- a/cpp/memilio/geography/regions.h +++ b/cpp/memilio/geography/regions.h @@ -109,14 +109,14 @@ struct EpidataFilenames { private: - EpidataFilenames(std::string& pydata) : + EpidataFilenames(const std::string& pydata) : population_data_path(mio::path_join(pydata, "county_current_population.json")) { } public: - static EpidataFilenames county(std::string& pydata) + static EpidataFilenames county(const std::string& pydata) { EpidataFilenames s(pydata); @@ -127,7 +127,7 @@ struct EpidataFilenames return s; } - static EpidataFilenames states(std::string& pydata) + static EpidataFilenames states(const std::string& pydata) { EpidataFilenames s(pydata); @@ -138,7 +138,7 @@ struct EpidataFilenames return s; } - static EpidataFilenames country(std::string& pydata) + static EpidataFilenames country(const std::string& pydata) { EpidataFilenames s(pydata); From 356b84df2ddd03caba605597704e3fe42ca7feb2 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 24 Nov 2025 15:45:37 +0000 Subject: [PATCH 15/26] Fix bindings --- cpp/memilio/geography/regions.h | 8 ++++---- .../memilio/simulation/bindings/models/osecir.cpp | 8 +++++--- .../memilio/simulation/bindings/models/osecirvvs.cpp | 6 +++--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/cpp/memilio/geography/regions.h b/cpp/memilio/geography/regions.h index bfc8d1edb6..c885633191 100644 --- a/cpp/memilio/geography/regions.h +++ b/cpp/memilio/geography/regions.h @@ -109,14 +109,14 @@ struct EpidataFilenames { private: - EpidataFilenames(const std::string& pydata) : + EpidataFilenames(std::string& pydata) : population_data_path(mio::path_join(pydata, "county_current_population.json")) { } public: - static EpidataFilenames county(const std::string& pydata) + static EpidataFilenames county(std::string& pydata) { EpidataFilenames s(pydata); @@ -127,7 +127,7 @@ struct EpidataFilenames return s; } - static EpidataFilenames states(const std::string& pydata) + static EpidataFilenames states(std::string& pydata) { EpidataFilenames s(pydata); @@ -138,7 +138,7 @@ struct EpidataFilenames return s; } - static EpidataFilenames country(const std::string& pydata) + static EpidataFilenames country(std::string& pydata) { EpidataFilenames s(pydata); diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp index 3d66c038b7..023b8e3764 100644 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp @@ -286,18 +286,20 @@ PYBIND11_MODULE(_simulation_osecir, m) m.def( "read_input_data_german_county", [](mio::Graph, mio::MobilityParameters>& params_graph, mio::Date start_date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path) { + const std::vector& scaling_factor_inf, double scaling_factor_icu, std::string& pydata_path) { auto result = mio::osecir::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, mio::regions::de::EpidataFilenames::county(pydata_path)); return pymio::check_and_throw(result); }, - py::return_value_policy::move); + "Reads compartments for german counties at a specified date from data files.", + py::arg("params_graph"), py::arg("start_date"), py::arg("scaling_factor_inf"), py::arg("scaling_factor_icu"), + py::arg("pydata_path"), py::return_value_policy::move); m.def( "create_graph_german_county", [](const mio::osecir::Parameters& params, mio::Date start_date, mio::Date end_date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path, + const std::vector& scaling_factor_inf, double scaling_factor_icu, std::string& pydata_path, double tnt_capacity_factor) { auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp index 06f18f6095..3e7d0ddc5a 100755 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp @@ -337,20 +337,20 @@ PYBIND11_MODULE(_simulation_osecirvvs, m) m.def( "read_input_data_german_county", [](mio::Graph, mio::MobilityParameters>& params_graph, mio::Date start_date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path) { + const std::vector& scaling_factor_inf, double scaling_factor_icu, std::string& pydata_path) { auto result = mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, mio::regions::de::EpidataFilenames::county(pydata_path)); return pymio::check_and_throw(result); }, - "Reads compartments for german counties at a specified date from data files." + "Reads compartments for german counties at a specified date from data files.", py::arg("params_graph"), py::arg("start_date"), py::arg("scaling_factor_inf"), py::arg("scaling_factor_icu"), py::arg("pydata_path"), py::return_value_policy::move); m.def( "create_graph_german_county", [](const mio::osecirvvs::Parameters& params, mio::Date start_date, mio::Date end_date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, const std::string& pydata_path, + const std::vector& scaling_factor_inf, double scaling_factor_icu, std::string& pydata_path, double tnt_capacity_factor) { auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); From d7cf12ca7e8a273f62557407520ded9ae7cf7dd6 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 24 Nov 2025 23:34:08 +0000 Subject: [PATCH 16/26] Fix tests --- cpp/models/ode_secir/parameters_io.cpp | 2 +- cpp/tests/test_odesecir.cpp | 1 - .../simulation/bindings/models/osecir.cpp | 2 +- .../simulation/bindings/models/osecirvvs.cpp | 21 ++++++++++--------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index c25a3e6675..749aa45de4 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -306,7 +306,7 @@ IOResult set_population_data(Model& model, const std::vector(0); j < InfectionState::Count; ++j) { if (model.populations[{i, j}] < 0) { log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i), size_t(j), diff --git a/cpp/tests/test_odesecir.cpp b/cpp/tests/test_odesecir.cpp index 5f3fba97a2..007e26b729 100755 --- a/cpp/tests/test_odesecir.cpp +++ b/cpp/tests/test_odesecir.cpp @@ -1551,7 +1551,6 @@ TEST(TestOdeSecirIO, read_input_data_county_aggregates_one_group) models1[0].property.parameters.get>()[mio::AgeGroup(0)] = 0.25; auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); - const std::vector counties{1002}; const auto date = mio::Date(2020, 12, 1); std::vector scale6(num_age_groups, 1.0); diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp index 023b8e3764..c2b8cfb9fc 100644 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp @@ -305,7 +305,7 @@ PYBIND11_MODULE(_simulation_osecir, m) auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); mio::Graph, mio::MobilityParameters> params_graph(node_ids, - mio::osecir::Model::Populations({params.get_num_groups(), mio::osecir::InfectionState::Count}), params); + mio::osecir::Model::Populations({params.get_num_groups(), mio::osecir::InfectionState::Count}), params); pymio::check_and_throw(mio::osecir::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, mio::regions::de::EpidataFilenames::county(pydata_path))); diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp index 3e7d0ddc5a..79b06b2463 100755 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp @@ -336,29 +336,30 @@ PYBIND11_MODULE(_simulation_osecirvvs, m) pymio::bind_read_graph>(m); m.def( "read_input_data_german_county", - [](mio::Graph, mio::MobilityParameters>& params_graph, mio::Date start_date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, std::string& pydata_path) { + [](mio::Graph, mio::MobilityParameters>& params_graph, + mio::Date start_date, const std::vector& scaling_factor_inf, double scaling_factor_icu, + int num_days, std::string& pydata_path) { auto result = mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, - mio::regions::de::EpidataFilenames::county(pydata_path)); + num_days, mio::regions::de::EpidataFilenames::county(pydata_path)); return pymio::check_and_throw(result); }, "Reads compartments for german counties at a specified date from data files.", py::arg("params_graph"), py::arg("start_date"), py::arg("scaling_factor_inf"), py::arg("scaling_factor_icu"), - py::arg("pydata_path"), py::return_value_policy::move); + py::arg("num_days"), py::arg("pydata_path"), py::return_value_policy::move); m.def( "create_graph_german_county", [](const mio::osecirvvs::Parameters& params, mio::Date start_date, mio::Date end_date, - const std::vector& scaling_factor_inf, double scaling_factor_icu, std::string& pydata_path, - double tnt_capacity_factor) { + const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, + std::string& pydata_path, double tnt_capacity_factor) { auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); mio::Graph, mio::MobilityParameters> params_graph(node_ids, - mio::osecirvvs::Model::Populations({params.get_num_groups(), mio::osecirvvs::InfectionState::Count}), params); - pymio::check_and_throw(mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, - mio::regions::de::EpidataFilenames::county(pydata_path))); + mio::osecirvvs::Model::Populations({params.get_num_groups(), mio::osecirvvs::InfectionState::Count}), params); + pymio::check_and_throw(mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, + scaling_factor_inf, scaling_factor_icu, num_days, mio::regions::de::EpidataFilenames::county(pydata_path))); mio::set_test_and_trace_capacity, mio::osecirvvs::TestAndTraceCapacity>(params_graph.nodes(), tnt_capacity_factor); mio::set_german_holidays, mio::osecirvvs::ContactPatterns>(params_graph.nodes(), start_date, end_date); @@ -368,7 +369,7 @@ PYBIND11_MODULE(_simulation_osecirvvs, m) }, "Creates graph of germany with compartments for geographic units at a specified date from data files.", py::arg("params"), py::arg("start_date"), py::arg("end_date"), py::arg("scaling_factor_inf"), - py::arg("scaling_factor_icu"), py::arg("pydata_path"), py::arg("tnt_capacity_factor"), + py::arg("scaling_factor_icu"), py::arg("num_days"), py::arg("pydata_path"), py::arg("tnt_capacity_factor"), py::return_value_policy::move); #endif // MEMILIO_HAS_JSONCPP From e5de2e2d487a22d3a0543781eb0de30f60c73bbe Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 25 Nov 2025 09:53:46 +0000 Subject: [PATCH 17/26] Fix bindings --- .../memilio/simulation/bindings/models/osecir.cpp | 9 ++++++--- .../memilio/simulation/bindings/models/osecirvvs.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp index c2b8cfb9fc..a98a180e2a 100644 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp @@ -302,12 +302,15 @@ PYBIND11_MODULE(_simulation_osecir, m) const std::vector& scaling_factor_inf, double scaling_factor_icu, std::string& pydata_path, double tnt_capacity_factor) { - auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); + auto result_node_id = mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true); + auto node_ids = pymio::check_and_throw(result_node_id); mio::Graph, mio::MobilityParameters> params_graph(node_ids, mio::osecir::Model::Populations({params.get_num_groups(), mio::osecir::InfectionState::Count}), params); - pymio::check_and_throw(mio::osecir::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, - mio::regions::de::EpidataFilenames::county(pydata_path))); + auto result_read_input_data = mio::osecir::read_input_data(params_graph.nodes(), start_date, + scaling_factor_inf, scaling_factor_icu, + mio::regions::de::EpidataFilenames::county(pydata_path)) + pymio::check_and_throw(result_read_input_data); mio::set_test_and_trace_capacity, mio::osecir::TestAndTraceCapacity>(params_graph.nodes(), tnt_capacity_factor); mio::set_german_holidays, mio::osecir::ContactPatterns>(params_graph.nodes(), start_date, end_date); diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp index 79b06b2463..e932390af0 100755 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp @@ -354,12 +354,15 @@ PYBIND11_MODULE(_simulation_osecirvvs, m) const std::vector& scaling_factor_inf, double scaling_factor_icu, int num_days, std::string& pydata_path, double tnt_capacity_factor) { - auto node_ids = pymio::check_and_throw(mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true)); + auto result_node_id = mio::get_node_ids(mio::path_join(pydata_path, "county_current_population.json"), true); + auto node_ids = pymio::check_and_throw(result_node_id); mio::Graph, mio::MobilityParameters> params_graph(node_ids, mio::osecirvvs::Model::Populations({params.get_num_groups(), mio::osecirvvs::InfectionState::Count}), params); - pymio::check_and_throw(mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, - scaling_factor_inf, scaling_factor_icu, num_days, mio::regions::de::EpidataFilenames::county(pydata_path))); + auto result_read_input_data = mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, + scaling_factor_inf, scaling_factor_icu, num_days, + mio::regions::de::EpidataFilenames::county(pydata_path)) + pymio::check_and_throw(result_read_input_data); mio::set_test_and_trace_capacity, mio::osecirvvs::TestAndTraceCapacity>(params_graph.nodes(), tnt_capacity_factor); mio::set_german_holidays, mio::osecirvvs::ContactPatterns>(params_graph.nodes(), start_date, end_date); From 4e58516cd508a77d44153799689e14efd6af4484 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 25 Nov 2025 10:14:13 +0000 Subject: [PATCH 18/26] pre-commit --- .../examples/simulation/2020_npis_sarscov2_wildtype_germany.py | 3 ++- .../simulation/2021_vaccination_sarscov2_delta_germany.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py b/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py index 00c3c2af99..10ed55eee6 100644 --- a/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py +++ b/pycode/examples/simulation/2020_npis_sarscov2_wildtype_germany.py @@ -536,7 +536,8 @@ def get_graph(self, end_date): graph = mio.osecir.create_graph_german_county( model.parameters, - mio.Date(self.start_date.year,self.start_date.month, self.start_date.day), + mio.Date(self.start_date.year, + self.start_date.month, self.start_date.day), mio.Date(end_date.year, end_date.month, end_date.day), scaling_factor_infected, scaling_factor_icu, pydata_dir, tnt_capacity_factor) diff --git a/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py b/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py index 68f6d35afa..0b5fd8c5b8 100644 --- a/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py +++ b/pycode/examples/simulation/2021_vaccination_sarscov2_delta_germany.py @@ -623,7 +623,7 @@ def get_graph(self, end_date): mobility_data_file = os.path.join( data_dir_Germany, "mobility", "commuter_mobility_2022.txt") pydata_dir = os.path.join(data_dir_Germany, "pydata") - + graph = mio.osecir.create_graph_german_county( model.parameters, self.start_date, end_date, scaling_factor_infected, scaling_factor_icu, pydata_dir, tnt_capacity_factor) From 460db728dee6ef8733f76d843215d0cf48a7f8e1 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 25 Nov 2025 10:42:42 +0000 Subject: [PATCH 19/26] missing characters --- .../memilio/simulation/bindings/models/osecir.cpp | 2 +- .../memilio/simulation/bindings/models/osecirvvs.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp index a98a180e2a..e7d37bd1dd 100644 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecir.cpp @@ -309,7 +309,7 @@ PYBIND11_MODULE(_simulation_osecir, m) mio::osecir::Model::Populations({params.get_num_groups(), mio::osecir::InfectionState::Count}), params); auto result_read_input_data = mio::osecir::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, - mio::regions::de::EpidataFilenames::county(pydata_path)) + mio::regions::de::EpidataFilenames::county(pydata_path)); pymio::check_and_throw(result_read_input_data); mio::set_test_and_trace_capacity, mio::osecir::TestAndTraceCapacity>(params_graph.nodes(), tnt_capacity_factor); diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp index e932390af0..0182b87d5e 100755 --- a/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/models/osecirvvs.cpp @@ -361,7 +361,7 @@ PYBIND11_MODULE(_simulation_osecirvvs, m) mio::osecirvvs::Model::Populations({params.get_num_groups(), mio::osecirvvs::InfectionState::Count}), params); auto result_read_input_data = mio::osecirvvs::read_input_data(params_graph.nodes(), start_date, scaling_factor_inf, scaling_factor_icu, num_days, - mio::regions::de::EpidataFilenames::county(pydata_path)) + mio::regions::de::EpidataFilenames::county(pydata_path)); pymio::check_and_throw(result_read_input_data); mio::set_test_and_trace_capacity, mio::osecirvvs::TestAndTraceCapacity>(params_graph.nodes(), tnt_capacity_factor); From 15beb327cf20e6a8746d9717c457a65c04635fb6 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 25 Nov 2025 11:15:34 +0000 Subject: [PATCH 20/26] Add include --- cpp/models/ode_secir/parameters_io.h | 1 + cpp/models/ode_secirvvs/parameters_io.h | 1 + 2 files changed, 2 insertions(+) diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 16385e2b18..0da76e9c44 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -27,6 +27,7 @@ #include "ode_secir/model.h" #include "memilio/geography/regions.h" +#include "memilio/mobility/graph.h" #include "memilio/io/epi_data.h" #include "memilio/io/parameters_io.h" #include "memilio/io/result_io.h" diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index e25911d4f1..e7f8db92da 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -26,6 +26,7 @@ #include "ode_secirvvs/model.h" #include "memilio/geography/regions.h" +#include "memilio/mobility/graph.h" #include "memilio/io/epi_data.h" #include "memilio/io/parameters_io.h" #include "memilio/io/io.h" From cade4eb922a07254c0da2c78e71ccffa94089c00 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Tue, 25 Nov 2025 12:53:22 +0000 Subject: [PATCH 21/26] Convert Population --- cpp/memilio/epidemiology/populations.h | 5 +++-- cpp/models/ode_secir/parameters_io.h | 4 ++-- cpp/models/ode_secirts/parameters_io.h | 5 ++--- cpp/models/ode_secirvvs/parameters_io.h | 5 ++--- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/cpp/memilio/epidemiology/populations.h b/cpp/memilio/epidemiology/populations.h index 1d3e63ca2f..b21d810839 100644 --- a/cpp/memilio/epidemiology/populations.h +++ b/cpp/memilio/epidemiology/populations.h @@ -55,6 +55,7 @@ class Populations : public CustomIndexArray, Categories...> { public: using Base = CustomIndexArray, Categories...>; + using BaseFP = FP; using Index = typename Base::Index; template , Categories...> * @tparam OtherType The type to convert into. * @return New Populations of OtherType with copy of internal data. */ - template requires std::convertible_to + template requires std::convertible_to Populations convert() const { - return Populations(Base::template convert()); + return Populations(Base::template convert().template convert>()); } /** diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 0da76e9c44..82250d88d2 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -161,11 +161,11 @@ void convert_input_data_type(const mio::VectorRange>>& mo assert(model_from.size() == model_to.size()); assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()); // Todo: add conversion of ParameterSet and then re-use code from other model parameters io - + for (size_t region_idx = 0; region_idx < model_from.size(); ++region_idx) { // convert populations to mio::UncertainValue // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_to[region_idx].property.populations.template convert().template convert>(); + model_to[region_idx].property.populations = model_from[region_idx].property.populations.template convert(); } } diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index be129c0685..e7fa9294b3 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -387,9 +387,8 @@ IOResult convert_input_data_type(const mio::VectorRange // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_to[region_idx] - .property.populations.template convert() - .template convert>(); + model_to[region_idx].property.populations = model_from[region_idx] + .property.populations.template convert(); } return success(); } diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index e7f8db92da..e5614e0273 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -372,9 +372,8 @@ IOResult convert_input_data_type(const mio::VectorRange // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_to[region_idx] - .property.populations.template convert() - .template convert>(); + model_to[region_idx].property.populations = model_from[region_idx] + .property.populations.template convert(); } return success(); } From d188bc965e429c5cf0960907fd55a1eeb94b2c9e Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Thu, 27 Nov 2025 18:43:06 +0000 Subject: [PATCH 22/26] fix ad types --- cpp/memilio/ad/ad.h | 61 ------------------------- cpp/models/ode_secirts/parameters_io.h | 7 +-- cpp/models/ode_secirvvs/parameters_io.h | 8 ++-- 3 files changed, 9 insertions(+), 67 deletions(-) diff --git a/cpp/memilio/ad/ad.h b/cpp/memilio/ad/ad.h index 8ea41afc6f..96c93bcd29 100644 --- a/cpp/memilio/ad/ad.h +++ b/cpp/memilio/ad/ad.h @@ -27,67 +27,6 @@ #include #include -// Extend automatic differentiation (AD) library to support std::round and std::trunc. -namespace ad -{ -namespace internal -{ -using std::round; -template -static inline double round(const ad::internal::active_type& x) -{ - return round(x._value()); -} -template -static inline double round(const ad::internal::binary_intermediate_aa& x) -{ - return round(x._value()); -} -template -static inline double round(const ad::internal::binary_intermediate_ap& x) -{ - return round(x._value()); -} -template -static inline double round(const ad::internal::binary_intermediate_pa& x) -{ - return round(x._value()); -} -template -static inline double round(const ad::internal::unary_intermediate& x) -{ - return round(x._value()); -} - -using std::trunc; -template -static inline double trunc(const ad::internal::active_type& x) -{ - return trunc(x._value()); -} -template -static inline double trunc(const ad::internal::binary_intermediate_aa& x) -{ - return trunc(x._value()); -} -template -static inline double trunc(const ad::internal::binary_intermediate_ap& x) -{ - return trunc(x._value()); -} -template -static inline double trunc(const ad::internal::binary_intermediate_pa& x) -{ - return trunc(x._value()); -} -template -static inline double trunc(const ad::internal::unary_intermediate& x) -{ - return trunc(x._value()); -} -} // namespace internal -} // namespace ad - // Allow std::numeric_limits to work with AD types. template struct std::numeric_limits> : public numeric_limits { diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index e7fa9294b3..0abf0c946b 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -239,6 +239,7 @@ template IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, Date date, int num_days) { + using std::floor; auto max_date_entry = std::max_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; @@ -258,11 +259,11 @@ IOResult set_vaccination_data(Model& model, const std::vector( - static_cast(model.parameters.template get>()[AgeGroup(0)])); + floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); auto days_until_effective_pi = static_cast( - static_cast(model.parameters.template get>()[AgeGroup(0)])); + floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); auto days_until_effective_ii = static_cast( - static_cast(model.parameters.template get>()[AgeGroup(0)])); + floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); for (auto&& vacc_data_entry : vacc_data) { BOOST_OUTCOME_TRY(set_vaccination_data(model, vacc_data_entry, date, num_days, max_date, diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index e5614e0273..5cf50d8e6e 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -160,6 +160,8 @@ template IOResult set_vaccination_data(Model& model, const std::vector& vacc_data, Date date, int num_days) { + using std::floor; + auto max_date_entry = std::max_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) { return a.date < b.date; }); @@ -181,11 +183,11 @@ IOResult set_vaccination_data(Model& model, const std::vector FP -> int auto days_until_effective1 = static_cast( - static_cast(model.parameters.template get>()[AgeGroup(0)])); + floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); auto days_until_effective2 = static_cast( - static_cast(model.parameters.template get>()[AgeGroup(0)])); + floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); auto vaccination_distance = - static_cast(static_cast(model.parameters.template get>()[AgeGroup(0)])); + floor(static_cast(static_cast(model.parameters.template get>()[AgeGroup(0)]))); for (auto&& vacc_data_entry : vacc_data) { auto date_df = vacc_data_entry.date; From adcee20b929e4c96e2566cd76b6e3d85c71cf7ea Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:34:27 +0000 Subject: [PATCH 23/26] move regions change to followup issue --- cpp/memilio/epidemiology/populations.h | 5 +- cpp/memilio/geography/holiday_data.ipp | 9 +-- cpp/memilio/geography/regions.cpp | 37 +++++------ cpp/memilio/geography/regions.h | 32 +++++----- cpp/memilio/io/epi_data.h | 48 +++++++------- cpp/memilio/io/parameters_io.cpp | 10 +-- cpp/memilio/mobility/graph.h | 40 +----------- cpp/memilio/mobility/graph_simulation.h | 8 +-- cpp/models/ode_secirts/parameters_io.h | 14 ++-- cpp/models/ode_secirvvs/parameters_io.h | 7 +- cpp/tests/test_epi_data_io.cpp | 36 +++++------ cpp/tests/test_odesecir.cpp | 85 ++++++++++++------------- cpp/tests/test_regions.cpp | 40 ++++++------ 13 files changed, 157 insertions(+), 214 deletions(-) diff --git a/cpp/memilio/epidemiology/populations.h b/cpp/memilio/epidemiology/populations.h index 337f063680..3c300bd79a 100644 --- a/cpp/memilio/epidemiology/populations.h +++ b/cpp/memilio/epidemiology/populations.h @@ -54,9 +54,8 @@ template class Populations : public CustomIndexArray, Categories...> { public: - using Base = CustomIndexArray, Categories...>; - using BaseFP = FP; - using Index = typename Base::Index; + using Base = CustomIndexArray, Categories...>; + using Index = typename Base::Index; template , Ts...>::value>* = nullptr> diff --git a/cpp/memilio/geography/holiday_data.ipp b/cpp/memilio/geography/holiday_data.ipp index 1fdbb6e82f..b7aab2dc8e 100644 --- a/cpp/memilio/geography/holiday_data.ipp +++ b/cpp/memilio/geography/holiday_data.ipp @@ -25,10 +25,7 @@ #include #include -namespace mio -{ - -namespace regions +namespace holidays { namespace de @@ -302,6 +299,4 @@ static const std::vector> holidays_16_th = { } // namespace de -} // namespace regions - -} // namespace mio +} // namespace holidays diff --git a/cpp/memilio/geography/regions.cpp b/cpp/memilio/geography/regions.cpp index 308b34db58..fa94248e0a 100644 --- a/cpp/memilio/geography/regions.cpp +++ b/cpp/memilio/geography/regions.cpp @@ -28,9 +28,6 @@ namespace mio namespace regions { -namespace de -{ - StateId get_state_id(int county) { // integer division @@ -46,52 +43,52 @@ get_holidays(StateId state) auto data = &def; switch (int(state)) { case 1: - data = &holidays_01_sh; + data = &holidays::de::holidays_01_sh; break; case 2: - data = &holidays_02_hh; + data = &holidays::de::holidays_02_hh; break; case 3: - data = &holidays_03_ni; + data = &holidays::de::holidays_03_ni; break; case 4: - data = &holidays_04_hb; + data = &holidays::de::holidays_04_hb; break; case 5: - data = &holidays_05_nw; + data = &holidays::de::holidays_05_nw; break; case 6: - data = &holidays_06_he; + data = &holidays::de::holidays_06_he; break; case 7: - data = &holidays_07_rp; + data = &holidays::de::holidays_07_rp; break; case 8: - data = &holidays_08_bw; + data = &holidays::de::holidays_08_bw; break; case 9: - data = &holidays_09_by; + data = &holidays::de::holidays_09_by; break; case 10: - data = &holidays_10_sl; + data = &holidays::de::holidays_10_sl; break; case 11: - data = &holidays_11_be; + data = &holidays::de::holidays_11_be; break; case 12: - data = &holidays_12_bb; + data = &holidays::de::holidays_12_bb; break; case 13: - data = &holidays_13_mv; + data = &holidays::de::holidays_13_mv; break; case 14: - data = &holidays_14_sn; + data = &holidays::de::holidays_14_sn; break; case 15: - data = &holidays_15_st; + data = &holidays::de::holidays_15_st; break; case 16: - data = &holidays_16_th; + data = &holidays::de::holidays_16_th; break; default: break; @@ -114,8 +111,6 @@ get_holidays(StateId state, Date start_date, Date end_date) return {holidays_in_range}; } -} // namespace de - } // namespace regions } // namespace mio diff --git a/cpp/memilio/geography/regions.h b/cpp/memilio/geography/regions.h index c885633191..47730ec7aa 100644 --- a/cpp/memilio/geography/regions.h +++ b/cpp/memilio/geography/regions.h @@ -46,9 +46,6 @@ struct Region : public mio::Index { } }; -namespace de -{ - /** * Id of a state. * For Germany the Ids are: @@ -105,23 +102,24 @@ get_holidays(StateId state); */ Range>::const_iterator, std::vector>::const_iterator>> get_holidays(StateId state, Date start_date, Date end_date); -struct EpidataFilenames + +namespace de { - private: - EpidataFilenames(std::string& pydata) : - population_data_path(mio::path_join(pydata, "county_current_population.json")) +struct EpidataFilenames { +private: + EpidataFilenames(std::string& pydata) + : population_data_path(mio::path_join(pydata, "county_current_population.json")) { } - - public: +public: static EpidataFilenames county(std::string& pydata) { EpidataFilenames s(pydata); - s.case_data_path = mio::path_join(pydata, "cases_all_county_age_ma7.json"); - s.divi_data_path = mio::path_join(pydata, "county_divi_ma7.json"); + s.case_data_path = mio::path_join(pydata, "cases_all_county_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "county_divi_ma7.json"); s.vaccination_data_path = mio::path_join(pydata, "vacc_county_ageinf_ma7.json"); return s; @@ -131,10 +129,10 @@ struct EpidataFilenames { EpidataFilenames s(pydata); - s.case_data_path = mio::path_join(pydata, "cases_all_state_age_ma7.json"); - s.divi_data_path = mio::path_join(pydata, "state_divi_ma7.json"); + s.case_data_path = mio::path_join(pydata, "cases_all_state_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "state_divi_ma7.json"); s.vaccination_data_path = mio::path_join(pydata, "vacc_state_ageinf_ma7.json"); - + return s; } @@ -142,10 +140,10 @@ struct EpidataFilenames { EpidataFilenames s(pydata); - s.case_data_path = mio::path_join(pydata, "cases_all_age_ma7.json"); - s.divi_data_path = mio::path_join(pydata, "germany_divi_ma7.json"); + s.case_data_path = mio::path_join(pydata, "cases_all_age_ma7.json"); + s.divi_data_path = mio::path_join(pydata, "germany_divi_ma7.json"); s.vaccination_data_path = mio::path_join(pydata, "vacc_ageinf_ma7.json"); - + return s; } diff --git a/cpp/memilio/io/epi_data.h b/cpp/memilio/io/epi_data.h index 3716a9b468..ac62270809 100644 --- a/cpp/memilio/io/epi_data.h +++ b/cpp/memilio/io/epi_data.h @@ -133,9 +133,9 @@ class ConfirmedCasesDataEntry ScalarType num_deaths; Date date; AgeGroup age_group; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IOContext& io) @@ -146,9 +146,9 @@ class ConfirmedCasesDataEntry auto num_deaths = obj.expect_element("Deaths", Tag{}); auto date = obj.expect_element("Date", Tag{}); auto age_group_str = obj.expect_element("Age_RKI", Tag{}); - auto state_id = obj.expect_optional("ID_State", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_State", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); return apply( io, [](auto&& nc, auto&& nr, auto&& nd, auto&& d, auto&& a_str, auto&& sid, auto&& cid, @@ -208,9 +208,9 @@ class DiviEntry public: ScalarType num_icu; Date date; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IoContext& io) @@ -218,9 +218,9 @@ class DiviEntry auto obj = io.expect_object("DiviEntry"); auto num_icu = obj.expect_element("ICU", Tag{}); auto date = obj.expect_element("Date", Tag{}); - auto state_id = obj.expect_optional("ID_State", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_State", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); return apply( io, [](auto&& ni, auto&& d, auto&& sid, auto&& cid, auto&& did) { @@ -304,17 +304,17 @@ class PopulationDataEntry static std::vector age_group_names; CustomIndexArray population; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IoContext& io) { auto obj = io.expect_object("PopulationDataEntry"); - auto state_id = obj.expect_optional("ID_State", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_State", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); std::vector> age_groups; age_groups.reserve(age_group_names.size()); std::transform(age_group_names.begin(), age_group_names.end(), std::back_inserter(age_groups), @@ -487,9 +487,9 @@ class VaccinationDataEntry num_vaccinations_refreshed_additional; Date date; AgeGroup age_group; - boost::optional state_id; - boost::optional county_id; - boost::optional district_id; + boost::optional state_id; + boost::optional county_id; + boost::optional district_id; template static IOResult deserialize(IoContext& io) @@ -501,9 +501,9 @@ class VaccinationDataEntry auto num_vaccinations_refreshed_additional = obj.expect_optional("Vacc_refreshed_2", Tag{}); auto date = obj.expect_element("Date", Tag{}); auto age_group_str = obj.expect_element("Age_RKI", Tag{}); - auto state_id = obj.expect_optional("ID_County", Tag{}); - auto county_id = obj.expect_optional("ID_County", Tag{}); - auto district_id = obj.expect_optional("ID_District", Tag{}); + auto state_id = obj.expect_optional("ID_County", Tag{}); + auto county_id = obj.expect_optional("ID_County", Tag{}); + auto district_id = obj.expect_optional("ID_District", Tag{}); return mio::apply( io, [](auto np, auto nc, auto n_refreshed_1, auto n_refreshed_2, auto d, auto&& a_str, auto sid, auto cid, diff --git a/cpp/memilio/io/parameters_io.cpp b/cpp/memilio/io/parameters_io.cpp index e584a3e13a..d3bdd0ff33 100644 --- a/cpp/memilio/io/parameters_io.cpp +++ b/cpp/memilio/io/parameters_io.cpp @@ -31,7 +31,8 @@ namespace mio { -IOResult> compute_divi_data(const std::vector& divi_data, const std::vector& vregion, Date date) +IOResult> compute_divi_data(const std::vector& divi_data, + const std::vector& vregion, Date date) { auto max_date_entry = std::max_element(divi_data.begin(), divi_data.end(), [](auto&& a, auto&& b) { @@ -49,7 +50,6 @@ IOResult> compute_divi_data(const std::vector std::vector vnum_icu(vregion.size(), 0.0); - for (auto&& entry : divi_data) { auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) { return r == 0 || r == get_region_id(entry); @@ -86,9 +86,9 @@ read_population_data(const std::vector& population_data, co auto it = std::find_if(vregion.begin(), vregion.end(), [&county_entry](auto r) { return r == 0 || (county_entry.county_id && - regions::de::StateId(r) == regions::de::get_state_id(int(*county_entry.county_id))) || - (county_entry.county_id && regions::de::CountyId(r) == *county_entry.county_id) || - (county_entry.district_id && regions::de::DistrictId(r) == *county_entry.district_id); + regions::StateId(r) == regions::get_state_id(int(*county_entry.county_id))) || + (county_entry.county_id && regions::CountyId(r) == *county_entry.county_id) || + (county_entry.district_id && regions::DistrictId(r) == *county_entry.district_id); }); if (it != vregion.end()) { auto region_idx = size_t(it - vregion.begin()); diff --git a/cpp/memilio/mobility/graph.h b/cpp/memilio/mobility/graph.h index 6025c30abe..5e7f64edd8 100644 --- a/cpp/memilio/mobility/graph.h +++ b/cpp/memilio/mobility/graph.h @@ -155,42 +155,6 @@ class Graph using NodeProperty = NodePropertyT; using EdgeProperty = EdgePropertyT; - Graph(const std::vector& node_ids, const std::vector& node_properties) - { - assert(node_ids.size() == node_properties.size()); - - for (auto i = size_t(0); i < node_ids.size(); ++i) { - add_node(node_ids[i], node_properties[i]); - } - } - - Graph(std::vector& node_properties) - { - for (auto i = size_t(0); i < node_properties.size(); ++i) { - add_node(i, node_properties[i]); - } - } - - template - requires std::constructible_from - Graph(const std::vector& node_ids, Args&&... node_args) - { - for (int id : node_ids) { - add_node(id, std::forward(node_args)...); - } - } - - template - requires std::constructible_from - Graph(const int number_of_nodes, Args&&... args) - { - for (int id = 0; id < number_of_nodes; ++id) { - add_node(id, std::forward(args)...); - } - } - - Graph() = default; - /** * @brief Construct graph without edges from pairs of node_ids and node_properties. */ @@ -376,8 +340,8 @@ void set_german_holidays(const mio::VectorRange>& nodes, const mio:: const mio::Date& end_date) { for (size_t node_idx = 0; node_idx < nodes.size(); ++node_idx) { - auto state_id = regions::de::get_state_id(nodes[node_idx].id); - auto holiday_periods = regions::de::get_holidays(state_id, start_date, end_date); + auto state_id = regions::get_state_id(nodes[node_idx].id); + auto holiday_periods = regions::get_holidays(state_id, start_date, end_date); auto& contacts = nodes[node_idx].property.parameters.template get(); contacts.get_school_holidays() = diff --git a/cpp/memilio/mobility/graph_simulation.h b/cpp/memilio/mobility/graph_simulation.h index 1a339860ec..0ceb33a821 100644 --- a/cpp/memilio/mobility/graph_simulation.h +++ b/cpp/memilio/mobility/graph_simulation.h @@ -370,7 +370,7 @@ class FeedbackGraphSimulation { std::unordered_map regional_population; for (auto& node : m_graph.nodes()) { - auto region_id = mio::regions::de::get_state_id(node.id).get(); + auto region_id = mio::regions::get_state_id(node.id).get(); regional_population[region_id] += node.property.get_simulation().get_model().populations.get_total(); } @@ -388,7 +388,7 @@ class FeedbackGraphSimulation // Sum up for (auto& node : m_graph.nodes()) { - auto region_id = mio::regions::de::get_state_id(node.id).get(); + auto region_id = mio::regions::get_state_id(node.id).get(); auto& sim = node.property.get_simulation(); auto& icu_history = sim.get_parameters().template get>(); FP pop = node.property.get_simulation().get_model().populations.get_total(); @@ -436,7 +436,7 @@ class FeedbackGraphSimulation for (auto& [region_id, regional_data] : m_regional_icu_occupancy) { Eigen::VectorXd sum = Eigen::VectorXd::Zero(regional_data.get_num_elements()); for (auto& node : m_graph.nodes()) { - if (mio::regions::de::get_state_id(node.id).get() == region_id) { + if (mio::regions::get_state_id(node.id).get() == region_id) { auto& sim = node.property.get_simulation(); auto& icu_history = sim.get_parameters().template get>(); sum += icu_history.get_last_value() * @@ -456,7 +456,7 @@ class FeedbackGraphSimulation void distribute_icu_data() { for (auto& node : m_graph.nodes()) { - auto region_id = mio::regions::de::get_state_id(node.id).get(); + auto region_id = mio::regions::get_state_id(node.id).get(); auto& sim = node.property.get_simulation(); sim.set_regional_icu_occupancy(m_regional_icu_occupancy.at(region_id)); sim.set_global_icu_occupancy(m_global_icu_occupancy); diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index 0abf0c946b..f6a6d1d9ab 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -260,8 +260,8 @@ IOResult set_vaccination_data(Model& model, const std::vector( floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); - auto days_until_effective_pi = static_cast( - floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); + auto days_until_effective_pi = static_cast(floor( + static_cast(model.parameters.template get>()[AgeGroup(0)]))); auto days_until_effective_ii = static_cast( floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); @@ -320,10 +320,9 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { - return m.id == 0 || - (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(m.id)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(m.id)); + return m.id == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(m.id)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(m.id)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(m.id)); }); if (it != model.end()) { auto region_idx = size_t(it - model.begin()); @@ -388,8 +387,7 @@ IOResult convert_input_data_type(const mio::VectorRange // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_from[region_idx] - .property.populations.template convert(); + model_to[region_idx].property.populations = model_from[region_idx].property.populations.template convert(); } return success(); } diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 5397be913e..2e989e6e42 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -306,10 +306,9 @@ IOResult set_vaccination_data(const mio::VectorRange>>& mod std::vector> vvacc_data{model.size()}; for (auto&& vacc_data_entry : vacc_data) { auto it = std::find_if(model.begin(), model.end(), [&vacc_data_entry](auto&& m) { - return m.id == 0 || - (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::de::CountyId(m.id)) || - (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::de::StateId(m.id)) || - (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::de::DistrictId(m.id)); + return m.id == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(m.id)) || + (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(m.id)) || + (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(m.id)); }); if (it != model.end()) { auto region_idx = size_t(it - model.begin()); diff --git a/cpp/tests/test_epi_data_io.cpp b/cpp/tests/test_epi_data_io.cpp index bbd2884b78..503603fe44 100644 --- a/cpp/tests/test_epi_data_io.cpp +++ b/cpp/tests/test_epi_data_io.cpp @@ -68,7 +68,7 @@ TEST(TestEpiDataIo, read_rki) ASSERT_EQ(rki_data[0].num_confirmed, 1); ASSERT_EQ(rki_data[0].num_deaths, 2); ASSERT_EQ(rki_data[0].num_recovered, 3); - ASSERT_EQ(rki_data[0].county_id, mio::regions::de::CountyId(1001)); + ASSERT_EQ(rki_data[0].county_id, mio::regions::CountyId(1001)); ASSERT_EQ(rki_data[0].state_id, boost::none); ASSERT_EQ(rki_data[1].age_group, mio::AgeGroup(0)); @@ -76,7 +76,7 @@ TEST(TestEpiDataIo, read_rki) ASSERT_EQ(rki_data[1].num_confirmed, 3); ASSERT_EQ(rki_data[1].num_deaths, 4); ASSERT_EQ(rki_data[1].num_recovered, 5); - ASSERT_EQ(rki_data[1].county_id, mio::regions::de::CountyId(1001)); + ASSERT_EQ(rki_data[1].county_id, mio::regions::CountyId(1001)); ASSERT_EQ(rki_data[1].state_id, boost::none); } @@ -141,11 +141,11 @@ TEST(TestEpiDataIo, read_divi) auto& divi_data = r.value(); ASSERT_EQ(divi_data.size(), 2); - ASSERT_EQ(divi_data[0].county_id, mio::regions::de::CountyId(1001)); + ASSERT_EQ(divi_data[0].county_id, mio::regions::CountyId(1001)); ASSERT_EQ(divi_data[0].date, mio::Date(2022, 10, 5)); ASSERT_EQ(divi_data[0].num_icu, 10.0); - ASSERT_EQ(divi_data[1].county_id, mio::regions::de::CountyId(1002)); + ASSERT_EQ(divi_data[1].county_id, mio::regions::CountyId(1002)); ASSERT_EQ(divi_data[1].date, mio::Date(2022, 10, 7)); ASSERT_EQ(divi_data[1].num_icu, 20.0); } @@ -185,14 +185,14 @@ TEST(TestEpiDataIo, read_population) auto& population_data = r.value(); ASSERT_EQ(population_data.size(), 2); - ASSERT_EQ(population_data[0].county_id, mio::regions::de::CountyId(1001)); + ASSERT_EQ(population_data[0].county_id, mio::regions::CountyId(1001)); ASSERT_THAT(population_data[0].population, testing::ElementsAre(testing::DoubleEq(10.0 + 2 * 10.0 / 3), testing::DoubleEq(10.0 / 3 + 10.0), testing::DoubleEq(10.0 + 10.0 + 10.0 + 0.5 * 10.0), testing::DoubleEq(0.5 * 10.0 + 10.0 + 2 * 10.0 / 3), testing::DoubleEq(10.0 / 3 + 10.0 + 0.2 * 10.0), testing::DoubleEq(0.8 * 10.0))); - ASSERT_EQ(population_data[1].county_id, mio::regions::de::CountyId(1002)); + ASSERT_EQ(population_data[1].county_id, mio::regions::CountyId(1002)); ASSERT_THAT(population_data[1].population, testing::ElementsAre(testing::DoubleEq(10.0 + 2 * 20.0 / 3), testing::DoubleEq(20.0 / 3 + 30.0), testing::DoubleEq(40.0 + 50.0 + 60.0 + 0.5 * 70.0), @@ -280,19 +280,19 @@ TEST(TestEpiDataIo, read_divi_data) ASSERT_EQ(divi_data.size(), 4); - ASSERT_EQ(divi_data[0].district_id, mio::regions::de::DistrictId(1234)); + ASSERT_EQ(divi_data[0].district_id, mio::regions::DistrictId(1234)); ASSERT_EQ(divi_data[0].date, mio::Date(2022, 04, 24)); ASSERT_EQ(divi_data[0].num_icu, 0.5437); - ASSERT_EQ(divi_data[1].district_id, mio::regions::de::DistrictId(1234)); + ASSERT_EQ(divi_data[1].district_id, mio::regions::DistrictId(1234)); ASSERT_EQ(divi_data[1].date, mio::Date(2022, 04, 25)); ASSERT_EQ(divi_data[1].num_icu, 0.64532); - ASSERT_EQ(divi_data[2].district_id, mio::regions::de::DistrictId(1235)); + ASSERT_EQ(divi_data[2].district_id, mio::regions::DistrictId(1235)); ASSERT_EQ(divi_data[2].date, mio::Date(2022, 04, 24)); ASSERT_EQ(divi_data[2].num_icu, 0.3574); - ASSERT_EQ(divi_data[3].district_id, mio::regions::de::DistrictId(1235)); + ASSERT_EQ(divi_data[3].district_id, mio::regions::DistrictId(1235)); ASSERT_EQ(divi_data[3].date, mio::Date(2022, 04, 25)); ASSERT_EQ(divi_data[3].num_icu, 0.35437); } @@ -335,7 +335,7 @@ TEST(TestEpiDataIo, read_confirmed_cases_data) ASSERT_EQ(case_data[0].num_confirmed, 1); ASSERT_EQ(case_data[0].num_deaths, 0); ASSERT_EQ(case_data[0].num_recovered, 0); - ASSERT_EQ(case_data[0].district_id, mio::regions::de::DistrictId(1234)); + ASSERT_EQ(case_data[0].district_id, mio::regions::DistrictId(1234)); ASSERT_EQ(case_data[0].county_id, boost::none); ASSERT_EQ(case_data[0].state_id, boost::none); @@ -344,7 +344,7 @@ TEST(TestEpiDataIo, read_confirmed_cases_data) ASSERT_EQ(case_data[1].num_confirmed, 20); ASSERT_EQ(case_data[1].num_deaths, 1); ASSERT_EQ(case_data[1].num_recovered, 5); - ASSERT_EQ(case_data[1].district_id, mio::regions::de::DistrictId(1234)); + ASSERT_EQ(case_data[1].district_id, mio::regions::DistrictId(1234)); ASSERT_EQ(case_data[1].county_id, boost::none); ASSERT_EQ(case_data[1].state_id, boost::none); @@ -353,7 +353,7 @@ TEST(TestEpiDataIo, read_confirmed_cases_data) ASSERT_EQ(case_data[2].num_confirmed, 15); ASSERT_EQ(case_data[2].num_deaths, 3); ASSERT_EQ(case_data[2].num_recovered, 2); - ASSERT_EQ(case_data[2].district_id, mio::regions::de::DistrictId(1235)); + ASSERT_EQ(case_data[2].district_id, mio::regions::DistrictId(1235)); ASSERT_EQ(case_data[2].county_id, boost::none); ASSERT_EQ(case_data[2].state_id, boost::none); } @@ -394,8 +394,8 @@ TEST(TestEpiDataIO, read_vaccination_data) ASSERT_EQ(vacc_data[0].date, mio::Date(2022, 4, 12)); ASSERT_EQ(vacc_data[0].age_group, mio::AgeGroup(0)); - ASSERT_EQ(vacc_data[0].county_id, mio::regions::de::CountyId(1001)); - ASSERT_EQ(vacc_data[0].district_id, mio::regions::de::DistrictId(1234)); + ASSERT_EQ(vacc_data[0].county_id, mio::regions::CountyId(1001)); + ASSERT_EQ(vacc_data[0].district_id, mio::regions::DistrictId(1234)); ASSERT_EQ(vacc_data[0].num_vaccinations_partial, 0.0); ASSERT_EQ(vacc_data[0].num_vaccinations_completed, 5.0); ASSERT_EQ(vacc_data[0].num_vaccinations_refreshed_first, 2.0); @@ -404,7 +404,7 @@ TEST(TestEpiDataIO, read_vaccination_data) ASSERT_EQ(vacc_data[1].date, mio::Date(2022, 4, 15)); ASSERT_EQ(vacc_data[1].age_group, mio::AgeGroup(2)); ASSERT_EQ(vacc_data[1].county_id, boost::none); - ASSERT_EQ(vacc_data[1].district_id, mio::regions::de::DistrictId(1235)); + ASSERT_EQ(vacc_data[1].district_id, mio::regions::DistrictId(1235)); ASSERT_EQ(vacc_data[1].num_vaccinations_partial, 1.0); ASSERT_EQ(vacc_data[1].num_vaccinations_completed, 1.0); ASSERT_EQ(vacc_data[1].num_vaccinations_refreshed_first, 4.0); @@ -438,7 +438,7 @@ TEST(TestEpiData, vaccination_data) EXPECT_EQ(vacc_data[0].date, mio::Date(2021, 12, 1)); EXPECT_EQ(vacc_data[0].age_group, mio::AgeGroup(1)); - EXPECT_EQ(vacc_data[0].county_id, mio::regions::de::CountyId(1011)); + EXPECT_EQ(vacc_data[0].county_id, mio::regions::CountyId(1011)); EXPECT_EQ(vacc_data[0].num_vaccinations_completed, 23.05); EXPECT_EQ(vacc_data[0].num_vaccinations_partial, 2.0); EXPECT_EQ(vacc_data[0].num_vaccinations_refreshed_first, 6.2); @@ -446,7 +446,7 @@ TEST(TestEpiData, vaccination_data) EXPECT_EQ(vacc_data[1].date, mio::Date(2021, 12, 2)); EXPECT_EQ(vacc_data[1].age_group, mio::AgeGroup(5)); - EXPECT_EQ(vacc_data[1].county_id, mio::regions::de::CountyId(1012)); + EXPECT_EQ(vacc_data[1].county_id, mio::regions::CountyId(1012)); EXPECT_EQ(vacc_data[1].num_vaccinations_completed, 12.0); EXPECT_EQ(vacc_data[1].num_vaccinations_partial, 14.0); EXPECT_EQ(vacc_data[1].num_vaccinations_refreshed_first, 6.2); diff --git a/cpp/tests/test_odesecir.cpp b/cpp/tests/test_odesecir.cpp index 007e26b729..4add67c08f 100755 --- a/cpp/tests/test_odesecir.cpp +++ b/cpp/tests/test_odesecir.cpp @@ -98,8 +98,7 @@ TEST(TestOdeSecir, compareWithPreviousRun) integrator->set_dt_max(1.0); integrator->set_rel_tolerance(1e-3); integrator->set_abs_tolerance(1e-1); - mio::TimeSeries secihurd = - mio::simulate(t0, tmax, dt, model, std::move(integrator)); + mio::TimeSeries secihurd = mio::simulate(t0, tmax, dt, model, std::move(integrator)); auto compare = load_test_data_csv("secihurd-compare.csv"); @@ -1007,13 +1006,13 @@ TEST(TestOdeSecir, get_reproduction_number) TEST(Secir, get_mobility_factors) { - auto beta = 0.25; - auto max_beta = 0.5; - auto model = ModelT(1); - model.parameters.get>().array() = 3.; - model.parameters.get>().array() = 2.; - model.parameters.get>().array() = 0.1; - model.parameters.get>().array() = beta; + auto beta = 0.25; + auto max_beta = 0.5; + auto model = ModelT(1); + model.parameters.get>().array() = 3.; + model.parameters.get>().array() = 2.; + model.parameters.get>().array() = 0.1; + model.parameters.get>().array() = beta; model.parameters.get>().array() = max_beta; model.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedNoSymptoms}] = 100; mio::osecir::Simulation sim(model, 0.0); @@ -1281,16 +1280,14 @@ TEST_F(ModelTestOdeSecir, read_input_data) auto model2 = std::vector>{mio::Node(1002, model)}; auto pydata_germany_path = std::string(TEST_GERMANY_PYDATA_DIR); - auto read_result1 = - mio::osecir::read_input_data(mio::make_range(model1.begin(), model1.end()), {2020, 12, 01}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - mio::regions::de::EpidataFilenames::county(pydata_germany_path)); - + auto read_result1 = mio::osecir::read_input_data(mio::make_range(model1.begin(), model1.end()), {2020, 12, 01}, + std::vector(size_t(num_age_groups), 1.0), 1.0, + mio::regions::de::EpidataFilenames::county(pydata_germany_path)); + auto pydata_district_path = mio::path_join(TEST_DATA_DIR, "District", "pydata"); - auto read_result_district = - mio::osecir::read_input_data(mio::make_range(model2.begin(), model2.end()), {2020, 12, 01}, - std::vector(size_t(num_age_groups), 1.0), 1.0, - mio::regions::de::EpidataFilenames::county(pydata_district_path)); + auto read_result_district = mio::osecir::read_input_data( + mio::make_range(model2.begin(), model2.end()), {2020, 12, 01}, std::vector(size_t(num_age_groups), 1.0), + 1.0, mio::regions::de::EpidataFilenames::county(pydata_district_path)); EXPECT_THAT(read_result1, IsSuccess()); EXPECT_THAT(read_result_district, IsSuccess()); @@ -1320,11 +1317,11 @@ TEST_F(ModelTestOdeSecir, export_time_series_init) // Test exporting time series std::vector> models{mio::Node(1002, model)}; - EXPECT_THAT(mio::osecir::export_input_data_timeseries( - mio::make_range(models.begin(), models.end()), tmp_results_dir, {2020, 12, 01}, - std::vector(size_t(num_age_groups), 1.0), 1.0, 2, - mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), - IsSuccess()); + EXPECT_THAT( + mio::osecir::export_input_data_timeseries(mio::make_range(models.begin(), models.end()), tmp_results_dir, + {2020, 12, 01}, std::vector(size_t(num_age_groups), 1.0), 1.0, + 2, mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), + IsSuccess()); auto data_extrapolated = mio::read_result(mio::path_join(tmp_results_dir, "Results_rki.h5")); EXPECT_THAT(data_extrapolated, IsSuccess()); @@ -1349,11 +1346,11 @@ TEST_F(ModelTestOdeSecir, export_time_series_init_old_date) // Test exporting time series std::vector> models{mio::Node(1002, model)}; - EXPECT_THAT(mio::osecir::export_input_data_timeseries( - mio::make_range(models.begin(), models.end()), tmp_results_dir, {1000, 12, 01}, - std::vector(size_t(num_age_groups), 1.0), 1.0, 2, - mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), - IsSuccess()); + EXPECT_THAT( + mio::osecir::export_input_data_timeseries(mio::make_range(models.begin(), models.end()), tmp_results_dir, + {1000, 12, 01}, std::vector(size_t(num_age_groups), 1.0), 1.0, + 2, mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), + IsSuccess()); auto data_extrapolated = mio::read_result(mio::path_join(tmp_results_dir, "Results_rki.h5")); EXPECT_THAT(data_extrapolated, IsSuccess()); @@ -1379,10 +1376,10 @@ TEST_F(ModelTestOdeSecir, export_time_series_init_old_date) TEST_F(ModelTestOdeSecir, model_initialization) { // Vector assignment necessary as read_input_data_county changes model - auto model_vector = std::vector>{mio::Node(1002, model)}; + auto model_vector = std::vector>{mio::Node(1002, model)}; auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); - EXPECT_THAT(mio::osecir::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {2020, 12, 01}, + EXPECT_THAT(mio::osecir::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {2020, 12, 01}, std::vector(size_t(num_age_groups), 1.0), 1.0, mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); @@ -1406,10 +1403,10 @@ TEST_F(ModelTestOdeSecir, model_initialization_old_date) { mio::set_log_level(mio::LogLevel::off); // Vector assignment necessary as read_input_data_county changes model - auto model_vector = std::vector>{mio::Node(1002, model)}; + auto model_vector = std::vector>{mio::Node(1002, model)}; auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); - EXPECT_THAT(mio::osecir::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {1000, 12, 01}, + EXPECT_THAT(mio::osecir::read_input_data(mio::make_range(model_vector.begin(), model_vector.end()), {1000, 12, 01}, std::vector(size_t(num_age_groups), 1.0), 1.0, mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); @@ -1446,10 +1443,10 @@ TEST(TestOdeSecir, set_divi_data_invalid_dates) auto model_vector = std::vector>{mio::Node(1001, model)}; // Test with date before DIVI dataset was available. - EXPECT_THAT(mio::osecir::details::set_divi_data(mio::make_range(model_vector.begin(), model_vector.end()), - "", {2019, 12, 01}, 1.0), + EXPECT_THAT(mio::osecir::details::set_divi_data(mio::make_range(model_vector.begin(), model_vector.end()), "", + {2019, 12, 01}, 1.0), IsSuccess()); - + // Assure that populations is the same as before. EXPECT_THAT(print_wrap(model_vector[0].property.populations.array().cast()), MatrixNear(print_wrap(model.populations.array().cast()), 1e-10, 1e-10)); @@ -1474,7 +1471,7 @@ TEST(TestOdeSecir, set_divi_data_empty_data) TEST_F(ModelTestOdeSecir, set_confirmed_cases_data_with_ICU) { - auto model_test = ModelT{model}; + auto model_test = ModelT{model}; model_test.populations.array().setConstant(1); // set params @@ -1551,16 +1548,16 @@ TEST(TestOdeSecirIO, read_input_data_county_aggregates_one_group) models1[0].property.parameters.get>()[mio::AgeGroup(0)] = 0.25; auto pydata_dir_Germany = mio::path_join(TEST_DATA_DIR, "Germany", "pydata"); - const auto date = mio::Date(2020, 12, 1); + const auto date = mio::Date(2020, 12, 1); std::vector scale6(num_age_groups, 1.0); std::vector scale1{1.0}; // Initialize both models - ASSERT_THAT(mio::osecir::read_input_data(mio::make_range(models6.begin(), models6.end()), date, scale6, 1.0, + ASSERT_THAT(mio::osecir::read_input_data(mio::make_range(models6.begin(), models6.end()), date, scale6, 1.0, mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); - ASSERT_THAT(mio::osecir::read_input_data(mio::make_range(models1.begin(), models1.end()), date, scale1, 1.0, + ASSERT_THAT(mio::osecir::read_input_data(mio::make_range(models1.begin(), models1.end()), date, scale1, 1.0, mio::regions::de::EpidataFilenames::county(pydata_dir_Germany)), IsSuccess()); @@ -1592,7 +1589,7 @@ TEST(TestOdeSecirIO, set_population_data_single_age_group) // Test population data with 6 different values for age groups std::vector population_data6 = {10000.0, 20000.0, 30000.0, 25000.0, 15000.0, 8000.0}; std::vector population_data1 = {108000.0}; // sum of all age groups - const int region = 1002; + const int region = 1002; // Set population data for both models EXPECT_THAT(mio::osecir::details::set_population_data(models6, population_data6, region), IsSuccess()); @@ -1639,7 +1636,7 @@ TEST(TestOdeSecirIO, set_confirmed_cases_data_single_age_group) current_date, mio::AgeGroup(age_group), {}, - mio::regions::de::CountyId(1002), + mio::regions::CountyId(1002), {}}; case_data.push_back(entry); } @@ -1698,10 +1695,8 @@ TEST(TestOdeSecirIO, set_divi_data_single_age_group) auto num_icu = read_divi_data(divi_data_path, {region}, date).value(); - auto result_6_groups = - mio::osecir::details::set_divi_data(models6, num_icu[0], scaling_factor_icu); - auto result_1_group = - mio::osecir::details::set_divi_data(models1, num_icu[0], scaling_factor_icu); + auto result_6_groups = mio::osecir::details::set_divi_data(models6, num_icu[0], scaling_factor_icu); + auto result_1_group = mio::osecir::details::set_divi_data(models1, num_icu[0], scaling_factor_icu); EXPECT_THAT(result_6_groups, IsSuccess()); EXPECT_THAT(result_1_group, IsSuccess()); diff --git a/cpp/tests/test_regions.cpp b/cpp/tests/test_regions.cpp index ffcbf5b7d1..ec58b9d45a 100644 --- a/cpp/tests/test_regions.cpp +++ b/cpp/tests/test_regions.cpp @@ -23,67 +23,67 @@ TEST(TestRegions, get_holidays) { - auto s1 = mio::regions::de::get_holidays(mio::regions::de::StateId(1), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s1 = mio::regions::get_holidays(mio::regions::StateId(1), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s1.size(), 1); ASSERT_EQ(s1[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 18))); - auto s2 = mio::regions::de::get_holidays(mio::regions::de::StateId(2), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s2 = mio::regions::get_holidays(mio::regions::StateId(2), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s2.size(), 1); ASSERT_EQ(s2[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 17))); - auto s4 = mio::regions::de::get_holidays(mio::regions::de::StateId(4), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s4 = mio::regions::get_holidays(mio::regions::StateId(4), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s4.size(), 1); ASSERT_EQ(s4[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s5 = mio::regions::de::get_holidays(mio::regions::de::StateId(5), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s5 = mio::regions::get_holidays(mio::regions::StateId(5), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s5.size(), 1); ASSERT_EQ(s5[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s6 = mio::regions::de::get_holidays(mio::regions::de::StateId(6), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s6 = mio::regions::get_holidays(mio::regions::StateId(6), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s6.size(), 1); ASSERT_EQ(s6[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 18))); - auto s7 = mio::regions::de::get_holidays(mio::regions::de::StateId(7), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s7 = mio::regions::get_holidays(mio::regions::StateId(7), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s7.size(), 1); ASSERT_EQ(s7[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 24))); - auto s8 = mio::regions::de::get_holidays(mio::regions::de::StateId(8), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s8 = mio::regions::get_holidays(mio::regions::StateId(8), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s8.size(), 1); ASSERT_EQ(s8[0], std::make_pair(mio::Date(2020, 10, 26), mio::Date(2020, 10, 31))); - auto s9 = mio::regions::de::get_holidays(mio::regions::de::StateId(9), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s9 = mio::regions::get_holidays(mio::regions::StateId(9), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s9.size(), 1); ASSERT_EQ(s9[0], std::make_pair(mio::Date(2020, 10, 31), mio::Date(2020, 11, 7))); - auto s10 = mio::regions::de::get_holidays(mio::regions::de::StateId(10), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s10 = mio::regions::get_holidays(mio::regions::StateId(10), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s10.size(), 1); ASSERT_EQ(s10[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 24))); - auto s11 = mio::regions::de::get_holidays(mio::regions::de::StateId(11), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s11 = mio::regions::get_holidays(mio::regions::StateId(11), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s11.size(), 1); ASSERT_EQ(s11[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s12 = mio::regions::de::get_holidays(mio::regions::de::StateId(12), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s12 = mio::regions::get_holidays(mio::regions::StateId(12), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s12.size(), 1); ASSERT_EQ(s12[0], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 25))); - auto s13 = mio::regions::de::get_holidays(mio::regions::de::StateId(13), mio::Date(2020, 10, 1), mio::Date(2020, 11, 15)); + auto s13 = mio::regions::get_holidays(mio::regions::StateId(13), mio::Date(2020, 10, 1), mio::Date(2020, 11, 15)); ASSERT_EQ(s13.size(), 1); ASSERT_EQ(s13[0], std::make_pair(mio::Date(2020, 10, 5), mio::Date(2020, 10, 11))); - auto s14 = mio::regions::de::get_holidays(mio::regions::de::StateId(14), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s14 = mio::regions::get_holidays(mio::regions::StateId(14), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s14.size(), 1); ASSERT_EQ(s14[0], std::make_pair(mio::Date(2020, 10, 19), mio::Date(2020, 11, 1))); - auto s15 = mio::regions::de::get_holidays(mio::regions::de::StateId(15), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s15 = mio::regions::get_holidays(mio::regions::StateId(15), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s15.size(), 1); ASSERT_EQ(s15[0], std::make_pair(mio::Date(2020, 10, 19), mio::Date(2020, 10, 25))); - auto s16 = mio::regions::de::get_holidays(mio::regions::de::StateId(16), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); + auto s16 = mio::regions::get_holidays(mio::regions::StateId(16), mio::Date(2020, 10, 15), mio::Date(2020, 11, 15)); ASSERT_EQ(s16.size(), 1); ASSERT_EQ(s16[0], std::make_pair(mio::Date(2020, 10, 17), mio::Date(2020, 10, 31))); - auto s3 = mio::regions::de::get_holidays(mio::regions::de::StateId(3), mio::Date(2020, 7, 30), mio::Date(2020, 12, 31)); + auto s3 = mio::regions::get_holidays(mio::regions::StateId(3), mio::Date(2020, 7, 30), mio::Date(2020, 12, 31)); ASSERT_EQ(s3.size(), 3); ASSERT_EQ(s3[0], std::make_pair(mio::Date(2020, 7, 16), mio::Date(2020, 8, 27))); ASSERT_EQ(s3[1], std::make_pair(mio::Date(2020, 10, 12), mio::Date(2020, 10, 24))); @@ -92,8 +92,8 @@ TEST(TestRegions, get_holidays) TEST(TestRegions, get_state_id) { - ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(1001))), mio::regions::de::StateId(1)); - ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(2000))), mio::regions::de::StateId(2)); - ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(5970))), mio::regions::de::StateId(5)); - ASSERT_EQ(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(9161))), mio::regions::de::StateId(9)); + ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(1001))), mio::regions::StateId(1)); + ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(2000))), mio::regions::StateId(2)); + ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(5970))), mio::regions::StateId(5)); + ASSERT_EQ(mio::regions::get_state_id(int(mio::regions::CountyId(9161))), mio::regions::StateId(9)); } From 28dc35429302016253a333a3cbf3f2df914e1f65 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:38:00 +0000 Subject: [PATCH 24/26] remove redundant code --- cpp/models/ode_secir/parameters_io.h | 61 ++++++++----------------- cpp/models/ode_secirts/parameters_io.h | 33 ------------- cpp/models/ode_secirvvs/parameters_io.h | 2 +- 3 files changed, 20 insertions(+), 76 deletions(-) diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 82250d88d2..11c7b5e8d1 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -52,17 +52,16 @@ namespace details * @param[in] mu_* vector Probabilities to get from one compartement to another for each age group. * @param[in] scaling_factor_inf Factors by which to scale the confirmed cases of rki data. */ -IOResult compute_confirmed_cases_data( - std::vector& case_data, const int region, Date date, - std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, - std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, - std::vector& num_icu, std::vector& num_death, - std::vector& num_rec, const std::vector& t_Exposed, - const std::vector& t_InfectedNoSymptoms, - const std::vector& t_InfectedSymptoms, const std::vector& t_InfectedSevere, - const std::vector& t_InfectedCritical, const std::vector& mu_C_R, - const std::vector& mu_I_H, const std::vector& mu_H_U, - const std::vector& scaling_factor_inf); +IOResult +compute_confirmed_cases_data(std::vector& case_data, const int region, Date date, + std::vector& num_Exposed, std::vector& num_InfectedNoSymptoms, + std::vector& num_InfectedSymptoms, std::vector& num_InfectedSevere, + std::vector& num_icu, std::vector& num_death, + std::vector& num_rec, const std::vector& t_Exposed, + const std::vector& t_InfectedNoSymptoms, const std::vector& t_InfectedSymptoms, + const std::vector& t_InfectedSevere, const std::vector& t_InfectedCritical, + const std::vector& mu_C_R, const std::vector& mu_I_H, + const std::vector& mu_H_U, const std::vector& scaling_factor_inf); /** * @brief Sets populations data from already read case data with multiple age groups into a Model. @@ -123,12 +122,11 @@ IOResult set_divi_data(Model& model, const ScalarType num_icu, * @param[in] date Date at which the data is read. * @param[in] scaling_factor_icu Scaling factor for reported ICU cases. */ -IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, +IOResult set_divi_data(const mio::VectorRange>>& model, const std::string& path, Date date, ScalarType scaling_factor_icu); } //namespace details - /** * @brief Reads compartments for geographic units at a specified date from data files. * @@ -146,29 +144,6 @@ IOResult read_input_data(const mio::VectorRange>>& const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, const mio::regions::de::EpidataFilenames& epidata_filenames); -/** - * @brief Converts input data from one range of models to another with different type. - * - * @tparam FP Floating point type (default: double). - * @param[in] model_from VectorRange of Node%s each containing a Model with the input data. - * @param[in,out] model_to VectorRange of Node%s each containing a Model to be initialized with data. - * - * @return An IOResult indicating success or failure. - */ -template -void convert_input_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to) -{ - assert(model_from.size() == model_to.size()); - assert((size_t)model_from[0].property.parameters.get_num_groups() == (size_t)model_to[0].property.parameters.get_num_groups()); - // Todo: add conversion of ParameterSet and then re-use code from other model parameters io - - for (size_t region_idx = 0; region_idx < model_from.size(); ++region_idx) { - // convert populations to mio::UncertainValue - // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_from[region_idx].property.populations.template convert(); - } -} - #ifdef MEMILIO_HAS_HDF5 /** @@ -188,13 +163,15 @@ void convert_input_data_type(const mio::VectorRange>>& mo * * @return An IOResult indicating success or failure. */ -IOResult export_input_data_timeseries( - const mio::VectorRange>> model, const std::string& results_dir, Date date, - const std::vector& scaling_factor_inf, ScalarType scaling_factor_icu, int num_days, - const mio::regions::de::EpidataFilenames& epidata_filenames); +IOResult export_input_data_timeseries(const mio::VectorRange>> model, + const std::string& results_dir, Date date, + const std::vector& scaling_factor_inf, + ScalarType scaling_factor_icu, int num_days, + const mio::regions::de::EpidataFilenames& epidata_filenames); #else -IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, Date, const std::vector&, - const std::vector&, const ScalarType, const int, +IOResult export_input_data_county_timeseries(const mio::VectorRange>>, const std::string&, + Date, const std::vector&, const std::vector&, + const ScalarType, const int, const mio::regions::de::EpidataFilenames&); #endif // MEMILIO_HAS_HDF5 diff --git a/cpp/models/ode_secirts/parameters_io.h b/cpp/models/ode_secirts/parameters_io.h index f6a6d1d9ab..e5f5510890 100644 --- a/cpp/models/ode_secirts/parameters_io.h +++ b/cpp/models/ode_secirts/parameters_io.h @@ -359,39 +359,6 @@ IOResult read_input_data(const mio::VectorRange>>& int num_days, const std::vector>& immunity_population, const mio::regions::de::EpidataFilenames& epidata_filenames); -/** - * @brief Converts input data from one range of models to another with different type. - * - * @tparam FP Floating point type (default: double). - * @param[in] model_from VectorRange of Node%s each containing a Model with the input data. - * @param[in,out] model_to VectorRange of Node%s each containing a Model to be initialized with data. - * @param[in] date Date for which the data should be read. - * @param[in] num_days Number of days to simulate. - * @param[in] epidata_filenames Object containing the input data file paths. - * - * @return An IOResult indicating success or failure. - */ -template -IOResult convert_input_data_type(const mio::VectorRange>>& model_from, - const mio::VectorRange>>& model_to, Date date, int num_days, - const mio::regions::de::EpidataFilenames& epidata_filenames) -{ - assert(model_from.size() == model_to.size()); - assert((size_t)model_from[0].property.parameters.get_num_groups() == - (size_t)model_to[0].property.parameters.get_num_groups()); - // Todo: add conversion of ParameterSet and then re-use code from all model parameters io - // For now call set_vacination_data with FP to set correct parameters - BOOST_OUTCOME_TRY( - details::set_vaccination_data(model_to, epidata_filenames.vaccination_data_path, date, num_days)); - - for (size_t region_idx = 0; region_idx < model_from.size(); ++region_idx) { - // convert populations to mio::UncertainValue - // needs 2 converts as mio::UncertainValue -> mio::UncertainValue does not work - model_to[region_idx].property.populations = model_from[region_idx].property.populations.template convert(); - } - return success(); -} - #ifdef MEMILIO_HAS_HDF5 /** diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 2e989e6e42..2b6545cd22 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -392,7 +392,7 @@ IOResult export_input_data_county_timeseries(const mio::VectorRange -IOResult convert_input_data_type(const mio::VectorRange>>& model_from, +IOResult convert_model_data_type(const mio::VectorRange>>& model_from, const mio::VectorRange>>& model_to, Date date, int num_days, const mio::regions::de::EpidataFilenames& epidata_filenames) { From c3486141d88d058f18e220253bffdb14606e5c9b Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Thu, 27 Nov 2025 19:43:08 +0000 Subject: [PATCH 25/26] update bindings --- .../simulation/bindings/simulation.cpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp b/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp index 22ef15ac14..27ab2733d8 100755 --- a/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp +++ b/pycode/memilio-simulation/memilio/simulation/bindings/simulation.cpp @@ -59,7 +59,7 @@ PYBIND11_MODULE(_simulation, m) pymio::bind_CustomIndexArray, mio::AgeGroup>(m, "AgeGroupArray"); pymio::bind_class>(m, "AgeGroup") .def(py::init()); - + pymio::bind_CustomIndexArray(m, "AgeGroupSimulationDayArray"); pymio::bind_class>(m, "SimulationDay") @@ -70,7 +70,8 @@ PYBIND11_MODULE(_simulation, m) auto damping_class = pymio::bind_class, pymio::EnablePickling::Required>(m, "Damping"); pymio::bind_damping_members(damping_class); - auto dampings_class = pymio::bind_class, pymio::EnablePickling::Required>(m, "Dampings"); + auto dampings_class = + pymio::bind_class, pymio::EnablePickling::Required>(m, "Dampings"); pymio::bind_dampings_members(dampings_class); pymio::bind_time_series(m, "TimeSeries"); @@ -99,12 +100,13 @@ PYBIND11_MODULE(_simulation, m) pymio::bind_class, pymio::EnablePickling::Required>(m, "MobilityDampings"); pymio::bind_dampings_members(mobility_dampings_class); - auto mobility_coeffs_class = - pymio::bind_class, pymio::EnablePickling::Required>(m, "MobilityCoefficients"); + auto mobility_coeffs_class = pymio::bind_class, pymio::EnablePickling::Required>( + m, "MobilityCoefficients"); pymio::bind_damping_expression_members(mobility_coeffs_class); - auto mobility_coeff_group_class = pymio::bind_class, pymio::EnablePickling::Required>( - m, "MobilityCoefficientGroup"); + auto mobility_coeff_group_class = + pymio::bind_class, pymio::EnablePickling::Required>( + m, "MobilityCoefficientGroup"); pymio::bind_damping_expression_group_members(mobility_coeff_group_class); pymio::bind_dynamicNPI_members(m, "DynamicNPIs"); @@ -117,17 +119,17 @@ PYBIND11_MODULE(_simulation, m) m.def( "get_state_id_de", [](int county) { - return int(mio::regions::de::get_state_id(int(mio::regions::de::CountyId(county)))); + return int(mio::regions::get_state_id(int(mio::regions::CountyId(county)))); }, py::arg("county_id")); m.def( "get_holidays_de", [](int state, mio::Date start_date, mio::Date end_date) { - auto h = mio::regions::de::get_holidays(mio::regions::de::StateId(state), start_date, end_date); + auto h = mio::regions::get_holidays(mio::regions::StateId(state), start_date, end_date); return std::vector>(h.begin(), h.end()); }, py::arg("state_id"), py::arg("start_date") = mio::Date(std::numeric_limits::min(), 1, 1), - py::arg("end_date") = mio::Date(std::numeric_limits::max(), 1, 1)); + py::arg("end_date") = mio::Date(std::numeric_limits::max(), 1, 1)); m.def( "read_mobility_plain", From d6f990609c510906a45fe5e0421a63346b4b3f24 Mon Sep 17 00:00:00 2001 From: MaxBetz <104758467+MaxBetzDLR@users.noreply.github.com> Date: Mon, 1 Dec 2025 11:06:18 +0000 Subject: [PATCH 26/26] missplaced cast --- cpp/models/ode_secirvvs/parameters_io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/ode_secirvvs/parameters_io.h b/cpp/models/ode_secirvvs/parameters_io.h index 2b6545cd22..7b1cb75d1d 100644 --- a/cpp/models/ode_secirvvs/parameters_io.h +++ b/cpp/models/ode_secirvvs/parameters_io.h @@ -187,7 +187,7 @@ IOResult set_vaccination_data(Model& model, const std::vector( floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); auto vaccination_distance = - floor(static_cast(static_cast(model.parameters.template get>()[AgeGroup(0)]))); + static_cast(floor(static_cast(model.parameters.template get>()[AgeGroup(0)]))); for (auto&& vacc_data_entry : vacc_data) { auto date_df = vacc_data_entry.date;