Skip to content

Commit 1959d3b

Browse files
committed
Simplify parameters io
1 parent 08a6cf0 commit 1959d3b

File tree

5 files changed

+439
-619
lines changed

5 files changed

+439
-619
lines changed

cpp/memilio/io/parameters_io.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,45 @@
3030

3131
namespace mio
3232
{
33+
IOResult<std::vector<ScalarType>> compute_divi_data(const std::vector<DiviEntry>& divi_data, const std::vector<int>& vregion, Date date)
34+
{
35+
36+
auto max_date_entry = std::max_element(divi_data.begin(), divi_data.end(), [](auto&& a, auto&& b) {
37+
return a.date < b.date;
38+
});
39+
if (max_date_entry == divi_data.end()) {
40+
log_error("DIVI data is empty.");
41+
return failure(StatusCode::InvalidValue, "DIVI data is empty.");
42+
}
43+
auto max_date = max_date_entry->date;
44+
if (max_date < date) {
45+
log_error("DIVI data does not contain the specified date.");
46+
return failure(StatusCode::OutOfRange, "DIVI data does not contain the specified date.");
47+
}
48+
49+
std::vector<ScalarType> vnum_icu(vregion.size(), 0.0);
50+
51+
52+
for (auto&& entry : divi_data) {
53+
auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) {
54+
return r == 0 || r == get_region_id(entry);
55+
});
56+
auto date_df = entry.date;
57+
if (it != vregion.end() && date_df == date) {
58+
auto region_idx = size_t(it - vregion.begin());
59+
vnum_icu[region_idx] = entry.num_icu;
60+
}
61+
}
62+
63+
return success(vnum_icu);
64+
}
65+
66+
IOResult<std::vector<ScalarType>> read_divi_data(const std::string& path, const std::vector<int>& vregion, Date date)
67+
{
68+
BOOST_OUTCOME_TRY(auto&& divi_data, mio::read_divi_data(path));
69+
return compute_divi_data(divi_data, vregion, date);
70+
}
71+
3372
IOResult<std::vector<std::vector<ScalarType>>>
3473
read_population_data(const std::vector<PopulationDataEntry>& population_data, const std::vector<int>& vregion)
3574
{

cpp/memilio/io/parameters_io.h

Lines changed: 68 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -52,66 +52,94 @@ int get_region_id(const EpiDataEntry& data_entry)
5252

5353
/**
5454
* @brief Extracts the number of individuals in critical condition (ICU) for each region
55-
* on a specified date from the provided DIVI data.
55+
* on a specified date from the provided DIVI data-
5656
*
57+
* @param[in] divi_data Vector of DIVI data entries containing date, region, and ICU information.
58+
* @param[in] vregion Vector of region IDs for which the data is computed.
59+
* @param[in] date Date for which the ICU data is computed.
60+
* @return An IOResult containing a vector with the number of ICU cases for each region, or an
61+
* error if the function fails.
62+
*/
63+
IOResult<std::vector<ScalarType>> compute_divi_data(const std::vector<DiviEntry>& divi_data, const std::vector<int>& vregion, Date date);
64+
65+
/**
66+
* @brief Reads DIVI data from a file and computes the ICU data for specified regions and date.
67+
*
68+
* @param[in] path Path to the file containing DIVI data.
69+
* @param[in] vregion Vector of region IDs for which the data is computed.
70+
* @param[in] date Date for which the ICU data is computed.
71+
* @return An IOResult containing a vector with the number of ICU cases for each region, or an
72+
* error if the function fails.
73+
*/
74+
IOResult<std::vector<ScalarType>> read_divi_data(const std::string& path, const std::vector<int>& vregion, Date date);
75+
76+
/**
77+
* @brief Sets ICU data from DIVI data into the a vector of models, distributed across age groups.
78+
*
79+
* This function reads DIVI data from a file, computes the number of individuals in critical condition (ICU)
80+
* for each region, and sets these values in the model. The ICU cases are distributed across age groups
81+
* using the transition probabilities from severe to critical.
82+
*
83+
* @tparam Model The type of the model used.
5784
* @tparam FP Floating point type (default: double).
5885
*
59-
* @param[in] divi_data Vector of DIVI data entries containing date, region, and ICU information.
86+
* @param[in,out] model Vector of models, each representing a region, where the ICU population is updated.
87+
* @param[in] num_icu vector of icu data
6088
* @param[in] vregion Vector of region IDs for which the data is computed.
6189
* @param[in] date Date for which the ICU data is computed.
62-
* @param[in, out] vnum_icu Output vector containing the number of ICU cases for each region.
90+
* @param[in] scaling_factor_icu Scaling factor for reported ICU cases.
6391
*
6492
* @return An IOResult indicating success or failure.
6593
*/
66-
template <typename FP = ScalarType>
67-
IOResult<void> compute_divi_data(const std::vector<DiviEntry>& divi_data, const std::vector<int>& vregion, Date date,
68-
std::vector<FP>& vnum_icu)
94+
template <typename FP, class Model>
95+
IOResult<void> set_divi_data(std::vector<Model>& model, const std::vector<double>& num_icu, const std::vector<int>& vregion,
96+
Date date, FP scaling_factor_icu)
6997
{
70-
auto max_date_entry = std::max_element(divi_data.begin(), divi_data.end(), [](auto&& a, auto&& b) {
71-
return a.date < b.date;
72-
});
73-
if (max_date_entry == divi_data.end()) {
74-
log_error("DIVI data is empty.");
75-
return failure(StatusCode::InvalidValue, "DIVI data is empty.");
76-
}
77-
auto max_date = max_date_entry->date;
78-
if (max_date < date) {
79-
log_error("DIVI data does not contain the specified date.");
80-
return failure(StatusCode::OutOfRange, "DIVI data does not contain the specified date.");
98+
std::vector<FP> sum_mu_I_U(vregion.size(), 0);
99+
std::vector<std::vector<FP>> mu_I_U{model.size()};
100+
for (size_t region = 0; region < vregion.size(); region++) {
101+
auto num_groups = model[region].parameters.get_num_groups();
102+
for (auto i = AgeGroup(0); i < num_groups; i++) {
103+
sum_mu_I_U[region] += model[region].parameters.template get<CriticalPerSevere<FP>>()[i] *
104+
model[region].parameters.template get<SeverePerInfectedSymptoms<FP>>()[i];
105+
mu_I_U[region].push_back(model[region].parameters.template get<CriticalPerSevere<FP>>()[i] *
106+
model[region].parameters.template get<SeverePerInfectedSymptoms<FP>>()[i]);
107+
}
81108
}
82109

83-
for (auto&& entry : divi_data) {
84-
auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) {
85-
return r == 0 || r == get_region_id(entry);
86-
});
87-
auto date_df = entry.date;
88-
if (it != vregion.end() && date_df == date) {
89-
auto region_idx = size_t(it - vregion.begin());
90-
vnum_icu[region_idx] = entry.num_icu;
110+
for (size_t region = 0; region < vregion.size(); region++) {
111+
auto num_groups = model[region].parameters.get_num_groups();
112+
for (auto i = AgeGroup(0); i < num_groups; i++) {
113+
model[region].populations[{i, InfectionState::InfectedCriticalNaive}] =
114+
scaling_factor_icu * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region];
91115
}
92116
}
93117

94118
return success();
95119
}
96120

97121
/**
98-
* @brief Reads DIVI data from a file and computes the ICU data for specified regions and date.
99-
*
100-
* @tparam FP Floating point type (default: double).
101-
*
102-
* @param[in] path Path to the file containing DIVI data.
103-
* @param[in] vregion Vector of region IDs for which the data is computed.
104-
* @param[in] date Date for which the ICU data is computed.
105-
* @param[in, out] vnum_icu Output vector containing the number of ICU cases for each region.
106-
*
107-
* @return An IOResult indicating success or failure.
122+
* @brief sets populations data from DIVI register into Model
123+
* @param[in, out] model vector of objects in which the data is set
124+
* @param[in] path Path to transformed DIVI file
125+
* @param[in] vregion vector of keys of the regions of interest
126+
* @param[in] date Date for which the arrays are initialized
127+
* @param[in] scaling_factor_icu factor by which to scale the icu cases of divi data
108128
*/
109-
template <typename FP = ScalarType>
110-
IOResult<void> read_divi_data(const std::string& path, const std::vector<int>& vregion, Date date,
111-
std::vector<FP>& vnum_icu)
129+
template <class Model>
130+
IOResult<void> set_divi_data(std::vector<Model>& model, const std::string& path, const std::vector<int>& vregion,
131+
Date date, double scaling_factor_icu)
112132
{
113-
BOOST_OUTCOME_TRY(auto&& divi_data, mio::read_divi_data(path));
114-
return compute_divi_data(divi_data, vregion, date, vnum_icu);
133+
// DIVI dataset will no longer be updated from CW29 2024 on.
134+
if (!is_divi_data_available(date)) {
135+
log_warning("No DIVI data available for date: {}. "
136+
"ICU compartment will be set based on Case data.",
137+
date);
138+
return success();
139+
}
140+
BOOST_OUTCOME_TRY(auto&& num_icu, read_divi_data(path, vregion, date));
141+
BOOST_OUTCOME_TRY(set_divi_data(model, num_icu, rki_data, vregion, date, scaling_factor_icu));
142+
return success();
115143
}
116144

117145
/**

0 commit comments

Comments
 (0)