20 #ifndef MEMILIO_IO_EPI_DATA_H
21 #define MEMILIO_IO_EPI_DATA_H
25 #ifdef MEMILIO_HAS_JSONCPP
34 #include "json/value.h"
44 class StringDate :
public Date
49 StringDate(
const Date& other)
54 template <
class IoContext>
55 static IOResult<StringDate>
deserialize(IoContext& io)
60 [](
auto&& str_) -> IOResult<StringDate> {
61 BOOST_OUTCOME_TRY(
auto&& date,
parse_date(str_));
73 class ConfirmedCasesNoAgeEntry
81 template <
class IOContext>
82 static IOResult<ConfirmedCasesNoAgeEntry>
deserialize(IOContext& io)
84 auto obj = io.expect_object(
"ConfirmedCasesNoAgeEntry");
85 auto num_confirmed = obj.expect_element(
"Confirmed", Tag<ScalarType>{});
86 auto num_recovered = obj.expect_element(
"Recovered", Tag<ScalarType>{});
87 auto num_deaths = obj.expect_element(
"Deaths", Tag<ScalarType>{});
88 auto date = obj.expect_element(
"Date", Tag<StringDate>{});
91 [](
auto&& nc,
auto&& nr,
auto&& nd,
auto&& d) {
92 return ConfirmedCasesNoAgeEntry{nc, nr, nd, d};
94 num_confirmed, num_recovered, num_deaths, date);
104 inline IOResult<std::vector<ConfirmedCasesNoAgeEntry>> deserialize_confirmed_cases_noage(
const Json::Value& jsvalue)
106 return deserialize_json(jsvalue,
Tag<std::vector<ConfirmedCasesNoAgeEntry>>{});
115 inline IOResult<std::vector<ConfirmedCasesNoAgeEntry>> read_confirmed_cases_noage(
const std::string& filename)
117 return read_json(filename,
Tag<std::vector<ConfirmedCasesNoAgeEntry>>{});
126 class ConfirmedCasesDataEntry
129 static std::vector<const char*> age_group_names;
136 boost::optional<regions::StateId> state_id;
137 boost::optional<regions::CountyId> county_id;
138 boost::optional<regions::DistrictId> district_id;
140 template <
class IOContext>
141 static IOResult<ConfirmedCasesDataEntry>
deserialize(IOContext& io)
143 auto obj = io.expect_object(
"ConfirmedCasesDataEntry");
144 auto num_confirmed = obj.expect_element(
"Confirmed", Tag<ScalarType>{});
145 auto num_recovered = obj.expect_element(
"Recovered", Tag<ScalarType>{});
146 auto num_deaths = obj.expect_element(
"Deaths", Tag<ScalarType>{});
147 auto date = obj.expect_element(
"Date", Tag<StringDate>{});
148 auto age_group_str = obj.expect_element(
"Age_RKI", Tag<std::string>{});
149 auto state_id = obj.expect_optional(
"ID_State", Tag<regions::StateId>{});
150 auto county_id = obj.expect_optional(
"ID_County", Tag<regions::CountyId>{});
151 auto district_id = obj.expect_optional(
"ID_District", Tag<regions::DistrictId>{});
154 [](
auto&& nc,
auto&& nr,
auto&& nd,
auto&& d,
auto&& a_str,
auto&& sid,
auto&& cid,
155 auto&& did) -> IOResult<ConfirmedCasesDataEntry> {
156 auto a = AgeGroup(0);
157 auto it = std::find(age_group_names.begin(), age_group_names.end(), a_str);
158 if (it != age_group_names.end()) {
159 a = AgeGroup(
size_t(it - age_group_names.begin()));
161 else if (a_str ==
"unknown") {
162 a = AgeGroup(age_group_names.size());
167 return success(ConfirmedCasesDataEntry{nc, nr, nd, d, a, sid, cid, did});
169 num_confirmed, num_recovered, num_deaths, date, age_group_str, state_id, county_id, district_id);
178 inline IOResult<std::vector<ConfirmedCasesDataEntry>> deserialize_confirmed_cases_data(
const Json::Value& jsvalue)
180 BOOST_OUTCOME_TRY(
auto&& cases_data, deserialize_json(jsvalue,
Tag<std::vector<ConfirmedCasesDataEntry>>{}));
182 auto it = std::remove_if(cases_data.begin(), cases_data.end(), [](
auto&& rki_entry) {
183 return rki_entry.age_group >= AgeGroup(ConfirmedCasesDataEntry::age_group_names.size());
185 cases_data.erase(it, cases_data.end());
186 return success(std::move(cases_data));
194 inline IOResult<std::vector<ConfirmedCasesDataEntry>> read_confirmed_cases_data(
const std::string& filename)
196 BOOST_OUTCOME_TRY(
auto&& jsvalue, read_json(filename));
197 return deserialize_confirmed_cases_data(jsvalue);
211 boost::optional<regions::StateId> state_id;
212 boost::optional<regions::CountyId> county_id;
213 boost::optional<regions::DistrictId> district_id;
215 template <
class IoContext>
216 static IOResult<DiviEntry>
deserialize(IoContext& io)
218 auto obj = io.expect_object(
"DiviEntry");
219 auto num_icu = obj.expect_element(
"ICU", Tag<ScalarType>{});
220 auto date = obj.expect_element(
"Date", Tag<StringDate>{});
221 auto state_id = obj.expect_optional(
"ID_State", Tag<regions::StateId>{});
222 auto county_id = obj.expect_optional(
"ID_County", Tag<regions::CountyId>{});
223 auto district_id = obj.expect_optional(
"ID_District", Tag<regions::DistrictId>{});
226 [](
auto&& ni,
auto&& d,
auto&& sid,
auto&& cid,
auto&& did) {
227 return DiviEntry{ni, d, sid, cid, did};
229 num_icu, date, state_id, county_id, district_id);
238 inline bool is_divi_data_available(
const Date& date)
240 static const Date divi_data_start(2020, 4, 23);
241 return date >= divi_data_start;
252 inline bool is_vaccination_data_available(
const Date& start_date,
const Date& end_date)
254 static const Date vaccination_data_start(2020, 12, 27);
255 static const Date vaccination_data_end(2024, 7, 9);
256 return !(end_date < vaccination_data_start || start_date > vaccination_data_end);
264 inline IOResult<std::vector<DiviEntry>> deserialize_divi_data(
const Json::Value& jsvalue)
266 return deserialize_json(jsvalue,
Tag<std::vector<DiviEntry>>{});
274 inline IOResult<std::vector<DiviEntry>> read_divi_data(
const std::string& filename)
276 return read_json(filename,
Tag<std::vector<DiviEntry>>{});
283 IOResult<std::vector<T>> unpack_all(
const std::vector<IOResult<T>>& v)
288 BOOST_OUTCOME_TRY(
auto&& t, r);
301 class PopulationDataEntry
304 static std::vector<const char*> age_group_names;
306 CustomIndexArray<ScalarType, AgeGroup> population;
307 boost::optional<regions::StateId> state_id;
308 boost::optional<regions::CountyId> county_id;
309 boost::optional<regions::DistrictId> district_id;
311 template <
class IoContext>
312 static IOResult<PopulationDataEntry>
deserialize(IoContext& io)
314 auto obj = io.expect_object(
"PopulationDataEntry");
315 auto state_id = obj.expect_optional(
"ID_State", Tag<regions::StateId>{});
316 auto county_id = obj.expect_optional(
"ID_County", Tag<regions::CountyId>{});
317 auto district_id = obj.expect_optional(
"ID_District", Tag<regions::DistrictId>{});
318 std::vector<IOResult<ScalarType>> age_groups;
319 age_groups.reserve(age_group_names.size());
320 std::transform(age_group_names.begin(), age_group_names.end(), std::back_inserter(age_groups),
321 [&obj](
auto&& age_name) {
322 return obj.expect_element(age_name, Tag<ScalarType>{});
326 [](
auto&& ag,
auto&& sid,
auto&& cid,
auto&& did) {
327 return PopulationDataEntry{
328 CustomIndexArray<ScalarType, AgeGroup>(AgeGroup(ag.size()), ag.begin(), ag.end()), sid, cid, did};
330 details::unpack_all(age_groups), state_id, county_id, district_id);
336 inline void get_rki_age_interpolation_coefficients(
const std::vector<ScalarType>& age_ranges,
337 std::vector<std::vector<ScalarType>>& interpolation,
338 std::vector<bool>& carry_over)
340 std::array<ScalarType, 6> param_ranges = {5., 10., 20., 25., 20., 20.};
341 assert(param_ranges.size() == ConfirmedCasesDataEntry::age_group_names.size() &&
342 "Number of RKI age groups does not match number of age ranges.");
349 for (
size_t i = 0;
i < age_ranges.size();
i++) {
353 interpolation[
i].push_back(
std::min(-res / age_ranges[
i], 1.0));
356 if (counter < param_ranges.size() - 1) {
357 res += age_ranges[
i];
363 res -= param_ranges[counter];
364 interpolation[
i].push_back((param_ranges[counter] +
std::min(res, 0.0)) / age_ranges[
i]);
370 carry_over.push_back(
true);
373 carry_over.push_back(
false);
378 interpolation[
i].push_back((age_ranges[
i] + res) / age_ranges[
i]);
379 if (res < 0 || counter == 0) {
380 carry_over.push_back(
true);
383 carry_over.push_back(
false);
390 inline std::vector<PopulationDataEntry>
391 interpolate_to_rki_age_groups(
const std::vector<PopulationDataEntry>& population_data)
393 std::vector<ScalarType> age_ranges = {3., 3., 9., 3., 7., 5., 10., 10., 15., 10., 25.};
394 std::vector<std::vector<ScalarType>> coefficients{age_ranges.size()};
395 std::vector<bool> carry_over{};
396 get_rki_age_interpolation_coefficients(age_ranges, coefficients, carry_over);
398 std::vector<PopulationDataEntry> interpolated{population_data};
399 for (
auto region_entry_idx =
size_t(0); region_entry_idx < population_data.size(); ++region_entry_idx) {
400 interpolated[region_entry_idx].population =
401 CustomIndexArray<ScalarType, AgeGroup>(AgeGroup(ConfirmedCasesDataEntry::age_group_names.
size()), 0.0);
403 size_t interpolated_age_idx = 0;
404 for (
size_t age_idx = 0; age_idx < coefficients.size(); age_idx++) {
405 for (
size_t coeff_idx = 0; coeff_idx < coefficients[age_idx].size(); coeff_idx++) {
406 interpolated[region_entry_idx].population[AgeGroup(interpolated_age_idx)] +=
407 coefficients[age_idx][coeff_idx] * population_data[region_entry_idx].population[AgeGroup(age_idx)];
408 if (coeff_idx < coefficients[age_idx].
size() - 1 || !carry_over[age_idx]) {
409 interpolated_age_idx++;
426 inline IOResult<std::vector<PopulationDataEntry>> deserialize_population_data(
const Json::Value& jsvalue,
427 bool rki_age_groups =
true)
429 BOOST_OUTCOME_TRY(
auto&& population_data, deserialize_json(jsvalue,
Tag<std::vector<PopulationDataEntry>>{}));
430 if (rki_age_groups) {
431 return success(details::interpolate_to_rki_age_groups(population_data));
434 return success(population_data);
444 inline IOResult<std::vector<PopulationDataEntry>> read_population_data(
const std::string& filename,
445 bool rki_age_group =
true)
447 BOOST_OUTCOME_TRY(
auto&& jsvalue, read_json(filename));
448 return deserialize_population_data(jsvalue, rki_age_group);
455 IOResult<void> set_confirmed_cases_age_group_names(std::vector<const char*> names);
461 IOResult<void> set_population_data_age_group_names(std::vector<const char*> names);
467 IOResult<void> set_vaccination_data_age_group_names(std::vector<const char*> names);
476 IOResult<std::vector<int>> get_node_ids(
const std::string& path,
bool is_node_for_county,
bool rki_age_groups =
true);
481 class VaccinationDataEntry
484 static std::vector<const char*> age_group_names;
486 ScalarType num_vaccinations_partial, num_vaccinations_completed, num_vaccinations_refreshed_first,
487 num_vaccinations_refreshed_additional;
490 boost::optional<regions::StateId> state_id;
491 boost::optional<regions::CountyId> county_id;
492 boost::optional<regions::DistrictId> district_id;
494 template <
class IoContext>
495 static IOResult<VaccinationDataEntry>
deserialize(IoContext& io)
497 auto obj = io.expect_object(
"VaccinationDataEntry");
498 auto num_vaccinations_partial = obj.expect_element(
"Vacc_partially", Tag<ScalarType>{});
499 auto num_vaccinations_completed = obj.expect_element(
"Vacc_completed", Tag<ScalarType>{});
500 auto num_vaccinations_refreshed_first = obj.expect_optional(
"Vacc_refreshed", Tag<ScalarType>{});
501 auto num_vaccinations_refreshed_additional = obj.expect_optional(
"Vacc_refreshed_2", Tag<ScalarType>{});
502 auto date = obj.expect_element(
"Date", Tag<StringDate>{});
503 auto age_group_str = obj.expect_element(
"Age_RKI", Tag<std::string>{});
504 auto state_id = obj.expect_optional(
"ID_County", Tag<regions::StateId>{});
505 auto county_id = obj.expect_optional(
"ID_County", Tag<regions::CountyId>{});
506 auto district_id = obj.expect_optional(
"ID_District", Tag<regions::DistrictId>{});
509 [](
auto np,
auto nc,
auto n_refreshed_1,
auto n_refreshed_2,
auto d,
auto&& a_str,
auto sid,
auto cid,
510 auto did) -> IOResult<VaccinationDataEntry> {
511 auto it = std::find(age_group_names.begin(), age_group_names.end(), a_str);
512 auto a = AgeGroup(0);
513 if (it != age_group_names.end()) {
514 a = AgeGroup(
size_t(it - age_group_names.begin()));
517 return failure(StatusCode::InvalidValue,
"Invalid vaccination data age group.");
520 auto n_refreshed_1_value = n_refreshed_1.value_or(0.0);
521 auto n_refreshed_2_value = n_refreshed_2.value_or(0.0);
523 VaccinationDataEntry{np, nc, n_refreshed_1_value, n_refreshed_2_value, d, a, sid, cid, did});
525 num_vaccinations_partial, num_vaccinations_completed, num_vaccinations_refreshed_first,
526 num_vaccinations_refreshed_additional, date, age_group_str, state_id, county_id, district_id);
535 inline IOResult<std::vector<VaccinationDataEntry>> deserialize_vaccination_data(
const Json::Value& jsvalue)
537 return deserialize_json(jsvalue,
Tag<std::vector<VaccinationDataEntry>>{});
545 inline IOResult<std::vector<VaccinationDataEntry>> read_vaccination_data(
const std::string& filename)
547 BOOST_OUTCOME_TRY(
auto&& jsvalue, read_json(filename));
548 return deserialize_vaccination_data(jsvalue);
double ScalarType
Configuration of memilio library.
Definition: memilio/config.h:30
static min_max_return_type< ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > >::type min(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &a, const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &b)
Definition: ad.hpp:2599
ad::internal::unary_intermediate< AD_TAPE_REAL, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::operations::ad_fabs< AD_TAPE_REAL > > abs(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &x1)
Definition: ad.hpp:1144
int size(Comm comm)
Return the size of the given communicator.
Definition: miompi.cpp:75
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
IOResult< T > deserialize(IOContext &io, Tag< T > tag)
Restores an object from the data stored in an IO context.
Definition: io.h:860
auto failure(const IOStatus &s)
Create an object that is implicitly convertible to an error IOResult<T>.
Definition: io.h:380
boost::outcome_v2::in_place_type_t< T > Tag
Type that is used for overload resolution.
Definition: io.h:407
auto i
Definition: io.h:809
details::ApplyResultT< F, T... > apply(IOContext &io, F f, const IOResult< T > &... rs)
Evaluate a function with zero or more unpacked IOResults as arguments.
Definition: io.h:481
auto success()
Create an object that is implicitly convertible to a succesful IOResult<void>.
Definition: io.h:359
IOResult< Date > parse_date(const std::string &date_str)
parses a date from a string.
Definition: date.h:219
Date()=default
default constructor.