From 3fcb8773843cefd976624e52be3a0e461e873375 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 31 Jul 2023 17:30:37 +0200 Subject: [PATCH 001/488] firstcommit --- cpp/models/abm/infection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 504724a0eb..62fe109c75 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -130,6 +130,7 @@ void Infection::draw_infection_course_forward(AgeGroup age, const GlobalInfectio v = uniform_dist(); if (v < 0.5) { // TODO: subject to change time_period = days(params.get()[{ + //Todo:e.g. is this timelength m_virus_variant, age, VaccinationState::Unvaccinated}]); // TODO: subject to change next_state = InfectionState::InfectedSymptoms; } From 3113609dfd1de34080635910473ec6a622bc32d1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:23:55 +0200 Subject: [PATCH 002/488] add first draft for tree --- cpp/models/abm/test_tree.cpp | 10 +++++ cpp/models/abm/weighted_decision_tree.h | 54 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 cpp/models/abm/test_tree.cpp create mode 100644 cpp/models/abm/weighted_decision_tree.h diff --git a/cpp/models/abm/test_tree.cpp b/cpp/models/abm/test_tree.cpp new file mode 100644 index 0000000000..9a7b64e6b5 --- /dev/null +++ b/cpp/models/abm/test_tree.cpp @@ -0,0 +1,10 @@ +#include "weighted_decision_tree.h" +#include + +int main(int argc, char const* argv[]) +{ + auto nodes = std::vector({1, 4, 10}); + auto edges = std::vector>({{1, 4, 0.5}, {4, 10, 0.5}}); + auto decision_tree = weighted_decision_tree(nodes, edges); + return 0; +} diff --git a/cpp/models/abm/weighted_decision_tree.h b/cpp/models/abm/weighted_decision_tree.h new file mode 100644 index 0000000000..20047d5d98 --- /dev/null +++ b/cpp/models/abm/weighted_decision_tree.h @@ -0,0 +1,54 @@ +/* +* Copyright (C) 2020-2021 German Aerospace Center (DLR-SC) +* +* Authors: Sascha Korf +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include + +struct TreeNode { + int value; +}; + +struct TreeEdge { + double time_length; +}; + +class weighted_decision_tree +{ +public: + weighted_decision_tree(std::vector nodes, std::vector> edges) + { + for (auto edge : edges) { + auto parent_node = std::find(nodes.begin(), nodes.end(), std::get<0>(edge)); + auto child_node = std::find(nodes.begin(), nodes.end(), std::get<1>(edge)); + build_tree(TreeNode{*parent_node}, TreeEdge{std::get<2>(edge)}, TreeNode{*child_node}); + } + } + +private: + void build_tree(TreeNode node, TreeEdge edge, TreeNode child) + { + m_tree.insert({node, std::make_pair(edge, child)}); + } + + std::map> m_tree; +}; From 25e790541dd6e0a3424f4c79ffe28c91a5ef6a86 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:14:04 +0100 Subject: [PATCH 003/488] Update parameters --- cpp/models/abm/parameters.h | 126 +++++++++++++++------------ cpp/models/ode_secirvvs/parameters.h | 2 +- 2 files changed, 73 insertions(+), 55 deletions(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index ad1d37b49a..0031e50070 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -39,14 +39,17 @@ namespace mio namespace abm { +// Distribution that can be used for the time spend in InfectionStates +using InfectionStateTimesDistributionsParameters = UniformDistribution::ParamType; + /** - * @brief Time that a Person is infected but not yet infectious. + * @brief Time that a Person is infected but not yet infectious in day unit */ struct IncubationPeriod { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { @@ -54,113 +57,127 @@ struct IncubationPeriod { } }; -struct InfectedNoSymptomsToSymptoms { - using Type = CustomIndexArray; +/** +* @brief Time that a Person is infected but nonsymptomatic in day unit +*/ +struct TimeInfectedNoSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedNoSymptomsToSymptoms"; + return "TimeInfectedNoSymptoms"; } }; -struct InfectedNoSymptomsToRecovered { - using Type = CustomIndexArray; +/** +* @brief Time that a Person is infected and symptomatic but +* who do not need to be hospitalized (yet) in day unit +*/ +struct TimeInfectedSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedNoSymptomsToRecovered"; + return "TimeInfectedSymptoms"; } }; -struct InfectedSymptomsToRecovered { - using Type = CustomIndexArray; +/** + * @brief Time that a Person is infected and 'simply' hospitalized in day unit + */ +struct TimeInfectedSevere { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedSymptomsToRecovered"; + return "TimeInfectedSevere"; } }; -struct InfectedSymptomsToSevere { - using Type = CustomIndexArray; +/** + * @brief Time that a Person is treated by ICU in day unit + */ +struct TimeInfectedCritical { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "InfectedSymptomsToSevere"; + return "TimeInfectedCritical"; } }; -struct SevereToCritical { - using Type = CustomIndexArray; +/** +* @brief the percentage of symptomatic cases +*/ +struct SymptomsPerInfectedNoSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "SevereToCritical"; + return "SymptomaticPerInfectedNoSymptoms"; } }; -struct SevereToRecovered { - using Type = CustomIndexArray; +/** +* @brief the percentage of hospitalized patients per infected patients +*/ +struct SeverePerInfectedSymptoms { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "SevereToRecovered"; + return "SeverePerInfectedSymptoms"; } }; -struct CriticalToRecovered { - using Type = CustomIndexArray; +/** +* @brief the percentage of ICU patients per hospitalized patients +*/ +struct CriticalPerInfectedSevere { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "CriticalToRecovered"; + return "CriticalPerInfectedSevere"; } }; -struct CriticalToDead { - using Type = CustomIndexArray; +/** +* @brief the percentage of dead patients per ICU patients +*/ +struct DeathsPerInfectedCritical { + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); } static std::string name() { - return "CriticalToDead"; + return "DeathsPerInfectedCritical"; } }; -struct RecoveredToSusceptible { - using Type = CustomIndexArray; - static Type get_default(AgeGroup size) - { - return Type({VirusVariant::Count, size}, 1.); - } - static std::string name() - { - return "RecoveredToSusceptible"; - } -}; /** * @brief Parameters for the ViralLoad course. Default values taken as constant values from the average from * https://github.com/VirologyCharite/SARS-CoV-2-VL-paper/tree/main @@ -363,7 +380,7 @@ struct PCRTest : public GenericTest { */ struct LockdownDate { using Type = TimePoint; - static auto get_default(AgeGroup /*size*/) + static auto get_default() { return TimePoint(std::numeric_limits::max()); } @@ -524,11 +541,11 @@ struct AgeGroupGotoWork { }; using ParametersBase = - ParameterSet; @@ -597,8 +614,9 @@ class Parameters : public ParametersBase { for (auto i = AgeGroup(0); i < AgeGroup(m_num_groups); ++i) { - if (this->get()[{VirusVariant::Wildtype, i}] < 0) { - log_error("Constraint check: Parameter IncubationPeriod of age group {:.0f} smaller than {:.4f}", + if (this->get()[{VirusVariant::Wildtype, i}].params.a() < 0) { + log_error("Constraint check: Lower end of parameter range IncubationPeriod of age group {:.0f} smaller " + "than {:.4f}", (size_t)i, 0); return true; } diff --git a/cpp/models/ode_secirvvs/parameters.h b/cpp/models/ode_secirvvs/parameters.h index 75540be02a..6fbbe045bb 100644 --- a/cpp/models/ode_secirvvs/parameters.h +++ b/cpp/models/ode_secirvvs/parameters.h @@ -150,7 +150,7 @@ struct IncubationTime { /** * @brief the infectious time for symptomatic cases that are infected but -* who do not need to be hsopitalized in the SECIR model in day unit +* who do not need to be hospitalized in the SECIR model in day unit */ struct TimeInfectedSymptoms { using Type = CustomIndexArray; From 7d92aa8d60567c3b12ba0ddf9cbd8a883ff193bf Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:15:40 +0100 Subject: [PATCH 004/488] Use new enum iterator --- cpp/memilio/utils/stl_util.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/cpp/memilio/utils/stl_util.h b/cpp/memilio/utils/stl_util.h index 1c58e4d707..2c4603d55e 100644 --- a/cpp/memilio/utils/stl_util.h +++ b/cpp/memilio/utils/stl_util.h @@ -22,6 +22,8 @@ #include "memilio/utils/metaprogramming.h" +#include +#include #include #include #include @@ -289,6 +291,30 @@ bool contains(Iter b, Iter e, Pred p) return find_if(b, e, p) != e; } +/** + * Get an std::array that contains all members of an enum class. + * The enum class must be a valid index, i.e. members must be sequential starting at 0 and there must + * be a member `Count` at the end, that will not be included in the array. + * Example: + * ``` + * enum class E { A, B, Count }; + * assert(enum_members() == std::array<2, E>(E::A, E::B)); + * ``` + * @tparam T An enum class that is a valid index. + * @return Array of all members of the enum class not including T::Count. + */ +template +constexpr std::array enum_members() +{ + auto enum_members = std::array{}; + auto indices = std::array, size_t(T::Count)>{}; + std::iota(indices.begin(), indices.end(), std::underlying_type_t(0)); + std::transform(indices.begin(), indices.end(), enum_members.begin(), [](auto i) { + return T(i); + }); + return enum_members; +} + } // namespace mio #endif //STL_UTIL_H From a4f16e877f0440b26c95f4a1ff810c7c806aef5c Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:29:06 +0100 Subject: [PATCH 005/488] Fix parameters --- cpp/models/abm/parameters.h | 168 +++++++++++++++++++----------------- 1 file changed, 89 insertions(+), 79 deletions(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 0031e50070..34ad76353b 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -122,10 +122,10 @@ struct TimeInfectedCritical { * @brief the percentage of symptomatic cases */ struct SymptomsPerInfectedNoSymptoms { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -137,10 +137,10 @@ struct SymptomsPerInfectedNoSymptoms { * @brief the percentage of hospitalized patients per infected patients */ struct SeverePerInfectedSymptoms { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -152,10 +152,10 @@ struct SeverePerInfectedSymptoms { * @brief the percentage of ICU patients per hospitalized patients */ struct CriticalPerInfectedSevere { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -167,10 +167,10 @@ struct CriticalPerInfectedSevere { * @brief the percentage of dead patients per ICU patients */ struct DeathsPerInfectedCritical { - using Type = CustomIndexArray; + using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + return Type({VirusVariant::Count, size}, 1.); } static std::string name() { @@ -613,77 +613,87 @@ class Parameters : public ParametersBase bool check_constraints() const { for (auto i = AgeGroup(0); i < AgeGroup(m_num_groups); ++i) { - - if (this->get()[{VirusVariant::Wildtype, i}].params.a() < 0) { - log_error("Constraint check: Lower end of parameter range IncubationPeriod of age group {:.0f} smaller " - "than {:.4f}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error( - "Constraint check: Parameter InfectedNoSymptomsToSymptoms of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error( - "Constraint check: Parameter InfectedNoSymptomsToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error( - "Constraint check: Parameter InfectedSymptomsToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter InfectedSymptomsToSevere of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter SevereToCritical of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter SevereToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter CriticalToDead of age group {:.0f} smaller than {:d}", (size_t)i, - 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter CriticalToRecovered of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0) { - log_error("Constraint check: Parameter RecoveredToSusceptible of age group {:.0f} smaller than {:d}", - (size_t)i, 0); - return true; - } - - if (this->get()[{VirusVariant::Wildtype, i}] < 0.0 || - this->get()[{VirusVariant::Wildtype, i}] > 1.0) { - log_error("Constraint check: Parameter DetectInfection of age group {:.0f} smaller than {:d} or " - "larger than {:d}", - (size_t)i, 0, 1); - return true; + for (auto&& v : enum_members()) { + + if (this->get()[{v, i}].params.a() < 0) { + log_error("Constraint check: Lower end of parameter range IncubationPeriod of virus variant {} and " + "age group {:.0f} smaller " + "than {:.4f}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptoms of virus variant " + "{} and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSymptoms of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSevere of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedCritical of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter SymptomsPerInfectedNoSymptoms of virus variant {} and age " + "group {:.0f} smaller than {:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter SeverePerInfectedSymptoms of virus variant {} and age group " + "{:.0f} smaller than {:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter CriticalPerInfectedSevere of virus variant {} and age group " + "{:.0f} smaller than {:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || + this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter DeathsPerInfectedCritical of age group {:.0f} smaller than " + "{:d} or larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } + + if (this->get()[{v, i}] < 0.0 || this->get()[{v, i}] > 1.0) { + log_error("Constraint check: Parameter DetectInfection of virus variant {} and age group {:.0f} " + "smaller than {:d} or " + "larger than {:d}", + v, (size_t)i, 0, 1); + return true; + } } if (this->get()[i].seconds() < 0.0 || From 64f2edf5ce5bca2aeba6d39808d099b176900958 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:27:52 +0100 Subject: [PATCH 006/488] Fix infection setup --- cpp/models/abm/infection.cpp | 127 ++++++++++++++++++++--------------- cpp/models/abm/parameters.h | 8 +-- 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 1783942764..07c4f12d50 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -129,76 +129,79 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng InfectionState next_state{start_state}; // next state to enter m_infection_course.push_back(std::pair(t, next_state)); auto& uniform_dist = UniformDistribution::get_instance(); - ScalarType v; // random draws + ScalarType p; // uniform random draws from [0, 1] while ((next_state != InfectionState::Recovered && next_state != InfectionState::Dead)) { switch (next_state) { case InfectionState::Exposed: // roll out how long until infected without symptoms - time_period = days(params.get()[{m_virus_variant, age}]); // subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); next_state = InfectionState::InfectedNoSymptoms; break; case InfectionState::InfectedNoSymptoms: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.5) { // TODO: subject to change - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + p = uniform_dist(rng); + if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedSymptoms; } else { - time_period = days( - params.get()[{m_virus_variant, age}]); // TODO: subject to change next_state = InfectionState::Recovered; } break; case InfectionState::InfectedSymptoms: // roll out next infection step - { - ScalarType severity_protection_factor = 0.5; - v = uniform_dist(rng); - if (latest_exposure.first != ExposureType::NoProtection) { - severity_protection_factor = - params.get()[{latest_exposure.first, age, m_virus_variant}]( - t.days() - latest_exposure.second.days()); - } - if (v < (1 - severity_protection_factor) * 0.5) { - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change - next_state = InfectionState::InfectedSevere; - } - else { - time_period = days( - params.get()[{m_virus_variant, age}]); // TODO: subject to change - next_state = InfectionState::Recovered; - } - break; + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + ScalarType severity_protection_factor = 1.; + p = uniform_dist(rng); + if (latest_exposure.first != ExposureType::NoProtection) { + severity_protection_factor = + params.get()[{latest_exposure.first, age, m_virus_variant}]( + t.days() - latest_exposure.second.days()); } + if (p < + (1 - severity_protection_factor) * params.get()[{m_virus_variant, age}]) { + next_state = InfectionState::InfectedSevere; + } + else { + next_state = InfectionState::Recovered; + } + + break; + case InfectionState::InfectedSevere: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.5) { // TODO: subject to change - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + p = uniform_dist(rng); + if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedCritical; } else { - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change next_state = InfectionState::Recovered; } break; + case InfectionState::InfectedCritical: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.5) { // TODO: subject to change - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + + p = uniform_dist(rng); + if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::Dead; } else { - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change next_state = InfectionState::Recovered; } break; + default: break; } @@ -213,61 +216,73 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato { auto start_date = init_date; TimeSpan time_period{}; // time period for current infection state - InfectionState previous_state{init_state}; // next state to enter + InfectionState previous_state{init_state}; // previous state to enter auto& uniform_dist = UniformDistribution::get_instance(); - ScalarType v; // random draws + ScalarType p; // uniform random draws from [0, 1] while ((previous_state != InfectionState::Exposed)) { switch (previous_state) { case InfectionState::InfectedNoSymptoms: - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::Exposed; break; case InfectionState::InfectedSymptoms: - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedNoSymptoms; break; case InfectionState::InfectedSevere: - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSymptoms; break; case InfectionState::InfectedCritical: - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSevere; break; case InfectionState::Recovered: // roll out next infection step - v = uniform_dist(rng); - if (v < 0.25) { - time_period = days( - params.get()[{m_virus_variant, age}]); // TODO: subject to change + p = uniform_dist(rng); + // compute correct probabilities while factoring out the chance to die + auto p_death = params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}]; + if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedNoSymptoms; } - else if (v < 0.5) { // TODO: subject to change - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + else if (p < params.get()[{m_virus_variant, age}] * + (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSymptoms; } - else if (v < 0.75) { - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + else if (p < params.get()[{m_virus_variant, age}] * + params.get()[{m_virus_variant, age}] * + (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedSevere; } else { - time_period = - days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedCritical; } break; case InfectionState::Dead: - time_period = days(params.get()[{m_virus_variant, age}]); // TODO: subject to change + auto time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); previous_state = InfectionState::InfectedCritical; break; diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 34ad76353b..2b1e68f95f 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -125,7 +125,7 @@ struct SymptomsPerInfectedNoSymptoms { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { @@ -140,7 +140,7 @@ struct SeverePerInfectedSymptoms { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { @@ -155,7 +155,7 @@ struct CriticalPerInfectedSevere { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { @@ -170,7 +170,7 @@ struct DeathsPerInfectedCritical { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { - return Type({VirusVariant::Count, size}, 1.); + return Type({VirusVariant::Count, size}, .5); } static std::string name() { From 8b995e20d5fe0488205a9c3354df1febbba42003 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:57:17 +0100 Subject: [PATCH 007/488] Fix analyze_result --- cpp/models/abm/analyze_result.h | 63 ++++++++++++++++++++----- cpp/models/abm/test_tree.cpp | 10 ---- cpp/models/abm/weighted_decision_tree.h | 54 --------------------- 3 files changed, 51 insertions(+), 76 deletions(-) delete mode 100644 cpp/models/abm/test_tree.cpp delete mode 100644 cpp/models/abm/weighted_decision_tree.h diff --git a/cpp/models/abm/analyze_result.h b/cpp/models/abm/analyze_result.h index 0e93be84a9..301ee8bffd 100644 --- a/cpp/models/abm/analyze_result.h +++ b/cpp/models/abm/analyze_result.h @@ -62,39 +62,78 @@ std::vector ensemble_params_percentile(const std::vector((uint32_t)virus_variant + 1)) { + for (auto virus_variant : enum_members()) { // Global infection parameters param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.a(); + return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .viral_load_incline.params.b(); + return result; }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - return model.parameters.template get()[{virus_variant, age_group}]; + return model.parameters.template get()[{virus_variant, age_group}]; }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { return model.parameters.template get()[{virus_variant, age_group}]; }); diff --git a/cpp/models/abm/test_tree.cpp b/cpp/models/abm/test_tree.cpp deleted file mode 100644 index 9a7b64e6b5..0000000000 --- a/cpp/models/abm/test_tree.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "weighted_decision_tree.h" -#include - -int main(int argc, char const* argv[]) -{ - auto nodes = std::vector({1, 4, 10}); - auto edges = std::vector>({{1, 4, 0.5}, {4, 10, 0.5}}); - auto decision_tree = weighted_decision_tree(nodes, edges); - return 0; -} diff --git a/cpp/models/abm/weighted_decision_tree.h b/cpp/models/abm/weighted_decision_tree.h deleted file mode 100644 index 20047d5d98..0000000000 --- a/cpp/models/abm/weighted_decision_tree.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -* Copyright (C) 2020-2021 German Aerospace Center (DLR-SC) -* -* Authors: Sascha Korf -* -* Contact: Martin J. Kuehn -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include -#include -#include -#include - -struct TreeNode { - int value; -}; - -struct TreeEdge { - double time_length; -}; - -class weighted_decision_tree -{ -public: - weighted_decision_tree(std::vector nodes, std::vector> edges) - { - for (auto edge : edges) { - auto parent_node = std::find(nodes.begin(), nodes.end(), std::get<0>(edge)); - auto child_node = std::find(nodes.begin(), nodes.end(), std::get<1>(edge)); - build_tree(TreeNode{*parent_node}, TreeEdge{std::get<2>(edge)}, TreeNode{*child_node}); - } - } - -private: - void build_tree(TreeNode node, TreeEdge edge, TreeNode child) - { - m_tree.insert({node, std::make_pair(edge, child)}); - } - - std::map> m_tree; -}; From e74c26c578b54641750106b312e7bbc270fd2396 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 20 Nov 2023 18:05:15 +0100 Subject: [PATCH 008/488] Fix error in transmission --- cpp/models/abm/location.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 2e0c509a6a..4cc043ddb5 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -58,12 +58,13 @@ Location Location::copy_location_without_persons(size_t num_agegroups) ScalarType Location::transmission_contacts_per_day(uint32_t cell_index, VirusVariant virus, AgeGroup age_receiver, size_t num_agegroups) const { - ScalarType prob = 0; + ScalarType transmissions = 0; for (uint32_t age_transmitter = 0; age_transmitter != num_agegroups; ++age_transmitter) { - prob += m_cells[cell_index].m_cached_exposure_rate_contacts[{virus, static_cast(age_transmitter)}] * - m_parameters.get()[{age_receiver, static_cast(age_transmitter)}]; + transmissions += + m_cells[cell_index].m_cached_exposure_rate_contacts[{virus, static_cast(age_transmitter)}] * + m_parameters.get()[{age_receiver, static_cast(age_transmitter)}]; } - return prob; + return transmissions; } ScalarType Location::transmission_air_per_day(uint32_t cell_index, VirusVariant virus, @@ -118,12 +119,22 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou auto virus = inf.get_virus_variant(); auto age = p->get_age(); /* average infectivity over the time step - * to second order accuracy using midpoint rule + * to second order accuracy using midpoint rule */ cell.m_cached_exposure_rate_contacts[{virus, age}] += inf.get_infectivity(t + dt / 2); cell.m_cached_exposure_rate_air[{virus}] += inf.get_infectivity(t + dt / 2); } } + + for (auto age_group = AgeGroup(0); age_group < AgeGroup(num_agegroups); age_group++) { + for (auto& v : cell.m_cached_exposure_rate_contacts.slice(AgeGroup(age_group))) { + v = v / + std::count_if(cell.m_persons.begin(), cell.m_persons.end(), [age_group](observer_ptr p) { + return p->get_age() == age_group; + }); + } + } + if (m_capacity_adapted_transmission_risk) { cell.m_cached_exposure_rate_air.array() *= cell.compute_space_per_person_relative(); } From c7d6f129c43bd35403fa3bf21696bbc0b36a2e54 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 20 Dec 2023 13:07:20 +0100 Subject: [PATCH 009/488] Some fixes --- cpp/models/abm/infection.cpp | 100 +++++++++++++++---------------- cpp/models/abm/parameters.h | 26 ++++---- cpp/tests/test_abm_infection.cpp | 17 ++++-- 3 files changed, 73 insertions(+), 70 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 07c4f12d50..a7673882ee 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -132,16 +132,16 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng ScalarType p; // uniform random draws from [0, 1] while ((next_state != InfectionState::Recovered && next_state != InfectionState::Dead)) { switch (next_state) { - case InfectionState::Exposed: + case InfectionState::Exposed: { // roll out how long until infected without symptoms auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - next_state = InfectionState::InfectedNoSymptoms; - break; - case InfectionState::InfectedNoSymptoms: + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + next_state = InfectionState::InfectedNoSymptoms; + } break; + case InfectionState::InfectedNoSymptoms: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { @@ -150,12 +150,11 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng else { next_state = InfectionState::Recovered; } - - break; - case InfectionState::InfectedSymptoms: + } break; + case InfectionState::InfectedSymptoms: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); ScalarType severity_protection_factor = 1.; p = uniform_dist(rng); @@ -171,36 +170,35 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng else { next_state = InfectionState::Recovered; } + } break; - break; - - case InfectionState::InfectedSevere: + case InfectionState::InfectedSevere: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedCritical; + next_state = InfectionState::InfectedCritical; } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; } - break; + } break; - case InfectionState::InfectedCritical: + case InfectionState::InfectedCritical: { // roll out next infection step auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::Dead; + next_state = InfectionState::Dead; } else { next_state = InfectionState::Recovered; } - break; + } break; default: break; @@ -223,31 +221,31 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato while ((previous_state != InfectionState::Exposed)) { switch (previous_state) { - case InfectionState::InfectedNoSymptoms: + case InfectionState::InfectedNoSymptoms: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::Exposed; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::Exposed; + } break; - case InfectionState::InfectedSymptoms: + case InfectionState::InfectedSymptoms: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedNoSymptoms; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; + } break; - case InfectionState::InfectedSevere: + case InfectionState::InfectedSevere: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSymptoms; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; + } break; - case InfectionState::InfectedCritical: + case InfectionState::InfectedCritical: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSevere; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; + } break; - case InfectionState::Recovered: + case InfectionState::Recovered: { // roll out next infection step p = uniform_dist(rng); // compute correct probabilities while factoring out the chance to die @@ -257,34 +255,34 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}]; if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedNoSymptoms; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSymptoms; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedSevere; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; } else { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedCritical; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; } - break; + } break; - case InfectionState::Dead: + case InfectionState::Dead: { auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state)); - previous_state = InfectionState::InfectedCritical; - break; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; + } break; default: break; diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 2958b21056..d57e8cbc2a 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -134,7 +134,7 @@ struct SymptomsPerInfectedNoSymptoms { }; /** -* @brief the percentage of hospitalized patients per infected patients +* @brief the percentage of hospitalized cases per infected cases */ struct SeverePerInfectedSymptoms { using Type = CustomIndexArray; @@ -149,7 +149,7 @@ struct SeverePerInfectedSymptoms { }; /** -* @brief the percentage of ICU patients per hospitalized patients +* @brief the percentage of ICU cases per hospitalized cases */ struct CriticalPerInfectedSevere { using Type = CustomIndexArray; @@ -164,7 +164,7 @@ struct CriticalPerInfectedSevere { }; /** -* @brief the percentage of dead patients per ICU patients +* @brief the percentage of dead cases per ICU cases */ struct DeathsPerInfectedCritical { using Type = CustomIndexArray; @@ -619,7 +619,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range IncubationPeriod of virus variant {} and " "age group {:.0f} smaller " "than {:.4f}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -627,7 +627,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptoms of virus variant " "{} and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -635,7 +635,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedSymptoms of virus variant {} " "and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -643,7 +643,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedSevere of virus variant {} " "and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -651,7 +651,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Lower end of parameter range TimeInfectedCritical of virus variant {} " "and age group {:.0f} smaller " "than {:d}", - v, (size_t)i, 0); + (uint32_t)v, (size_t)i, 0); return true; } @@ -659,7 +659,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter SymptomsPerInfectedNoSymptoms of virus variant {} and age " "group {:.0f} smaller than {:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -667,7 +667,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter SeverePerInfectedSymptoms of virus variant {} and age group " "{:.0f} smaller than {:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -675,7 +675,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter CriticalPerInfectedSevere of virus variant {} and age group " "{:.0f} smaller than {:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -683,7 +683,7 @@ class Parameters : public ParametersBase this->get()[{v, i}] > 1.0) { log_error("Constraint check: Parameter DeathsPerInfectedCritical of age group {:.0f} smaller than " "{:d} or larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } @@ -691,7 +691,7 @@ class Parameters : public ParametersBase log_error("Constraint check: Parameter DetectInfection of virus variant {} and age group {:.0f} " "smaller than {:d} or " "larger than {:d}", - v, (size_t)i, 0, 1); + (uint32_t)v, (size_t)i, 0, 1); return true; } } diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index 82ad0c67e8..ce1a2f4042 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -118,17 +118,22 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(NUM_AGE_GROUPS); - // Time to go from all infected states to recover is 1 day (dt). - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + // Time in all infected states 1 day (dt). + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; + + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(14)) .WillOnce(testing::Return(0.1)) // Transition to InfectedNoSymptoms - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) // Time rollout .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) From 5100fb8b9d1ee59f376a9e222b552bfe69153907 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 25 Jan 2024 11:59:08 +0100 Subject: [PATCH 010/488] Add author Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/models/abm/parameters.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index d57e8cbc2a..3d47b4d21a 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2020-2024 MEmilio * -* Authors: Daniel Abele, Elisabeth Kluth, Khoa Nguyen +* Authors: Daniel Abele, Elisabeth Kluth, Khoa Nguyen, David Kerkmann * * Contact: Martin J. Kuehn * From 413e118f81f4b87d352d2621f75350e4cafdda4a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:19:49 +0100 Subject: [PATCH 011/488] first changes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/examples/abm_minimal.cpp | 4 +- cpp/simulations/CMakeLists.txt | 4 + cpp/simulations/abm_braunschweig.cpp | 5 +- cpp/simulations/paper_abm_bs_testing.cpp | 1110 +++++++++++++++++ .../memilio/epidata/analyze_bs_run.py | 94 ++ 5 files changed, 1213 insertions(+), 4 deletions(-) create mode 100644 cpp/simulations/paper_abm_bs_testing.cpp create mode 100644 pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py diff --git a/cpp/examples/abm_minimal.cpp b/cpp/examples/abm_minimal.cpp index e42b48b651..fbbf26701f 100644 --- a/cpp/examples/abm_minimal.cpp +++ b/cpp/examples/abm_minimal.cpp @@ -41,10 +41,10 @@ int main() world.parameters.get() = 4.; // Set the age group the can go to school is AgeGroup(1) (i.e. 5-14) - world.parameters.get() = false; + world.parameters.get() = false; world.parameters.get()[age_group_5_to_14] = true; // Set the age group the can go to work is AgeGroup(2) and AgeGroup(3) (i.e. 15-34 and 35-59) - world.parameters.get() = false; + world.parameters.get() = false; world.parameters.get()[age_group_15_to_34] = true; world.parameters.get()[age_group_35_to_59] = true; diff --git a/cpp/simulations/CMakeLists.txt b/cpp/simulations/CMakeLists.txt index a784b83ba5..3a04021edf 100644 --- a/cpp/simulations/CMakeLists.txt +++ b/cpp/simulations/CMakeLists.txt @@ -18,4 +18,8 @@ if(MEMILIO_HAS_JSONCPP AND MEMILIO_HAS_HDF5) add_executable(abm_braunschweig abm_braunschweig.cpp) target_link_libraries(abm_braunschweig PRIVATE memilio abm Boost::filesystem ${HDF5_C_LIBRARIES}) target_compile_options(abm_braunschweig PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) + + add_executable(paper_abm_bs_testing paper_abm_bs_testing.cpp) + target_link_libraries(paper_abm_bs_testing PRIVATE memilio abm Boost::filesystem ${HDF5_C_LIBRARIES}) + target_compile_options(paper_abm_bs_testing PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) endif() diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index d56b9d6ec4..5a6b7b94ef 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -1026,6 +1026,7 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di } write_log_to_file_person_and_location_data(historyPersonInf); write_log_to_file_trip_data(historyPersonInfDelta); + ++run_idx; } BOOST_OUTCOME_TRY(save_result_result); @@ -1037,7 +1038,7 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_file = ""; + std::string input_file = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/bs_sorted.csv"; size_t num_runs; bool save_single_runs = true; @@ -1062,7 +1063,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); printf("Running with number of runs = 1.\n"); - num_runs = 1; + num_runs = 10; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp new file mode 100644 index 0000000000..c76bff46b3 --- /dev/null +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -0,0 +1,1110 @@ +/* +* Copyright (C) 2020-2024 MEmilio +* +* Authors: Sascha Korf, Carlotta Gerstein +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include "abm/abm.h" +#include "memilio/io/result_io.h" +#include "memilio/utils/uncertain_value.h" +#include "boost/filesystem.hpp" +#include "boost/algorithm/string/split.hpp" +#include "boost/algorithm/string/classification.hpp" +#include "abm/vaccine.h" +#include "abm/common_abm_loggers.h" + +namespace fs = boost::filesystem; + +// Assign the name to general age group. +size_t num_age_groups = 6; +const auto age_group_0_to_4 = mio::AgeGroup(0); +const auto age_group_5_to_14 = mio::AgeGroup(1); +const auto age_group_15_to_34 = mio::AgeGroup(2); +const auto age_group_35_to_59 = mio::AgeGroup(3); +const auto age_group_60_to_79 = mio::AgeGroup(4); +const auto age_group_80_plus = mio::AgeGroup(5); + +/** + * Set a value and distribution of an UncertainValue. + * Assigns average of min and max as a value and UNIFORM(min, max) as a distribution. + * @param p uncertain value to set. + * @param min minimum of distribution. + * @param max minimum of distribution. + */ +void assign_uniform_distribution(mio::UncertainValue& p, ScalarType min, ScalarType max) +{ + p = mio::UncertainValue(0.5 * (max + min)); + p.set_distribution(mio::ParameterDistributionUniform(min, max)); +} + +/** + * Determine the infection state of a person at the beginning of the simulation. + * The infection states are chosen randomly. They are distributed according to the probabilites set in the example. + * @return random infection state + */ +mio::abm::InfectionState determine_infection_state(mio::abm::Person::RandomNumberGenerator& rng, ScalarType exposed, + ScalarType infected_no_symptoms, ScalarType infected_symptoms, + ScalarType recovered) +{ + ScalarType susceptible = 1 - exposed - infected_no_symptoms - infected_symptoms - recovered; + std::vector weights = { + susceptible, exposed, infected_no_symptoms, infected_symptoms / 3, infected_symptoms / 3, + infected_symptoms / 3, recovered}; + if (weights.size() != (size_t)mio::abm::InfectionState::Count - 1) { + mio::log_error("Initialization in ABM wrong, please correct vector length."); + } + auto state = mio::DiscreteDistribution::get_instance()(rng, weights); + return (mio::abm::InfectionState)state; +} + +/** + * Assign an infection state to each person. + */ +void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t, double exposed_prob, + double infected_no_symptoms_prob, double infected_symptoms_prob, double recovered_prob) +{ + auto persons = world.get_persons(); + for (auto& person : persons) { + auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); + auto infection_state = determine_infection_state(rng, exposed_prob, infected_no_symptoms_prob, + infected_symptoms_prob, recovered_prob); + if (infection_state != mio::abm::InfectionState::Susceptible) + person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), + world.parameters, t, infection_state)); + } +} +int stringToMinutes(const std::string& input) +{ + size_t colonPos = input.find(":"); + if (colonPos == std::string::npos) { + // Handle invalid input (no colon found) + return -1; // You can choose a suitable error code here. + } + + std::string xStr = input.substr(0, colonPos); + std::string yStr = input.substr(colonPos + 1); + + int x = std::stoi(xStr); + int y = std::stoi(yStr); + return x * 60 + y; +} + +int longLatToInt(const std::string& input) +{ + double y = std::stod(input) * 1e+5; //we want the 5 numbers after digit + return (int)y; +} +void split_line(std::string string, std::vector* row) +{ + std::vector strings; + + std::string x = ",,", y = ",-1,"; + size_t pos; + while ((pos = string.find(x)) != std::string::npos) { + string.replace(pos, 2, y); + } // Temporary fix to handle empty cells. + boost::split(strings, string, boost::is_any_of(",")); + std::transform(strings.begin(), strings.end(), std::back_inserter(*row), [&](std::string s) { + if (s.find(":") != std::string::npos) { + return stringToMinutes(s); + } + else if (s.find(".") != std::string::npos) { + return longLatToInt(s); + } + else { + return std::stoi(s); + } + }); +} + +mio::abm::LocationType get_location_type(uint32_t acitivity_end) +{ + mio::abm::LocationType type; + switch (acitivity_end) { + case 1: + type = mio::abm::LocationType::Work; + break; + case 2: + type = mio::abm::LocationType::School; + break; + case 3: + type = mio::abm::LocationType::BasicsShop; + break; + case 4: + type = mio::abm::LocationType::SocialEvent; // Freizeit + break; + case 5: + type = mio::abm::LocationType::BasicsShop; // Private Erledigung + break; + case 6: + type = mio::abm::LocationType::SocialEvent; // Sonstiges + break; + default: + type = mio::abm::LocationType::Home; + break; + } + return type; +} + +mio::AgeGroup determine_age_group(uint32_t age) +{ + if (age <= 4) { + return age_group_0_to_4; + } + else if (age <= 14) { + return age_group_5_to_14; + } + else if (age <= 34) { + return age_group_15_to_34; + } + else if (age <= 59) { + return age_group_35_to_59; + } + else if (age <= 79) { + return age_group_60_to_79; + } + else { + return age_group_80_plus; + } +} + +void create_world_from_data(mio::abm::World& world, const std::string& filename, const mio::abm::TimePoint t0, + int max_number_persons) +{ + // Open File + const fs::path p = filename; + if (!fs::exists(p)) { + mio::log_error("Cannot read in data. File does not exist."); + } + // File pointer + std::fstream fin; + + // Open an existing file + fin.open(filename, std::ios::in); + std::vector row; + std::vector row_string; + std::string line; + + // Read the Titles from the Data file + std::getline(fin, line); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); + std::vector titles; + boost::split(titles, line, boost::is_any_of(",")); + uint32_t count_of_titles = 0; + std::map index = {}; + for (auto const& title : titles) { + index.insert({title, count_of_titles}); + row_string.push_back(title); + count_of_titles++; + } + + std::map locations = {}; + std::map persons = {}; + std::map person_ids = {}; + std::map> locations_before; + std::map> locations_after; + + // For the world we need: Hospitals, ICUs (for both we just create one for now), Homes for each unique householdID, One Person for each person_id with respective age and home_id. + + // We assume that no person goes to an hospital, altough e.g. "Sonstiges" could be a hospital + auto hospital = world.add_location(mio::abm::LocationType::Hospital); + world.get_individualized_location(hospital).get_infection_parameters().set(5); + world.get_individualized_location(hospital).set_capacity(std::numeric_limits::max(), + std::numeric_limits::max()); + auto icu = world.add_location(mio::abm::LocationType::ICU); + world.get_individualized_location(icu).get_infection_parameters().set(5); + world.get_individualized_location(icu).set_capacity(std::numeric_limits::max(), + std::numeric_limits::max()); + + // First we determine the persons number and their starting locations + int number_of_persons = 0; + + while (std::getline(fin, line)) { + row.clear(); + + // read columns in this row + split_line(line, &row); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); + + uint32_t person_id = row[index["puid"]]; + auto it_person_id = person_ids.find(person_id); + if (it_person_id == person_ids.end()) { + if (number_of_persons >= max_number_persons) + break; //This is okay because the data is sorted by person_id + person_ids.insert({person_id, number_of_persons}); + number_of_persons++; + } + + // The starting location of a person is the end location of the last trip he made, either on the same day or on + // the day before + uint32_t target_location_id = std::abs(row[index["loc_id_end"]]); + int trip_start = row[index["start_time"]]; + if (trip_start < t0.hour_of_day()) { + auto it_person = locations_before.find(person_id); + if (it_person == locations_before.end()) { + locations_before.insert({person_id, std::make_pair(target_location_id, trip_start)}); + } + else { + if (it_person->second.second <= trip_start) { + it_person->second.first = target_location_id; + it_person->second.second = trip_start; + } + } + } + else { + auto it_person = locations_after.find(person_id); + if (it_person == locations_after.end()) { + locations_after.insert({person_id, std::make_pair(target_location_id, trip_start)}); + } + else { + if (it_person->second.second <= trip_start) { + it_person->second.first = target_location_id; + it_person->second.second = trip_start; + } + } + } + } + + fin.clear(); + fin.seekg(0); + std::getline(fin, line); // Skip header row + + // Add all locations to the world + while (std::getline(fin, line)) { + row.clear(); + + // read columns in this row + split_line(line, &row); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); + + uint32_t person_id = row[index["puid"]]; + if (person_ids.find(person_id) == person_ids.end()) + break; + + uint32_t home_id = row[index["huid"]]; + uint32_t target_location_id = std::abs(row[index["loc_id_end"]]); + uint32_t activity_end = row[index["activity_end"]]; + mio::abm::GeographicalLocation location_long_lat = {(double)row[index["lon_end"]] / 1e+5, + (double)row[index["lat_end"]] / 1e+5}; + mio::abm::LocationId home; + auto it_home = locations.find(home_id); + if (it_home == locations.end()) { + home = world.add_location(mio::abm::LocationType::Home, 1); + locations.insert({home_id, home}); + mio::abm::GeographicalLocation location_long_lat_home = {(double)row[index["lon_start"]] / 1e+5, + (double)row[index["lat_start"]] / 1e+5}; + world.get_individualized_location(home).set_geographical_location(location_long_lat_home); + } + else { + home = it_home->second; + } + + mio::abm::LocationId location; + auto it_location = locations.find( + target_location_id); // Check if location already exists also for home which have the same id (home_id = target_location_id) + if (it_location == locations.end()) { + location = world.add_location( + get_location_type(activity_end), + 1); // Assume one place has one activity, this may be untrue but not important for now(?) + locations.insert({target_location_id, location}); + world.get_individualized_location(location).set_geographical_location(location_long_lat); + } + } + fin.clear(); + fin.seekg(0); + std::getline(fin, line); // Skip header row + + // Add the persons and trips + while (std::getline(fin, line)) { + row.clear(); + + // read columns in this row + split_line(line, &row); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); + + uint32_t person_id = row[index["puid"]]; + if (person_ids.find(person_id) == person_ids.end()) + break; + + uint32_t age = row[index["age"]]; + uint32_t home_id = row[index["huid"]]; + uint32_t target_location_id = std::abs(row[index["loc_id_end"]]); + uint32_t start_location_id = std::abs(row[index["loc_id_start"]]); + uint32_t trip_start = row[index["start_time"]]; + uint32_t transport_mode = row[index["travel_mode"]]; + uint32_t acticity_end = row[index["activity_end"]]; + + // Add the trip to the trip list person and location must exist at this point + auto target_location = locations.find(target_location_id)->second; + auto start_location = locations.find(start_location_id)->second; + + auto it_person = persons.find(person_id); + + if (it_person == persons.end()) { + auto it_first_location_id = locations_before.find(person_id); + if (it_first_location_id == locations_before.end()) { + it_first_location_id = locations_after.find(person_id); + } + auto first_location_id = it_first_location_id->second.first; + auto first_location = locations.find(first_location_id)->second; + auto& person = world.add_person(first_location, determine_age_group(age)); + auto home = locations.find(home_id)->second; + person.set_assigned_location(home); + person.set_assigned_location(hospital); + person.set_assigned_location(icu); + persons.insert({person_id, person}); + it_person = persons.find(person_id); + } + + it_person->second.set_assigned_location( + target_location); //This assumes that we only have in each tripchain only one location type for each person + if (locations.find(start_location_id) == locations.end()) { + // For trips where the start location is not known use Home instead + start_location = {it_person->second.get_assigned_location_index(mio::abm::LocationType::Home), + mio::abm::LocationType::Home}; + } + world.get_trip_list().add_trip(mio::abm::Trip( + it_person->second.get_person_id(), mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location, + start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); + } + world.get_trip_list().use_weekday_trips_on_weekend(); +} + +void set_parameters(mio::abm::Parameters params) +{ + params.set({{mio::abm::VirusVariant::Count, mio::AgeGroup(num_age_groups)}, 4.}); + + // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 + params.get() = [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); + }; + + //0-4 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.092; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; + + //5-14 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.092; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.; + + //15-34 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.079; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.139; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.021; + + //35-59 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.079; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.; + + //60-79 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.079; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.123; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.024; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.; + + //80+ + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.079; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.115; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.033; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.; + + // Set each parameter for vaccinated people including personal infection and vaccine protection levels. + // Summary: https://doi.org/10.1038/s41577-021-00550-x, + + //0-4 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.132; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.0; + // Protection of reinfection is the same for all age-groups, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_0_to_4, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.852}, + {180, 0.852}, + {210, 0.845}, + {240, 0.828}, + {270, 0.797}, + {300, 0.759}, + {330, 0.711}, + {360, 0.661}, + {390, 0.616}, + {420, 0.580}, + {450, 0.559}, + {450, 0.550}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_0_to_4, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.91}, {60, 0.92}, {90, 0.88}, {120, 0.84}, {150, 0.81}, {180, 0.88}, {450, 0.5}}, days); + }; + + // Set up age-related severe protection levels, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_0_to_4, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.967}, + {30, 0.975}, + {60, 0.977}, + {90, 0.974}, + {120, 0.963}, + {150, 0.947}, + {180, 0.93}, + {210, 0.929}, + {240, 0.923}, + {270, 0.908}, + {300, 0.893}, + {330, 0.887}, + {360, 0.887}, + {450, 0.5}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_0_to_4, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {450, 0.5}}, days); + }; + + //5-14 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.132; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.0; + // Protection of reinfection is the same for all age-groups, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_5_to_14, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.852}, + {180, 0.852}, + {210, 0.845}, + {240, 0.828}, + {270, 0.797}, + {300, 0.759}, + {330, 0.711}, + {360, 0.661}, + {390, 0.616}, + {420, 0.580}, + {450, 0.559}, + {450, 0.550}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_5_to_14, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.91}, {60, 0.92}, {90, 0.88}, {120, 0.84}, {150, 0.81}, {180, 0.88}, {450, 0.5}}, days); + }; + // Set up age-related severe protection levels, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_5_to_14, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.967}, + {30, 0.975}, + {60, 0.977}, + {90, 0.974}, + {120, 0.963}, + {150, 0.947}, + {180, 0.93}, + {210, 0.929}, + {240, 0.923}, + {270, 0.908}, + {300, 0.893}, + {330, 0.887}, + {360, 0.887}, + {450, 0.5}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_5_to_14, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {450, 0.5}}, days); + }; + + //15-34 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.021; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.0; + // Set up personal infection and vaccine protection levels, based on: https://doi.org/10.1038/s41577-021-00550-x, https://doi.org/10.1038/s41591-021-01377-8 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_15_to_34, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.852}, + {180, 0.852}, + {210, 0.845}, + {240, 0.828}, + {270, 0.797}, + {300, 0.759}, + {330, 0.711}, + {360, 0.661}, + {390, 0.616}, + {420, 0.580}, + {450, 0.559}, + {450, 0.550}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_15_to_34, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.89}, {60, 0.84}, {90, 0.78}, {120, 0.68}, {150, 0.57}, {180, 0.39}, {450, 0.1}}, days); + }; + // Set up age-related severe protection levels, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_15_to_34, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.967}, + {30, 0.975}, + {60, 0.977}, + {90, 0.974}, + {120, 0.963}, + {150, 0.947}, + {180, 0.93}, + {210, 0.929}, + {240, 0.923}, + {270, 0.908}, + {300, 0.893}, + {330, 0.887}, + {360, 0.887}, + {450, 0.5}}, + days); + }; + // Information is from: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_15_to_34, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {180, 0.90}, {450, 0.5}}, days); + }; + + //35-59 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.141; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.0; + // Protection of reinfection is the same for all age-groups, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_35_to_59, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.852}, + {180, 0.852}, + {210, 0.845}, + {240, 0.828}, + {270, 0.797}, + {300, 0.759}, + {330, 0.711}, + {360, 0.661}, + {390, 0.616}, + {420, 0.580}, + {450, 0.559}, + {450, 0.550}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_35_to_59, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.89}, {60, 0.84}, {90, 0.78}, {120, 0.68}, {150, 0.57}, {180, 0.39}, {450, 0.1}}, days); + }; + // Set up age-related severe protection levels, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_35_to_59, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.967}, + {30, 0.975}, + {60, 0.977}, + {90, 0.974}, + {120, 0.963}, + {150, 0.947}, + {180, 0.93}, + {210, 0.929}, + {240, 0.923}, + {270, 0.908}, + {300, 0.893}, + {330, 0.887}, + {360, 0.887}, + {450, 0.5}}, + days); + }; + // Information is from: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_35_to_59, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {180, 0.90}, {450, 0.5}}, days); + }; + + //60-79 + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.0; + // Protection of reinfection is the same for all age-groups, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.852}, + {180, 0.852}, + {210, 0.845}, + {240, 0.828}, + {270, 0.797}, + {300, 0.759}, + {330, 0.711}, + {360, 0.661}, + {390, 0.616}, + {420, 0.580}, + {450, 0.559}, + {450, 0.550}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_60_to_79, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.87}, {60, 0.85}, {90, 0.78}, {120, 0.67}, {150, 0.61}, {180, 0.50}, {450, 0.1}}, days); + }; + // Set up personal severe protection levels. + // Protection of severe infection of age group 65 + is different from other age group, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.967}, + {30, 0.975}, + {60, 0.977}, + {90, 0.974}, + {120, 0.963}, + {150, 0.947}, + {180, 0.93}, + {210, 0.929}, + {240, 0.923}, + {270, 0.908}, + {300, 0.893}, + {330, 0.887}, + {360, 0.887}, + {360, 0.5}}, + days); + }; + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_60_to_79, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.91}, {60, 0.86}, {90, 0.91}, {120, 0.94}, {150, 0.95}, {180, 0.90}, {450, 0.5}}, days); + }; + + //80+ + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.133; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.012; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.0; + // Protection of reinfection is the same for all age-groups, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_80_plus, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.852}, + {180, 0.852}, + {210, 0.845}, + {240, 0.828}, + {270, 0.797}, + {300, 0.759}, + {330, 0.711}, + {360, 0.661}, + {390, 0.616}, + {420, 0.580}, + {450, 0.559}, + {450, 0.550}}, + days); + }; + // Information is from: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_80_plus, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.80}, {60, 0.79}, {90, 0.75}, {120, 0.56}, {150, 0.49}, {180, 0.43}, {450, 0.1}}, days); + }; + // Set up personal severe protection levels. + // Protection of severe infection of age group 65 + is different from other age group, based on: + // https://doi.org/10.1016/S0140-6736(22)02465-5 + params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_0_to_4, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.967}, + {30, 0.975}, + {60, 0.977}, + {90, 0.974}, + {120, 0.963}, + {150, 0.947}, + {180, 0.93}, + {210, 0.929}, + {240, 0.923}, + {270, 0.908}, + {300, 0.893}, + {330, 0.887}, + {360, 0.887}, + {360, 0.5}}, + days); + }; + // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 + params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_80_plus, + mio::abm::VirusVariant::Wildtype}] = + [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.5}, {30, 0.84}, {60, 0.88}, {90, 0.89}, {120, 0.86}, {150, 0.85}, {180, 0.83}, {450, 0.5}}, days); + }; +} + +/** + * Create a sampled simulation with start time t0. + * @param t0 The start time of the Simulation. + */ +mio::abm::Simulation create_sampled_simulation(const std::string& input_file, const mio::abm::TimePoint& t0, + int max_num_persons) +{ + // Assumed percentage of infection state at the beginning of the simulation. + ScalarType exposed_prob = 0.5, infected_no_symptoms_prob = 0.001, infected_symptoms_prob = 0.001, + recovered_prob = 0.0; + + //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world + auto world = mio::abm::World(num_age_groups); + + set_parameters(world.parameters); + + // Create the world object from statistical data. + create_world_from_data(world, input_file, t0, max_num_persons); + world.use_migration_rules(false); + + // Assign an infection state to each person. + assign_infection_state(world, t0, exposed_prob, infected_no_symptoms_prob, infected_symptoms_prob, recovered_prob); + + auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); + + // During the lockdown, 25% of people work from home and schools are closed for 90% of students. + // Social events are very rare. + mio::abm::set_home_office(t_lockdown, 0.25, world.parameters); + mio::abm::set_school_closure(t_lockdown, 0.9, world.parameters); + mio::abm::close_social_events(t_lockdown, 0.9, world.parameters); + + auto sim = mio::abm::Simulation(t0, std::move(world)); + return sim; +} + +template +void write_log_to_file_person_and_location_data(const T& history) +{ + auto logg = history.get_log(); + auto loc_id = std::get<0>(logg)[0]; + auto agent_id = std::get<1>(logg)[0]; + // Write lo to a text file. + std::ofstream myfile("locations_lookup.txt"); + myfile << "location_id, location_type, latitude, longitude\n"; + for (uint32_t loc_id_index = 0; loc_id_index < loc_id.size(); ++loc_id_index) { + auto id = std::get<0>(loc_id[loc_id_index]); + auto location_type = (int)std::get<1>(loc_id[loc_id_index]); + auto id_longitute = std::get<2>(loc_id[loc_id_index]).longitude; + auto id_latitude = std::get<2>(loc_id[loc_id_index]).latitude; + myfile << id << ", " << location_type << ", " << id_longitute << ", " << id_latitude << "\n"; + } + myfile.close(); + + std::ofstream myfile2("agents_lookup.txt"); + myfile2 << "agent_id, home_id, age\n"; + for (uint32_t agent_id_index = 0; agent_id_index < agent_id.size(); ++agent_id_index) { + auto id = std::get<0>(agent_id[agent_id_index]); + auto home_id = std::get<1>(agent_id[agent_id_index]); + auto age = std::get<2>(agent_id[agent_id_index]); + myfile2 << id << ", " << home_id << ", " << age << "\n"; + } + myfile2.close(); +} + +template +void write_log_to_file_trip_data(const T& history) +{ + + auto movement_data = std::get<0>(history.get_log()); + std::ofstream myfile3("movement_data.txt"); + myfile3 << "agent_id, trip_id, start_location, end_location, start_time, end_time, transport_mode, activity, " + "infection_state \n"; + int trips_id = 0; + for (uint32_t movement_data_index = 2; movement_data_index < movement_data.size(); ++movement_data_index) { + myfile3 << "timestep Nr.: " << movement_data_index - 1 << "\n"; + for (uint32_t trip_index = 0; trip_index < movement_data[movement_data_index].size(); trip_index++) { + auto agent_id = (int)std::get<0>(movement_data[movement_data_index][trip_index]); + + int start_index = movement_data_index - 1; + using Type = std::tuple; + while (!std::binary_search(std::begin(movement_data[start_index]), std::end(movement_data[start_index]), + movement_data[movement_data_index][trip_index], + [](const Type& v1, const Type& v2) { + return std::get<0>(v1) < std::get<0>(v2); + })) { + start_index--; + } + auto start_location_pointer = + std::lower_bound(std::begin(movement_data[start_index]), std::end(movement_data[start_index]), + movement_data[movement_data_index][trip_index], [](const Type& v1, const Type& v2) { + return std::get<0>(v1) < std::get<0>(v2); + }); + int start_location = (int)std::get<1>(*start_location_pointer); + + auto end_location = (int)std::get<1>(movement_data[movement_data_index][trip_index]); + + auto start_time = (int)std::get<2>(movement_data[movement_data_index][trip_index]).seconds(); + auto end_time = (int)std::get<2>(movement_data[movement_data_index][trip_index]).seconds(); + + auto transport_mode = (int)std::get<3>(movement_data[movement_data_index][trip_index]); + auto activity = (int)std::get<4>(movement_data[movement_data_index][trip_index]); + auto infection_state = (int)std::get<5>(movement_data[movement_data_index][trip_index]); + myfile3 << agent_id << ", " << trips_id << ", " << start_location << " , " << end_location << " , " + << start_time << " , " << end_time << " , " << transport_mode << " , " << activity << " , " + << infection_state << "\n"; + trips_id++; + } + } + myfile3.close(); +} + +void write_txt_file_for_graphical_compartment_output(std::vector>> input_file) +{ + // mio::unused(input_file); + // In the input file is a h5 file there are multiple runs with each having the amount of people in each compartment for each timestep. + // The output folder should have the following format: + // for each run there is a file with the name "run_1.txt" and so on. + // in each file the the rows represent the timesteps and the columns represent the compartments. + // The first row is the header with the compartment names. + // Time = Time in days, S = Susceptible, E = Exposed, I_NS = InfectedNoSymptoms, I_Sy = InfectedSymptoms, I_Sev = InfectedSevere, + // I_Crit = InfectedCritical, R = Recovered, D = Dead + + // Output folder name: + std::string folderName = "folder_run_bs"; + // Create folder + fs::create_directory(folderName); + // Loop over all runs + for (int run = 0; run < (int)input_file.size(); run++) { + // Create file name + std::string fileName = folderName + "/run_" + std::to_string(run) + ".txt"; + // Create file + std::ofstream myfile; + myfile.open(fileName); + // Write header + input_file.at(run).at(0).print_table({"S", "E", "I_NS", "I_Sy", "I_Sev", "I_Crit", "R", "D"}, 7, 4, myfile); + } +} + +mio::IOResult run(const std::string& input_file, const fs::path& result_dir, size_t num_runs, + bool save_single_runs = true) +{ + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation + auto ensemble_results = std::vector>>{}; // Vector of collected results + ensemble_results.reserve(size_t(num_runs)); + auto run_idx = size_t(1); // The run index + auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations + auto max_num_persons = 1000; + + // Loop over a number of runs + while (run_idx <= num_runs) { + + // Create the sampled simulation with start time t0. + auto sim = create_sampled_simulation(input_file, t0, max_num_persons); + //output object + mio::History + historyPersonInf; + mio::History historyTimeSeries{ + Eigen::Index(mio::abm::InfectionState::Count)}; + mio::History historyPersonInfDelta; + // Collect the id of location in world. + std::vector loc_ids; + for (auto& location : sim.get_world().get_locations()) { + loc_ids.push_back(location.get_index()); + } + // Advance the world to tmax + sim.advance(tmax, historyPersonInf, historyTimeSeries, historyPersonInfDelta); + // TODO: update result of the simulation to be a vector of location result. + auto temp_sim_result = std::vector>{std::get<0>(historyTimeSeries.get_log())}; + // Push result of the simulation back to the result vector + ensemble_results.push_back(temp_sim_result); + // Option to save the current run result to file + if (save_result_result && save_single_runs) { + auto result_dir_run = result_dir / ("abm_result_run_" + std::to_string(run_idx) + ".h5"); + BOOST_OUTCOME_TRY(save_result(ensemble_results.back(), loc_ids, 1, result_dir_run.string())); + } + write_log_to_file_person_and_location_data(historyPersonInf); + write_log_to_file_trip_data(historyPersonInfDelta); + + std::cout << "Run " << run_idx << " of " << num_runs << " finished." << std::endl; + ++run_idx; + } + write_txt_file_for_graphical_compartment_output(ensemble_results); + BOOST_OUTCOME_TRY(save_result_result); + return mio::success(); +} + +int main(int argc, char** argv) +{ + mio::set_log_level(mio::LogLevel::warn); + + std::string result_dir = "."; + std::string input_file = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/bs_sorted.csv"; + size_t num_runs; + bool save_single_runs = true; + + if (argc == 2) { + num_runs = atoi(argv[1]); + printf("Number of run is %s.\n", argv[1]); + printf("Saving results to the current directory.\n"); + } + + else if (argc == 3) { + num_runs = atoi(argv[1]); + result_dir = argv[2]; + printf("Number of run is %s.\n", argv[1]); + printf("Saving results to \"%s\".\n", result_dir.c_str()); + } + else { + printf("Usage:\n"); + printf("abm_example \n"); + printf("\tRun the simulation for time(s).\n"); + printf("\tStore the results in the current directory.\n"); + printf("abm_braunschweig \n"); + printf("\tRun the simulation for time(s).\n"); + printf("\tStore the results in .\n"); + printf("Running with number of runs = 10.\n"); + num_runs = 10; + } + + // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging + //printf("Seeds: "); + //for (auto s : mio::thread_local_rng().get_seeds()) { + // printf("%u, ", s); + //} + //printf("\n"); + + auto result = run(input_file, result_dir, num_runs, save_single_runs); + if (!result) { + printf("%s\n", result.error().formatted_message().c_str()); + return -1; + } + return 0; +} diff --git a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py new file mode 100644 index 0000000000..b5db426359 --- /dev/null +++ b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py @@ -0,0 +1,94 @@ +# Python script to analyze bs runs +# input is a bs run folder with the following structure: +# bs_run_folder has a txt file for each bs run +# each txt file has a line for each time step +# each line has a column for each compartment as well as the timestep +# each column has the number of individuals in that compartment +# the first line of each txt file is the header + +import sys +import argparse +import os +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import matplotlib +import matplotlib.colors as colors +import matplotlib.cm as cmx +import matplotlib.patches as mpatches +import matplotlib.lines as mlines + +def main(n_runs): + # read in folder and convert txt files to numpy arrays + + #folder path + folder_path = "memilio/epidata/folder_run_bs" + + # get first_file in folder + first_file = os.listdir(folder_path)[0] + file_path = os.path.join(folder_path, first_file) + # read in txt file + df = pd.read_csv(file_path, delim_whitespace=True ) + # convert to numpy array + df_np = df.to_numpy() + # get the number of rows and columns + num_rows = df_np.shape[0] + num_cols = df_np.shape[1] + # get the number of compartments + num_compartments = num_cols - 1 + # get the number of time steps + num_time_steps = num_rows-1 + # get the compartment names + compartment_names = df.columns[1:] + # get the time steps + time_steps = df_np[:,0] + + #get number of files in folder + num_files = len([entry for entry in os.listdir(folder_path)]) + + # read in each txt file and convert to numpy array + df_np_3d = np.empty((num_rows, num_cols, n_runs)) + for (file, i) in zip(os.listdir(folder_path), range(n_runs)): + if file.endswith(".txt"): + file_path = os.path.join(folder_path, file) + # read in txt file + df = pd.read_csv(file_path, delim_whitespace=True) + # convert to numpy array + df_np = df.to_numpy() + #attach to array + df_np_3d[:,:,i] = df_np + + plot_mean_and_std(df_np_3d) + + + + +def plot_mean_and_std(Y): + + + x_plot = Y[:,0,0] + compartments = Y[:,1:,1:] + # average value + compartments_avg = np.mean(compartments,axis=2) + #plot average + for i in range(compartments_avg.shape[1]): + plt.plot(x_plot,compartments_avg[:,i]) + + #plt.plot(x_plot,compartments_avg) + #legend + plt.legend(['S', 'E', 'I_NS', 'I_Sy', 'I_Sev', 'I_Crit', 'R', 'D']) + plt.show() + # standard deviation + #compartments_std = np.std(compartments,axis=2) + #plt.plot(x_plot,compartments_avg + compartments_std) + #plt.plot(x_plot,compartments_avg - compartments_std) + #plt.show() + + +if __name__ == "__main__": + if (len(sys.argv) > 1): + n_runs = sys.argv[1] + else: + folder_path = "memilio/epidata/folder_run_bs" + n_runs = len([entry for entry in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, entry))]) + main(n_runs) \ No newline at end of file From 85ab275afe12e65568e01a2fb67eca8b7b11dbea Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Jan 2024 17:35:33 +0100 Subject: [PATCH 012/488] Fix recovered people not beeing able to reinfect. Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/models/abm/person.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index dd493adfc1..bb19191c33 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -61,7 +61,8 @@ Person Person::copy_person(Location& location) void Person::interact(RandomNumberGenerator& rng, TimePoint t, TimeSpan dt, const Parameters& params) { - if (get_infection_state(t) == InfectionState::Susceptible) { // Susceptible + if (get_infection_state(t) == InfectionState::Susceptible || + get_infection_state(t) == InfectionState::Recovered) { // Susceptible or Recovered people can be (re)infected m_location->interact(rng, *this, t, dt, params); } m_time_at_location += dt; From 10bd31e75f24ee3a00243049c828fa56f36c85f5 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 31 Jan 2024 15:44:33 +0100 Subject: [PATCH 013/488] Change back to infection course related time parameters and fix build. --- cpp/models/abm/analyze_result.h | 100 ++++++++--- cpp/models/abm/infection.cpp | 53 ++++-- cpp/models/abm/infection.h | 1 + cpp/models/abm/parameters.h | 164 ++++++++++++++--- cpp/simulations/abm.cpp | 255 ++++++++++++++++----------- cpp/simulations/abm_braunschweig.cpp | 254 +++++++++++++++----------- cpp/tests/test_abm_infection.cpp | 18 +- cpp/tests/test_abm_location.cpp | 4 +- cpp/tests/test_abm_person.cpp | 2 +- cpp/tests/test_abm_world.cpp | 97 +++++----- cpp/tests/test_analyze_result.cpp | 72 ++++---- 11 files changed, 655 insertions(+), 365 deletions(-) diff --git a/cpp/models/abm/analyze_result.h b/cpp/models/abm/analyze_result.h index 301ee8bffd..8b359c3031 100644 --- a/cpp/models/abm/analyze_result.h +++ b/cpp/models/abm/analyze_result.h @@ -65,59 +65,109 @@ std::vector ensemble_params_percentile(const std::vector()) { // Global infection parameters param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { - static auto result = model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.a(); + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}] - .viral_load_incline.params.b(); + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}] + .params.b(); return result; }); @@ -197,6 +247,16 @@ std::vector ensemble_params_percentile(const std::vector auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.a(); + return result; + }); + param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { + static auto result = + model.parameters.template get()[{virus_variant, age_group}].params.b(); + return result; + }); param_percentil(node, [virus_variant](auto&& model) -> auto& { return model.parameters.template get()[{virus_variant}]; }); diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index a7673882ee..1118788ca6 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -54,6 +54,9 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age m_log_norm_alpha = inf_params.infectivity_alpha.get_distribution_instance()(rng, inf_params.infectivity_alpha.params); m_log_norm_beta = inf_params.infectivity_beta.get_distribution_instance()(rng, inf_params.infectivity_beta.params); + + auto shedfactor_param = params.get()[{virus, age}]; + m_individual_virus_shed_factor = shedfactor_param.get_distribution_instance()(rng, shedfactor_param.params); } ScalarType Infection::get_viral_load(TimePoint t) const @@ -76,7 +79,7 @@ ScalarType Infection::get_infectivity(TimePoint t) const { if (m_viral_load.start_date >= t || get_infection_state(t) == InfectionState::Exposed) return 0; - return 1 / (1 + exp(-(m_log_norm_alpha + m_log_norm_beta * get_viral_load(t)))); + return m_individual_virus_shed_factor / (1 + exp(-(m_log_norm_alpha + m_log_norm_beta * get_viral_load(t)))); } VirusVariant Infection::get_virus_variant() const @@ -126,6 +129,8 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng { auto t = init_date; TimeSpan time_period{}; // time period for current infection state + auto time_in_state = params.get()[{ + m_virus_variant, age}]; // time distribution parameters for current infection state InfectionState next_state{start_state}; // next state to enter m_infection_course.push_back(std::pair(t, next_state)); auto& uniform_dist = UniformDistribution::get_instance(); @@ -134,27 +139,27 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng switch (next_state) { case InfectionState::Exposed: { // roll out how long until infected without symptoms - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); next_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedNoSymptoms: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; case InfectionState::InfectedSymptoms: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); ScalarType severity_protection_factor = 1.; p = uniform_dist(rng); @@ -166,37 +171,45 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng if (p < (1 - severity_protection_factor) * params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedSevere; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; case InfectionState::InfectedSevere: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::InfectedCritical; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; case InfectionState::InfectedCritical: { // roll out next infection step - auto time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { next_state = InfectionState::Dead; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { next_state = InfectionState::Recovered; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } } break; @@ -214,6 +227,8 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato { auto start_date = init_date; TimeSpan time_period{}; // time period for current infection state + auto time_in_state = params.get()[{ + m_virus_variant, age}]; // time distribution parameters for current infection state InfectionState previous_state{init_state}; // previous state to enter auto& uniform_dist = UniformDistribution::get_instance(); ScalarType p; // uniform random draws from [0, 1] @@ -222,25 +237,25 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato switch (previous_state) { case InfectionState::InfectedNoSymptoms: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::Exposed; } break; case InfectionState::InfectedSymptoms: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedSevere: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSymptoms; } break; case InfectionState::InfectedCritical: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSevere; } break; @@ -254,32 +269,32 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}]; if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSymptoms; } else if (p < params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSevere; } else { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedCritical; } } break; case InfectionState::Dead: { - auto time_in_state = params.get()[{m_virus_variant, age}]; + time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedCritical; } break; diff --git a/cpp/models/abm/infection.h b/cpp/models/abm/infection.h index f882d22af2..0e2cc2ce40 100644 --- a/cpp/models/abm/infection.h +++ b/cpp/models/abm/infection.h @@ -159,6 +159,7 @@ class Infection ViralLoad m_viral_load; ///< ViralLoad of the Infection. ScalarType m_log_norm_alpha, m_log_norm_beta; ///< Parameters for the infectivity mapping, which is modelled through an invlogit function. + ScalarType m_individual_virus_shed_factor; ///< Individual virus shed factor. bool m_detected; ///< Whether an Infection is detected or not. }; diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 3d47b4d21a..047227a0c4 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -58,9 +58,9 @@ struct IncubationPeriod { }; /** -* @brief Time that a Person is infected but nonsymptomatic in day unit +* @brief Time that a Person is infected but presymptomatic in day unit */ -struct TimeInfectedNoSymptoms { +struct TimeInfectedNoSymptomsToSymptoms { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -68,15 +68,75 @@ struct TimeInfectedNoSymptoms { } static std::string name() { - return "TimeInfectedNoSymptoms"; + return "TimeInfectedNoSymptomsToSymptoms"; + } +}; + +/** +* @brief Time that a Person is infected when staying asymptomatic in day unit +*/ +struct TimeInfectedNoSymptomsToRecovered { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedNoSymptomsToRecovered"; } }; /** * @brief Time that a Person is infected and symptomatic but -* who do not need to be hospitalized (yet) in day unit +* who do not need to be hospitalized yet in day unit +*/ +struct TimeInfectedSymptomsToSevere { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedSymptomsToSevere"; + } +}; + +/** +* @brief Time that a Person is infected and symptomatic who will recover in day unit */ -struct TimeInfectedSymptoms { +struct TimeInfectedSymptomsToRecovered { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedSymptomsToRecovered"; + } +}; + +/** + * @brief Time that a Person is infected and 'simply' hospitalized before becoming critical in day unit + */ +struct TimeInfectedSevereToCritical { + using Type = CustomIndexArray; + static Type get_default(AgeGroup size) + { + return Type({VirusVariant::Count, size}, InfectionStateTimesDistributionsParameters{1., 1.}); + } + static std::string name() + { + return "TimeInfectedSevereToCritical"; + } +}; + +/** + * @brief Time that a Person is infected and 'simply' hospitalized before recovering in day unit + */ +struct TimeInfectedSevereToRecovered { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -84,14 +144,14 @@ struct TimeInfectedSymptoms { } static std::string name() { - return "TimeInfectedSymptoms"; + return "TimeInfectedSevereToRecovered"; } }; /** - * @brief Time that a Person is infected and 'simply' hospitalized in day unit + * @brief Time that a Person is treated by ICU before dying in day unit */ -struct TimeInfectedSevere { +struct TimeInfectedCriticalToDead { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -99,14 +159,14 @@ struct TimeInfectedSevere { } static std::string name() { - return "TimeInfectedSevere"; + return "TimeInfectedCriticalToDead"; } }; /** - * @brief Time that a Person is treated by ICU in day unit + * @brief Time that a Person is treated by ICU before recovering in day unit */ -struct TimeInfectedCritical { +struct TimeInfectedCriticalToRecovered { using Type = CustomIndexArray; static Type get_default(AgeGroup size) { @@ -114,7 +174,7 @@ struct TimeInfectedCritical { } static std::string name() { - return "TimeInfectedCritical"; + return "TimeInfectedCriticalToRecovered"; } }; @@ -225,6 +285,22 @@ struct InfectivityDistributions { } }; +/** + * @brief Individual virus shed factor to account for variability in infectious viral load spread. +*/ +struct VirusShedFactor { + using Type = CustomIndexArray::ParamType, VirusVariant, AgeGroup>; + static Type get_default(AgeGroup size) + { + Type default_val({VirusVariant::Count, size}, UniformDistribution::ParamType{0., 0.28}); + return default_val; + } + static std::string name() + { + return "VirusShedFactor"; + } +}; + /** * @brief Probability that an Infection is detected. */ @@ -541,9 +617,11 @@ struct AgeGroupGotoWork { }; using ParametersBase = - ParameterSetget()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptoms of virus variant " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptomsToSymptoms " + "of virus variant " + "{} and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptomsToRecovered of " + "virus variant " "{} and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); return true; } - if (this->get()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedSymptoms of virus variant {} " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSymptomsToSevere of virus " + "variant {} " + "and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSymptomsToRecovered of virus " + "variant {} " + "and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSevereToCritical of virus " + "variant {} " "and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); return true; } - if (this->get()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedSevere of virus variant {} " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedSevereToRecovered of virus " + "variant {} " "and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); return true; } - if (this->get()[{v, i}].params.a() < 0.0) { - log_error("Constraint check: Lower end of parameter range TimeInfectedCritical of virus variant {} " + if (this->get()[{v, i}].params.a() < 0.0) { + log_error( + "Constraint check: Lower end of parameter range TimeInfectedCriticalToDead of virus variant {} " + "and age group {:.0f} smaller " + "than {:d}", + (uint32_t)v, (size_t)i, 0); + return true; + } + + if (this->get()[{v, i}].params.a() < 0.0) { + log_error("Constraint check: Lower end of parameter range TimeInfectedCriticalToRecovered of virus " + "variant {} " "and age group {:.0f} smaller " "than {:d}", (uint32_t)v, (size_t)i, 0); diff --git a/cpp/simulations/abm.cpp b/cpp/simulations/abm.cpp index ba1cb50e9c..49886ea686 100644 --- a/cpp/simulations/abm.cpp +++ b/cpp/simulations/abm.cpp @@ -470,153 +470,194 @@ void set_parameters(mio::abm::Parameters params) }; //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.092; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.; - + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.139; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.139; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.123; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.024; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.123; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.024; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.115; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.115; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; // Set each parameter for vaccinated people including personal infection and vaccine protection levels. // Summary: https://doi.org/10.1038/s41577-021-00550-x, //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.132; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.141; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.141; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.133; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.133; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; } /** diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index d9480ed15f..394d107d5e 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -398,90 +398,115 @@ void set_parameters(mio::abm::Parameters params) }; //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.092; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.276; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.139; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.139; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.123; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.024; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.123; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.024; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.315; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.115; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.115; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.033; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; // Set each parameter for vaccinated people including personal infection and vaccine protection levels. // Summary: https://doi.org/10.1038/s41577-021-00550-x, //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.132; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.001; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_0_TO_4, @@ -539,16 +564,19 @@ void set_parameters(mio::abm::Parameters params) }; //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_5_TO_14}] = 0.001; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_5_TO_14, @@ -605,17 +633,21 @@ void set_parameters(mio::abm::Parameters params) }; //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 0.021; // Set up personal infection and vaccine protection levels, based on: https://doi.org/10.1038/s41577-021-00550-x, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_15_TO_34, mio::abm::VirusVariant::Wildtype}] = @@ -671,17 +703,20 @@ void set_parameters(mio::abm::Parameters params) }; //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.141; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.141; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.008; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_35_TO_59, @@ -738,17 +773,21 @@ void set_parameters(mio::abm::Parameters params) }; //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.023; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_60_TO_79, @@ -805,16 +844,19 @@ void set_parameters(mio::abm::Parameters params) }; //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.179; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.133; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.0; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.133; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.012; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_80_PLUS}] = 0.052; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, AGE_GROUP_80_PLUS, diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index ce1a2f4042..89589070d1 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -118,22 +118,18 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(NUM_AGE_GROUPS); - // Time in all infected states 1 day (dt). - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = {1., 1.}; - - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = .5; + // Time to go from all infected states to recover is 1 day (dt). + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 1; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + 1; ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(14)) .WillOnce(testing::Return(0.1)) // Transition to InfectedNoSymptoms - .WillOnce(testing::Return(0.1)) // Time rollout + .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) diff --git a/cpp/tests/test_abm_location.cpp b/cpp/tests/test_abm_location.cpp index d596fa8ada..c71f461d37 100644 --- a/cpp/tests/test_abm_location.cpp +++ b/cpp/tests/test_abm_location.cpp @@ -159,10 +159,10 @@ TEST(TestLocation, reachCapacity) //setup so p1 doesn't do transition world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto home_id = world.add_location(mio::abm::LocationType::Home); diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index fd14098de8..f5328dcfcc 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -121,7 +121,7 @@ TEST(TestPerson, quarantine) auto t_morning = mio::abm::TimePoint(0) + mio::abm::hours(7); auto dt = mio::abm::hours(1); infection_parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_35_TO_59}] = 0.5 * dt.days(); auto person = make_test_person(home, AGE_GROUP_35_TO_59, mio::abm::InfectionState::InfectedSymptoms, t_morning, diff --git a/cpp/tests/test_abm_world.cpp b/cpp/tests/test_abm_world.cpp index 026b1809db..cc69dcd614 100644 --- a/cpp/tests/test_abm_world.cpp +++ b/cpp/tests/test_abm_world.cpp @@ -133,15 +133,16 @@ TEST(TestWorld, evolveStateTransition) world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto location1 = world.add_location(mio::abm::LocationType::School); @@ -175,11 +176,10 @@ TEST(TestWorld, evolveMigration) auto world = mio::abm::World(NUM_AGE_GROUPS); //setup so p1 doesn't do transition world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = - 2 * dt.days(); - world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); + world.parameters.get()[{mio::abm::VirusVariant::Wildtype, + AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto home_id = world.add_location(mio::abm::LocationType::Home); auto school_id = world.add_location(mio::abm::LocationType::School); @@ -230,14 +230,15 @@ TEST(TestWorld, evolveMigration) auto world = mio::abm::World(NUM_AGE_GROUPS); //setup so p1-p5 don't do transition world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); + world.parameters.get()[{mio::abm::VirusVariant::Wildtype, + AGE_GROUP_15_TO_34}] = 2 * dt.days(); world.parameters - .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = - 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = 2 * dt.days(); auto home_id = world.add_location(mio::abm::LocationType::Home); @@ -359,10 +360,12 @@ TEST(TestWorld, evolveMigration) auto world = mio::abm::World(NUM_AGE_GROUPS); // Time to go from severe to critical infection is 1 day (dt). - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.5; // Time to go from critical infection to dead state is 1/2 day (0.5 * dt). - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.5; + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_60_TO_79}] = 0.5; auto home_id = world.add_location(mio::abm::LocationType::Home); auto work_id = world.add_location(mio::abm::LocationType::Work); @@ -409,9 +412,10 @@ TEST(TestWorldTestingCriteria, testAddingAndUpdatingAndRunningTestingSchemes) auto world = mio::abm::World(NUM_AGE_GROUPS); // make sure the infected person stay in Infected long enough - world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = + world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = + 100; + world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = 100; - world.parameters.get()[{mio::abm::VirusVariant(0), AGE_GROUP_15_TO_34}] = 100; auto home_id = world.add_location(mio::abm::LocationType::Home); auto work_id = world.add_location(mio::abm::LocationType::Work); @@ -463,15 +467,15 @@ TEST(TestWorld, checkParameterConstraints) auto params = world.parameters; params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 1.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 3.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 10.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 3.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.3; params.get()[AGE_GROUP_35_TO_59] = mio::abm::hours(4); params.get()[AGE_GROUP_35_TO_59] = mio::abm::hours(8); @@ -486,33 +490,34 @@ TEST(TestWorld, checkParameterConstraints) params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -1.; ASSERT_EQ(params.check_constraints(), true); params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 1.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -2.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + -2.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -3.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 2.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + -3.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 3.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -4.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = + 3.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -4.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -5.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 4.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -5.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -6.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 5.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -6.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -7.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 6.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -7.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -8.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 7.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -8.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -9.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 8.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -9.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = -10.; + params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 9.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 10.; params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 1.1; ASSERT_EQ(params.check_constraints(), true); params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] = 0.3; @@ -580,12 +585,12 @@ TEST(TestWorld, copyWorld) auto infection_params = world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] - .value(); + .params.a(); auto copied_world = mio::abm::World(world); auto copied_infection_params = copied_world.parameters.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_0_TO_4}] - .value(); + .params.a(); // Assert the parameters, trips, locations and persons of copied world are logically equal to that of original world ASSERT_EQ(copied_infection_params, infection_params); diff --git a/cpp/tests/test_analyze_result.cpp b/cpp/tests/test_analyze_result.cpp index 8648171b6a..54f4e8c824 100644 --- a/cpp/tests/test_analyze_result.cpp +++ b/cpp/tests/test_analyze_result.cpp @@ -475,27 +475,31 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) auto world1 = mio::abm::World(num_age_groups); auto world2 = mio::abm::World(num_age_groups); - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.1; - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.1; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.2; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.3; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.3; auto g1 = std::vector({world1, world2}); world1.parameters - .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.3; - world1.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.4; + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.2; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.3; + world1.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.4; world2.parameters - .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.7; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = - 0.4; - world2.parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.5; + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.7; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.4; + world2.parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] = 0.5; auto g2 = std::vector({world1, world2}); @@ -506,48 +510,56 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) auto check1 = ensemble_p49_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check2 = ensemble_p49_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check1, 0.1); EXPECT_EQ(check2, 0.2); auto check3 = ensemble_p51_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check4 = ensemble_p51_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check3, 0.3); EXPECT_EQ(check4, 0.4); auto check5 = ensemble_p49_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check6 = ensemble_p49_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check5, 0.2); EXPECT_EQ(check6, 0.3); auto check7 = ensemble_p51_params[0] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); auto check8 = ensemble_p51_params[1] - .parameters.get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .value(); + .parameters + .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] + .params.a(); EXPECT_EQ(check7, 0.4); EXPECT_EQ(check8, 0.5); From 6f489f69042df007b11fe501015ad631615ba621 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:20:49 +0100 Subject: [PATCH 014/488] Fix from merge --- cpp/simulations/abm.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/abm.cpp b/cpp/simulations/abm.cpp index 685134e28b..1b472a70ab 100644 --- a/cpp/simulations/abm.cpp +++ b/cpp/simulations/abm.cpp @@ -578,15 +578,15 @@ void set_parameters(mio::abm::Parameters params) 0.179; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, AGE_GROUP_15_TO_34}] = + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.142; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.001; From 054b7462c98f1162495faa8abbcbdf91d1f8bf4b Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:00:15 +0100 Subject: [PATCH 015/488] Fix infection tests --- cpp/models/abm/infection.cpp | 6 +-- cpp/tests/test_abm_infection.cpp | 73 ++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index c59d85eb3c..5ba22dd079 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -272,18 +272,18 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}]; - if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + if (p > (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; } - else if (p < params.get()[{m_virus_variant, age}] * + else if (p > params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSymptoms; } - else if (p < params.get()[{m_virus_variant, age}] * + else if (p > params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index 17d2894bc2..ab62404fa6 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -30,6 +30,8 @@ TEST(TestInfection, init) auto virus_variant_test = mio::abm::VirusVariant::Wildtype; auto age_group_test = age_group_15_to_34; + params.get()[{virus_variant_test, age_group_test}] = {0.1, 0.2}; + //set up a personal RNG for infections //uses uniformdistribution but result doesn't matter, so init before the mock mio::abm::Location loc(mio::abm::LocationType::Hospital, 0); @@ -38,9 +40,13 @@ TEST(TestInfection, init) ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) - .Times(testing::AtLeast(7)) + .Times(testing::AtLeast(21)) + // 1st infection + .WillOnce(testing::Return(1.)) // IncubationTime .WillOnce(testing::Return(0.4)) // Transition to Infected + .WillOnce(testing::Return(0.4)) // TimeInfectedNoSymptomsToSymptoms .WillOnce(testing::Return(0.6)) // Transition to Recovered + .WillOnce(testing::Return(0.4)) // TimeInfectedSymptomsToRecovered .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .viral_load_peak.params.a())) // Viral load draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] @@ -51,8 +57,13 @@ TEST(TestInfection, init) .infectivity_alpha.params.a())) // Infectivity draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) - .WillOnce(testing::Return(0.1)) // Transition to Infected - .WillOnce(testing::Return(0.1)) // Transition to Recovered + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor + // 2nd infection + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms + .WillOnce(testing::Return(1.0)) // IncubationTime + .WillOnce(testing::Return(1.0)) // Transition to Recovered + .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToRecovered .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .viral_load_peak.params.a())) // Viral load draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] @@ -63,6 +74,8 @@ TEST(TestInfection, init) .infectivity_alpha.params.a())) // Infectivity draws .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor .WillRepeatedly(testing::Return(1.0)); auto infection = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, @@ -75,7 +88,7 @@ TEST(TestInfection, init) mio::abm::InfectionState::Exposed); EXPECT_EQ(infection.get_infection_state(mio::abm::TimePoint(0) + mio::abm::days(1)), mio::abm::InfectionState::InfectedNoSymptoms); - EXPECT_NEAR(infection.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), 0.2689414213699951, 1e-14); + EXPECT_NEAR(infection.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), 0.02689414213699951, 1e-14); params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_test, virus_variant_test}] = [](ScalarType days) -> ScalarType { @@ -94,7 +107,7 @@ TEST(TestInfection, init) EXPECT_EQ(infection_w_previous_exp.get_infection_state(mio::abm::TimePoint(0) + mio::abm::days(1)), mio::abm::InfectionState::Recovered); EXPECT_NEAR(infection_w_previous_exp.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), - 0.45760205922564895, 1e-14); + 9.1105119440064545e-05, 1e-14); } TEST(TestInfection, getInfectionState) @@ -118,30 +131,46 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); - // Time to go from all infected states to recover is 1 day (dt). - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = - 1; - ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) - .Times(testing::AtLeast(14)) - .WillOnce(testing::Return(0.1)) // Transition to InfectedNoSymptoms + .Times(testing::AtLeast(32)) + // 1st infection + .WillOnce(testing::Return(1.0)) // Transition to InfectedNoSymptoms + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToRecovered + .WillOnce(testing::Return(1.0)) // IncubationPeriod + .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + // 2nd infection + .WillOnce(testing::Return(0.4)) // Transition to InfectedSymptoms + .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToRecovered + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms + .WillOnce(testing::Return(1.0)) // IncubationPeriod + .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.3)) // Transition to InfectedSymptoms - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.3)) - .WillOnce(testing::Return(0.6)) // Transition to InfectedSevere - .WillRepeatedly(testing::Return(0.9)); // Transition to InfectedCritical + // 3rd infection + .WillOnce(testing::Return(0.2)) // Transition to InfectedSevere + .WillOnce(testing::Return(1.0)) // TimeInfectedSevereToRecovered + .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToSevere + .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms + .WillOnce(testing::Return(1.0)) // IncubationPeriod + .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(0.1)) + // 4th infection + .WillOnce(testing::Return(0.0)) // Transition to InfectedCritical + .WillOnce(testing::Return(1.0)) //TimeInfectedCriticalToRecovered + .WillRepeatedly(testing::Return(1.0)); auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, From 61ea949bbdca3439ba78e496e0c3ef6d8ca24920 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:27:17 +0100 Subject: [PATCH 016/488] add analysis script Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- .../memilio/epidata/check_bs_data.py | 509 ++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 pycode/memilio-epidata/memilio/epidata/check_bs_data.py diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py new file mode 100644 index 0000000000..2324bae8e1 --- /dev/null +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -0,0 +1,509 @@ +import pandas as pd +import matplotlib +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import os + +import sys +if sys.version_info[0] == 3: + import tkinter as tk +else: + import Tkinter as tk + + +####### minimal sanity check on data ####### +bd = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/pycode/memilio-epidata/memilio/epidata/bs_und_umgebung.csv', header=None, skiprows=1) + +# setup dictionary for the leisure activities, and vehicle choice and column names +# bd.rename( +# columns={0: 'idTrafficZone', 1: 'tripID', 2: 'personID', 3: 'tripChain', 4: 'startZone', 5: 'destZone', 6: 'loc_id_start', 7: 'loc_id_end', +# 8: 'countyStart', 9: 'countyEnd', 10: 'hhID', 11: 'tripChainID', 12: 'tripDistance', 13: 'startTime', 14: 'travelTime', 19: 'vehicleChoice', 20: +# 'ActivityBefore', 21: 'ActivityAfter', 15: 'loCs', 16: 'laCs', 17: 'loCe', 18: 'laCe', 22: 'age'}, +# inplace=True) +bd.rename( + columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', + 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', 10: 'travelTime' , 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', 16: + 'ActivityBefore', 17: 'ActivityAfter', 18: 'age'}, + inplace=True) + +dict_leisure = {1: 'work', 2: 'education', 3: 'Shopping', 4: 'free time', + 5: 'private matters', 6: 'others', 7: 'home', 0: 'not specified'} +dict_vehicle = {1: 'bicyle', 2: 'car_driver', + 3: 'car_codriver', 4: 'public transport', 5: 'walk'} + +# check if people do the same trip more than once +trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] +duplicate_trips = trips.duplicated() +if (duplicate_trips.any()): + print('Error: The Person does the "same" trip more than once (or dos 2 things in 5 mins). Number of duplicate trips: ' + str(duplicate_trips[duplicate_trips==True].size)) + # if (~bd[['tripID']].duplicated().any()): + # print('There are no duplicate TripIDs. There are multiple TripIDs for the same Trip. \n') +activities_after_duplicate_trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime', 'ActivityAfter']].loc[trips.duplicated(keep=False)] +if (~activities_after_duplicate_trips.duplicated(keep=False).all()): + print('Error: Multiple activities after the same trip. \n') + +# check if persons have more than one home +person_homes = bd[['personID', 'loc_id_end', 'ActivityAfter']].loc[bd['ActivityAfter']==7] +person_homes = person_homes.drop_duplicates().groupby(['personID']).size().reset_index(name='counts') +person_homes.drop(person_homes.loc[person_homes['counts']<2].index, inplace=True) +if(person_homes.size > 0): + print('Error: There are people that have more than one home. \n') + +# check if the proportion of single-person-households is too high +households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) + +if households.drop(households.loc[households['counts']>1].index).size / bd[['personID']].drop_duplicates().size >= 0.4: + print("Error: The proportion of single-person-households is too high: " + + str(households.drop(households.loc[households['counts']>1].index).size / bd[['personID']].drop_duplicates().size)) + +# check if there are invalid entries +# if not bd['idTrafficZone'].ge(30000000).all(): +# print('Error: There is an entry in "tripID" that is not assignable. \n') +# # number of entries that are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripID'].ge(30000000)].size) + '. \n') +if not bd['personID'].ge(100000000).all(): + print('Error: There is an entry in "personID" that is not assignable. \n') + # number of entries that are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['personID'].ge(100000000)].size) + '. \n') +# if not bd['tripChain'].between(1, 100).all(): +# print('Error: There is an entry in "tripChain" that is not assignable. \n') +# # number of entries that are not assignable + # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripChain'].between(1, 100)].size) + '. \n') + # # max assigned value + # print('Max assigned value: ' + str(bd['tripChain'].max()) + '. \n') +# if not bd['countyStart'].ge(30000000).all(): +# print('Error: There is an entry in "countyStart" that is not assignable. \n') +# # which ones are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyStart'].ge(30000000)].size) + '. \n') +# if not bd['countyEnd'].ge(30000000).all(): +# print('Error: There is an entry in "countyEnd" that is not assignable. \n') +# # which ones are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyEnd'].ge(30000000)].size) + '. \n') +# if not bd['hhID'].ge(100000000).all(): +# print('Error: There is an entry in "hhID" that is not assignable. \n') +# if not bd['tripChainID'].between(-1, -1).all(): +# print('Error: There is an entry in "tripChainID" that is not assignable. \n') +if not bd['vehicleChoice'].between(1, 5).all(): + print('Error: There is an entry in "vehicleChoice" that is not assignable. \n') + #print number of entries that are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['vehicleChoice'].between(1, 5)].size) + '. \n') +if not bd['ActivityAfter'].between(0, 7).all(): + print('Error: There is an entry in "ActivityAfter" that is not assignable. \n') + #print number of entries that are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['ActivityAfter'].between(0, 7)].size) + '. \n') + +# check if there are empty cells +for header in bd.columns: + if (bd[header].isna().any()): + print('Error: ' + str(len(bd[bd[header].isna()])) + ' empty entries in column' + str(header) + '. \n') + +# check age groups with schools +number_of_people = bd[['personID']].drop_duplicates().size +print(str(number_of_people) + ' are people. \n') + +# number_of_trips = bd[['tripID']].drop_duplicates().size +# print(str(number_of_trips) + ' trips. \n') + +students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] +print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') +print(str(students.loc[students['age'] > 20].size) + ' persons of ' + str(students.size) + ' people going to school are in a higher age group than 10. \n') + +children = bd[['personID','ActivityAfter']].loc[(bd['age']<=17) & (bd['age']>=7)] +number_of_children = children['personID'].drop_duplicates().size +number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size +print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') + + +workers = bd[['personID','ActivityAfter']].loc[(bd['age']>0)] +number_of_workers = workers['personID'].drop_duplicates().size +number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size +print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' children do not go to school. \n') + + + +############################################### + + +####### visual check on values in data frame ####### + +# def get_trip_chain_activity_after(person_id): +# bd_persons_trip_chain_activity_after = bd.loc[bd['personID'] == person_id, [ +# 'tripChain', 'ActivityAfter']] +# bd_persons_trip_chain_activity_after = bd_persons_trip_chain_activity_after.sort_values( +# by=['tripChain'], ascending=True, ignore_index=True) +# bd_persons_trip_chain_activity_after['ActivityAfter'] = bd_persons_trip_chain_activity_after['ActivityAfter'].map( +# dict_leisure) +# # and vehicle choice +# bd_persons_trip_chain_vehicle_choice = bd.loc[bd['personID'] == person_id, [ +# 'tripChain', 'vehicleChoice']] +# bd_persons_trip_chain_vehicle_choice = bd_persons_trip_chain_vehicle_choice.sort_values( +# by=['tripChain'], ascending=True, ignore_index=True) +# bd_persons_trip_chain_vehicle_choice['vehicleChoice'] = bd_persons_trip_chain_vehicle_choice['vehicleChoice'].map( +# dict_vehicle) +# return bd_persons_trip_chain_activity_after, bd_persons_trip_chain_vehicle_choice + + +# read in the data +if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'figs_bs_data')): + os.makedirs(os.path.join(os.path.dirname( + os.path.abspath(__file__)), 'figs_bs_data')) +figs_path = os.path.join(os.path.dirname( + os.path.abspath(__file__)), 'figs_bs_data') + +# check whether first start location is the last end location +first_trip = bd[['personID','loc_id_start']].sort_values(by=['personID']).drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) +last_trip = bd[['personID', 'loc_id_end', 'ActivityAfter']].sort_values(by=['personID']).drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) +compare_first_and_last_trip = first_trip['loc_id_start'].compare(last_trip['loc_id_end']) +print("Number of persons where first start location is not the last end location: " + str(compare_first_and_last_trip.size)+ ".") + +# check what persons are doing which only do one trip +location_types = last_trip.groupby(['ActivityAfter']).size() + +location_types.plot(kind='bar') +plt.xlabel('Activity') +plt.ylabel('Number of persons') +plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) + +# probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located +# bd_tz_bs = bd.groupby(['idTrafficZone']).size().reset_index( +# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # Count traffic zones where person is residing and longitude and latuitude of this in "EPSG:3035" format +# bd_traffic_zones_persons = bd.groupby(['idTrafficZone']).size().reset_index( +# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# for row in bd_traffic_zones_persons.iterrows(): +# bd_traffic_zones_persons.loc[row[0], ['longitude', 'latitude'] +# ] = bd.loc[bd_traffic_zones_persons.loc[row[0], 'idTrafficZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +# print(bd_traffic_zones_persons) + +#### Counting people #### +bd_persons = bd.groupby(['personID']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# Get the frequency of each number in the 'numbers' column +bd_personss = bd_persons['counts'].value_counts().sort_index() +# Plot the frequency of each number +bd_personss.plot(kind='bar') +plt.xlabel('Number of trips per day') +plt.ylabel('Number of persons') +plt.title('Number of trips per person tripcount (Braunschweig)') +plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) + +bd_persons_ages = bd[['personID', 'age']].drop_duplicates() +bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ + '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +bd_persons_ages_cohorts = bd_persons_ages.groupby( + ['AgeCohort']).size().reset_index(name='counts') +bd_persons_ages_cohorts.index = bd_persons_ages_cohorts['AgeCohort'].to_list() +bd_persons_ages_cohorts.plot.bar(figsize=( + 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) +plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) + +# get the id with the persons with the highest number and print them +# [id_person_max_trips, id_person_max_1_trips] = [ +# bd_persons['personID'][0], bd_persons['personID'][1]] +# print(get_trip_chain_activity_after(id_person_max_trips)) + +# select internal and external trips (from/to Braunschweig) +# bd_persons_inside_bs = bd.loc[bd['startZone'].isin( +# bd_tz_bs['idTrafficZone']) & bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] +# bd_persons_outside_bs = bd.loc[~bd['startZone'].isin( +# bd_tz_bs['idTrafficZone']) & ~bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] + +# check how many trips are in the same traffic zone +bd_taz_start = bd.groupby('startZone').size().reset_index(name='counts') +#bd_same_taz = bd.loc[bd['startZone'] == bd['destZone']] +bd_different_taz = bd.loc[bd['startZone'] != bd['destZone']] +#bd_same_taz = bd_same_taz.groupby(['startZone']).size().reset_index(name='counts') +bd_different_taz = bd_different_taz.groupby( + ['startZone']).size().reset_index(name='counts') +#bd_same_taz['percentage'] = bd_same_taz['counts']/bd_taz_start['counts'] +bd_different_taz['complement_counts'] = bd_taz_start['counts'] - \ + bd_different_taz['counts'] +bd_different_taz['total_counts'] = bd_taz_start['counts'] +bd_different_taz = (bd_different_taz.sort_values( + by='total_counts', ascending=False, ignore_index=True)) +plt.figure() +plt.plot(bd_different_taz['counts']) +plt.plot(bd_different_taz['complement_counts']) +plt.legend(['different TAZ', 'same TAZ']) +plt.xlabel('Traffic analysis zones') +plt.ylabel('Amount of trips inside/outside a TAZ') +plt.savefig(os.path.join(figs_path, 'TAZ_distribution.png'), dpi=300) + +# which age takes which mode of transport +bd_persons_age_vehicle_choice = bd.loc[:, ['personID', 'age', 'vehicleChoice']].sort_values( + by=['age'], ascending=True, ignore_index=True) +bd_persons_age_vehicle_choice['vehicleChoice'] = bd_persons_age_vehicle_choice['vehicleChoice'].map( + dict_vehicle) +# accumulate the number of trips per age and vehicle choice +bd_persons_age_vehicle_choice = bd_persons_age_vehicle_choice.groupby( + ['age', 'vehicleChoice']).size().reset_index( + name='counts').sort_values( + by=['age'], + ascending=True, ignore_index=True) +# assign each age to an age cohort +bd_persons_age_vehicle_choice['ageCohort'] = pd.cut(bd_persons_age_vehicle_choice['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ + '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# plot a cake chart for each age cohort +bd_persons_age_vehicle_choice_cake = bd_persons_age_vehicle_choice.groupby( + ['ageCohort', 'vehicleChoice']).sum().reset_index() +bd_persons_age_vehicle_choice_cake_age_veh = bd_persons_age_vehicle_choice_cake.pivot( + index='ageCohort', columns='vehicleChoice', values='counts') +bd_persons_age_vehicle_choice_cake_age_veh.plot.pie(subplots=True, layout=(3, 2), figsize=( + 10, 10), title=bd_persons_age_vehicle_choice_cake_age_veh.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'vehicle_choice_per_age.png'), dpi=300) + +# switch age cohort and vehicle choice +bd_persons_age_vehicle_choice_cake_veh_age = bd_persons_age_vehicle_choice_cake.pivot( + index='vehicleChoice', columns='ageCohort', values='counts') +bd_persons_age_vehicle_choice_cake_veh_age.plot.pie(subplots=True, layout=(3, 3), figsize=( + 20, 10), title=bd_persons_age_vehicle_choice_cake_veh_age.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'vehicle_choice_reversed.png'), dpi=300) + +# Analyse trip purposes per age cohort +bd_persons_age_purpose = bd.loc[:, ['personID', 'age', 'ActivityAfter']] +bd_persons_age_purpose['ActivityAfter'] = bd_persons_age_purpose['ActivityAfter'].map( + dict_leisure) +bd_persons_age_purpose['ageCohort'] = pd.cut(bd_persons_age_purpose['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ + '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +bd_persons_age_purpose_acc = bd_persons_age_purpose.groupby( + ['ActivityAfter', 'ageCohort']).size().reset_index(name='counts') +bd_persons_age_purpose_cake = bd_persons_age_purpose_acc.pivot( + index='ageCohort', columns='ActivityAfter', values='counts') +bd_persons_age_purpose_cake.plot.pie(subplots=True, layout=(2, 4), figsize=( + 15, 5), title=bd_persons_age_purpose_cake.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'trip_purpose.png'), dpi=300) + +# switch age cohorts and purpose +bd_persons_age_purpose_cake_reversed = bd_persons_age_purpose_acc.pivot( + index='ActivityAfter', columns='ageCohort', values='counts') +bd_persons_age_purpose_cake_reversed.plot.pie(subplots=True, layout=(2, 5), figsize=( + 15, 5), title=bd_persons_age_purpose_cake_reversed.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'trip_purpose_reversed.png'), dpi=300) + +# Count traffic zones where people are starting their trips +bd_traffic_zones_start = bd.groupby(['startZone']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +for row in bd_traffic_zones_start.iterrows(): + bd_traffic_zones_start.loc[row[0], ['longitude', 'latitude'] + ] = bd.loc[bd_traffic_zones_start.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +print(bd_traffic_zones_start) + +# plot longitude and latitude of traffic zones +bd_traffic_zones_start.plot( + kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_start['counts'] / 100, figsize=(10, 15), + title='Traffic zones where people are starting their trips (Braunschweig)') +plt.savefig(os.path.join(figs_path, 'traffic_zones_start.png'), dpi=300) + +# Count traffic zones where people are going and leaving +bd_traffic_zones_end = bd.groupby(['destZone']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +for row in bd_traffic_zones_end.iterrows(): + bd_traffic_zones_end.loc[row[0], ['longitude', 'latitude'] + ] = bd.loc[bd_traffic_zones_end.loc[row[0], 'destZone'] == bd['destZone'], ['loCs', 'laCs']].values[0] +print(bd_traffic_zones_end) + +# plot longitude and latitude of traffic zones +bd_traffic_zones_end.plot( + kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_end['counts'] / 100, figsize=(10, 10), + title='Traffic zones where people are ending their trips (Braunschweig)') +plt.savefig(os.path.join(figs_path, 'traffic_zones_end.png'), dpi=300) + +# Time analyzing +# Time of day +bd_time = bd.groupby(['startTime']).size().reset_index(name='counts') +print(bd_time) +bd_time.plot(kind='line', x='startTime', y='counts') +plt.xlabel('Time of day') +plt.ylabel('Number of trips') +plt.title('Time of day (Braunschweig)' + ' (n = ' + str(len(bd)) + ' trips)') +plt.savefig(os.path.join(figs_path, 'time_of_day.png'), dpi=300) + +# time of day rolling average +bd_time['rolling_mean'] = bd_time['counts'].rolling(window=7).mean() +bd_time.plot(kind='line', x='startTime', y='rolling_mean') +plt.xlabel('Time of day') +plt.ylabel('Number of trips') +plt.title('Time of day (Braunschweig)' + ' (n = ' + + str(len(bd)) + ' trips), rolling mean with window size 7') +plt.savefig(os.path.join(figs_path, 'time_of_day_rolling.png'), dpi=300) + +# Frequency matrix of trips between traffic zones +matrix_freq = pd.crosstab(bd['startZone'], bd['destZone']) +nnz_matrix_freq = np.count_nonzero(matrix_freq) +subset_matrix_freq = matrix_freq.iloc[0:30, 0:30] +nnz_sub_matrix_freq = np.count_nonzero(subset_matrix_freq) +sns.heatmap(subset_matrix_freq, cmap="Blues", vmin=0) +plt.xlabel('Destination traffic zone') +plt.ylabel('Start traffic zone') +plt.title('Number of non-zero entries in frequency matrix: ' + str(nnz_sub_matrix_freq) + ' out of ' + str(subset_matrix_freq.size) + ' entries (' + + str(round(nnz_sub_matrix_freq / subset_matrix_freq.size * 100, 2)) + '%)') +plt.savefig(os.path.join(figs_path, 'heatmap.png'), dpi=300) + +# frequency matrix of trips from which leisure activity to which leisure activity + +# check if all activities of bd activity before are in the dictionary +if bd['ActivityBefore'].isin(dict_leisure.keys()).all(): + print('All activities in dictionary') +# check if there is a activity missing that is in the dictionary +if not set(dict_leisure.keys()).issubset(set(bd['ActivityBefore'].unique())): + print('There is an activity missing that is in the dictionary:') + for key in (set(dict_leisure.keys()).difference(set(bd['ActivityBefore'].unique()))): + print(key, dict_leisure[key]) + + +matrix_frqu_leisure = pd.crosstab( + bd['ActivityBefore'], + bd['ActivityAfter'], + normalize='index') +sns.heatmap(matrix_frqu_leisure, vmin=0, xticklabels=dict_leisure.values(), + yticklabels=dict_leisure.values()) +plt.xlabel('Leisure activity after trip') +plt.ylabel('Leisure activity before trip') +plt.title('Frequency of trips from which leisure activity to which leisure activity') +plt.savefig(os.path.join(figs_path, 'heatmap_leisure.png'), dpi=300) + + +# quick check if a data point in the matrix is correct +check = bd.loc[(bd['startZone'] == 31010011) & ( + bd['destZone'] == 31010011), 'startZone'].count() + + +# plotting the duration of trips +fig, axs = plt.subplots(2) +axs[0].hist(bd['travelTime']/60/60, bins=100, + range=(0, max(bd['travelTime'])*1.2/60/60)) +axs[0].set_title('Trip duration (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips)') +axs[0].set_xlabel('Trip duration in hours') +axs[0].set_ylabel('Number of trips') +axs[1].hist(bd['travelTime']/60/60, bins=100, + range=(0, max(bd['travelTime'])*1.2/60/60)) +axs[1].set_yscale('log') +axs[1].set_title('Trip duration (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips) log scale') +axs[1].set_xlabel('Trip duration in hours') +axs[1].set_ylabel('Number of trips') + +# same thing with the distance of the trips +fig2, axs2 = plt.subplots(2) +axs2[0].hist(bd['tripDistance'], bins=100, + range=(0, max(bd['tripDistance'])*1.2,)) +axs2[0].set_title('Trip distance (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips)') +axs2[0].set_xlabel('Trip distance in Kilometers') +axs2[0].set_ylabel('Number of trips') +axs2[1].hist(bd['tripDistance'], bins=100, + range=(0, max(bd['tripDistance'])*1.2,)) +axs2[1].set_yscale('log') +axs2[1].set_title('Trip distance (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips) log scale') +axs2[1].set_xlabel('Trip distance in Kilometers') +axs2[1].set_ylabel('Number of trips') + + +# analyze age distribution with age cohorts +bd_persons_id_and_age = bd[['personID', 'age']].drop_duplicates() +bd_age_cohorts = pd.cut( + bd_persons_id_and_age['age'], + bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95, 106], + labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95', '96-105']).reset_index( + name='age_cohort').groupby( + ['age_cohort']).size().reset_index( + name='counts') +bd_age_cohorts.plot(kind='bar', x='age_cohort', y='counts') +plt.xlabel('Age cohort') +plt.ylabel('Number of persons') +plt.title('Age distribution of persons in Braunschweig in age cohorts, number ') +plt.savefig(os.path.join(figs_path, 'age_cohorts.png'), dpi=300) + +# relation between age and trip duration in minutes and hours +bd_age_duration = bd.groupby(['age']).mean().reset_index() +bd_age_duration['travelTime'] = bd_age_duration['travelTime'] / 60 +bd_age_duration.plot(kind='bar', x='age', y='travelTime') + +# also do this for trip distance +bd_age_distance = bd.groupby(['age']).mean().reset_index() +bd_age_distance.plot(kind='bar', x='age', y='tripDistance') + +# analyze trip distance in distance cohort +bd_trip_distance_cohorts = pd.cut( + bd['tripDistance'], + bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], + labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( + name='trip_distance_cohort').groupby( + ['trip_distance_cohort']).size().reset_index( + name='counts') +bd_trip_distance_cohorts.plot(kind='bar', x='trip_distance_cohort', y='counts') +plt.xlabel('Trip distance cohort in km') +plt.ylabel('Number of trips') +plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + str(len(bd))) +plt.savefig(os.path.join(figs_path, 'trip_distance_cohorts.png'), dpi=300) + +# pie diagram of trip distance cohorts for each age cohort +bd_trip_distance_cohorts_vehicle = pd.cut( + bd['tripDistance'], + bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], + labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( + name='trip_distance_cohort') +bd_age_cohorts = pd.cut(bd['age'], + bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95], + labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95']).reset_index( + name='age_cohort') +# attach the age cohort to the dataframe +bd_trip_distance_cohorts_vehicle = pd.concat( + [bd_trip_distance_cohorts_vehicle['trip_distance_cohort'], bd_age_cohorts['age_cohort']], axis=1) +# group by age cohort and distance cohort +bd_trip_distance_cohorts_vehicle = bd_trip_distance_cohorts_vehicle.groupby( + ['trip_distance_cohort', 'age_cohort']).size().reset_index(name='counts') +# plot a pie chart for each age cohort +for age_cohort in bd_trip_distance_cohorts_vehicle['age_cohort'].unique(): + bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort].plot( + kind='pie', y='counts', labels=bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort]['trip_distance_cohort'], autopct='%1.1f%%', startangle=90) + plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + + str(len(bd)) + ' for age cohort ' + age_cohort) + plt.savefig(os.path.join( + figs_path, 'trip_distance_cohorts_' + age_cohort + '.png'), dpi=300) + +# now the same for trip duration vs vehicle type +bd_trip_duration_cohorts_vehicle = pd.cut( + bd['travelTime'], + bins=[-1, 500, 1000, 5000, 10000, 423789798324], + labels=['0-500', '500-1000', '1000-5000', '5000-10000', '10000+']).reset_index( + name='trip_duration_cohort') +bd_vehicle_type = bd['vehicleChoice'].reset_index(name='vehicleChoice') +# attach the age cohort to the dataframe +bd_trip_duration_cohorts_vehicle = pd.concat( + [bd_trip_duration_cohorts_vehicle['trip_duration_cohort'], bd_vehicle_type['vehicleChoice']], axis=1) +# group by age cohort and distance cohort +bd_trip_duration_cohorts_vehicle = bd_trip_duration_cohorts_vehicle.groupby( + ['trip_duration_cohort', 'vehicleChoice']).size().reset_index(name='counts') +# plot a pie chart for each age cohort +for vehicle_type in bd_trip_duration_cohorts_vehicle['vehicleChoice'].unique(): + bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type].plot( + kind='pie', y='counts', labels=bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type]['trip_duration_cohort'], autopct='%1.1f%%', startangle=90) + plt.title('Trip duration distribution in Braunschweig in trip duration cohorts, in minutes. Number of trips: ' + str(len(bd) + ) + ' for vehicle type ' + str(dict_vehicle[vehicle_type])) + plt.savefig(os.path.join(figs_path, 'trip_duration_cohorts_' + + str(dict_vehicle[vehicle_type]) + '.png'), dpi=300) + + +# also do a scatter plot of trip duration and trip distance with a regression line +bd_age_distance.plot(kind='scatter', x='age', y='tripDistance') +plt.plot(np.unique(bd_age_distance['age']), np.poly1d(np.polyfit(bd_age_distance['age'], + bd_age_distance['tripDistance'], 1))(np.unique(bd_age_distance['age']))) +bd_age_duration.plot(kind='scatter', x='age', y='travelTime') +plt.plot(np.unique(bd_age_duration['age']), np.poly1d(np.polyfit( + bd_age_duration['age'], bd_age_duration['travelTime'], 1))(np.unique(bd_age_duration['age']))) +plt.show() + +### draft to compute number of locations of type 6? +x = bd[bd.ActivityAfter==6].loc[:, 'loc_id_end'].nunique() +# downscaling of locations of type 6 to 2000 agents +x / (bd['personID'].nunique()/2000) + + + + +x = 42 From 472fb8ca02f0de7482f4956c6a365f242b725807 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:27:35 +0100 Subject: [PATCH 017/488] add analysis script Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- pycode/memilio-epidata/memilio/epidata/check_bs_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py index 2324bae8e1..8e69f431ac 100644 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -14,7 +14,7 @@ ####### minimal sanity check on data ####### -bd = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/pycode/memilio-epidata/memilio/epidata/bs_und_umgebung.csv', header=None, skiprows=1) +bd = pd.read_csv(r'', header=None, skiprows=1) # setup dictionary for the leisure activities, and vehicle choice and column names # bd.rename( From 82f8ec00ce5ea40f85d0b5fdbd971cb6a29f0ddb Mon Sep 17 00:00:00 2001 From: reneSchm <49305466+reneSchm@users.noreply.github.com> Date: Fri, 2 Feb 2024 11:06:21 +0100 Subject: [PATCH 018/488] add plot script --- .../memilio/epidata/mpm_plotter.py | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 pycode/memilio-epidata/memilio/epidata/mpm_plotter.py diff --git a/pycode/memilio-epidata/memilio/epidata/mpm_plotter.py b/pycode/memilio-epidata/memilio/epidata/mpm_plotter.py new file mode 100644 index 0000000000..b2e8a234e9 --- /dev/null +++ b/pycode/memilio-epidata/memilio/epidata/mpm_plotter.py @@ -0,0 +1,62 @@ +import numpy as np +import matplotlib.pyplot as plt + +# reads a table written by print_table from the given file +def read_from_terminal(filename): + with open(filename) as file: + lines = file.readlines() + skip_to = 0 + labels = "" + # find first line of the output table + for i in range(len(lines)): + if "Time" in lines[i]: + skip_to = i + 1 + # read labels + labels = lines[i].split()[1:] + break + # throw error if table was not found + if labels == "": + raise EOFError("Could not find results table in " + filename) + result = [] + for i in range(skip_to, len(lines)): + result+=[[]] + for txt in lines[i].split(): + try: + result[-1] += [float(txt)] + except ValueError: + # remove entries from failed line (should be empty) + result = result[:-1] + return np.array(result), labels + if len(result[-1]) != len(labels) + 1: + # remove entries from failed line + result = result[:-1] + return np.array(result), labels + return np.array(result), labels + +def plot_populations(time, metapopulations, labels, name): + fig_ctr = 1 + lbl_ctr = 0 + for x in metapopulations: + ys = [np.zeros_like(time)] + for y in reversed([x[:, i] for i in range(len(x[0]))]): + ys = [y + ys[0]] + ys + + plt.figure() + + for i in range(len(ys) - 1): + plt.fill_between(time, ys[i], ys[i+1], label=labels[lbl_ctr]) + plt.plot(time, ys[i], c='black') + lbl_ctr += 1 + plt.plot(time, ys[-1], c='black') + + plt.legend() + plt.savefig(name+str(fig_ctr - 1)+".png") + fig_ctr += 1 + +if __name__ == "__main__": + table, labels = read_from_terminal("abm_minimal.txt") + time = table[:,0] + # subtables = [table[:, 1:4],table[:, 4:7]] + subtables = [table[:, 1:]] + # subtables = [table[:, 1 + i * 6: 2+i*6] for i in range(8)] + plot_populations(time, subtables, labels, "mpm") From e9069a4896fcbe1458c3bd859c57e1aec518ae9e Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 2 Feb 2024 17:41:46 +0100 Subject: [PATCH 019/488] Adjust contact rates correctly and fix dividing by 0 in exposure rate. --- cpp/models/abm/location.cpp | 49 +++++++++++++++------ cpp/models/abm/location.h | 6 +++ cpp/models/abm/world.cpp | 1 + cpp/tests/test_abm_infection.cpp | 73 ++++++++++++++++++++------------ cpp/tests/test_abm_location.cpp | 14 +++--- 5 files changed, 99 insertions(+), 44 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 3067fb14cb..a24cd2a724 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -59,13 +59,14 @@ ScalarType Location::transmission_contacts_per_day(uint32_t cell_index, VirusVar size_t num_agegroups) const { assert(age_receiver.get() < num_agegroups); - ScalarType transmissions = 0; + + ScalarType transmissions_per_day = 0; for (uint32_t age_transmitter = 0; age_transmitter != num_agegroups; ++age_transmitter) { - transmissions += + transmissions_per_day += m_cells[cell_index].m_cached_exposure_rate_contacts[{virus, static_cast(age_transmitter)}] * m_parameters.get()[{age_receiver, static_cast(age_transmitter)}]; } - return transmissions; + return transmissions_per_day; } ScalarType Location::transmission_air_per_day(uint32_t cell_index, VirusVariant virus, @@ -84,21 +85,19 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time assert(person.get_cells().size() && "Person is in multiple cells. Interact logic is incorrect at the moment."); for (auto cell_index : person.get_cells()) { // TODO: the logic here is incorrect in case a person is in multiple cells - std::pair local_indiv_trans_prob[static_cast(VirusVariant::Count)]; + std::pair local_indiv_expected_trans[static_cast(VirusVariant::Count)]; for (uint32_t v = 0; v != static_cast(VirusVariant::Count); ++v) { VirusVariant virus = static_cast(v); - ScalarType local_indiv_trans_prob_v = - (std::min( - m_parameters.get(), - transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups())) + + ScalarType local_indiv_expected_trans_v = + (transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups()) + transmission_air_per_day(cell_index, virus, global_params)) * - (1 - mask_protection) * dt.days() * (1 - person.get_protection_factor(t, virus, global_params)); + (1 - mask_protection) * (1 - person.get_protection_factor(t, virus, global_params)); - local_indiv_trans_prob[v] = std::make_pair(virus, local_indiv_trans_prob_v); + local_indiv_expected_trans[v] = std::make_pair(virus, local_indiv_expected_trans_v); } VirusVariant virus = random_transition(rng, VirusVariant::Count, dt, - local_indiv_trans_prob); // use VirusVariant::Count for no virus submission + local_indiv_expected_trans); // use VirusVariant::Count for no virus submission if (virus != VirusVariant::Count) { person.add_new_infection(Infection(rng, virus, age_receiver, global_params, t + dt / 2, mio::abm::InfectionState::Exposed, person.get_latest_protection(), @@ -107,6 +106,28 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time } } +void Location::adjust_contact_rates(size_t num_agegroups) +{ + ScalarType total_contacts = 0.; + for (auto contact_from = AgeGroup(0); contact_from < AgeGroup(num_agegroups); contact_from++) { + // slizing would be preferred but is problematic since both Tags of ContactRates are AgeGroup + for (auto contact_to = AgeGroup(0); contact_to < AgeGroup(num_agegroups); contact_to++) { + total_contacts += m_parameters.get()[{contact_from, contact_to}]; + } + if (total_contacts > m_parameters.get()) { + for (auto contact_to = AgeGroup(0); contact_to < AgeGroup(num_agegroups); contact_to++) { + m_parameters.get()[{contact_from, contact_to}] = + m_parameters.get()[{contact_from, contact_to}] * m_parameters.get() / + total_contacts; + } + } + total_contacts = 0; + //auto contact_rates_slice = m_parameters.get().slice(AgeGroup(contact_from)); + //auto total_contacts = std::accumulate(contact_rates_slice.begin(), contact_rates_slice.end(), 0.); + //contact_rates_slice = std::min(1., m_parameters.get() / total_contacts) * contact_rates_slice; + } +} + void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegroups) { //cache for next step so it stays constant during the step while subpopulations change @@ -127,12 +148,16 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou } } + // normalize contact exposure rate by number of people in age groups for (auto age_group = AgeGroup(0); age_group < AgeGroup(num_agegroups); age_group++) { for (auto& v : cell.m_cached_exposure_rate_contacts.slice(AgeGroup(age_group))) { - v = v / + auto number_persons_in_age_group = std::count_if(cell.m_persons.begin(), cell.m_persons.end(), [age_group](observer_ptr p) { return p->get_age() == age_group; }); + if (number_persons_in_age_group > 0) { + v = v / number_persons_in_age_group; + } } } diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index 1c8f2d027c..04bf941f73 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -213,6 +213,12 @@ class Location */ void remove_person(Person& person); + /** + * @brief Adjust local contact rates based on maximum contacts. + * @param[in] num_agegroups The number of age groups in the model. + */ + void adjust_contact_rates(size_t num_agegroups); + /** * @brief Prepare the Location for the next Simulation step. * @param[in] t Current TimePoint of the Simulation. diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index e534b8cec0..859b93320e 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -152,6 +152,7 @@ void World::begin_step(TimePoint t, TimeSpan dt) PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; + location->adjust_contact_rates(parameters.get_num_groups()); location->cache_exposure_rates(t, dt, parameters.get_num_groups()); } } diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index ab62404fa6..2f1b78aabb 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -131,6 +131,9 @@ TEST(TestInfection, drawInfectionCourseBackward) auto dt = mio::abm::days(1); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); + auto virus_variant_test = mio::abm::VirusVariant::Wildtype; + auto age_group_test = age_group_60_to_79; + ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(32)) @@ -138,51 +141,69 @@ TEST(TestInfection, drawInfectionCourseBackward) .WillOnce(testing::Return(1.0)) // Transition to InfectedNoSymptoms .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToRecovered .WillOnce(testing::Return(1.0)) // IncubationPeriod - .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_peak.params.a())) // Viral load draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_incline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_decline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_alpha.params.a())) // Infectivity draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor // 2nd infection .WillOnce(testing::Return(0.4)) // Transition to InfectedSymptoms .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToRecovered .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms .WillOnce(testing::Return(1.0)) // IncubationPeriod - .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_peak.params.a())) // Viral load draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_incline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_decline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_alpha.params.a())) // Infectivity draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor // 3rd infection .WillOnce(testing::Return(0.2)) // Transition to InfectedSevere .WillOnce(testing::Return(1.0)) // TimeInfectedSevereToRecovered .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToSevere .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms .WillOnce(testing::Return(1.0)) // IncubationPeriod - .WillOnce(testing::Return(0.1)) // ViralLoad, Infectivity and VirusShedFactor draws - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) - .WillOnce(testing::Return(0.1)) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_peak.params.a())) // Viral load draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_incline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .viral_load_decline.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_alpha.params.a())) // Infectivity draws + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .infectivity_beta.params.a())) + .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] + .params.a())) // Virus Shed Factor // 4th infection .WillOnce(testing::Return(0.0)) // Transition to InfectedCritical .WillOnce(testing::Return(1.0)) //TimeInfectedCriticalToRecovered .WillRepeatedly(testing::Return(1.0)); - auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection1 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); - auto infection2 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection2 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); - auto infection3 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection3 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); - auto infection4 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_60_to_79, params, - mio::abm::TimePoint(t + dt), mio::abm::InfectionState::Recovered, + auto infection4 = mio::abm::Infection(rng, virus_variant_test, age_group_test, params, mio::abm::TimePoint(t + dt), + mio::abm::InfectionState::Recovered, {mio::abm::ExposureType::NoProtection, mio::abm::TimePoint(0)}, false); EXPECT_EQ(infection1.get_infection_state(t), mio::abm::InfectionState::InfectedNoSymptoms); diff --git a/cpp/tests/test_abm_location.cpp b/cpp/tests/test_abm_location.cpp index 85943b9302..d9166250f9 100644 --- a/cpp/tests/test_abm_location.cpp +++ b/cpp/tests/test_abm_location.cpp @@ -111,6 +111,7 @@ TEST(TestLocation, CacheExposureRate) auto dt = mio::abm::seconds(10000); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); + params.get()[{variant, age}] = 0.1; // setup a location with some chance of exposure mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups, 1); @@ -129,11 +130,12 @@ TEST(TestLocation, CacheExposureRate) //cache precomputed results location.cache_exposure_rates(t, dt, num_age_groups); - EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_contacts[{variant, age}]), 0.015015859523894731, 1e-14); - EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.015015859523894731, 1e-14); - EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_contacts[{variant, age}]), 0.0075079297619473654, + EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_contacts[{variant, age}]), 0.0015015859523894731, 1e-14); - EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.0075079297619473654, 1e-14); + EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.0015015859523894731, 1e-14); + EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_contacts[{variant, age}]), 0.00075079297619473654, + 1e-14); + EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.00075079297619473654, 1e-14); EXPECT_NEAR((location.get_cells()[2].m_cached_exposure_rate_contacts[{variant, age}]), 0, 1e-14); EXPECT_NEAR((location.get_cells()[2].m_cached_exposure_rate_air[{variant}]), 0, 1e-14); @@ -144,8 +146,8 @@ TEST(TestLocation, CacheExposureRate) location.set_capacity(2, 22, 2); // Capacity for Cell 3 location.cache_exposure_rates(t, dt, num_age_groups); - EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.045047578571684191, 1e-14); - EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.022523789285842095, 1e-14); + EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.0045047578571684191, 1e-14); + EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.0022523789285842095, 1e-14); EXPECT_NEAR((location.get_cells()[2].m_cached_exposure_rate_air[{variant}]), 0, 1e-14); } From 7b03148b020f896cae7646a43207e523fc210c18 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Wed, 7 Feb 2024 10:35:22 +0100 Subject: [PATCH 020/488] Add functions to print out number of infections per LocationType and AgeGroup --- cpp/models/abm/common_abm_loggers.h | 52 ++++++++++++++++++++++++++++ cpp/models/abm/simulation.cpp | 2 ++ cpp/models/abm/simulation.h | 9 +++++ cpp/simulations/abm_braunschweig.cpp | 30 ++++++++++++++-- 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index c5029be6ea..99f5acb94d 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -182,6 +182,58 @@ struct LogInfectionState : mio::LogAlways { } }; +/** +* @brief Logger to log the TimeSeries of the number of Person%s got new infection per LocationType. +*/ +struct LogInfectionPerLocationType : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the number of Person%s got new infection per LocationType. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the number of Person%s got new infection per LocationType. + */ + static Type log(const mio::abm::Simulation& sim) + { + Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::LocationType::Count)); + auto prev_time = sim.get_prev_time(); + auto curr_time = sim.get_time(); + PRAGMA_OMP(for) + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + sum[(int)(person.get_location().get_type())] += 1; + } + } + return std::make_pair(curr_time, sum); + } +}; + +/** +* @brief Logger to log the TimeSeries of the number of Person%s got new infection per AgeGroup. +*/ +struct LogInfectionPerAgeGroup : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the number of Person%s got new infection per AgeGroup. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the number of Person%s got new infection per AgeGroup. + */ + static Type log(const mio::abm::Simulation& sim) + { + Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); + auto prev_time = sim.get_prev_time(); + auto curr_time = sim.get_time(); + PRAGMA_OMP(for) + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + sum[(size_t)(person.get_age())] += 1; + } + } + return std::make_pair(curr_time, sum); + } +}; + /** * @brief This is like the DataWriterToMemory, but it only logs time series data. * @tparam Loggers The loggers that are used to log data. The loggers must return a touple with a TimePoint and a value. diff --git a/cpp/models/abm/simulation.cpp b/cpp/models/abm/simulation.cpp index 54e9024ce7..d10ae971e1 100644 --- a/cpp/models/abm/simulation.cpp +++ b/cpp/models/abm/simulation.cpp @@ -30,6 +30,7 @@ namespace abm Simulation::Simulation(TimePoint t, World&& world) : m_world(std::move(world)) , m_t(t) + , m_prev_t(t) , m_dt(hours(1)) { } @@ -38,6 +39,7 @@ void Simulation::evolve_world(TimePoint tmax) { auto dt = std::min(m_dt, tmax - m_t); m_world.evolve(m_t, dt); + m_prev_t = m_t; m_t += m_dt; } diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index 7247a69819..2e25e1d39d 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -81,6 +81,14 @@ class Simulation return m_t; } + /** + * @brief Get the previous time of the Simulation. + */ + TimePoint get_prev_time() const + { + return m_prev_t; + } + /** * @brief Get the World that this Simulation evolves. */ @@ -99,6 +107,7 @@ class Simulation World m_world; ///< The World to simulate. TimePoint m_t; ///< The current TimePoint of the Simulation. + TimePoint m_prev_t; ///< The previous TimePoint of the Simulation. TimeSpan m_dt; ///< The length of the time steps. }; diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index 5a6b7b94ef..e52ce90f7c 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -939,7 +939,6 @@ void write_log_to_file_person_and_location_data(const T& history) template void write_log_to_file_trip_data(const T& history) { - auto movement_data = std::get<0>(history.get_log()); std::ofstream myfile3("movement_data.txt"); myfile3 << "agent_id, trip_id, start_location, end_location, start_time, end_time, transport_mode, activity, " @@ -984,10 +983,28 @@ void write_log_to_file_trip_data(const T& history) myfile3.close(); } +template +void write_log_to_file_infection_per_location_type(const T& history) +{ + std::ofstream myfile4("infection_per_location_type.txt"); + const std::vector& labels = { + "Home", "Work", "School", "SocialEvent", "BasicsShop", + "Hospital", "ICU", "Car", "PublicTransport", "TransportWithoutContact", + "Cemetery"}; + std::get<0>(history.get_log()).print_table(labels, 12, 4, myfile4); +} + +template +void write_log_to_file_infection_per_age_group(const T& history) +{ + std::ofstream myfile5("infection_per_age_group.txt"); + const std::vector& labels = {"0_to_4", "5_to_14", "15_to_34", "35_to_59", "60_to_79", "80_plus"}; + std::get<0>(history.get_log()).print_table(labels, 7, 4, myfile5); +} + mio::IOResult run(const std::string& input_file, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { - auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(2); // End time per simulation auto ensemble_results = std::vector>>{}; // Vector of collected results @@ -1007,6 +1024,10 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di historyPersonInf; mio::History historyTimeSeries{ Eigen::Index(mio::abm::InfectionState::Count)}; + mio::History historyInfectionPerLocationType{ + Eigen::Index(mio::abm::LocationType::Count)}; + mio::History historyInfectionPerAgeGroup{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; mio::History historyPersonInfDelta; // Collect the id of location in world. std::vector loc_ids; @@ -1014,7 +1035,8 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di loc_ids.push_back(location.get_index()); } // Advance the world to tmax - sim.advance(tmax, historyPersonInf, historyTimeSeries, historyPersonInfDelta); + sim.advance(tmax, historyPersonInf, historyTimeSeries, historyInfectionPerLocationType, + historyInfectionPerAgeGroup, historyPersonInfDelta); // TODO: update result of the simulation to be a vector of location result. auto temp_sim_result = std::vector>{std::get<0>(historyTimeSeries.get_log())}; // Push result of the simulation back to the result vector @@ -1026,6 +1048,8 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di } write_log_to_file_person_and_location_data(historyPersonInf); write_log_to_file_trip_data(historyPersonInfDelta); + write_log_to_file_infection_per_location_type(historyInfectionPerLocationType); + write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup); ++run_idx; } From 8a58d6bc74c170e05492166bf68e108b80d486da Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 8 Feb 2024 17:18:03 +0100 Subject: [PATCH 021/488] Add functions to pycode display the infections per location and per age group graphs --- cpp/models/abm/common_abm_loggers.h | 4 +- cpp/simulations/abm_braunschweig.cpp | 2 +- .../memilio/epidata/analyze_bs_run.py | 74 +++++++++++-------- 3 files changed, 45 insertions(+), 35 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index 99f5acb94d..085a0511a8 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -1,7 +1,7 @@ /* -* Copyright (C) 2020-2023 German Aerospace Center (DLR-SC) +* Copyright (C) 2020-2024 MEmilio * -* Authors: Sascha Korf +* Authors: Sascha Korf, Khoa Nguyen * * Contact: Martin J. Kuehn * diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index e52ce90f7c..b3de78901d 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2020-2024 MEmilio * -* Authors: Sascha Korf, Carlotta Gerstein +* Authors: Sascha Korf, Carlotta Gerstein, Khoa Nguyen * * Contact: Martin J. Kuehn * diff --git a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py index b5db426359..fb2b91b8cb 100644 --- a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py +++ b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py @@ -20,15 +20,14 @@ def main(n_runs): # read in folder and convert txt files to numpy arrays - - #folder path - folder_path = "memilio/epidata/folder_run_bs" + # folder path + folder_path = "memilio/epidata/folder_run_bs" # get first_file in folder first_file = os.listdir(folder_path)[0] file_path = os.path.join(folder_path, first_file) # read in txt file - df = pd.read_csv(file_path, delim_whitespace=True ) + df = pd.read_csv(file_path, delim_whitespace=True) # convert to numpy array df_np = df.to_numpy() # get the number of rows and columns @@ -41,54 +40,65 @@ def main(n_runs): # get the compartment names compartment_names = df.columns[1:] # get the time steps - time_steps = df_np[:,0] + time_steps = df_np[:, 0] - #get number of files in folder + # get number of files in folder num_files = len([entry for entry in os.listdir(folder_path)]) - # read in each txt file and convert to numpy array df_np_3d = np.empty((num_rows, num_cols, n_runs)) for (file, i) in zip(os.listdir(folder_path), range(n_runs)): - if file.endswith(".txt"): - file_path = os.path.join(folder_path, file) - # read in txt file - df = pd.read_csv(file_path, delim_whitespace=True) + file_path = os.path.join(folder_path, file) + # read in txt file + df = pd.read_csv(file_path, delim_whitespace=True) + if file.startswith("infection_per_location_type"): + plot_infection_per_location_type(df) + if file.startswith("infection_per_age_group"): + plot_infection_per_age_group(df) + if file.startswith("abm_result"): # convert to numpy array df_np = df.to_numpy() - #attach to array - df_np_3d[:,:,i] = df_np - - plot_mean_and_std(df_np_3d) + # attach to array + df_np_3d[:, :, i] = df_np + plot_mean_and_std(df_np_3d) - + +def plot_infection_per_location_type(df): + df.plot(x='Time', y=['Home', 'Work', 'School', 'SocialEvent', 'BasicsShop', 'Hospital', + 'ICU', 'Car', 'PublicTransport', 'TransportWithoutContact', 'Cemetery'], figsize=(10, 6)) + plt.show() + + +def plot_infection_per_age_group(df): + df.plot(x='Time', y=['0_to_4', '5_to_14', '15_to_34', + '35_to_59', '60_to_79', '80_plus'], figsize=(10, 6)) + plt.show() def plot_mean_and_std(Y): - - x_plot = Y[:,0,0] - compartments = Y[:,1:,1:] + x_plot = Y[:, 0, 0] + compartments = Y[:, 1:, 1:] # average value - compartments_avg = np.mean(compartments,axis=2) - #plot average + compartments_avg = np.mean(compartments, axis=2) + # plot average for i in range(compartments_avg.shape[1]): - plt.plot(x_plot,compartments_avg[:,i]) - - #plt.plot(x_plot,compartments_avg) - #legend + plt.plot(x_plot, compartments_avg[:, i]) + # plt.plot(x_plot,compartments_avg) + # legend plt.legend(['S', 'E', 'I_NS', 'I_Sy', 'I_Sev', 'I_Crit', 'R', 'D']) plt.show() # standard deviation - #compartments_std = np.std(compartments,axis=2) - #plt.plot(x_plot,compartments_avg + compartments_std) - #plt.plot(x_plot,compartments_avg - compartments_std) - #plt.show() + # compartments_std = np.std(compartments,axis=2) + # plt.plot(x_plot,compartments_avg + compartments_std) + # plt.plot(x_plot,compartments_avg - compartments_std) + # plt.show() if __name__ == "__main__": if (len(sys.argv) > 1): n_runs = sys.argv[1] else: - folder_path = "memilio/epidata/folder_run_bs" - n_runs = len([entry for entry in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, entry))]) - main(n_runs) \ No newline at end of file + folder_path = "memilio/epidata/folder_run_bs" + n_runs = len([entry for entry in os.listdir(folder_path) + if os.path.isfile(os.path.join(folder_path, entry))]) + main(n_runs) From b4bf56d13f75f669f35ff8199b956e165143b590 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Tue, 13 Feb 2024 09:36:33 +0100 Subject: [PATCH 022/488] Add to check_bs_data.py a draft to add collumn to check if the location in Braunschweig --- .../memilio/epidata/check_bs_data.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py index 8e69f431ac..d50b7417ee 100644 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -503,7 +503,20 @@ # downscaling of locations of type 6 to 2000 agents x / (bd['personID'].nunique()/2000) - - - x = 42 + +### draft to add collumn to check if the location in Braunschweig +# pip install geopy +# from geopy.geocoders import Nominatim +# geolocator = Nominatim(user_agent="MEmilio") +# longitude = bd['loCe'] +# latitude = bd['laCe'] +# coordination = str(longitude) + "," + str(latitude) +# location = geolocator.reverse(coordination) +# loc_dict = location.raw +# print(loc_dict['address']['city']) +# if loc_dict['address']['city'] == 'Braunschweig' : +# bd['in_bs'] = 1 +# else: +# bd['in_bs'] = 0 +# bd.to_csv('modified_input.csv', index=False) From 397e56f8569e0b9adc5fad6758317b3a0ab03307 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 13 Feb 2024 13:07:00 +0100 Subject: [PATCH 023/488] some bug fixes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- .../memilio/epidata/analyze_bs_run.py | 14 ++++---- .../memilio/epidata/check_bs_data.py | 32 ++++++++++--------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py index fb2b91b8cb..51f1d38fd7 100644 --- a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py +++ b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py @@ -17,6 +17,7 @@ import matplotlib.cm as cmx import matplotlib.patches as mpatches import matplotlib.lines as mlines +from mpm_plotter import read_from_terminal, plot_populations def main(n_runs): # read in folder and convert txt files to numpy arrays @@ -77,14 +78,15 @@ def plot_infection_per_age_group(df): def plot_mean_and_std(Y): x_plot = Y[:, 0, 0] - compartments = Y[:, 1:, 1:] + compartments = Y[:,1:,1:] # average value - compartments_avg = np.mean(compartments, axis=2) - # plot average + compartments_avg = np.mean(compartments,axis=2) + #plot average for i in range(compartments_avg.shape[1]): - plt.plot(x_plot, compartments_avg[:, i]) - # plt.plot(x_plot,compartments_avg) - # legend + plt.plot(x_plot,compartments_avg[:,i]) + + #plt.plot(x_plot,compartments_avg) + #legend plt.legend(['S', 'E', 'I_NS', 'I_Sy', 'I_Sev', 'I_Crit', 'R', 'D']) plt.show() # standard deviation diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py index d50b7417ee..7d04852f6d 100644 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -54,9 +54,10 @@ # check if the proportion of single-person-households is too high households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -if households.drop(households.loc[households['counts']>1].index).size / bd[['personID']].drop_duplicates().size >= 0.4: +# check if the proportion of single-person-households is too high +if (households.loc[households['counts']==1]['counts'].size)/(households['counts'].size) > 0.5: print("Error: The proportion of single-person-households is too high: " + - str(households.drop(households.loc[households['counts']>1].index).size / bd[['personID']].drop_duplicates().size)) + str((households.loc[households['counts']==1]['counts'].size)/(households['counts'].size))) # check if there are invalid entries # if not bd['idTrafficZone'].ge(30000000).all(): @@ -106,20 +107,21 @@ # number_of_trips = bd[['tripID']].drop_duplicates().size # print(str(number_of_trips) + ' trips. \n') + students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') -print(str(students.loc[students['age'] > 20].size) + ' persons of ' + str(students.size) + ' people going to school are in a higher age group than 10. \n') +print(str(students.loc[students['age'] > 20].size) + ' trips of ' + str(students.size) + ' trips going to school are in a higher age group than 10. \n') -children = bd[['personID','ActivityAfter']].loc[(bd['age']<=17) & (bd['age']>=7)] +children = bd[['personID','ActivityAfter']].loc[(bd['age']<=16) & (bd['age']>=7)] number_of_children = children['personID'].drop_duplicates().size number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') -workers = bd[['personID','ActivityAfter']].loc[(bd['age']>0)] +workers = bd[['personID','ActivityAfter']].loc[(bd['age']>30)] number_of_workers = workers['personID'].drop_duplicates().size number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size -print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' children do not go to school. \n') +print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' workers do not go to work. \n') @@ -153,18 +155,18 @@ os.path.abspath(__file__)), 'figs_bs_data') # check whether first start location is the last end location -first_trip = bd[['personID','loc_id_start']].sort_values(by=['personID']).drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) -last_trip = bd[['personID', 'loc_id_end', 'ActivityAfter']].sort_values(by=['personID']).drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) -compare_first_and_last_trip = first_trip['loc_id_start'].compare(last_trip['loc_id_end']) -print("Number of persons where first start location is not the last end location: " + str(compare_first_and_last_trip.size)+ ".") +first_trip = bd[['personID','loc_id_start']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) +last_trip = bd[['personID', 'loc_id_end']].drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) +print("Number of persons where first start location is home: " + str(first_trip.loc[first_trip['loc_id_start']==-1]['loc_id_start'].size)+ ".") +print("Number of persons where last end location is home: " + str(last_trip.loc[last_trip['loc_id_end']==-1]['loc_id_end'].size)+ ".") # check what persons are doing which only do one trip -location_types = last_trip.groupby(['ActivityAfter']).size() +# location_types = last_trip.groupby(['ActivityAfter']).size() -location_types.plot(kind='bar') -plt.xlabel('Activity') -plt.ylabel('Number of persons') -plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) +# location_types.plot(kind='bar') +# plt.xlabel('Activity') +# plt.ylabel('Number of persons') +# plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) # probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located # bd_tz_bs = bd.groupby(['idTrafficZone']).size().reset_index( From d5494c770381051ec328e617ea4ca8ab04ebc516 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 14 Feb 2024 00:31:36 +0100 Subject: [PATCH 024/488] some enhancements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/memilio/utils/random_number_generator.h | 18 +- cpp/models/abm/analyze_result.h | 36 +- cpp/models/abm/infection.cpp | 79 ++- cpp/models/abm/parameters.h | 32 +- cpp/simulations/paper_abm_bs_testing.cpp | 593 +++--------------- cpp/tests/test_abm_world.cpp | 40 +- cpp/tests/test_analyze_result.cpp | 16 +- .../memilio/epidata/analyze_bs_run.py | 2 +- 8 files changed, 211 insertions(+), 605 deletions(-) diff --git a/cpp/memilio/utils/random_number_generator.h b/cpp/memilio/utils/random_number_generator.h index c5883e7465..74e28ed53d 100644 --- a/cpp/memilio/utils/random_number_generator.h +++ b/cpp/memilio/utils/random_number_generator.h @@ -182,7 +182,9 @@ static_assert(sizeof(Key) == sizeof(uint32_t), "Empty Base Optimizatio * @tparam an unsigned integer type that determines the size of the counter, i.e., the length of the random sequence. */ template -struct MEMILIO_ENABLE_EBO Counter : TypeSafe>, OperatorComparison>, OperatorAdditionSubtraction> { +struct MEMILIO_ENABLE_EBO Counter : TypeSafe>, + OperatorComparison>, + OperatorAdditionSubtraction> { static_assert(std::is_unsigned::value, "Underlying Integer type must be unsigned."); using TypeSafe>::TypeSafe; }; @@ -243,12 +245,13 @@ Counter rng_totalsequence_counter(UIntN subsequence_idx, CounterS counter static_assert(N_BITS <= C_BITS, "Subsequence index must not be bigger than total sequence counter."); static_assert(N_BITS <= sizeof(UIntN) * BITS_PER_BYTE, "Subsequence index must be at least N bits"); - assert(UIntC(subsequence_idx) <= (UIntC(1) << N_BITS) && "Subsequence index is too large."); //(1 << N) is the same as (2^N) + assert(UIntC(subsequence_idx) <= (UIntC(1) << N_BITS) && + "Subsequence index is too large."); //(1 << N) is the same as (2^N) //N high bits: subsequence idx //S low bits: subsequence counter //=> C = N + S bits: total sequence counter - //example: + //example: //subsequence index uint32_t(181) = 0x000000B5 //subsequence counter uint32_t(41309) = 0x0000A15D //total sequence counter = 0x000000B50000A15D @@ -271,7 +274,7 @@ Counter rng_totalsequence_counter(UIntN subsequence_idx, CounterS counter template Counter rng_subsequence_counter(CounterC counter) { - using UIntC = typename CounterC::ValueType; + using UIntC = typename CounterC::ValueType; static const UIntC C_BYTES = sizeof(UIntC); static const UIntC S_BYTES = sizeof(UIntS); @@ -673,6 +676,13 @@ using UniformDistribution = DistributionAdapter using PoissonDistribution = DistributionAdapter>; +/** + * adapted lognormal_distribution. + * @see DistributionAdapter + */ +template +using LogNormalDistribution = DistributionAdapter>; + } // namespace mio #endif diff --git a/cpp/models/abm/analyze_result.h b/cpp/models/abm/analyze_result.h index 8b359c3031..745f52379e 100644 --- a/cpp/models/abm/analyze_result.h +++ b/cpp/models/abm/analyze_result.h @@ -66,108 +66,108 @@ std::vector ensemble_params_percentile(const std::vector auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}].params.a(); + model.parameters.template get()[{virus_variant, age_group}].params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}].params.b(); + model.parameters.template get()[{virus_variant, age_group}].params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.a(); + .params.m(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = model.parameters.template get()[{virus_variant, age_group}] - .params.b(); + .params.s(); return result; }); diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 5ba22dd079..9004f61d67 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -38,8 +38,7 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age auto vl_params = params.get()[{virus, age}]; ScalarType high_viral_load_factor = 1; if (latest_exposure.first != ExposureType::NoProtection) { - high_viral_load_factor -= - params.get()(init_date.days() - latest_exposure.second.days()); + high_viral_load_factor -= 0; } m_viral_load.peak = vl_params.viral_load_peak.get_distribution_instance()(rng, vl_params.viral_load_peak.params) * high_viral_load_factor; @@ -142,21 +141,21 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng switch (next_state) { case InfectionState::Exposed: { // roll out how long until infected without symptoms - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - next_state = InfectionState::InfectedNoSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + next_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedNoSymptoms: { // roll out next infection step p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedSymptoms; + next_state = InfectionState::InfectedSymptoms; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -173,12 +172,12 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng } if (p < (1 - severity_protection_factor) * params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedSevere; + next_state = InfectionState::InfectedSevere; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -189,12 +188,12 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedCritical; + next_state = InfectionState::InfectedCritical; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -205,12 +204,12 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::Dead; + next_state = InfectionState::Dead; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } else { - next_state = InfectionState::Recovered; + next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); } @@ -241,27 +240,27 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato switch (previous_state) { case InfectionState::InfectedNoSymptoms: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::Exposed; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::Exposed; } break; case InfectionState::InfectedSymptoms: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedNoSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedSevere: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; } break; case InfectionState::InfectedCritical: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSevere; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; } break; case InfectionState::Recovered: { @@ -273,34 +272,34 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}]; if (p > (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedNoSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedNoSymptoms; } else if (p > params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSymptoms; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSymptoms; } else if (p > params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedSevere; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedSevere; } else { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedCritical; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; } } break; case InfectionState::Dead: { - time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - previous_state = InfectionState::InfectedCritical; + time_in_state = params.get()[{m_virus_variant, age}]; + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + previous_state = InfectionState::InfectedCritical; } break; default: diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 3be6ae6488..d10cdc1cfc 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -40,7 +40,7 @@ namespace abm { // Distribution that can be used for the time spend in InfectionStates -using InfectionStateTimesDistributionsParameters = UniformDistribution::ParamType; +using InfectionStateTimesDistributionsParameters = LogNormalDistribution::ParamType; /** * @brief Time that a Person is infected but not yet infectious in day unit @@ -428,7 +428,7 @@ struct AntigenTest : public GenericTest { using Type = TestParameters; static Type get_default() { - return Type{0.8, 0.88}; + return Type{0.69, 0.99}; } static std::string name() { @@ -443,7 +443,7 @@ struct PCRTest : public GenericTest { using Type = TestParameters; static Type get_default() { - return Type{0.9, 0.99}; + return Type{0.99, 0.99}; } static std::string name() { @@ -642,10 +642,10 @@ using ParametersBase = TimeInfectedSevereToRecovered, TimeInfectedCriticalToDead, TimeInfectedCriticalToRecovered, SymptomsPerInfectedNoSymptoms, SeverePerInfectedSymptoms, CriticalPerInfectedSevere, DeathsPerInfectedCritical, ViralLoadDistributions, InfectivityDistributions, VirusShedFactor, - DetectInfection, MaskProtection, AerosolTransmissionRates, LockdownDate, QuarantineDuration, SocialEventRate, - BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, - GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, - AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor>; + DetectInfection, MaskProtection, AerosolTransmissionRates, LockdownDate, QuarantineDuration, + SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, GotoWorkTimeMaximum, + GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, AgeGroupGotoWork, + InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. @@ -713,7 +713,7 @@ class Parameters : public ParametersBase for (auto i = AgeGroup(0); i < AgeGroup(m_num_groups); ++i) { for (auto&& v : enum_members()) { - if (this->get()[{v, i}].params.a() < 0) { + if (this->get()[{v, i}].params.m() < 0) { log_error("Constraint check: Lower end of parameter range IncubationPeriod of virus variant {} and " "age group {:.0f} smaller " "than {:.4f}", @@ -721,7 +721,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptomsToSymptoms " "of virus variant " "{} and age group {:.0f} smaller " @@ -730,7 +730,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error("Constraint check: Lower end of parameter range TimeInfectedNoSymptomsToRecovered of " "virus variant " "{} and age group {:.0f} smaller " @@ -739,7 +739,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error("Constraint check: Lower end of parameter range TimeInfectedSymptomsToSevere of virus " "variant {} " "and age group {:.0f} smaller " @@ -748,7 +748,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error("Constraint check: Lower end of parameter range TimeInfectedSymptomsToRecovered of virus " "variant {} " "and age group {:.0f} smaller " @@ -757,7 +757,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error("Constraint check: Lower end of parameter range TimeInfectedSevereToCritical of virus " "variant {} " "and age group {:.0f} smaller " @@ -766,7 +766,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error("Constraint check: Lower end of parameter range TimeInfectedSevereToRecovered of virus " "variant {} " "and age group {:.0f} smaller " @@ -775,7 +775,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error( "Constraint check: Lower end of parameter range TimeInfectedCriticalToDead of virus variant {} " "and age group {:.0f} smaller " @@ -784,7 +784,7 @@ class Parameters : public ParametersBase return true; } - if (this->get()[{v, i}].params.a() < 0.0) { + if (this->get()[{v, i}].params.m() < 0.0) { log_error("Constraint check: Lower end of parameter range TimeInfectedCriticalToRecovered of virus " "variant {} " "and age group {:.0f} smaller " diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c76bff46b3..bf2bce39ba 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -41,19 +41,6 @@ const auto age_group_35_to_59 = mio::AgeGroup(3); const auto age_group_60_to_79 = mio::AgeGroup(4); const auto age_group_80_plus = mio::AgeGroup(5); -/** - * Set a value and distribution of an UncertainValue. - * Assigns average of min and max as a value and UNIFORM(min, max) as a distribution. - * @param p uncertain value to set. - * @param min minimum of distribution. - * @param max minimum of distribution. - */ -void assign_uniform_distribution(mio::UncertainValue& p, ScalarType min, ScalarType max) -{ - p = mio::UncertainValue(0.5 * (max + min)); - p.set_distribution(mio::ParameterDistributionUniform(min, max)); -} - /** * Determine the infection state of a person at the beginning of the simulation. * The infection states are chosen randomly. They are distributed according to the probabilites set in the example. @@ -128,6 +115,9 @@ void split_line(std::string string, std::vector* row) else if (s.find(".") != std::string::npos) { return longLatToInt(s); } + else if (s == "null") { + return 10; // This shouldnt be too often, just assume a short time after 12:00 o'clock for now + } else { return std::stoi(s); } @@ -387,489 +377,91 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, world.get_trip_list().use_weekday_trips_on_weekend(); } +std::pair get_my_and_sigma(std::pair mean_and_qstd) +{ + auto mean = mean_and_qstd.first; + auto stddev = mean_and_qstd.second; + double my = log(mean * mean / sqrt(mean * mean + stddev * stddev)); + double sigma = sqrt(log(1 + stddev * stddev / (mean * mean))); + return {my, sigma}; +} + void set_parameters(mio::abm::Parameters params) { - params.set({{mio::abm::VirusVariant::Count, mio::AgeGroup(num_age_groups)}, 4.}); - - // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 - params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); - }; - - //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; - - //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.276; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = - 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.; - - //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = - 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = - 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.139; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.021; - - //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = - 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = - 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.; - - //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = - 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = - 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.123; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.024; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.; - - //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.315; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = - 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.115; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.033; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.; - - // Set each parameter for vaccinated people including personal infection and vaccine protection levels. - // Summary: https://doi.org/10.1038/s41577-021-00550-x, - - //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.0; - // Protection of reinfection is the same for all age-groups, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_0_to_4, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.852}, - {180, 0.852}, - {210, 0.845}, - {240, 0.828}, - {270, 0.797}, - {300, 0.759}, - {330, 0.711}, - {360, 0.661}, - {390, 0.616}, - {420, 0.580}, - {450, 0.559}, - {450, 0.550}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_0_to_4, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.91}, {60, 0.92}, {90, 0.88}, {120, 0.84}, {150, 0.81}, {180, 0.88}, {450, 0.5}}, days); - }; - - // Set up age-related severe protection levels, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_0_to_4, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.967}, - {30, 0.975}, - {60, 0.977}, - {90, 0.974}, - {120, 0.963}, - {150, 0.947}, - {180, 0.93}, - {210, 0.929}, - {240, 0.923}, - {270, 0.908}, - {300, 0.893}, - {330, 0.887}, - {360, 0.887}, - {450, 0.5}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_0_to_4, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {450, 0.5}}, days); - }; - - //5-14 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = - 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.0; - // Protection of reinfection is the same for all age-groups, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_5_to_14, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.852}, - {180, 0.852}, - {210, 0.845}, - {240, 0.828}, - {270, 0.797}, - {300, 0.759}, - {330, 0.711}, - {360, 0.661}, - {390, 0.616}, - {420, 0.580}, - {450, 0.559}, - {450, 0.550}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_5_to_14, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.91}, {60, 0.92}, {90, 0.88}, {120, 0.84}, {150, 0.81}, {180, 0.88}, {450, 0.5}}, days); - }; - // Set up age-related severe protection levels, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_5_to_14, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.967}, - {30, 0.975}, - {60, 0.977}, - {90, 0.974}, - {120, 0.963}, - {150, 0.947}, - {180, 0.93}, - {210, 0.929}, - {240, 0.923}, - {270, 0.908}, - {300, 0.893}, - {330, 0.887}, - {360, 0.887}, - {450, 0.5}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_5_to_14, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {450, 0.5}}, days); - }; - - //15-34 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = - 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = - 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.021; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.0; - // Set up personal infection and vaccine protection levels, based on: https://doi.org/10.1038/s41577-021-00550-x, https://doi.org/10.1038/s41591-021-01377-8 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_15_to_34, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.852}, - {180, 0.852}, - {210, 0.845}, - {240, 0.828}, - {270, 0.797}, - {300, 0.759}, - {330, 0.711}, - {360, 0.661}, - {390, 0.616}, - {420, 0.580}, - {450, 0.559}, - {450, 0.550}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_15_to_34, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.89}, {60, 0.84}, {90, 0.78}, {120, 0.68}, {150, 0.57}, {180, 0.39}, {450, 0.1}}, days); - }; - // Set up age-related severe protection levels, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_15_to_34, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.967}, - {30, 0.975}, - {60, 0.977}, - {90, 0.974}, - {120, 0.963}, - {150, 0.947}, - {180, 0.93}, - {210, 0.929}, - {240, 0.923}, - {270, 0.908}, - {300, 0.893}, - {330, 0.887}, - {360, 0.887}, - {450, 0.5}}, - days); - }; - // Information is from: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_15_to_34, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {180, 0.90}, {450, 0.5}}, days); - }; - - //35-59 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = - 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = - 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.141; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.0; - // Protection of reinfection is the same for all age-groups, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_35_to_59, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.852}, - {180, 0.852}, - {210, 0.845}, - {240, 0.828}, - {270, 0.797}, - {300, 0.759}, - {330, 0.711}, - {360, 0.661}, - {390, 0.616}, - {420, 0.580}, - {450, 0.559}, - {450, 0.550}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_35_to_59, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.89}, {60, 0.84}, {90, 0.78}, {120, 0.68}, {150, 0.57}, {180, 0.39}, {450, 0.1}}, days); - }; - // Set up age-related severe protection levels, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_35_to_59, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.967}, - {30, 0.975}, - {60, 0.977}, - {90, 0.974}, - {120, 0.963}, - {150, 0.947}, - {180, 0.93}, - {210, 0.929}, - {240, 0.923}, - {270, 0.908}, - {300, 0.893}, - {330, 0.887}, - {360, 0.887}, - {450, 0.5}}, - days); - }; - // Information is from: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_35_to_59, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.88}, {60, 0.91}, {90, 0.98}, {120, 0.94}, {150, 0.88}, {180, 0.90}, {450, 0.5}}, days); - }; - - //60-79 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = - 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = - 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.0; - // Protection of reinfection is the same for all age-groups, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.852}, - {180, 0.852}, - {210, 0.845}, - {240, 0.828}, - {270, 0.797}, - {300, 0.759}, - {330, 0.711}, - {360, 0.661}, - {390, 0.616}, - {420, 0.580}, - {450, 0.559}, - {450, 0.550}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_60_to_79, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.87}, {60, 0.85}, {90, 0.78}, {120, 0.67}, {150, 0.61}, {180, 0.50}, {450, 0.1}}, days); - }; - // Set up personal severe protection levels. - // Protection of severe infection of age group 65 + is different from other age group, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.967}, - {30, 0.975}, - {60, 0.977}, - {90, 0.974}, - {120, 0.963}, - {150, 0.947}, - {180, 0.93}, - {210, 0.929}, - {240, 0.923}, - {270, 0.908}, - {300, 0.893}, - {330, 0.887}, - {360, 0.887}, - {360, 0.5}}, - days); - }; - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_60_to_79, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.91}, {60, 0.86}, {90, 0.91}, {120, 0.94}, {150, 0.95}, {180, 0.90}, {450, 0.5}}, days); - }; - - //80+ - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.179; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = - 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.133; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.012; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.0; - // Protection of reinfection is the same for all age-groups, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_80_plus, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.852}, - {180, 0.852}, - {210, 0.845}, - {240, 0.828}, - {270, 0.797}, - {300, 0.759}, - {330, 0.711}, - {360, 0.661}, - {390, 0.616}, - {420, 0.580}, - {450, 0.559}, - {450, 0.550}}, - days); - }; - // Information is from: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_80_plus, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.80}, {60, 0.79}, {90, 0.75}, {120, 0.56}, {150, 0.49}, {180, 0.43}, {450, 0.1}}, days); - }; - // Set up personal severe protection levels. - // Protection of severe infection of age group 65 + is different from other age group, based on: - // https://doi.org/10.1016/S0140-6736(22)02465-5 - params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_0_to_4, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.967}, - {30, 0.975}, - {60, 0.977}, - {90, 0.974}, - {120, 0.963}, - {150, 0.947}, - {180, 0.93}, - {210, 0.929}, - {240, 0.923}, - {270, 0.908}, - {300, 0.893}, - {330, 0.887}, - {360, 0.887}, - {360, 0.5}}, - days); - }; - // Information is based on: https://doi.org/10.1016/S0140-6736(21)02183-8 - params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_80_plus, - mio::abm::VirusVariant::Wildtype}] = - [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.5}, {30, 0.84}, {60, 0.88}, {90, 0.89}, {120, 0.86}, {150, 0.85}, {180, 0.83}, {450, 0.5}}, days); - }; + mio::RandomNumberGenerator rng; + + // Set the Time parameters for the infection same for every age group for now + + auto incubation_period_my_sigma = get_my_and_sigma({4.5, 1.5}); + params.get() = {incubation_period_my_sigma.first, incubation_period_my_sigma.second}; + + auto InfectedNoSymptoms_to_symptoms_my_sigma = get_my_and_sigma({0.5, 0.5}); + params.get() = {InfectedNoSymptoms_to_symptoms_my_sigma.first, + InfectedNoSymptoms_to_symptoms_my_sigma.second}; + + auto TimeInfectedNoSymptomsToRecovered_my_sigma = get_my_and_sigma({10, 5}); + params.get() = {TimeInfectedNoSymptomsToRecovered_my_sigma.first, + TimeInfectedNoSymptomsToRecovered_my_sigma.second}; + + auto TimeInfectedSymptomsToSevere_my_sigma = get_my_and_sigma({7, 2}); + params.get() = {TimeInfectedSymptomsToSevere_my_sigma.first, + TimeInfectedSymptomsToSevere_my_sigma.second}; + + auto TimeInfectedSymptomsToRecovered_my_sigma = get_my_and_sigma({14, 3}); + params.get() = {TimeInfectedSymptomsToRecovered_my_sigma.first, + TimeInfectedSymptomsToRecovered_my_sigma.second}; + + auto TimeInfectedSevereToCritical_my_sigma = get_my_and_sigma({7, 2}); + params.get() = {TimeInfectedSevereToCritical_my_sigma.first, + TimeInfectedSevereToCritical_my_sigma.second}; + + auto TimeInfectedSevereToRecovered_my_sigma = get_my_and_sigma({14, 3}); + params.get() = {TimeInfectedSevereToRecovered_my_sigma.first, + TimeInfectedSevereToRecovered_my_sigma.second}; + + auto TimeInfectedCriticalToDead_my_sigma = get_my_and_sigma({7, 2}); + params.get() = {TimeInfectedCriticalToDead_my_sigma.first, + TimeInfectedCriticalToDead_my_sigma.second}; + + auto TimeInfectedCriticalToRecovered_my_sigma = get_my_and_sigma({14, 3}); + params.get() = {TimeInfectedCriticalToRecovered_my_sigma.first, + TimeInfectedCriticalToRecovered_my_sigma.second}; + + // Set percentage parameters + params.get() = 0.05; + params.get() = 0.1; + + // Set infection parameters + // // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 + // params.get() = [](ScalarType days) -> ScalarType { + // return mio::linear_interpolation_of_data_set( + // {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); + // }; + + // Set protection level from low viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 + // params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, + // mio::abm::VirusVariant::Wildtype}] = + // [](ScalarType days) -> ScalarType { + // return mio::linear_interpolation_of_data_set({{0, 0.967}, + // {30, 0.975}, + // {60, 0.977}, + // {90, 0.974}, + // {120, 0.963}, + // {150, 0.947}, + // {180, 0.93}, + // {210, 0.929}, + // {240, 0.923}, + // {270, 0.908}, + // {300, 0.893}, + // {330, 0.887}, + // {360, 0.887}, + // {360, 0.5}}, + // days); + // }; + + //Set other parameters + params.get() = 0.5; + params.get() = 1.0; } /** @@ -880,7 +472,7 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co int max_num_persons) { // Assumed percentage of infection state at the beginning of the simulation. - ScalarType exposed_prob = 0.5, infected_no_symptoms_prob = 0.001, infected_symptoms_prob = 0.001, + ScalarType exposed_prob = 0.05, infected_no_symptoms_prob = 0.001, infected_symptoms_prob = 0.001, recovered_prob = 0.0; //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -1015,12 +607,12 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di bool save_single_runs = true) { auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation auto ensemble_results = std::vector>>{}; // Vector of collected results ensemble_results.reserve(size_t(num_runs)); auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 1000; + auto max_num_persons = 10000; // Loop over a number of runs while (run_idx <= num_runs) { @@ -1066,7 +658,8 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_file = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/bs_sorted.csv"; + std::string input_file = + "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/bs_und_umgebung.csv"; size_t num_runs; bool save_single_runs = true; @@ -1090,8 +683,8 @@ int main(int argc, char** argv) printf("abm_braunschweig \n"); printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - printf("Running with number of runs = 10.\n"); - num_runs = 10; + printf("Running with number of runs = 1.\n"); + num_runs = 1; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging diff --git a/cpp/tests/test_abm_world.cpp b/cpp/tests/test_abm_world.cpp index 65bc84d363..1166179579 100644 --- a/cpp/tests/test_abm_world.cpp +++ b/cpp/tests/test_abm_world.cpp @@ -237,9 +237,11 @@ TEST(TestWorld, evolveMigration) world.parameters .get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 2 * dt.days(); - world.parameters.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + world.parameters + .get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 2 * dt.days(); auto home_id = world.add_location(mio::abm::LocationType::Home); @@ -417,7 +419,8 @@ TEST(TestWorldTestingCriteria, testAddingAndUpdatingAndRunningTestingSchemes) 100; world.parameters.get()[{mio::abm::VirusVariant(0), age_group_15_to_34}] = 100; - world.parameters.get()[{mio::abm::VirusVariant(0), age_group_15_to_34}] = 100; + world.parameters.get()[{mio::abm::VirusVariant(0), age_group_15_to_34}] = + 100; auto home_id = world.add_location(mio::abm::LocationType::Home); auto work_id = world.add_location(mio::abm::LocationType::Work); @@ -468,16 +471,17 @@ TEST(TestWorld, checkParameterConstraints) auto world = mio::abm::World(num_age_groups); auto params = world.parameters; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 1.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 2.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 3.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 4.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 5.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 6.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 7.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 8.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 9.; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.3; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 1.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 2.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = + 3.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 4.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 5.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 6.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 7.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 8.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 9.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.3; params.get()[age_group_35_to_59] = mio::abm::hours(4); params.get()[age_group_35_to_59] = mio::abm::hours(8); params.get()[age_group_0_to_4] = mio::abm::hours(3); @@ -490,7 +494,7 @@ TEST(TestWorld, checkParameterConstraints) params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = -1.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 1.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 1.; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = -2.; ASSERT_EQ(params.check_constraints(), true); @@ -517,9 +521,9 @@ TEST(TestWorld, checkParameterConstraints) params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 8.; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = -9.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 9.; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 9.; ASSERT_EQ(params.check_constraints(), true); - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 1.1; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 1.1; ASSERT_EQ(params.check_constraints(), true); params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.3; @@ -586,12 +590,12 @@ TEST(TestWorld, copyWorld) auto infection_params = world.parameters.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] - .params.a(); + .params.m(); auto copied_world = mio::abm::World(world); auto copied_infection_params = copied_world.parameters.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] - .params.a(); + .params.m(); // Assert the parameters, trips, locations and persons of copied world are logically equal to that of original world ASSERT_EQ(copied_infection_params, infection_params); diff --git a/cpp/tests/test_analyze_result.cpp b/cpp/tests/test_analyze_result.cpp index 54f4e8c824..5dc63d647b 100644 --- a/cpp/tests/test_analyze_result.cpp +++ b/cpp/tests/test_analyze_result.cpp @@ -512,12 +512,12 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) ensemble_p49_params[0] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.m(); auto check2 = ensemble_p49_params[1] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.m(); EXPECT_EQ(check1, 0.1); EXPECT_EQ(check2, 0.2); @@ -526,12 +526,12 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) ensemble_p51_params[0] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.m(); auto check4 = ensemble_p51_params[1] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.m(); EXPECT_EQ(check3, 0.3); EXPECT_EQ(check4, 0.4); @@ -540,12 +540,12 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) ensemble_p49_params[0] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.m(); auto check6 = ensemble_p49_params[1] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.m(); EXPECT_EQ(check5, 0.2); EXPECT_EQ(check6, 0.3); @@ -554,12 +554,12 @@ TEST(TestEnsembleParamsPercentile, graph_abm_basic) ensemble_p51_params[0] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.m(); auto check8 = ensemble_p51_params[1] .parameters .get()[{mio::abm::VirusVariant::Wildtype, mio::AgeGroup(0)}] - .params.a(); + .params.s(); EXPECT_EQ(check7, 0.4); EXPECT_EQ(check8, 0.5); diff --git a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py index 51f1d38fd7..965a937276 100644 --- a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py +++ b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py @@ -55,7 +55,7 @@ def main(n_runs): plot_infection_per_location_type(df) if file.startswith("infection_per_age_group"): plot_infection_per_age_group(df) - if file.startswith("abm_result"): + if file.startswith("run_"): # convert to numpy array df_np = df.to_numpy() # attach to array From 238e09d0c7e82e27a6b09480f50e0e908e6cd9d1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 14 Feb 2024 10:46:34 +0100 Subject: [PATCH 025/488] some fixes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/infection.cpp | 3 +- cpp/simulations/paper_abm_bs_testing.cpp | 40 +- .../memilio/epidata/folder_run_bs/run_0.txt | 1442 +++++++++++++++++ .../memilio/epidata/folder_run_bs/run_1.txt | 1442 +++++++++++++++++ 4 files changed, 2907 insertions(+), 20 deletions(-) create mode 100644 pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_0.txt create mode 100644 pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_1.txt diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 9004f61d67..8804aa0c94 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -38,7 +38,8 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age auto vl_params = params.get()[{virus, age}]; ScalarType high_viral_load_factor = 1; if (latest_exposure.first != ExposureType::NoProtection) { - high_viral_load_factor -= 0; + auto test = init_date.days() - latest_exposure.second.days(); + high_viral_load_factor -= params.get()(test); } m_viral_load.peak = vl_params.viral_load_peak.get_distribution_instance()(rng, vl_params.viral_load_peak.params) * high_viral_load_factor; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bf2bce39ba..24fef2c0ef 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -377,10 +377,10 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, world.get_trip_list().use_weekday_trips_on_weekend(); } -std::pair get_my_and_sigma(std::pair mean_and_qstd) +std::pair get_my_and_sigma(std::pair mean_and_std) { - auto mean = mean_and_qstd.first; - auto stddev = mean_and_qstd.second; + auto mean = mean_and_std.first; + auto stddev = mean_and_std.second; double my = log(mean * mean / sqrt(mean * mean + stddev * stddev)); double sigma = sqrt(log(1 + stddev * stddev / (mean * mean))); return {my, sigma}; @@ -395,48 +395,50 @@ void set_parameters(mio::abm::Parameters params) auto incubation_period_my_sigma = get_my_and_sigma({4.5, 1.5}); params.get() = {incubation_period_my_sigma.first, incubation_period_my_sigma.second}; - auto InfectedNoSymptoms_to_symptoms_my_sigma = get_my_and_sigma({0.5, 0.5}); + auto InfectedNoSymptoms_to_symptoms_my_sigma = get_my_and_sigma({1.1, 0.9}); params.get() = {InfectedNoSymptoms_to_symptoms_my_sigma.first, InfectedNoSymptoms_to_symptoms_my_sigma.second}; - auto TimeInfectedNoSymptomsToRecovered_my_sigma = get_my_and_sigma({10, 5}); + auto TimeInfectedNoSymptomsToRecovered_my_sigma = get_my_and_sigma({8.0, 2.0}); params.get() = {TimeInfectedNoSymptomsToRecovered_my_sigma.first, TimeInfectedNoSymptomsToRecovered_my_sigma.second}; - auto TimeInfectedSymptomsToSevere_my_sigma = get_my_and_sigma({7, 2}); + auto TimeInfectedSymptomsToSevere_my_sigma = get_my_and_sigma({6.6, 4.9}); params.get() = {TimeInfectedSymptomsToSevere_my_sigma.first, TimeInfectedSymptomsToSevere_my_sigma.second}; - auto TimeInfectedSymptomsToRecovered_my_sigma = get_my_and_sigma({14, 3}); + auto TimeInfectedSymptomsToRecovered_my_sigma = get_my_and_sigma({8.0, 2.0}); params.get() = {TimeInfectedSymptomsToRecovered_my_sigma.first, TimeInfectedSymptomsToRecovered_my_sigma.second}; - auto TimeInfectedSevereToCritical_my_sigma = get_my_and_sigma({7, 2}); + auto TimeInfectedSevereToCritical_my_sigma = get_my_and_sigma({1.5, 2.0}); params.get() = {TimeInfectedSevereToCritical_my_sigma.first, TimeInfectedSevereToCritical_my_sigma.second}; - auto TimeInfectedSevereToRecovered_my_sigma = get_my_and_sigma({14, 3}); + auto TimeInfectedSevereToRecovered_my_sigma = get_my_and_sigma({18.1, 6.3}); params.get() = {TimeInfectedSevereToRecovered_my_sigma.first, TimeInfectedSevereToRecovered_my_sigma.second}; - auto TimeInfectedCriticalToDead_my_sigma = get_my_and_sigma({7, 2}); + auto TimeInfectedCriticalToDead_my_sigma = get_my_and_sigma({10.7, 4.8}); params.get() = {TimeInfectedCriticalToDead_my_sigma.first, TimeInfectedCriticalToDead_my_sigma.second}; - auto TimeInfectedCriticalToRecovered_my_sigma = get_my_and_sigma({14, 3}); + auto TimeInfectedCriticalToRecovered_my_sigma = get_my_and_sigma({18.1, 6.3}); params.get() = {TimeInfectedCriticalToRecovered_my_sigma.first, TimeInfectedCriticalToRecovered_my_sigma.second}; // Set percentage parameters - params.get() = 0.05; - params.get() = 0.1; + params.get() = 0.5; + params.get() = 0.1; + params.get() = 0.05; + params.get() = 0.002; // Set infection parameters - // // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 - // params.get() = [](ScalarType days) -> ScalarType { - // return mio::linear_interpolation_of_data_set( - // {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); - // }; + // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 + params.get() = [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); + }; // Set protection level from low viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 // params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, @@ -487,7 +489,7 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co // Assign an infection state to each person. assign_infection_state(world, t0, exposed_prob, infected_no_symptoms_prob, infected_symptoms_prob, recovered_prob); - auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); + auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(1); // During the lockdown, 25% of people work from home and schools are closed for 90% of students. // Social events are very rare. diff --git a/pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_0.txt b/pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_0.txt new file mode 100644 index 0000000000..020d49c58c --- /dev/null +++ b/pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_0.txt @@ -0,0 +1,1442 @@ +Time S E I_NS I_Sy I_Sev I_Crit R D + 0.0000 9480.0000 506.0000 6.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.0417 9412.0000 574.0000 6.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.0833 9354.0000 632.0000 6.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.1250 9294.0000 691.0000 7.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.1667 9232.0000 753.0000 7.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.2083 9168.0000 816.0000 8.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.2500 9103.0000 879.0000 10.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.2917 9039.0000 941.0000 12.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.3333 8988.0000 991.0000 13.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.3750 8958.0000 1016.0000 18.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.4167 8947.0000 1021.0000 24.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.4583 8934.0000 1025.0000 33.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.5000 8921.0000 1035.0000 36.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.5417 8910.0000 1040.0000 42.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.5833 8873.0000 1064.0000 55.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.6250 8846.0000 1083.0000 63.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.6667 8819.0000 1098.0000 75.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.7083 8784.0000 1125.0000 83.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.7500 8755.0000 1144.0000 93.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.7917 8742.0000 1144.0000 106.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.8333 8702.0000 1175.0000 115.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.8750 8655.0000 1207.0000 129.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 0.9167 8613.0000 1238.0000 140.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 0.9583 8538.0000 1299.0000 154.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 1.0000 8445.0000 1382.0000 164.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 1.0417 8344.0000 1474.0000 171.0000 6.0000 0.0000 5.0000 0.0000 0.0000 + 1.0833 8229.0000 1576.0000 183.0000 7.0000 0.0000 5.0000 0.0000 0.0000 + 1.1250 8118.0000 1673.0000 195.0000 7.0000 0.0000 5.0000 2.0000 0.0000 + 1.1667 8004.0000 1775.0000 206.0000 7.0000 0.0000 4.0000 3.0000 1.0000 + 1.2083 7887.0000 1882.0000 216.0000 7.0000 0.0000 4.0000 3.0000 1.0000 + 1.2500 7786.0000 1966.0000 232.0000 7.0000 0.0000 4.0000 4.0000 1.0000 + 1.2917 7656.0000 2079.0000 247.0000 8.0000 0.0000 4.0000 5.0000 1.0000 + 1.3333 7533.0000 2187.0000 258.0000 11.0000 0.0000 4.0000 6.0000 1.0000 + 1.3750 7464.0000 2237.0000 276.0000 12.0000 0.0000 4.0000 6.0000 1.0000 + 1.4167 7426.0000 2262.0000 289.0000 12.0000 0.0000 4.0000 6.0000 1.0000 + 1.4583 7403.0000 2268.0000 304.0000 13.0000 0.0000 4.0000 7.0000 1.0000 + 1.5000 7380.0000 2274.0000 319.0000 14.0000 0.0000 3.0000 8.0000 2.0000 + 1.5417 7350.0000 2291.0000 330.0000 14.0000 0.0000 3.0000 10.0000 2.0000 + 1.5833 7280.0000 2338.0000 350.0000 15.0000 0.0000 3.0000 12.0000 2.0000 + 1.6250 7200.0000 2402.0000 364.0000 16.0000 0.0000 3.0000 13.0000 2.0000 + 1.6667 7082.0000 2493.0000 388.0000 17.0000 0.0000 3.0000 15.0000 2.0000 + 1.7083 6985.0000 2570.0000 405.0000 17.0000 0.0000 3.0000 18.0000 2.0000 + 1.7500 6840.0000 2694.0000 425.0000 18.0000 0.0000 3.0000 18.0000 2.0000 + 1.7917 6673.0000 2843.0000 438.0000 20.0000 0.0000 3.0000 21.0000 2.0000 + 1.8333 6498.0000 2994.0000 461.0000 20.0000 0.0000 3.0000 22.0000 2.0000 + 1.8750 6304.0000 3167.0000 478.0000 21.0000 0.0000 3.0000 25.0000 2.0000 + 1.9167 6057.0000 3392.0000 498.0000 22.0000 0.0000 3.0000 26.0000 2.0000 + 1.9583 5767.0000 3656.0000 522.0000 24.0000 0.0000 3.0000 26.0000 2.0000 + 2.0000 5434.0000 3967.0000 541.0000 25.0000 0.0000 3.0000 28.0000 2.0000 + 2.0417 5137.0000 4229.0000 573.0000 27.0000 0.0000 3.0000 29.0000 2.0000 + 2.0833 4795.0000 4547.0000 593.0000 30.0000 0.0000 3.0000 30.0000 2.0000 + 2.1250 4507.0000 4800.0000 624.0000 33.0000 0.0000 3.0000 31.0000 2.0000 + 2.1667 4200.0000 5076.0000 656.0000 34.0000 0.0000 3.0000 29.0000 2.0000 + 2.2083 3925.0000 5313.0000 690.0000 40.0000 0.0000 3.0000 27.0000 2.0000 + 2.2500 3639.0000 5557.0000 730.0000 43.0000 0.0000 3.0000 26.0000 2.0000 + 2.2917 3406.0000 5758.0000 753.0000 52.0000 0.0000 2.0000 26.0000 3.0000 + 2.3333 3234.0000 5892.0000 792.0000 53.0000 0.0000 2.0000 24.0000 3.0000 + 2.3750 3117.0000 5955.0000 842.0000 55.0000 0.0000 2.0000 26.0000 3.0000 + 2.4167 3048.0000 5992.0000 864.0000 58.0000 0.0000 2.0000 33.0000 3.0000 + 2.4583 3006.0000 5982.0000 912.0000 59.0000 0.0000 2.0000 36.0000 3.0000 + 2.5000 2967.0000 5973.0000 952.0000 60.0000 0.0000 2.0000 43.0000 3.0000 + 2.5417 2886.0000 6009.0000 992.0000 59.0000 0.0000 2.0000 49.0000 3.0000 + 2.5833 2787.0000 6049.0000 1042.0000 65.0000 0.0000 2.0000 52.0000 3.0000 + 2.6250 2691.0000 6091.0000 1091.0000 69.0000 0.0000 2.0000 53.0000 3.0000 + 2.6667 2505.0000 6222.0000 1145.0000 72.0000 0.0000 2.0000 51.0000 3.0000 + 2.7083 2344.0000 6327.0000 1193.0000 81.0000 0.0000 2.0000 50.0000 3.0000 + 2.7500 2145.0000 6478.0000 1241.0000 87.0000 0.0000 2.0000 44.0000 3.0000 + 2.7917 1972.0000 6603.0000 1282.0000 97.0000 0.0000 2.0000 41.0000 3.0000 + 2.8333 1837.0000 6679.0000 1342.0000 101.0000 0.0000 2.0000 36.0000 3.0000 + 2.8750 1742.0000 6721.0000 1390.0000 111.0000 0.0000 2.0000 31.0000 3.0000 + 2.9167 1664.0000 6740.0000 1445.0000 121.0000 0.0000 2.0000 25.0000 3.0000 + 2.9583 1594.0000 6743.0000 1508.0000 125.0000 0.0000 2.0000 25.0000 3.0000 + 3.0000 1540.0000 6737.0000 1568.0000 126.0000 0.0000 2.0000 24.0000 3.0000 + 3.0417 1509.0000 6699.0000 1633.0000 130.0000 0.0000 2.0000 24.0000 3.0000 + 3.0833 1497.0000 6637.0000 1702.0000 134.0000 0.0000 2.0000 25.0000 3.0000 + 3.1250 1486.0000 6574.0000 1773.0000 139.0000 0.0000 2.0000 23.0000 3.0000 + 3.1667 1482.0000 6527.0000 1823.0000 143.0000 0.0000 2.0000 20.0000 3.0000 + 3.2083 1478.0000 6473.0000 1874.0000 150.0000 0.0000 2.0000 20.0000 3.0000 + 3.2500 1475.0000 6421.0000 1920.0000 158.0000 0.0000 2.0000 21.0000 3.0000 + 3.2917 1474.0000 6361.0000 1978.0000 161.0000 0.0000 2.0000 21.0000 3.0000 + 3.3333 1468.0000 6303.0000 2033.0000 171.0000 0.0000 2.0000 20.0000 3.0000 + 3.3750 1465.0000 6250.0000 2069.0000 177.0000 0.0000 2.0000 34.0000 3.0000 + 3.4167 1446.0000 6212.0000 2120.0000 181.0000 0.0000 2.0000 36.0000 3.0000 + 3.4583 1425.0000 6171.0000 2171.0000 189.0000 0.0000 2.0000 39.0000 3.0000 + 3.5000 1406.0000 6120.0000 2223.0000 201.0000 0.0000 2.0000 45.0000 3.0000 + 3.5417 1370.0000 6090.0000 2278.0000 209.0000 0.0000 2.0000 48.0000 3.0000 + 3.5833 1313.0000 6086.0000 2328.0000 210.0000 0.0000 2.0000 58.0000 3.0000 + 3.6250 1285.0000 6052.0000 2370.0000 224.0000 0.0000 2.0000 64.0000 3.0000 + 3.6667 1180.0000 6095.0000 2428.0000 233.0000 0.0000 2.0000 59.0000 3.0000 + 3.7083 1109.0000 6104.0000 2485.0000 240.0000 0.0000 2.0000 57.0000 3.0000 + 3.7500 1040.0000 6119.0000 2540.0000 247.0000 0.0000 2.0000 49.0000 3.0000 + 3.7917 1010.0000 6108.0000 2582.0000 258.0000 0.0000 2.0000 37.0000 3.0000 + 3.8333 1002.0000 6050.0000 2638.0000 267.0000 0.0000 2.0000 38.0000 3.0000 + 3.8750 997.0000 6011.0000 2679.0000 279.0000 0.0000 2.0000 29.0000 3.0000 + 3.9167 997.0000 5944.0000 2738.0000 284.0000 0.0000 2.0000 32.0000 3.0000 + 3.9583 997.0000 5891.0000 2786.0000 292.0000 0.0000 2.0000 29.0000 3.0000 + 4.0000 992.0000 5844.0000 2830.0000 303.0000 0.0000 2.0000 26.0000 3.0000 + 4.0417 991.0000 5791.0000 2867.0000 317.0000 0.0000 2.0000 29.0000 3.0000 + 4.0833 988.0000 5748.0000 2905.0000 326.0000 0.0000 2.0000 28.0000 3.0000 + 4.1250 987.0000 5692.0000 2949.0000 338.0000 0.0000 2.0000 29.0000 3.0000 + 4.1667 986.0000 5646.0000 2977.0000 349.0000 0.0000 2.0000 37.0000 3.0000 + 4.2083 982.0000 5591.0000 3023.0000 360.0000 0.0000 2.0000 39.0000 3.0000 + 4.2500 980.0000 5547.0000 3064.0000 373.0000 0.0000 2.0000 31.0000 3.0000 + 4.2917 978.0000 5484.0000 3107.0000 385.0000 0.0000 2.0000 41.0000 3.0000 + 4.3333 975.0000 5451.0000 3136.0000 393.0000 0.0000 2.0000 40.0000 3.0000 + 4.3750 972.0000 5396.0000 3160.0000 418.0000 0.0000 2.0000 49.0000 3.0000 + 4.4167 969.0000 5348.0000 3194.0000 431.0000 0.0000 2.0000 53.0000 3.0000 + 4.4583 953.0000 5304.0000 3233.0000 435.0000 0.0000 2.0000 70.0000 3.0000 + 4.5000 946.0000 5263.0000 3257.0000 446.0000 0.0000 2.0000 83.0000 3.0000 + 4.5417 936.0000 5221.0000 3292.0000 461.0000 0.0000 2.0000 85.0000 3.0000 + 4.5833 914.0000 5192.0000 3328.0000 475.0000 0.0000 2.0000 86.0000 3.0000 + 4.6250 910.0000 5151.0000 3359.0000 486.0000 0.0000 2.0000 89.0000 3.0000 + 4.6667 899.0000 5143.0000 3362.0000 498.0000 0.0000 2.0000 93.0000 3.0000 + 4.7083 886.0000 5145.0000 3365.0000 515.0000 0.0000 2.0000 84.0000 3.0000 + 4.7500 867.0000 5150.0000 3393.0000 522.0000 0.0000 2.0000 63.0000 3.0000 + 4.7917 865.0000 5125.0000 3409.0000 534.0000 0.0000 2.0000 62.0000 3.0000 + 4.8333 862.0000 5095.0000 3439.0000 543.0000 0.0000 2.0000 56.0000 3.0000 + 4.8750 862.0000 5055.0000 3467.0000 550.0000 0.0000 2.0000 61.0000 3.0000 + 4.9167 862.0000 5019.0000 3489.0000 565.0000 1.0000 2.0000 59.0000 3.0000 + 4.9583 861.0000 4986.0000 3515.0000 582.0000 1.0000 2.0000 50.0000 3.0000 + 5.0000 861.0000 4934.0000 3555.0000 597.0000 1.0000 2.0000 47.0000 3.0000 + 5.0417 861.0000 4898.0000 3565.0000 615.0000 1.0000 2.0000 55.0000 3.0000 + 5.0833 859.0000 4875.0000 3572.0000 626.0000 1.0000 2.0000 62.0000 3.0000 + 5.1250 859.0000 4853.0000 3590.0000 631.0000 2.0000 2.0000 60.0000 3.0000 + 5.1667 856.0000 4821.0000 3620.0000 636.0000 2.0000 2.0000 60.0000 3.0000 + 5.2083 855.0000 4795.0000 3620.0000 651.0000 2.0000 2.0000 72.0000 3.0000 + 5.2500 853.0000 4772.0000 3632.0000 670.0000 2.0000 2.0000 66.0000 3.0000 + 5.2917 851.0000 4743.0000 3636.0000 689.0000 2.0000 2.0000 74.0000 3.0000 + 5.3333 850.0000 4717.0000 3651.0000 701.0000 2.0000 2.0000 74.0000 3.0000 + 5.3750 843.0000 4692.0000 3672.0000 716.0000 2.0000 2.0000 70.0000 3.0000 + 5.4167 836.0000 4654.0000 3697.0000 723.0000 2.0000 2.0000 83.0000 3.0000 + 5.4583 825.0000 4632.0000 3710.0000 737.0000 2.0000 2.0000 89.0000 3.0000 + 5.5000 821.0000 4616.0000 3715.0000 745.0000 2.0000 2.0000 96.0000 3.0000 + 5.5417 815.0000 4595.0000 3734.0000 754.0000 2.0000 2.0000 95.0000 3.0000 + 5.5833 811.0000 4572.0000 3740.0000 767.0000 2.0000 2.0000 103.0000 3.0000 + 5.6250 807.0000 4557.0000 3745.0000 778.0000 2.0000 2.0000 106.0000 3.0000 + 5.6667 803.0000 4536.0000 3760.0000 789.0000 2.0000 2.0000 105.0000 3.0000 + 5.7083 802.0000 4528.0000 3775.0000 800.0000 2.0000 2.0000 88.0000 3.0000 + 5.7500 801.0000 4529.0000 3777.0000 816.0000 2.0000 2.0000 70.0000 3.0000 + 5.7917 795.0000 4517.0000 3783.0000 830.0000 2.0000 2.0000 68.0000 3.0000 + 5.8333 795.0000 4491.0000 3794.0000 842.0000 2.0000 2.0000 71.0000 3.0000 + 5.8750 795.0000 4478.0000 3788.0000 864.0000 2.0000 2.0000 68.0000 3.0000 + 5.9167 794.0000 4455.0000 3798.0000 877.0000 2.0000 2.0000 69.0000 3.0000 + 5.9583 792.0000 4448.0000 3801.0000 891.0000 2.0000 2.0000 61.0000 3.0000 + 6.0000 791.0000 4430.0000 3808.0000 906.0000 2.0000 2.0000 58.0000 3.0000 + 6.0417 791.0000 4409.0000 3807.0000 923.0000 2.0000 2.0000 63.0000 3.0000 + 6.0833 791.0000 4404.0000 3803.0000 932.0000 2.0000 2.0000 63.0000 3.0000 + 6.1250 791.0000 4391.0000 3798.0000 944.0000 2.0000 2.0000 69.0000 3.0000 + 6.1667 789.0000 4368.0000 3807.0000 962.0000 2.0000 2.0000 67.0000 3.0000 + 6.2083 789.0000 4353.0000 3802.0000 977.0000 2.0000 2.0000 72.0000 3.0000 + 6.2500 787.0000 4336.0000 3804.0000 982.0000 2.0000 2.0000 84.0000 3.0000 + 6.2917 786.0000 4324.0000 3812.0000 993.0000 2.0000 2.0000 78.0000 3.0000 + 6.3333 784.0000 4309.0000 3809.0000 1002.0000 2.0000 2.0000 89.0000 3.0000 + 6.3750 783.0000 4286.0000 3802.0000 1011.0000 2.0000 2.0000 111.0000 3.0000 + 6.4167 782.0000 4258.0000 3813.0000 1018.0000 2.0000 2.0000 122.0000 3.0000 + 6.4583 778.0000 4245.0000 3813.0000 1028.0000 2.0000 2.0000 129.0000 3.0000 + 6.5000 768.0000 4219.0000 3847.0000 1033.0000 2.0000 2.0000 126.0000 3.0000 + 6.5417 764.0000 4202.0000 3845.0000 1043.0000 2.0000 2.0000 139.0000 3.0000 + 6.5833 760.0000 4195.0000 3841.0000 1051.0000 2.0000 2.0000 146.0000 3.0000 + 6.6250 755.0000 4185.0000 3844.0000 1062.0000 2.0000 2.0000 147.0000 3.0000 + 6.6667 752.0000 4190.0000 3851.0000 1068.0000 3.0000 2.0000 131.0000 3.0000 + 6.7083 749.0000 4195.0000 3845.0000 1084.0000 3.0000 2.0000 119.0000 3.0000 + 6.7500 749.0000 4216.0000 3838.0000 1098.0000 4.0000 2.0000 90.0000 3.0000 + 6.7917 748.0000 4212.0000 3844.0000 1110.0000 4.0000 2.0000 77.0000 3.0000 + 6.8333 746.0000 4193.0000 3852.0000 1124.0000 4.0000 2.0000 76.0000 3.0000 + 6.8750 745.0000 4189.0000 3849.0000 1136.0000 4.0000 2.0000 72.0000 3.0000 + 6.9167 744.0000 4189.0000 3833.0000 1147.0000 7.0000 2.0000 75.0000 3.0000 + 6.9583 742.0000 4188.0000 3836.0000 1156.0000 6.0000 3.0000 66.0000 3.0000 + 7.0000 741.0000 4182.0000 3830.0000 1165.0000 7.0000 3.0000 69.0000 3.0000 + 7.0417 740.0000 4171.0000 3829.0000 1176.0000 6.0000 3.0000 72.0000 3.0000 + 7.0833 739.0000 4165.0000 3830.0000 1182.0000 7.0000 3.0000 71.0000 3.0000 + 7.1250 739.0000 4146.0000 3835.0000 1181.0000 7.0000 3.0000 86.0000 3.0000 + 7.1667 738.0000 4140.0000 3842.0000 1181.0000 7.0000 3.0000 86.0000 3.0000 + 7.2083 737.0000 4139.0000 3842.0000 1193.0000 7.0000 3.0000 76.0000 3.0000 + 7.2500 735.0000 4114.0000 3848.0000 1204.0000 7.0000 3.0000 86.0000 3.0000 + 7.2917 735.0000 4098.0000 3852.0000 1210.0000 8.0000 3.0000 91.0000 3.0000 + 7.3333 734.0000 4090.0000 3849.0000 1226.0000 8.0000 3.0000 87.0000 3.0000 + 7.3750 733.0000 4053.0000 3854.0000 1241.0000 7.0000 4.0000 105.0000 3.0000 + 7.4167 730.0000 4047.0000 3840.0000 1251.0000 7.0000 4.0000 118.0000 3.0000 + 7.4583 724.0000 4039.0000 3837.0000 1261.0000 6.0000 4.0000 126.0000 3.0000 + 7.5000 717.0000 4028.0000 3835.0000 1274.0000 6.0000 4.0000 133.0000 3.0000 + 7.5417 715.0000 4020.0000 3839.0000 1272.0000 6.0000 4.0000 141.0000 3.0000 + 7.5833 712.0000 4018.0000 3842.0000 1275.0000 5.0000 3.0000 142.0000 3.0000 + 7.6250 711.0000 4008.0000 3837.0000 1291.0000 5.0000 3.0000 142.0000 3.0000 + 7.6667 709.0000 4012.0000 3836.0000 1306.0000 5.0000 3.0000 126.0000 3.0000 + 7.7083 703.0000 4006.0000 3849.0000 1309.0000 6.0000 3.0000 121.0000 3.0000 + 7.7500 702.0000 4017.0000 3841.0000 1313.0000 7.0000 3.0000 114.0000 3.0000 + 7.7917 700.0000 4022.0000 3857.0000 1308.0000 7.0000 3.0000 100.0000 3.0000 + 7.8333 699.0000 4019.0000 3855.0000 1311.0000 6.0000 3.0000 104.0000 3.0000 + 7.8750 695.0000 4012.0000 3859.0000 1316.0000 6.0000 3.0000 106.0000 3.0000 + 7.9167 691.0000 4003.0000 3852.0000 1336.0000 6.0000 3.0000 106.0000 3.0000 + 7.9583 690.0000 4008.0000 3858.0000 1349.0000 7.0000 3.0000 82.0000 3.0000 + 8.0000 689.0000 4008.0000 3840.0000 1363.0000 8.0000 3.0000 86.0000 3.0000 + 8.0417 689.0000 3985.0000 3860.0000 1366.0000 9.0000 3.0000 85.0000 3.0000 + 8.0833 689.0000 3976.0000 3857.0000 1369.0000 10.0000 3.0000 93.0000 3.0000 + 8.1250 688.0000 3974.0000 3860.0000 1374.0000 10.0000 3.0000 88.0000 3.0000 + 8.1667 687.0000 3955.0000 3855.0000 1386.0000 10.0000 3.0000 101.0000 3.0000 + 8.2083 685.0000 3945.0000 3865.0000 1392.0000 10.0000 3.0000 97.0000 3.0000 + 8.2500 684.0000 3926.0000 3874.0000 1396.0000 10.0000 3.0000 104.0000 3.0000 + 8.2917 683.0000 3916.0000 3878.0000 1394.0000 11.0000 3.0000 112.0000 3.0000 + 8.3333 682.0000 3899.0000 3893.0000 1398.0000 11.0000 3.0000 111.0000 3.0000 + 8.3750 679.0000 3885.0000 3895.0000 1407.0000 11.0000 3.0000 117.0000 3.0000 + 8.4167 676.0000 3869.0000 3906.0000 1408.0000 11.0000 3.0000 124.0000 3.0000 + 8.4583 673.0000 3861.0000 3904.0000 1407.0000 11.0000 3.0000 138.0000 3.0000 + 8.5000 665.0000 3854.0000 3908.0000 1410.0000 11.0000 3.0000 146.0000 3.0000 + 8.5417 662.0000 3849.0000 3901.0000 1413.0000 11.0000 3.0000 158.0000 3.0000 + 8.5833 660.0000 3854.0000 3885.0000 1429.0000 11.0000 3.0000 155.0000 3.0000 + 8.6250 657.0000 3845.0000 3888.0000 1430.0000 11.0000 3.0000 163.0000 3.0000 + 8.6667 655.0000 3851.0000 3900.0000 1434.0000 11.0000 4.0000 142.0000 3.0000 + 8.7083 652.0000 3863.0000 3903.0000 1434.0000 12.0000 4.0000 129.0000 3.0000 + 8.7500 650.0000 3881.0000 3890.0000 1431.0000 12.0000 4.0000 129.0000 3.0000 + 8.7917 648.0000 3907.0000 3888.0000 1433.0000 12.0000 4.0000 105.0000 3.0000 + 8.8333 645.0000 3900.0000 3880.0000 1444.0000 12.0000 4.0000 112.0000 3.0000 + 8.8750 643.0000 3899.0000 3871.0000 1452.0000 12.0000 4.0000 116.0000 3.0000 + 8.9167 642.0000 3895.0000 3879.0000 1450.0000 14.0000 4.0000 113.0000 3.0000 + 8.9583 642.0000 3912.0000 3867.0000 1466.0000 14.0000 4.0000 92.0000 3.0000 + 9.0000 642.0000 3904.0000 3872.0000 1467.0000 15.0000 4.0000 93.0000 3.0000 + 9.0417 640.0000 3899.0000 3867.0000 1478.0000 17.0000 4.0000 92.0000 3.0000 + 9.0833 640.0000 3884.0000 3869.0000 1485.0000 18.0000 4.0000 97.0000 3.0000 + 9.1250 640.0000 3871.0000 3865.0000 1499.0000 20.0000 4.0000 98.0000 3.0000 + 9.1667 638.0000 3860.0000 3861.0000 1510.0000 20.0000 4.0000 104.0000 3.0000 + 9.2083 637.0000 3852.0000 3846.0000 1523.0000 21.0000 4.0000 114.0000 3.0000 + 9.2500 637.0000 3853.0000 3831.0000 1532.0000 21.0000 4.0000 119.0000 3.0000 + 9.2917 637.0000 3841.0000 3837.0000 1536.0000 21.0000 4.0000 121.0000 3.0000 + 9.3333 636.0000 3824.0000 3848.0000 1529.0000 25.0000 4.0000 131.0000 3.0000 + 9.3750 635.0000 3805.0000 3854.0000 1534.0000 24.0000 5.0000 140.0000 3.0000 + 9.4167 629.0000 3799.0000 3856.0000 1533.0000 24.0000 5.0000 151.0000 3.0000 + 9.4583 627.0000 3797.0000 3838.0000 1541.0000 25.0000 5.0000 164.0000 3.0000 + 9.5000 620.0000 3778.0000 3850.0000 1542.0000 26.0000 5.0000 176.0000 3.0000 + 9.5417 618.0000 3788.0000 3842.0000 1547.0000 28.0000 5.0000 169.0000 3.0000 + 9.5833 615.0000 3791.0000 3849.0000 1546.0000 28.0000 5.0000 163.0000 3.0000 + 9.6250 613.0000 3789.0000 3839.0000 1549.0000 28.0000 5.0000 174.0000 3.0000 + 9.6667 612.0000 3798.0000 3836.0000 1547.0000 31.0000 5.0000 168.0000 3.0000 + 9.7083 609.0000 3809.0000 3841.0000 1552.0000 30.0000 5.0000 151.0000 3.0000 + 9.7500 607.0000 3825.0000 3837.0000 1550.0000 31.0000 4.0000 143.0000 3.0000 + 9.7917 605.0000 3850.0000 3831.0000 1556.0000 31.0000 4.0000 120.0000 3.0000 + 9.8333 604.0000 3839.0000 3846.0000 1551.0000 32.0000 4.0000 121.0000 3.0000 + 9.8750 604.0000 3848.0000 3845.0000 1560.0000 35.0000 4.0000 101.0000 3.0000 + 9.9167 604.0000 3836.0000 3848.0000 1557.0000 34.0000 5.0000 113.0000 3.0000 + 9.9583 603.0000 3852.0000 3842.0000 1556.0000 32.0000 7.0000 105.0000 3.0000 +10.0000 603.0000 3850.0000 3841.0000 1564.0000 33.0000 7.0000 99.0000 3.0000 +10.0417 602.0000 3849.0000 3832.0000 1562.0000 32.0000 8.0000 112.0000 3.0000 +10.0833 601.0000 3855.0000 3824.0000 1566.0000 35.0000 8.0000 108.0000 3.0000 +10.1250 600.0000 3843.0000 3829.0000 1565.0000 35.0000 8.0000 117.0000 3.0000 +10.1667 600.0000 3847.0000 3833.0000 1561.0000 36.0000 8.0000 112.0000 3.0000 +10.2083 599.0000 3829.0000 3844.0000 1567.0000 36.0000 8.0000 114.0000 3.0000 +10.2500 599.0000 3811.0000 3846.0000 1564.0000 37.0000 9.0000 131.0000 3.0000 +10.2917 599.0000 3793.0000 3862.0000 1573.0000 41.0000 9.0000 120.0000 3.0000 +10.3333 597.0000 3791.0000 3857.0000 1577.0000 42.0000 9.0000 124.0000 3.0000 +10.3750 597.0000 3783.0000 3847.0000 1574.0000 45.0000 9.0000 142.0000 3.0000 +10.4167 596.0000 3791.0000 3830.0000 1575.0000 48.0000 9.0000 148.0000 3.0000 +10.4583 592.0000 3782.0000 3845.0000 1575.0000 50.0000 10.0000 143.0000 3.0000 +10.5000 585.0000 3771.0000 3865.0000 1571.0000 52.0000 10.0000 143.0000 3.0000 +10.5417 583.0000 3762.0000 3861.0000 1577.0000 52.0000 11.0000 151.0000 3.0000 +10.5833 583.0000 3764.0000 3857.0000 1575.0000 54.0000 11.0000 153.0000 3.0000 +10.6250 583.0000 3763.0000 3844.0000 1575.0000 57.0000 11.0000 164.0000 3.0000 +10.6667 582.0000 3766.0000 3842.0000 1576.0000 56.0000 11.0000 164.0000 3.0000 +10.7083 581.0000 3766.0000 3836.0000 1589.0000 61.0000 11.0000 153.0000 3.0000 +10.7500 581.0000 3791.0000 3849.0000 1587.0000 62.0000 11.0000 116.0000 3.0000 +10.7917 578.0000 3800.0000 3856.0000 1588.0000 64.0000 11.0000 100.0000 3.0000 +10.8333 576.0000 3790.0000 3867.0000 1579.0000 65.0000 11.0000 109.0000 3.0000 +10.8750 573.0000 3787.0000 3872.0000 1573.0000 66.0000 11.0000 115.0000 3.0000 +10.9167 572.0000 3799.0000 3869.0000 1580.0000 66.0000 11.0000 100.0000 3.0000 +10.9583 572.0000 3798.0000 3867.0000 1585.0000 66.0000 11.0000 98.0000 3.0000 +11.0000 572.0000 3799.0000 3866.0000 1588.0000 66.0000 12.0000 94.0000 3.0000 +11.0417 571.0000 3785.0000 3861.0000 1590.0000 70.0000 12.0000 108.0000 3.0000 +11.0833 567.0000 3786.0000 3861.0000 1586.0000 71.0000 15.0000 111.0000 3.0000 +11.1250 567.0000 3788.0000 3848.0000 1594.0000 69.0000 15.0000 116.0000 3.0000 +11.1667 566.0000 3795.0000 3840.0000 1597.0000 70.0000 15.0000 114.0000 3.0000 +11.2083 565.0000 3786.0000 3828.0000 1604.0000 72.0000 15.0000 127.0000 3.0000 +11.2500 565.0000 3777.0000 3830.0000 1604.0000 74.0000 15.0000 132.0000 3.0000 +11.2917 565.0000 3764.0000 3838.0000 1607.0000 74.0000 15.0000 134.0000 3.0000 +11.3333 564.0000 3747.0000 3842.0000 1612.0000 77.0000 15.0000 140.0000 3.0000 +11.3750 564.0000 3737.0000 3843.0000 1616.0000 78.0000 15.0000 144.0000 3.0000 +11.4167 563.0000 3738.0000 3823.0000 1620.0000 76.0000 16.0000 161.0000 3.0000 +11.4583 561.0000 3729.0000 3822.0000 1631.0000 76.0000 17.0000 160.0000 4.0000 +11.5000 557.0000 3722.0000 3835.0000 1624.0000 78.0000 15.0000 164.0000 5.0000 +11.5417 557.0000 3717.0000 3842.0000 1619.0000 81.0000 15.0000 164.0000 5.0000 +11.5833 556.0000 3700.0000 3840.0000 1618.0000 83.0000 15.0000 183.0000 5.0000 +11.6250 555.0000 3698.0000 3837.0000 1614.0000 86.0000 16.0000 189.0000 5.0000 +11.6667 553.0000 3708.0000 3848.0000 1615.0000 87.0000 16.0000 168.0000 5.0000 +11.7083 552.0000 3733.0000 3821.0000 1628.0000 87.0000 17.0000 157.0000 5.0000 +11.7500 552.0000 3761.0000 3818.0000 1627.0000 90.0000 17.0000 130.0000 5.0000 +11.7917 552.0000 3786.0000 3801.0000 1633.0000 93.0000 17.0000 113.0000 5.0000 +11.8333 551.0000 3791.0000 3786.0000 1630.0000 95.0000 17.0000 125.0000 5.0000 +11.8750 549.0000 3798.0000 3785.0000 1632.0000 95.0000 18.0000 118.0000 5.0000 +11.9167 549.0000 3799.0000 3783.0000 1632.0000 98.0000 18.0000 116.0000 5.0000 +11.9583 549.0000 3808.0000 3771.0000 1630.0000 100.0000 17.0000 120.0000 5.0000 +12.0000 549.0000 3801.0000 3787.0000 1630.0000 100.0000 18.0000 110.0000 5.0000 +12.0417 548.0000 3790.0000 3792.0000 1634.0000 100.0000 18.0000 113.0000 5.0000 +12.0833 547.0000 3784.0000 3778.0000 1647.0000 100.0000 18.0000 121.0000 5.0000 +12.1250 546.0000 3787.0000 3774.0000 1652.0000 104.0000 17.0000 114.0000 6.0000 +12.1667 544.0000 3776.0000 3774.0000 1661.0000 104.0000 18.0000 117.0000 6.0000 +12.2083 544.0000 3762.0000 3752.0000 1677.0000 102.0000 21.0000 136.0000 6.0000 +12.2500 544.0000 3765.0000 3744.0000 1678.0000 105.0000 21.0000 137.0000 6.0000 +12.2917 544.0000 3764.0000 3736.0000 1684.0000 106.0000 20.0000 140.0000 6.0000 +12.3333 544.0000 3759.0000 3731.0000 1686.0000 111.0000 20.0000 143.0000 6.0000 +12.3750 544.0000 3743.0000 3735.0000 1682.0000 112.0000 21.0000 157.0000 6.0000 +12.4167 544.0000 3737.0000 3745.0000 1680.0000 113.0000 23.0000 152.0000 6.0000 +12.4583 542.0000 3730.0000 3742.0000 1679.0000 115.0000 23.0000 163.0000 6.0000 +12.5000 539.0000 3717.0000 3741.0000 1675.0000 118.0000 23.0000 181.0000 6.0000 +12.5417 538.0000 3715.0000 3736.0000 1680.0000 119.0000 24.0000 182.0000 6.0000 +12.5833 535.0000 3718.0000 3734.0000 1678.0000 123.0000 25.0000 181.0000 6.0000 +12.6250 533.0000 3704.0000 3740.0000 1682.0000 126.0000 25.0000 184.0000 6.0000 +12.6667 530.0000 3709.0000 3739.0000 1672.0000 127.0000 26.0000 191.0000 6.0000 +12.7083 529.0000 3730.0000 3738.0000 1679.0000 125.0000 29.0000 164.0000 6.0000 +12.7500 528.0000 3759.0000 3725.0000 1682.0000 128.0000 29.0000 143.0000 6.0000 +12.7917 527.0000 3767.0000 3744.0000 1676.0000 132.0000 29.0000 119.0000 6.0000 +12.8333 527.0000 3747.0000 3749.0000 1685.0000 136.0000 29.0000 121.0000 6.0000 +12.8750 525.0000 3740.0000 3756.0000 1683.0000 138.0000 31.0000 121.0000 6.0000 +12.9167 525.0000 3734.0000 3751.0000 1695.0000 140.0000 32.0000 117.0000 6.0000 +12.9583 525.0000 3738.0000 3746.0000 1693.0000 139.0000 34.0000 119.0000 6.0000 +13.0000 525.0000 3733.0000 3743.0000 1697.0000 142.0000 34.0000 120.0000 6.0000 +13.0417 524.0000 3725.0000 3749.0000 1693.0000 145.0000 35.0000 123.0000 6.0000 +13.0833 523.0000 3719.0000 3753.0000 1697.0000 145.0000 36.0000 121.0000 6.0000 +13.1250 523.0000 3714.0000 3751.0000 1700.0000 148.0000 37.0000 121.0000 6.0000 +13.1667 523.0000 3712.0000 3741.0000 1704.0000 149.0000 38.0000 127.0000 6.0000 +13.2083 523.0000 3711.0000 3735.0000 1712.0000 150.0000 39.0000 124.0000 6.0000 +13.2500 521.0000 3702.0000 3737.0000 1708.0000 151.0000 39.0000 136.0000 6.0000 +13.2917 521.0000 3693.0000 3743.0000 1712.0000 154.0000 37.0000 134.0000 6.0000 +13.3333 519.0000 3683.0000 3749.0000 1712.0000 155.0000 38.0000 138.0000 6.0000 +13.3750 519.0000 3671.0000 3746.0000 1706.0000 160.0000 38.0000 154.0000 6.0000 +13.4167 518.0000 3651.0000 3759.0000 1706.0000 163.0000 40.0000 157.0000 6.0000 +13.4583 515.0000 3637.0000 3749.0000 1709.0000 167.0000 39.0000 177.0000 7.0000 +13.5000 514.0000 3638.0000 3742.0000 1714.0000 168.0000 39.0000 177.0000 8.0000 +13.5417 512.0000 3632.0000 3739.0000 1718.0000 170.0000 40.0000 181.0000 8.0000 +13.5833 510.0000 3620.0000 3750.0000 1721.0000 173.0000 40.0000 178.0000 8.0000 +13.6250 508.0000 3612.0000 3751.0000 1723.0000 174.0000 41.0000 183.0000 8.0000 +13.6667 508.0000 3625.0000 3745.0000 1727.0000 178.0000 42.0000 167.0000 8.0000 +13.7083 508.0000 3628.0000 3737.0000 1733.0000 176.0000 44.0000 166.0000 8.0000 +13.7500 505.0000 3649.0000 3740.0000 1730.0000 174.0000 45.0000 149.0000 8.0000 +13.7917 505.0000 3665.0000 3736.0000 1723.0000 177.0000 45.0000 141.0000 8.0000 +13.8333 503.0000 3666.0000 3719.0000 1723.0000 182.0000 46.0000 153.0000 8.0000 +13.8750 503.0000 3681.0000 3714.0000 1733.0000 180.0000 48.0000 133.0000 8.0000 +13.9167 503.0000 3674.0000 3700.0000 1726.0000 184.0000 48.0000 157.0000 8.0000 +13.9583 503.0000 3688.0000 3705.0000 1730.0000 182.0000 52.0000 132.0000 8.0000 +14.0000 503.0000 3668.0000 3710.0000 1723.0000 183.0000 51.0000 154.0000 8.0000 +14.0417 502.0000 3679.0000 3703.0000 1713.0000 182.0000 52.0000 161.0000 8.0000 +14.0833 501.0000 3675.0000 3709.0000 1716.0000 183.0000 55.0000 153.0000 8.0000 +14.1250 501.0000 3664.0000 3709.0000 1716.0000 184.0000 56.0000 162.0000 8.0000 +14.1667 501.0000 3653.0000 3717.0000 1716.0000 186.0000 55.0000 164.0000 8.0000 +14.2083 500.0000 3651.0000 3719.0000 1709.0000 186.0000 54.0000 171.0000 10.0000 +14.2500 500.0000 3654.0000 3708.0000 1716.0000 188.0000 54.0000 170.0000 10.0000 +14.2917 500.0000 3654.0000 3698.0000 1716.0000 191.0000 55.0000 176.0000 10.0000 +14.3333 499.0000 3659.0000 3699.0000 1711.0000 195.0000 55.0000 172.0000 10.0000 +14.3750 498.0000 3648.0000 3699.0000 1704.0000 201.0000 55.0000 185.0000 10.0000 +14.4167 493.0000 3651.0000 3696.0000 1704.0000 205.0000 55.0000 186.0000 10.0000 +14.4583 490.0000 3648.0000 3692.0000 1703.0000 207.0000 54.0000 195.0000 11.0000 +14.5000 487.0000 3642.0000 3700.0000 1693.0000 209.0000 54.0000 204.0000 11.0000 +14.5417 486.0000 3643.0000 3694.0000 1696.0000 210.0000 54.0000 206.0000 11.0000 +14.5833 485.0000 3637.0000 3697.0000 1697.0000 212.0000 53.0000 207.0000 12.0000 +14.6250 482.0000 3627.0000 3703.0000 1699.0000 215.0000 54.0000 208.0000 12.0000 +14.6667 481.0000 3644.0000 3703.0000 1696.0000 214.0000 53.0000 197.0000 12.0000 +14.7083 481.0000 3650.0000 3697.0000 1702.0000 215.0000 53.0000 190.0000 12.0000 +14.7500 480.0000 3681.0000 3693.0000 1701.0000 217.0000 52.0000 164.0000 12.0000 +14.7917 480.0000 3698.0000 3686.0000 1699.0000 219.0000 52.0000 153.0000 13.0000 +14.8333 479.0000 3694.0000 3684.0000 1703.0000 224.0000 51.0000 151.0000 14.0000 +14.8750 478.0000 3682.0000 3673.0000 1710.0000 225.0000 51.0000 166.0000 15.0000 +14.9167 478.0000 3677.0000 3682.0000 1713.0000 225.0000 52.0000 158.0000 15.0000 +14.9583 478.0000 3680.0000 3683.0000 1719.0000 228.0000 52.0000 145.0000 15.0000 +15.0000 478.0000 3682.0000 3680.0000 1713.0000 232.0000 52.0000 148.0000 15.0000 +15.0417 478.0000 3674.0000 3681.0000 1704.0000 237.0000 51.0000 159.0000 16.0000 +15.0833 478.0000 3673.0000 3684.0000 1695.0000 242.0000 51.0000 161.0000 16.0000 +15.1250 478.0000 3650.0000 3717.0000 1687.0000 244.0000 52.0000 155.0000 17.0000 +15.1667 477.0000 3653.0000 3709.0000 1683.0000 246.0000 52.0000 162.0000 18.0000 +15.2083 477.0000 3651.0000 3704.0000 1678.0000 245.0000 54.0000 172.0000 19.0000 +15.2500 477.0000 3647.0000 3716.0000 1678.0000 244.0000 55.0000 164.0000 19.0000 +15.2917 477.0000 3635.0000 3722.0000 1673.0000 248.0000 54.0000 172.0000 19.0000 +15.3333 477.0000 3630.0000 3722.0000 1669.0000 250.0000 55.0000 178.0000 19.0000 +15.3750 476.0000 3609.0000 3724.0000 1665.0000 257.0000 57.0000 193.0000 19.0000 +15.4167 475.0000 3604.0000 3706.0000 1670.0000 259.0000 57.0000 210.0000 19.0000 +15.4583 474.0000 3604.0000 3705.0000 1673.0000 258.0000 59.0000 208.0000 19.0000 +15.5000 474.0000 3599.0000 3695.0000 1679.0000 257.0000 60.0000 217.0000 19.0000 +15.5417 474.0000 3592.0000 3702.0000 1674.0000 257.0000 61.0000 221.0000 19.0000 +15.5833 473.0000 3592.0000 3712.0000 1677.0000 259.0000 62.0000 206.0000 19.0000 +15.6250 472.0000 3580.0000 3709.0000 1679.0000 265.0000 61.0000 215.0000 19.0000 +15.6667 471.0000 3600.0000 3711.0000 1680.0000 266.0000 60.0000 192.0000 20.0000 +15.7083 471.0000 3614.0000 3691.0000 1688.0000 266.0000 62.0000 188.0000 20.0000 +15.7500 471.0000 3626.0000 3694.0000 1684.0000 269.0000 62.0000 174.0000 20.0000 +15.7917 471.0000 3631.0000 3692.0000 1691.0000 272.0000 62.0000 160.0000 21.0000 +15.8333 468.0000 3615.0000 3697.0000 1690.0000 270.0000 64.0000 175.0000 21.0000 +15.8750 467.0000 3616.0000 3707.0000 1687.0000 272.0000 65.0000 165.0000 21.0000 +15.9167 467.0000 3614.0000 3693.0000 1696.0000 271.0000 69.0000 169.0000 21.0000 +15.9583 467.0000 3622.0000 3703.0000 1688.0000 273.0000 71.0000 155.0000 21.0000 +16.0000 467.0000 3622.0000 3695.0000 1695.0000 274.0000 70.0000 155.0000 22.0000 +16.0417 466.0000 3612.0000 3695.0000 1695.0000 278.0000 70.0000 162.0000 22.0000 +16.0833 464.0000 3609.0000 3693.0000 1693.0000 279.0000 71.0000 169.0000 22.0000 +16.1250 464.0000 3610.0000 3692.0000 1689.0000 280.0000 72.0000 171.0000 22.0000 +16.1667 464.0000 3610.0000 3678.0000 1688.0000 284.0000 71.0000 182.0000 23.0000 +16.2083 463.0000 3622.0000 3664.0000 1691.0000 286.0000 73.0000 178.0000 23.0000 +16.2500 463.0000 3614.0000 3667.0000 1685.0000 285.0000 77.0000 186.0000 23.0000 +16.2917 463.0000 3604.0000 3667.0000 1689.0000 285.0000 79.0000 189.0000 24.0000 +16.3333 463.0000 3598.0000 3667.0000 1684.0000 289.0000 80.0000 194.0000 25.0000 +16.3750 463.0000 3588.0000 3655.0000 1692.0000 290.0000 81.0000 206.0000 25.0000 +16.4167 463.0000 3568.0000 3666.0000 1691.0000 290.0000 82.0000 215.0000 25.0000 +16.4583 461.0000 3561.0000 3670.0000 1689.0000 295.0000 83.0000 216.0000 25.0000 +16.5000 457.0000 3547.0000 3670.0000 1691.0000 296.0000 85.0000 229.0000 25.0000 +16.5417 456.0000 3539.0000 3679.0000 1687.0000 298.0000 86.0000 230.0000 25.0000 +16.5833 455.0000 3533.0000 3679.0000 1679.0000 300.0000 86.0000 243.0000 25.0000 +16.6250 454.0000 3534.0000 3674.0000 1672.0000 307.0000 86.0000 248.0000 25.0000 +16.6667 453.0000 3556.0000 3668.0000 1678.0000 310.0000 86.0000 224.0000 25.0000 +16.7083 452.0000 3575.0000 3650.0000 1680.0000 313.0000 88.0000 217.0000 25.0000 +16.7500 451.0000 3568.0000 3675.0000 1690.0000 313.0000 88.0000 190.0000 25.0000 +16.7917 451.0000 3580.0000 3673.0000 1684.0000 320.0000 88.0000 178.0000 26.0000 +16.8333 451.0000 3574.0000 3664.0000 1687.0000 320.0000 90.0000 188.0000 26.0000 +16.8750 451.0000 3580.0000 3672.0000 1686.0000 321.0000 91.0000 173.0000 26.0000 +16.9167 450.0000 3571.0000 3672.0000 1686.0000 318.0000 94.0000 182.0000 27.0000 +16.9583 450.0000 3575.0000 3680.0000 1680.0000 320.0000 97.0000 171.0000 27.0000 +17.0000 450.0000 3562.0000 3680.0000 1682.0000 328.0000 97.0000 174.0000 27.0000 +17.0417 450.0000 3551.0000 3679.0000 1687.0000 327.0000 101.0000 178.0000 27.0000 +17.0833 449.0000 3542.0000 3672.0000 1683.0000 335.0000 101.0000 191.0000 27.0000 +17.1250 448.0000 3544.0000 3682.0000 1678.0000 334.0000 102.0000 184.0000 28.0000 +17.1667 448.0000 3539.0000 3687.0000 1670.0000 337.0000 103.0000 188.0000 28.0000 +17.2083 448.0000 3535.0000 3690.0000 1670.0000 336.0000 103.0000 189.0000 29.0000 +17.2500 447.0000 3540.0000 3676.0000 1663.0000 333.0000 108.0000 204.0000 29.0000 +17.2917 447.0000 3545.0000 3674.0000 1668.0000 336.0000 109.0000 192.0000 29.0000 +17.3333 447.0000 3547.0000 3661.0000 1671.0000 337.0000 108.0000 198.0000 31.0000 +17.3750 446.0000 3543.0000 3652.0000 1674.0000 333.0000 108.0000 213.0000 31.0000 +17.4167 445.0000 3538.0000 3646.0000 1678.0000 331.0000 110.0000 221.0000 31.0000 +17.4583 443.0000 3530.0000 3652.0000 1670.0000 335.0000 110.0000 229.0000 31.0000 +17.5000 439.0000 3522.0000 3647.0000 1674.0000 329.0000 116.0000 242.0000 31.0000 +17.5417 438.0000 3513.0000 3651.0000 1678.0000 324.0000 122.0000 243.0000 31.0000 +17.5833 436.0000 3512.0000 3655.0000 1681.0000 324.0000 122.0000 239.0000 31.0000 +17.6250 435.0000 3507.0000 3649.0000 1676.0000 329.0000 121.0000 252.0000 31.0000 +17.6667 434.0000 3514.0000 3652.0000 1682.0000 324.0000 123.0000 239.0000 32.0000 +17.7083 434.0000 3524.0000 3650.0000 1682.0000 323.0000 125.0000 229.0000 33.0000 +17.7500 434.0000 3559.0000 3637.0000 1683.0000 329.0000 126.0000 199.0000 33.0000 +17.7917 433.0000 3575.0000 3629.0000 1690.0000 329.0000 123.0000 186.0000 35.0000 +17.8333 430.0000 3583.0000 3618.0000 1689.0000 328.0000 120.0000 196.0000 36.0000 +17.8750 429.0000 3579.0000 3621.0000 1697.0000 326.0000 121.0000 190.0000 37.0000 +17.9167 429.0000 3573.0000 3627.0000 1700.0000 331.0000 117.0000 182.0000 41.0000 +17.9583 429.0000 3567.0000 3626.0000 1705.0000 333.0000 116.0000 182.0000 42.0000 +18.0000 429.0000 3568.0000 3627.0000 1703.0000 338.0000 116.0000 176.0000 43.0000 +18.0417 429.0000 3560.0000 3617.0000 1709.0000 338.0000 117.0000 186.0000 44.0000 +18.0833 429.0000 3548.0000 3618.0000 1712.0000 341.0000 117.0000 191.0000 44.0000 +18.1250 429.0000 3550.0000 3623.0000 1711.0000 345.0000 117.0000 181.0000 44.0000 +18.1667 429.0000 3546.0000 3618.0000 1721.0000 342.0000 117.0000 183.0000 44.0000 +18.2083 429.0000 3547.0000 3612.0000 1714.0000 345.0000 116.0000 192.0000 45.0000 +18.2500 429.0000 3535.0000 3619.0000 1713.0000 345.0000 119.0000 194.0000 46.0000 +18.2917 426.0000 3526.0000 3625.0000 1710.0000 344.0000 120.0000 203.0000 46.0000 +18.3333 426.0000 3530.0000 3615.0000 1714.0000 349.0000 118.0000 202.0000 46.0000 +18.3750 423.0000 3515.0000 3615.0000 1722.0000 353.0000 118.0000 208.0000 46.0000 +18.4167 422.0000 3504.0000 3619.0000 1716.0000 358.0000 118.0000 216.0000 47.0000 +18.4583 422.0000 3505.0000 3601.0000 1731.0000 359.0000 118.0000 216.0000 48.0000 +18.5000 418.0000 3497.0000 3595.0000 1740.0000 354.0000 121.0000 227.0000 48.0000 +18.5417 418.0000 3488.0000 3604.0000 1742.0000 356.0000 121.0000 222.0000 49.0000 +18.5833 418.0000 3490.0000 3580.0000 1754.0000 352.0000 123.0000 232.0000 51.0000 +18.6250 417.0000 3470.0000 3597.0000 1749.0000 354.0000 124.0000 238.0000 51.0000 +18.6667 416.0000 3483.0000 3588.0000 1747.0000 357.0000 124.0000 233.0000 52.0000 +18.7083 415.0000 3483.0000 3592.0000 1752.0000 354.0000 126.0000 225.0000 53.0000 +18.7500 415.0000 3502.0000 3577.0000 1758.0000 355.0000 128.0000 212.0000 53.0000 +18.7917 414.0000 3511.0000 3582.0000 1760.0000 356.0000 127.0000 195.0000 55.0000 +18.8333 411.0000 3503.0000 3578.0000 1771.0000 358.0000 125.0000 197.0000 57.0000 +18.8750 409.0000 3498.0000 3574.0000 1778.0000 356.0000 125.0000 202.0000 58.0000 +18.9167 409.0000 3497.0000 3573.0000 1774.0000 357.0000 129.0000 203.0000 58.0000 +18.9583 409.0000 3501.0000 3573.0000 1775.0000 357.0000 130.0000 196.0000 59.0000 +19.0000 409.0000 3490.0000 3573.0000 1782.0000 359.0000 131.0000 197.0000 59.0000 +19.0417 409.0000 3491.0000 3566.0000 1784.0000 360.0000 132.0000 199.0000 59.0000 +19.0833 409.0000 3484.0000 3569.0000 1776.0000 363.0000 134.0000 206.0000 59.0000 +19.1250 407.0000 3489.0000 3559.0000 1786.0000 366.0000 134.0000 200.0000 59.0000 +19.1667 407.0000 3470.0000 3551.0000 1788.0000 370.0000 133.0000 220.0000 61.0000 +19.2083 407.0000 3485.0000 3549.0000 1779.0000 373.0000 132.0000 214.0000 61.0000 +19.2500 406.0000 3486.0000 3545.0000 1789.0000 377.0000 134.0000 202.0000 61.0000 +19.2917 405.0000 3478.0000 3549.0000 1785.0000 382.0000 137.0000 203.0000 61.0000 +19.3333 405.0000 3468.0000 3539.0000 1790.0000 382.0000 136.0000 219.0000 61.0000 +19.3750 404.0000 3460.0000 3521.0000 1794.0000 379.0000 135.0000 244.0000 63.0000 +19.4167 404.0000 3463.0000 3524.0000 1795.0000 380.0000 135.0000 235.0000 64.0000 +19.4583 402.0000 3461.0000 3516.0000 1795.0000 384.0000 136.0000 242.0000 64.0000 +19.5000 400.0000 3445.0000 3529.0000 1782.0000 389.0000 136.0000 254.0000 65.0000 +19.5417 400.0000 3430.0000 3523.0000 1780.0000 393.0000 140.0000 268.0000 66.0000 +19.5833 398.0000 3426.0000 3529.0000 1779.0000 396.0000 140.0000 265.0000 67.0000 +19.6250 396.0000 3413.0000 3534.0000 1784.0000 397.0000 141.0000 268.0000 67.0000 +19.6667 395.0000 3426.0000 3531.0000 1782.0000 400.0000 140.0000 258.0000 68.0000 +19.7083 395.0000 3437.0000 3534.0000 1773.0000 401.0000 145.0000 246.0000 69.0000 +19.7500 395.0000 3455.0000 3527.0000 1777.0000 401.0000 148.0000 228.0000 69.0000 +19.7917 393.0000 3482.0000 3521.0000 1771.0000 402.0000 147.0000 211.0000 73.0000 +19.8333 392.0000 3479.0000 3531.0000 1765.0000 402.0000 148.0000 210.0000 73.0000 +19.8750 392.0000 3485.0000 3532.0000 1758.0000 401.0000 152.0000 206.0000 74.0000 +19.9167 392.0000 3486.0000 3533.0000 1760.0000 401.0000 153.0000 201.0000 74.0000 +19.9583 391.0000 3487.0000 3525.0000 1764.0000 403.0000 153.0000 202.0000 75.0000 +20.0000 390.0000 3493.0000 3526.0000 1758.0000 408.0000 152.0000 198.0000 75.0000 +20.0417 390.0000 3485.0000 3526.0000 1765.0000 409.0000 158.0000 192.0000 75.0000 +20.0833 389.0000 3466.0000 3535.0000 1763.0000 408.0000 163.0000 201.0000 75.0000 +20.1250 388.0000 3455.0000 3538.0000 1763.0000 408.0000 162.0000 210.0000 76.0000 +20.1667 388.0000 3448.0000 3530.0000 1760.0000 410.0000 163.0000 224.0000 77.0000 +20.2083 387.0000 3446.0000 3522.0000 1765.0000 415.0000 163.0000 224.0000 78.0000 +20.2500 387.0000 3431.0000 3530.0000 1772.0000 419.0000 165.0000 218.0000 78.0000 +20.2917 386.0000 3419.0000 3533.0000 1770.0000 420.0000 164.0000 229.0000 79.0000 +20.3333 386.0000 3405.0000 3532.0000 1770.0000 421.0000 166.0000 239.0000 81.0000 +20.3750 386.0000 3396.0000 3524.0000 1765.0000 422.0000 165.0000 260.0000 82.0000 +20.4167 383.0000 3398.0000 3520.0000 1765.0000 421.0000 165.0000 265.0000 83.0000 +20.4583 379.0000 3401.0000 3511.0000 1763.0000 425.0000 163.0000 274.0000 84.0000 +20.5000 378.0000 3390.0000 3514.0000 1766.0000 425.0000 162.0000 281.0000 84.0000 +20.5417 377.0000 3395.0000 3516.0000 1764.0000 426.0000 163.0000 275.0000 84.0000 +20.5833 375.0000 3399.0000 3521.0000 1757.0000 423.0000 164.0000 276.0000 85.0000 +20.6250 375.0000 3397.0000 3523.0000 1759.0000 418.0000 164.0000 278.0000 86.0000 +20.6667 374.0000 3405.0000 3532.0000 1750.0000 411.0000 168.0000 274.0000 86.0000 +20.7083 374.0000 3422.0000 3533.0000 1745.0000 411.0000 173.0000 256.0000 86.0000 +20.7500 372.0000 3431.0000 3534.0000 1741.0000 415.0000 173.0000 247.0000 87.0000 +20.7917 372.0000 3458.0000 3532.0000 1740.0000 410.0000 175.0000 225.0000 88.0000 +20.8333 371.0000 3459.0000 3530.0000 1747.0000 413.0000 173.0000 217.0000 90.0000 +20.8750 371.0000 3461.0000 3534.0000 1747.0000 407.0000 175.0000 215.0000 90.0000 +20.9167 371.0000 3458.0000 3532.0000 1746.0000 406.0000 180.0000 216.0000 91.0000 +20.9583 370.0000 3451.0000 3531.0000 1746.0000 408.0000 181.0000 222.0000 91.0000 +21.0000 370.0000 3447.0000 3538.0000 1741.0000 413.0000 184.0000 215.0000 92.0000 +21.0417 369.0000 3436.0000 3541.0000 1742.0000 418.0000 183.0000 217.0000 94.0000 +21.0833 369.0000 3426.0000 3539.0000 1745.0000 418.0000 185.0000 223.0000 95.0000 +21.1250 368.0000 3431.0000 3536.0000 1739.0000 420.0000 187.0000 223.0000 96.0000 +21.1667 368.0000 3422.0000 3550.0000 1736.0000 425.0000 186.0000 216.0000 97.0000 +21.2083 368.0000 3400.0000 3555.0000 1736.0000 431.0000 186.0000 227.0000 97.0000 +21.2500 368.0000 3395.0000 3552.0000 1735.0000 431.0000 185.0000 237.0000 97.0000 +21.2917 368.0000 3402.0000 3549.0000 1724.0000 440.0000 185.0000 234.0000 98.0000 +21.3333 367.0000 3394.0000 3540.0000 1722.0000 442.0000 185.0000 250.0000 100.0000 +21.3750 367.0000 3393.0000 3520.0000 1721.0000 448.0000 187.0000 263.0000 101.0000 +21.4167 367.0000 3391.0000 3522.0000 1723.0000 447.0000 189.0000 260.0000 101.0000 +21.4583 366.0000 3385.0000 3525.0000 1724.0000 450.0000 189.0000 260.0000 101.0000 +21.5000 363.0000 3371.0000 3521.0000 1737.0000 449.0000 190.0000 266.0000 103.0000 +21.5417 363.0000 3373.0000 3520.0000 1733.0000 452.0000 191.0000 265.0000 103.0000 +21.5833 363.0000 3369.0000 3512.0000 1734.0000 455.0000 191.0000 272.0000 104.0000 +21.6250 362.0000 3357.0000 3514.0000 1738.0000 453.0000 191.0000 281.0000 104.0000 +21.6667 362.0000 3363.0000 3522.0000 1732.0000 453.0000 193.0000 271.0000 104.0000 +21.7083 360.0000 3367.0000 3515.0000 1748.0000 456.0000 194.0000 256.0000 104.0000 +21.7500 360.0000 3396.0000 3495.0000 1767.0000 453.0000 197.0000 228.0000 104.0000 +21.7917 360.0000 3390.0000 3507.0000 1756.0000 456.0000 196.0000 230.0000 105.0000 +21.8333 360.0000 3386.0000 3508.0000 1754.0000 459.0000 193.0000 232.0000 108.0000 +21.8750 360.0000 3392.0000 3509.0000 1749.0000 457.0000 193.0000 231.0000 109.0000 +21.9167 359.0000 3390.0000 3498.0000 1748.0000 462.0000 193.0000 239.0000 111.0000 +21.9583 359.0000 3406.0000 3489.0000 1743.0000 467.0000 194.0000 231.0000 111.0000 +22.0000 358.0000 3411.0000 3493.0000 1738.0000 470.0000 196.0000 223.0000 111.0000 +22.0417 358.0000 3411.0000 3485.0000 1742.0000 472.0000 192.0000 228.0000 112.0000 +22.0833 357.0000 3393.0000 3504.0000 1733.0000 474.0000 192.0000 235.0000 112.0000 +22.1250 357.0000 3392.0000 3489.0000 1738.0000 476.0000 190.0000 243.0000 115.0000 +22.1667 357.0000 3397.0000 3481.0000 1747.0000 479.0000 192.0000 231.0000 116.0000 +22.2083 357.0000 3388.0000 3482.0000 1751.0000 476.0000 197.0000 233.0000 116.0000 +22.2500 357.0000 3378.0000 3480.0000 1749.0000 477.0000 196.0000 247.0000 116.0000 +22.2917 356.0000 3375.0000 3482.0000 1749.0000 480.0000 194.0000 247.0000 117.0000 +22.3333 356.0000 3377.0000 3479.0000 1747.0000 483.0000 196.0000 243.0000 119.0000 +22.3750 356.0000 3376.0000 3459.0000 1747.0000 482.0000 195.0000 265.0000 120.0000 +22.4167 356.0000 3377.0000 3459.0000 1743.0000 488.0000 195.0000 262.0000 120.0000 +22.4583 354.0000 3380.0000 3461.0000 1743.0000 486.0000 195.0000 260.0000 121.0000 +22.5000 353.0000 3375.0000 3459.0000 1748.0000 481.0000 199.0000 263.0000 122.0000 +22.5417 353.0000 3367.0000 3461.0000 1742.0000 483.0000 199.0000 271.0000 124.0000 +22.5833 352.0000 3364.0000 3455.0000 1751.0000 482.0000 201.0000 271.0000 124.0000 +22.6250 352.0000 3363.0000 3458.0000 1742.0000 486.0000 200.0000 274.0000 125.0000 +22.6667 351.0000 3363.0000 3456.0000 1744.0000 494.0000 199.0000 268.0000 125.0000 +22.7083 349.0000 3376.0000 3454.0000 1745.0000 496.0000 200.0000 254.0000 126.0000 +22.7500 348.0000 3383.0000 3462.0000 1751.0000 497.0000 200.0000 232.0000 127.0000 +22.7917 347.0000 3390.0000 3458.0000 1746.0000 499.0000 201.0000 231.0000 128.0000 +22.8333 346.0000 3401.0000 3452.0000 1747.0000 501.0000 200.0000 223.0000 130.0000 +22.8750 346.0000 3401.0000 3447.0000 1744.0000 501.0000 203.0000 228.0000 130.0000 +22.9167 346.0000 3406.0000 3453.0000 1738.0000 509.0000 202.0000 213.0000 133.0000 +22.9583 345.0000 3407.0000 3445.0000 1745.0000 507.0000 199.0000 217.0000 135.0000 +23.0000 345.0000 3409.0000 3432.0000 1758.0000 503.0000 200.0000 218.0000 135.0000 +23.0417 344.0000 3413.0000 3420.0000 1763.0000 509.0000 201.0000 214.0000 136.0000 +23.0833 344.0000 3406.0000 3411.0000 1763.0000 510.0000 201.0000 226.0000 139.0000 +23.1250 344.0000 3397.0000 3425.0000 1757.0000 512.0000 201.0000 224.0000 140.0000 +23.1667 344.0000 3386.0000 3429.0000 1754.0000 518.0000 198.0000 230.0000 141.0000 +23.2083 344.0000 3380.0000 3426.0000 1752.0000 520.0000 198.0000 238.0000 142.0000 +23.2500 344.0000 3387.0000 3421.0000 1752.0000 520.0000 197.0000 236.0000 143.0000 +23.2917 344.0000 3379.0000 3429.0000 1754.0000 516.0000 198.0000 236.0000 144.0000 +23.3333 344.0000 3370.0000 3421.0000 1762.0000 511.0000 199.0000 249.0000 144.0000 +23.3750 343.0000 3369.0000 3403.0000 1771.0000 508.0000 201.0000 261.0000 144.0000 +23.4167 343.0000 3351.0000 3397.0000 1767.0000 510.0000 202.0000 285.0000 145.0000 +23.4583 340.0000 3360.0000 3392.0000 1764.0000 517.0000 201.0000 281.0000 145.0000 +23.5000 339.0000 3361.0000 3384.0000 1746.0000 527.0000 201.0000 296.0000 146.0000 +23.5417 338.0000 3361.0000 3388.0000 1743.0000 530.0000 198.0000 294.0000 148.0000 +23.5833 337.0000 3363.0000 3377.0000 1753.0000 533.0000 196.0000 292.0000 149.0000 +23.6250 336.0000 3332.0000 3400.0000 1745.0000 537.0000 196.0000 304.0000 150.0000 +23.6667 336.0000 3346.0000 3404.0000 1752.0000 535.0000 195.0000 281.0000 151.0000 +23.7083 335.0000 3353.0000 3413.0000 1741.0000 543.0000 198.0000 266.0000 151.0000 +23.7500 333.0000 3380.0000 3402.0000 1744.0000 549.0000 195.0000 243.0000 154.0000 +23.7917 333.0000 3398.0000 3404.0000 1742.0000 554.0000 197.0000 217.0000 155.0000 +23.8333 333.0000 3378.0000 3409.0000 1740.0000 556.0000 197.0000 231.0000 156.0000 +23.8750 333.0000 3378.0000 3416.0000 1741.0000 554.0000 201.0000 221.0000 156.0000 +23.9167 333.0000 3382.0000 3410.0000 1741.0000 561.0000 202.0000 215.0000 156.0000 +23.9583 331.0000 3386.0000 3403.0000 1748.0000 558.0000 202.0000 215.0000 157.0000 +24.0000 331.0000 3388.0000 3406.0000 1744.0000 556.0000 202.0000 214.0000 159.0000 +24.0417 330.0000 3380.0000 3402.0000 1752.0000 548.0000 202.0000 224.0000 162.0000 +24.0833 330.0000 3386.0000 3407.0000 1749.0000 551.0000 202.0000 212.0000 163.0000 +24.1250 330.0000 3369.0000 3408.0000 1750.0000 545.0000 205.0000 229.0000 164.0000 +24.1667 330.0000 3365.0000 3409.0000 1750.0000 548.0000 205.0000 228.0000 165.0000 +24.2083 330.0000 3359.0000 3398.0000 1756.0000 547.0000 205.0000 240.0000 165.0000 +24.2500 328.0000 3359.0000 3395.0000 1759.0000 552.0000 206.0000 235.0000 166.0000 +24.2917 327.0000 3346.0000 3400.0000 1754.0000 551.0000 206.0000 248.0000 168.0000 +24.3333 327.0000 3342.0000 3409.0000 1756.0000 547.0000 205.0000 246.0000 168.0000 +24.3750 325.0000 3333.0000 3417.0000 1753.0000 547.0000 204.0000 253.0000 168.0000 +24.4167 324.0000 3326.0000 3402.0000 1758.0000 547.0000 205.0000 270.0000 168.0000 +24.4583 321.0000 3327.0000 3390.0000 1753.0000 553.0000 201.0000 284.0000 171.0000 +24.5000 320.0000 3322.0000 3393.0000 1756.0000 549.0000 207.0000 282.0000 171.0000 +24.5417 320.0000 3318.0000 3393.0000 1762.0000 550.0000 209.0000 277.0000 171.0000 +24.5833 320.0000 3311.0000 3402.0000 1762.0000 551.0000 210.0000 272.0000 172.0000 +24.6250 320.0000 3301.0000 3398.0000 1772.0000 546.0000 211.0000 279.0000 173.0000 +24.6667 320.0000 3309.0000 3394.0000 1772.0000 543.0000 212.0000 276.0000 174.0000 +24.7083 320.0000 3323.0000 3387.0000 1778.0000 542.0000 216.0000 259.0000 175.0000 +24.7500 319.0000 3356.0000 3380.0000 1780.0000 548.0000 216.0000 225.0000 176.0000 +24.7917 319.0000 3358.0000 3385.0000 1785.0000 551.0000 217.0000 209.0000 176.0000 +24.8333 319.0000 3348.0000 3376.0000 1784.0000 547.0000 219.0000 228.0000 179.0000 +24.8750 318.0000 3343.0000 3376.0000 1785.0000 549.0000 222.0000 227.0000 180.0000 +24.9167 318.0000 3336.0000 3381.0000 1790.0000 550.0000 224.0000 220.0000 181.0000 +24.9583 318.0000 3331.0000 3394.0000 1788.0000 547.0000 225.0000 215.0000 182.0000 +25.0000 318.0000 3331.0000 3389.0000 1790.0000 547.0000 226.0000 216.0000 183.0000 +25.0417 318.0000 3330.0000 3384.0000 1783.0000 554.0000 224.0000 223.0000 184.0000 +25.0833 318.0000 3324.0000 3378.0000 1783.0000 557.0000 226.0000 229.0000 185.0000 +25.1250 318.0000 3320.0000 3378.0000 1780.0000 557.0000 226.0000 234.0000 187.0000 +25.1667 318.0000 3323.0000 3366.0000 1784.0000 561.0000 226.0000 234.0000 188.0000 +25.2083 317.0000 3315.0000 3366.0000 1779.0000 565.0000 225.0000 245.0000 188.0000 +25.2500 317.0000 3310.0000 3375.0000 1777.0000 569.0000 223.0000 241.0000 188.0000 +25.2917 317.0000 3299.0000 3377.0000 1780.0000 567.0000 222.0000 248.0000 190.0000 +25.3333 315.0000 3300.0000 3378.0000 1779.0000 567.0000 218.0000 252.0000 191.0000 +25.3750 314.0000 3305.0000 3361.0000 1781.0000 567.0000 218.0000 262.0000 192.0000 +25.4167 314.0000 3304.0000 3368.0000 1770.0000 570.0000 222.0000 260.0000 192.0000 +25.4583 312.0000 3300.0000 3362.0000 1772.0000 569.0000 223.0000 269.0000 193.0000 +25.5000 307.0000 3306.0000 3352.0000 1766.0000 575.0000 223.0000 276.0000 195.0000 +25.5417 307.0000 3312.0000 3355.0000 1760.0000 578.0000 221.0000 272.0000 195.0000 +25.5833 306.0000 3322.0000 3338.0000 1760.0000 578.0000 228.0000 273.0000 195.0000 +25.6250 306.0000 3309.0000 3346.0000 1765.0000 579.0000 228.0000 270.0000 197.0000 +25.6667 306.0000 3317.0000 3332.0000 1767.0000 587.0000 228.0000 264.0000 199.0000 +25.7083 306.0000 3326.0000 3332.0000 1756.0000 591.0000 229.0000 261.0000 199.0000 +25.7500 306.0000 3345.0000 3324.0000 1758.0000 591.0000 230.0000 247.0000 199.0000 +25.7917 306.0000 3358.0000 3319.0000 1760.0000 591.0000 235.0000 231.0000 200.0000 +25.8333 306.0000 3348.0000 3327.0000 1751.0000 598.0000 234.0000 235.0000 201.0000 +25.8750 306.0000 3360.0000 3314.0000 1752.0000 601.0000 234.0000 231.0000 202.0000 +25.9167 306.0000 3359.0000 3311.0000 1746.0000 605.0000 230.0000 241.0000 202.0000 +25.9583 306.0000 3375.0000 3296.0000 1754.0000 608.0000 229.0000 229.0000 203.0000 +26.0000 306.0000 3368.0000 3302.0000 1750.0000 611.0000 228.0000 231.0000 204.0000 +26.0417 306.0000 3361.0000 3297.0000 1758.0000 605.0000 232.0000 236.0000 205.0000 +26.0833 306.0000 3361.0000 3295.0000 1763.0000 605.0000 231.0000 232.0000 207.0000 +26.1250 306.0000 3359.0000 3290.0000 1767.0000 606.0000 229.0000 232.0000 211.0000 +26.1667 306.0000 3361.0000 3281.0000 1769.0000 604.0000 230.0000 237.0000 212.0000 +26.2083 306.0000 3351.0000 3281.0000 1775.0000 607.0000 228.0000 237.0000 215.0000 +26.2500 306.0000 3338.0000 3287.0000 1775.0000 604.0000 227.0000 247.0000 216.0000 +26.2917 306.0000 3332.0000 3290.0000 1770.0000 612.0000 230.0000 244.0000 216.0000 +26.3333 306.0000 3336.0000 3271.0000 1766.0000 609.0000 234.0000 261.0000 217.0000 +26.3750 306.0000 3325.0000 3273.0000 1768.0000 609.0000 234.0000 266.0000 219.0000 +26.4167 306.0000 3307.0000 3284.0000 1767.0000 602.0000 237.0000 278.0000 219.0000 +26.4583 305.0000 3299.0000 3275.0000 1782.0000 602.0000 238.0000 278.0000 221.0000 +26.5000 304.0000 3285.0000 3266.0000 1777.0000 597.0000 245.0000 305.0000 221.0000 +26.5417 304.0000 3290.0000 3260.0000 1774.0000 597.0000 249.0000 304.0000 222.0000 +26.5833 304.0000 3290.0000 3263.0000 1776.0000 597.0000 248.0000 298.0000 224.0000 +26.6250 304.0000 3286.0000 3262.0000 1779.0000 601.0000 249.0000 294.0000 225.0000 +26.6667 304.0000 3306.0000 3248.0000 1788.0000 598.0000 255.0000 276.0000 225.0000 +26.7083 304.0000 3311.0000 3243.0000 1786.0000 596.0000 256.0000 278.0000 226.0000 +26.7500 302.0000 3336.0000 3252.0000 1774.0000 594.0000 258.0000 256.0000 228.0000 +26.7917 301.0000 3335.0000 3267.0000 1767.0000 592.0000 260.0000 248.0000 230.0000 +26.8333 301.0000 3337.0000 3261.0000 1773.0000 593.0000 258.0000 244.0000 233.0000 +26.8750 301.0000 3335.0000 3257.0000 1768.0000 598.0000 257.0000 250.0000 234.0000 +26.9167 301.0000 3340.0000 3252.0000 1777.0000 598.0000 258.0000 239.0000 235.0000 +26.9583 301.0000 3341.0000 3255.0000 1783.0000 597.0000 257.0000 230.0000 236.0000 +27.0000 301.0000 3328.0000 3265.0000 1779.0000 605.0000 254.0000 231.0000 237.0000 +27.0417 300.0000 3317.0000 3280.0000 1774.0000 601.0000 254.0000 234.0000 240.0000 +27.0833 300.0000 3308.0000 3281.0000 1780.0000 594.0000 257.0000 240.0000 240.0000 +27.1250 299.0000 3309.0000 3289.0000 1778.0000 593.0000 257.0000 234.0000 241.0000 +27.1667 299.0000 3297.0000 3294.0000 1772.0000 595.0000 255.0000 244.0000 244.0000 +27.2083 299.0000 3298.0000 3284.0000 1775.0000 598.0000 257.0000 242.0000 247.0000 +27.2500 298.0000 3291.0000 3288.0000 1771.0000 600.0000 257.0000 246.0000 249.0000 +27.2917 297.0000 3288.0000 3292.0000 1759.0000 602.0000 259.0000 254.0000 249.0000 +27.3333 295.0000 3277.0000 3297.0000 1755.0000 602.0000 261.0000 264.0000 249.0000 +27.3750 295.0000 3269.0000 3294.0000 1761.0000 598.0000 261.0000 270.0000 252.0000 +27.4167 294.0000 3265.0000 3310.0000 1753.0000 604.0000 261.0000 260.0000 253.0000 +27.4583 294.0000 3252.0000 3308.0000 1752.0000 608.0000 259.0000 273.0000 254.0000 +27.5000 292.0000 3247.0000 3311.0000 1754.0000 603.0000 263.0000 276.0000 254.0000 +27.5417 292.0000 3239.0000 3314.0000 1756.0000 607.0000 260.0000 275.0000 257.0000 +27.5833 292.0000 3232.0000 3310.0000 1765.0000 602.0000 258.0000 282.0000 259.0000 +27.6250 292.0000 3219.0000 3321.0000 1762.0000 604.0000 257.0000 284.0000 261.0000 +27.6667 292.0000 3240.0000 3314.0000 1765.0000 603.0000 257.0000 266.0000 263.0000 +27.7083 292.0000 3243.0000 3322.0000 1758.0000 607.0000 253.0000 259.0000 266.0000 +27.7500 292.0000 3253.0000 3318.0000 1754.0000 612.0000 255.0000 250.0000 266.0000 +27.7917 292.0000 3252.0000 3311.0000 1752.0000 616.0000 256.0000 253.0000 268.0000 +27.8333 291.0000 3257.0000 3310.0000 1759.0000 617.0000 255.0000 242.0000 269.0000 +27.8750 291.0000 3255.0000 3301.0000 1763.0000 621.0000 255.0000 244.0000 270.0000 +27.9167 290.0000 3246.0000 3300.0000 1770.0000 619.0000 259.0000 246.0000 270.0000 +27.9583 290.0000 3244.0000 3301.0000 1770.0000 616.0000 264.0000 244.0000 271.0000 +28.0000 290.0000 3245.0000 3282.0000 1785.0000 618.0000 263.0000 244.0000 273.0000 +28.0417 290.0000 3240.0000 3281.0000 1786.0000 619.0000 262.0000 245.0000 277.0000 +28.0833 289.0000 3233.0000 3279.0000 1782.0000 619.0000 263.0000 257.0000 278.0000 +28.1250 289.0000 3234.0000 3273.0000 1783.0000 619.0000 264.0000 260.0000 278.0000 +28.1667 289.0000 3234.0000 3270.0000 1779.0000 622.0000 264.0000 263.0000 279.0000 +28.2083 289.0000 3230.0000 3275.0000 1785.0000 621.0000 264.0000 255.0000 281.0000 +28.2500 289.0000 3220.0000 3282.0000 1776.0000 627.0000 262.0000 260.0000 284.0000 +28.2917 288.0000 3222.0000 3275.0000 1775.0000 624.0000 264.0000 267.0000 285.0000 +28.3333 288.0000 3218.0000 3281.0000 1770.0000 625.0000 265.0000 266.0000 287.0000 +28.3750 288.0000 3207.0000 3272.0000 1777.0000 626.0000 265.0000 276.0000 289.0000 +28.4167 288.0000 3190.0000 3283.0000 1775.0000 619.0000 267.0000 288.0000 290.0000 +28.4583 288.0000 3188.0000 3286.0000 1770.0000 623.0000 272.0000 282.0000 291.0000 +28.5000 287.0000 3173.0000 3299.0000 1772.0000 627.0000 270.0000 280.0000 292.0000 +28.5417 287.0000 3173.0000 3300.0000 1771.0000 630.0000 270.0000 276.0000 293.0000 +28.5833 287.0000 3167.0000 3305.0000 1781.0000 625.0000 271.0000 270.0000 294.0000 +28.6250 287.0000 3151.0000 3301.0000 1781.0000 629.0000 272.0000 284.0000 295.0000 +28.6667 287.0000 3161.0000 3298.0000 1782.0000 630.0000 272.0000 273.0000 297.0000 +28.7083 287.0000 3173.0000 3286.0000 1786.0000 634.0000 274.0000 261.0000 299.0000 +28.7500 287.0000 3194.0000 3268.0000 1790.0000 634.0000 277.0000 250.0000 300.0000 +28.7917 287.0000 3190.0000 3277.0000 1792.0000 635.0000 274.0000 241.0000 304.0000 +28.8333 287.0000 3182.0000 3285.0000 1788.0000 637.0000 274.0000 243.0000 304.0000 +28.8750 287.0000 3186.0000 3282.0000 1785.0000 639.0000 276.0000 239.0000 306.0000 +28.9167 287.0000 3188.0000 3276.0000 1787.0000 644.0000 276.0000 235.0000 307.0000 +28.9583 287.0000 3192.0000 3275.0000 1785.0000 646.0000 276.0000 229.0000 310.0000 +29.0000 287.0000 3186.0000 3276.0000 1786.0000 649.0000 277.0000 229.0000 310.0000 +29.0417 286.0000 3186.0000 3274.0000 1781.0000 652.0000 274.0000 234.0000 313.0000 +29.0833 286.0000 3182.0000 3273.0000 1775.0000 658.0000 276.0000 237.0000 313.0000 +29.1250 286.0000 3169.0000 3275.0000 1775.0000 661.0000 274.0000 247.0000 313.0000 +29.1667 286.0000 3164.0000 3285.0000 1770.0000 660.0000 275.0000 246.0000 314.0000 +29.2083 285.0000 3155.0000 3298.0000 1764.0000 663.0000 272.0000 247.0000 316.0000 +29.2500 285.0000 3152.0000 3291.0000 1753.0000 673.0000 274.0000 256.0000 316.0000 +29.2917 285.0000 3154.0000 3292.0000 1759.0000 670.0000 276.0000 247.0000 317.0000 +29.3333 285.0000 3134.0000 3291.0000 1758.0000 671.0000 278.0000 265.0000 318.0000 +29.3750 284.0000 3123.0000 3276.0000 1760.0000 676.0000 276.0000 286.0000 319.0000 +29.4167 284.0000 3120.0000 3264.0000 1763.0000 668.0000 283.0000 299.0000 319.0000 +29.4583 283.0000 3125.0000 3265.0000 1753.0000 668.0000 282.0000 302.0000 322.0000 +29.5000 282.0000 3120.0000 3270.0000 1753.0000 665.0000 283.0000 305.0000 322.0000 +29.5417 282.0000 3116.0000 3270.0000 1752.0000 662.0000 285.0000 311.0000 322.0000 +29.5833 282.0000 3107.0000 3277.0000 1753.0000 662.0000 282.0000 313.0000 324.0000 +29.6250 282.0000 3107.0000 3276.0000 1756.0000 660.0000 285.0000 309.0000 325.0000 +29.6667 282.0000 3129.0000 3261.0000 1760.0000 665.0000 286.0000 291.0000 326.0000 +29.7083 280.0000 3135.0000 3261.0000 1764.0000 666.0000 286.0000 281.0000 327.0000 +29.7500 278.0000 3147.0000 3265.0000 1756.0000 664.0000 284.0000 276.0000 330.0000 +29.7917 277.0000 3169.0000 3266.0000 1745.0000 670.0000 283.0000 258.0000 332.0000 +29.8333 277.0000 3169.0000 3266.0000 1747.0000 666.0000 280.0000 261.0000 334.0000 +29.8750 277.0000 3182.0000 3255.0000 1758.0000 665.0000 280.0000 248.0000 335.0000 +29.9167 277.0000 3189.0000 3253.0000 1763.0000 663.0000 279.0000 238.0000 338.0000 +29.9583 277.0000 3190.0000 3245.0000 1770.0000 665.0000 279.0000 233.0000 341.0000 +30.0000 277.0000 3196.0000 3231.0000 1765.0000 661.0000 280.0000 247.0000 343.0000 +30.0417 277.0000 3216.0000 3197.0000 1772.0000 662.0000 281.0000 250.0000 345.0000 +30.0833 277.0000 3235.0000 3172.0000 1783.0000 660.0000 281.0000 245.0000 347.0000 +30.1250 277.0000 3232.0000 3170.0000 1797.0000 654.0000 285.0000 238.0000 347.0000 +30.1667 277.0000 3230.0000 3167.0000 1788.0000 657.0000 286.0000 248.0000 347.0000 +30.2083 276.0000 3227.0000 3160.0000 1786.0000 652.0000 286.0000 266.0000 347.0000 +30.2500 275.0000 3238.0000 3152.0000 1786.0000 655.0000 285.0000 261.0000 348.0000 +30.2917 275.0000 3231.0000 3150.0000 1787.0000 653.0000 283.0000 271.0000 350.0000 +30.3333 275.0000 3228.0000 3145.0000 1786.0000 655.0000 283.0000 276.0000 352.0000 +30.3750 275.0000 3222.0000 3139.0000 1783.0000 660.0000 281.0000 287.0000 353.0000 +30.4167 274.0000 3221.0000 3131.0000 1787.0000 656.0000 283.0000 294.0000 354.0000 +30.4583 274.0000 3208.0000 3147.0000 1791.0000 656.0000 283.0000 286.0000 355.0000 +30.5000 273.0000 3199.0000 3137.0000 1799.0000 655.0000 288.0000 294.0000 355.0000 +30.5417 272.0000 3196.0000 3133.0000 1798.0000 663.0000 287.0000 295.0000 356.0000 +30.5833 270.0000 3186.0000 3133.0000 1799.0000 660.0000 293.0000 303.0000 356.0000 +30.6250 269.0000 3180.0000 3135.0000 1791.0000 666.0000 294.0000 309.0000 356.0000 +30.6667 268.0000 3190.0000 3130.0000 1783.0000 678.0000 290.0000 301.0000 360.0000 +30.7083 268.0000 3203.0000 3124.0000 1785.0000 681.0000 289.0000 289.0000 361.0000 +30.7500 268.0000 3215.0000 3134.0000 1784.0000 685.0000 292.0000 261.0000 361.0000 +30.7917 268.0000 3223.0000 3131.0000 1781.0000 692.0000 290.0000 252.0000 363.0000 +30.8333 268.0000 3225.0000 3104.0000 1782.0000 697.0000 290.0000 271.0000 363.0000 +30.8750 268.0000 3233.0000 3113.0000 1786.0000 696.0000 288.0000 250.0000 366.0000 +30.9167 268.0000 3223.0000 3122.0000 1781.0000 695.0000 290.0000 253.0000 368.0000 +30.9583 268.0000 3228.0000 3103.0000 1791.0000 696.0000 292.0000 254.0000 368.0000 +31.0000 268.0000 3230.0000 3098.0000 1792.0000 696.0000 293.0000 255.0000 368.0000 +31.0417 268.0000 3212.0000 3105.0000 1795.0000 696.0000 297.0000 259.0000 368.0000 +31.0833 268.0000 3206.0000 3113.0000 1784.0000 703.0000 298.0000 259.0000 369.0000 +31.1250 268.0000 3208.0000 3111.0000 1784.0000 704.0000 301.0000 255.0000 369.0000 +31.1667 268.0000 3201.0000 3107.0000 1786.0000 704.0000 300.0000 262.0000 372.0000 +31.2083 268.0000 3197.0000 3112.0000 1781.0000 701.0000 300.0000 267.0000 374.0000 +31.2500 268.0000 3181.0000 3110.0000 1780.0000 703.0000 301.0000 281.0000 376.0000 +31.2917 268.0000 3181.0000 3113.0000 1782.0000 707.0000 302.0000 269.0000 378.0000 +31.3333 268.0000 3162.0000 3117.0000 1791.0000 699.0000 304.0000 278.0000 381.0000 +31.3750 268.0000 3154.0000 3123.0000 1796.0000 695.0000 305.0000 276.0000 383.0000 +31.4167 268.0000 3147.0000 3118.0000 1808.0000 693.0000 306.0000 275.0000 385.0000 +31.4583 268.0000 3133.0000 3120.0000 1813.0000 690.0000 307.0000 282.0000 387.0000 +31.5000 268.0000 3109.0000 3125.0000 1808.0000 690.0000 305.0000 304.0000 391.0000 +31.5417 268.0000 3115.0000 3129.0000 1800.0000 690.0000 304.0000 302.0000 392.0000 +31.5833 267.0000 3127.0000 3108.0000 1802.0000 689.0000 302.0000 311.0000 394.0000 +31.6250 267.0000 3135.0000 3101.0000 1807.0000 679.0000 304.0000 313.0000 394.0000 +31.6667 267.0000 3144.0000 3104.0000 1801.0000 671.0000 308.0000 310.0000 395.0000 +31.7083 267.0000 3157.0000 3111.0000 1797.0000 665.0000 314.0000 293.0000 396.0000 +31.7500 267.0000 3174.0000 3098.0000 1797.0000 663.0000 314.0000 290.0000 397.0000 +31.7917 267.0000 3187.0000 3098.0000 1792.0000 665.0000 315.0000 278.0000 398.0000 +31.8333 267.0000 3181.0000 3096.0000 1786.0000 670.0000 316.0000 283.0000 401.0000 +31.8750 267.0000 3188.0000 3101.0000 1788.0000 672.0000 317.0000 265.0000 402.0000 +31.9167 267.0000 3192.0000 3102.0000 1782.0000 672.0000 319.0000 262.0000 404.0000 +31.9583 267.0000 3200.0000 3087.0000 1788.0000 668.0000 323.0000 262.0000 405.0000 +32.0000 267.0000 3197.0000 3092.0000 1785.0000 671.0000 326.0000 256.0000 406.0000 +32.0417 267.0000 3193.0000 3094.0000 1783.0000 675.0000 322.0000 257.0000 409.0000 +32.0833 266.0000 3182.0000 3097.0000 1789.0000 670.0000 322.0000 263.0000 411.0000 +32.1250 266.0000 3178.0000 3091.0000 1788.0000 669.0000 321.0000 275.0000 412.0000 +32.1667 266.0000 3184.0000 3085.0000 1788.0000 678.0000 318.0000 266.0000 415.0000 +32.2083 266.0000 3183.0000 3085.0000 1783.0000 677.0000 316.0000 271.0000 419.0000 +32.2500 265.0000 3185.0000 3081.0000 1778.0000 676.0000 318.0000 278.0000 419.0000 +32.2917 265.0000 3187.0000 3068.0000 1777.0000 677.0000 319.0000 287.0000 420.0000 +32.3333 264.0000 3195.0000 3067.0000 1772.0000 679.0000 318.0000 284.0000 421.0000 +32.3750 264.0000 3188.0000 3066.0000 1767.0000 680.0000 317.0000 295.0000 423.0000 +32.4167 264.0000 3168.0000 3085.0000 1753.0000 681.0000 319.0000 305.0000 425.0000 +32.4583 262.0000 3168.0000 3083.0000 1749.0000 685.0000 323.0000 304.0000 426.0000 +32.5000 262.0000 3163.0000 3077.0000 1747.0000 691.0000 323.0000 309.0000 428.0000 +32.5417 262.0000 3153.0000 3083.0000 1748.0000 691.0000 318.0000 313.0000 432.0000 +32.5833 262.0000 3150.0000 3078.0000 1752.0000 700.0000 320.0000 305.0000 433.0000 +32.6250 262.0000 3135.0000 3092.0000 1749.0000 695.0000 319.0000 315.0000 433.0000 +32.6667 262.0000 3153.0000 3083.0000 1749.0000 697.0000 314.0000 304.0000 438.0000 +32.7083 262.0000 3159.0000 3098.0000 1747.0000 700.0000 314.0000 280.0000 440.0000 +32.7500 262.0000 3171.0000 3089.0000 1745.0000 696.0000 314.0000 280.0000 443.0000 +32.7917 262.0000 3176.0000 3093.0000 1747.0000 694.0000 316.0000 268.0000 444.0000 +32.8333 261.0000 3166.0000 3097.0000 1739.0000 697.0000 316.0000 278.0000 446.0000 +32.8750 261.0000 3160.0000 3104.0000 1743.0000 694.0000 314.0000 275.0000 449.0000 +32.9167 261.0000 3160.0000 3109.0000 1738.0000 693.0000 310.0000 278.0000 451.0000 +32.9583 261.0000 3167.0000 3113.0000 1735.0000 694.0000 308.0000 269.0000 453.0000 +33.0000 261.0000 3169.0000 3110.0000 1728.0000 695.0000 313.0000 271.0000 453.0000 +33.0417 261.0000 3168.0000 3120.0000 1728.0000 701.0000 312.0000 254.0000 456.0000 +33.0833 261.0000 3164.0000 3112.0000 1731.0000 697.0000 313.0000 264.0000 458.0000 +33.1250 261.0000 3154.0000 3112.0000 1739.0000 694.0000 313.0000 266.0000 461.0000 +33.1667 261.0000 3145.0000 3106.0000 1735.0000 700.0000 313.0000 276.0000 464.0000 +33.2083 261.0000 3145.0000 3100.0000 1745.0000 695.0000 317.0000 273.0000 464.0000 +33.2500 261.0000 3149.0000 3096.0000 1739.0000 698.0000 310.0000 278.0000 469.0000 +33.2917 261.0000 3148.0000 3091.0000 1742.0000 694.0000 309.0000 285.0000 470.0000 +33.3333 261.0000 3151.0000 3084.0000 1733.0000 697.0000 310.0000 293.0000 471.0000 +33.3750 261.0000 3142.0000 3096.0000 1728.0000 698.0000 310.0000 293.0000 472.0000 +33.4167 261.0000 3130.0000 3090.0000 1727.0000 699.0000 309.0000 312.0000 472.0000 +33.4583 258.0000 3126.0000 3089.0000 1727.0000 700.0000 310.0000 316.0000 474.0000 +33.5000 258.0000 3128.0000 3088.0000 1723.0000 701.0000 314.0000 314.0000 474.0000 +33.5417 258.0000 3120.0000 3094.0000 1724.0000 697.0000 317.0000 315.0000 475.0000 +33.5833 258.0000 3116.0000 3093.0000 1722.0000 699.0000 318.0000 318.0000 476.0000 +33.6250 257.0000 3116.0000 3088.0000 1719.0000 699.0000 318.0000 325.0000 478.0000 +33.6667 257.0000 3124.0000 3090.0000 1721.0000 699.0000 321.0000 310.0000 478.0000 +33.7083 257.0000 3132.0000 3091.0000 1722.0000 704.0000 322.0000 294.0000 478.0000 +33.7500 257.0000 3155.0000 3074.0000 1729.0000 711.0000 317.0000 275.0000 482.0000 +33.7917 257.0000 3171.0000 3071.0000 1735.0000 707.0000 319.0000 256.0000 484.0000 +33.8333 257.0000 3175.0000 3067.0000 1735.0000 710.0000 320.0000 252.0000 484.0000 +33.8750 256.0000 3173.0000 3062.0000 1739.0000 709.0000 318.0000 256.0000 487.0000 +33.9167 256.0000 3177.0000 3055.0000 1735.0000 717.0000 317.0000 255.0000 488.0000 +33.9583 256.0000 3181.0000 3067.0000 1726.0000 718.0000 316.0000 246.0000 490.0000 +34.0000 256.0000 3175.0000 3067.0000 1719.0000 719.0000 316.0000 257.0000 491.0000 +34.0417 256.0000 3180.0000 3065.0000 1712.0000 723.0000 317.0000 256.0000 491.0000 +34.0833 256.0000 3178.0000 3056.0000 1713.0000 724.0000 319.0000 261.0000 493.0000 +34.1250 256.0000 3178.0000 3059.0000 1707.0000 729.0000 319.0000 257.0000 495.0000 +34.1667 256.0000 3171.0000 3066.0000 1703.0000 729.0000 321.0000 258.0000 496.0000 +34.2083 256.0000 3169.0000 3066.0000 1699.0000 739.0000 323.0000 252.0000 496.0000 +34.2500 256.0000 3155.0000 3069.0000 1701.0000 744.0000 322.0000 257.0000 496.0000 +34.2917 255.0000 3156.0000 3058.0000 1698.0000 740.0000 322.0000 273.0000 498.0000 +34.3333 255.0000 3160.0000 3056.0000 1701.0000 738.0000 324.0000 266.0000 500.0000 +34.3750 255.0000 3163.0000 3050.0000 1701.0000 735.0000 322.0000 272.0000 502.0000 +34.4167 255.0000 3159.0000 3056.0000 1703.0000 735.0000 321.0000 269.0000 502.0000 +34.4583 255.0000 3152.0000 3063.0000 1701.0000 739.0000 318.0000 267.0000 505.0000 +34.5000 254.0000 3122.0000 3080.0000 1704.0000 739.0000 318.0000 278.0000 505.0000 +34.5417 254.0000 3109.0000 3094.0000 1700.0000 741.0000 317.0000 277.0000 508.0000 +34.5833 254.0000 3097.0000 3100.0000 1703.0000 735.0000 321.0000 281.0000 509.0000 +34.6250 254.0000 3087.0000 3099.0000 1699.0000 733.0000 323.0000 296.0000 509.0000 +34.6667 254.0000 3089.0000 3116.0000 1695.0000 736.0000 320.0000 277.0000 513.0000 +34.7083 254.0000 3093.0000 3110.0000 1692.0000 735.0000 321.0000 278.0000 517.0000 +34.7500 254.0000 3105.0000 3117.0000 1692.0000 737.0000 322.0000 256.0000 517.0000 +34.7917 253.0000 3101.0000 3121.0000 1686.0000 743.0000 322.0000 254.0000 520.0000 +34.8333 253.0000 3097.0000 3127.0000 1680.0000 746.0000 321.0000 252.0000 524.0000 +34.8750 253.0000 3097.0000 3115.0000 1687.0000 743.0000 325.0000 255.0000 525.0000 +34.9167 253.0000 3087.0000 3112.0000 1680.0000 750.0000 329.0000 264.0000 525.0000 +34.9583 253.0000 3093.0000 3105.0000 1679.0000 756.0000 326.0000 262.0000 526.0000 +35.0000 253.0000 3108.0000 3098.0000 1680.0000 757.0000 324.0000 251.0000 529.0000 +35.0417 253.0000 3103.0000 3100.0000 1677.0000 757.0000 322.0000 257.0000 531.0000 +35.0833 253.0000 3111.0000 3091.0000 1677.0000 760.0000 318.0000 257.0000 533.0000 +35.1250 253.0000 3103.0000 3090.0000 1674.0000 761.0000 319.0000 267.0000 533.0000 +35.1667 253.0000 3096.0000 3095.0000 1680.0000 754.0000 326.0000 262.0000 534.0000 +35.2083 253.0000 3089.0000 3099.0000 1680.0000 758.0000 327.0000 259.0000 535.0000 +35.2500 253.0000 3074.0000 3102.0000 1675.0000 764.0000 322.0000 271.0000 539.0000 +35.2917 253.0000 3082.0000 3092.0000 1672.0000 764.0000 325.0000 272.0000 540.0000 +35.3333 253.0000 3086.0000 3086.0000 1674.0000 759.0000 326.0000 274.0000 542.0000 +35.3750 253.0000 3075.0000 3078.0000 1685.0000 757.0000 326.0000 281.0000 545.0000 +35.4167 252.0000 3062.0000 3083.0000 1680.0000 762.0000 323.0000 290.0000 548.0000 +35.4583 251.0000 3054.0000 3086.0000 1669.0000 766.0000 326.0000 300.0000 548.0000 +35.5000 251.0000 3046.0000 3087.0000 1677.0000 758.0000 330.0000 302.0000 549.0000 +35.5417 251.0000 3039.0000 3091.0000 1675.0000 756.0000 330.0000 307.0000 551.0000 +35.5833 251.0000 3051.0000 3086.0000 1674.0000 759.0000 325.0000 301.0000 553.0000 +35.6250 251.0000 3044.0000 3080.0000 1671.0000 765.0000 319.0000 312.0000 558.0000 +35.6667 251.0000 3045.0000 3093.0000 1670.0000 765.0000 321.0000 297.0000 558.0000 +35.7083 251.0000 3043.0000 3107.0000 1671.0000 763.0000 317.0000 289.0000 559.0000 +35.7500 251.0000 3061.0000 3104.0000 1679.0000 756.0000 318.0000 271.0000 560.0000 +35.7917 251.0000 3081.0000 3111.0000 1678.0000 753.0000 320.0000 244.0000 562.0000 +35.8333 251.0000 3066.0000 3112.0000 1679.0000 757.0000 320.0000 250.0000 565.0000 +35.8750 251.0000 3066.0000 3095.0000 1684.0000 758.0000 325.0000 256.0000 565.0000 +35.9167 251.0000 3067.0000 3095.0000 1683.0000 758.0000 323.0000 255.0000 568.0000 +35.9583 251.0000 3067.0000 3088.0000 1687.0000 762.0000 322.0000 253.0000 570.0000 +36.0000 251.0000 3059.0000 3092.0000 1686.0000 764.0000 318.0000 256.0000 574.0000 +36.0417 251.0000 3052.0000 3097.0000 1688.0000 758.0000 317.0000 261.0000 576.0000 +36.0833 251.0000 3047.0000 3113.0000 1683.0000 759.0000 321.0000 249.0000 577.0000 +36.1250 251.0000 3028.0000 3121.0000 1685.0000 763.0000 320.0000 254.0000 578.0000 +36.1667 251.0000 3013.0000 3124.0000 1694.0000 758.0000 320.0000 259.0000 581.0000 +36.2083 251.0000 3000.0000 3130.0000 1690.0000 755.0000 321.0000 270.0000 583.0000 +36.2500 251.0000 2996.0000 3131.0000 1690.0000 758.0000 319.0000 272.0000 583.0000 +36.2917 251.0000 2994.0000 3133.0000 1682.0000 758.0000 319.0000 278.0000 585.0000 +36.3333 251.0000 2999.0000 3119.0000 1702.0000 755.0000 319.0000 268.0000 587.0000 +36.3750 251.0000 2991.0000 3118.0000 1706.0000 754.0000 323.0000 270.0000 587.0000 +36.4167 251.0000 2983.0000 3118.0000 1699.0000 760.0000 322.0000 279.0000 588.0000 +36.4583 251.0000 2975.0000 3108.0000 1700.0000 761.0000 322.0000 293.0000 590.0000 +36.5000 251.0000 2979.0000 3104.0000 1689.0000 766.0000 321.0000 298.0000 592.0000 +36.5417 251.0000 2968.0000 3111.0000 1690.0000 769.0000 320.0000 297.0000 594.0000 +36.5833 251.0000 2965.0000 3116.0000 1687.0000 766.0000 322.0000 295.0000 598.0000 +36.6250 251.0000 2961.0000 3121.0000 1688.0000 759.0000 324.0000 295.0000 601.0000 +36.6667 251.0000 2965.0000 3111.0000 1690.0000 760.0000 326.0000 296.0000 601.0000 +36.7083 251.0000 2981.0000 3113.0000 1690.0000 755.0000 330.0000 279.0000 601.0000 +36.7500 251.0000 3000.0000 3107.0000 1684.0000 756.0000 329.0000 272.0000 601.0000 +36.7917 251.0000 3014.0000 3109.0000 1684.0000 758.0000 328.0000 254.0000 602.0000 +36.8333 250.0000 3004.0000 3110.0000 1689.0000 757.0000 327.0000 259.0000 604.0000 +36.8750 250.0000 3003.0000 3110.0000 1686.0000 752.0000 331.0000 262.0000 606.0000 +36.9167 250.0000 2994.0000 3123.0000 1680.0000 753.0000 326.0000 264.0000 610.0000 +36.9583 250.0000 3007.0000 3120.0000 1677.0000 752.0000 322.0000 257.0000 615.0000 +37.0000 250.0000 3014.0000 3111.0000 1669.0000 754.0000 324.0000 259.0000 619.0000 +37.0417 250.0000 3016.0000 3110.0000 1664.0000 752.0000 329.0000 259.0000 620.0000 +37.0833 250.0000 3007.0000 3111.0000 1662.0000 755.0000 332.0000 263.0000 620.0000 +37.1250 250.0000 3002.0000 3099.0000 1677.0000 750.0000 335.0000 266.0000 621.0000 +37.1667 250.0000 2988.0000 3101.0000 1668.0000 758.0000 338.0000 276.0000 621.0000 +37.2083 250.0000 2988.0000 3091.0000 1662.0000 763.0000 338.0000 285.0000 623.0000 +37.2500 250.0000 2996.0000 3072.0000 1668.0000 758.0000 334.0000 292.0000 630.0000 +37.2917 250.0000 3001.0000 3072.0000 1664.0000 760.0000 332.0000 290.0000 631.0000 +37.3333 250.0000 3006.0000 3063.0000 1670.0000 759.0000 335.0000 284.0000 633.0000 +37.3750 250.0000 2986.0000 3073.0000 1667.0000 762.0000 333.0000 294.0000 635.0000 +37.4167 250.0000 2978.0000 3069.0000 1661.0000 767.0000 331.0000 306.0000 638.0000 +37.4583 250.0000 2957.0000 3072.0000 1664.0000 766.0000 329.0000 321.0000 641.0000 +37.5000 250.0000 2947.0000 3081.0000 1661.0000 761.0000 332.0000 327.0000 641.0000 +37.5417 250.0000 2940.0000 3090.0000 1653.0000 757.0000 337.0000 332.0000 641.0000 +37.5833 250.0000 2936.0000 3080.0000 1660.0000 759.0000 336.0000 338.0000 641.0000 +37.6250 250.0000 2925.0000 3084.0000 1662.0000 760.0000 338.0000 339.0000 642.0000 +37.6667 250.0000 2949.0000 3087.0000 1656.0000 762.0000 337.0000 316.0000 643.0000 +37.7083 250.0000 2957.0000 3071.0000 1670.0000 756.0000 337.0000 314.0000 645.0000 +37.7500 250.0000 2972.0000 3086.0000 1666.0000 755.0000 338.0000 286.0000 647.0000 +37.7917 250.0000 2983.0000 3088.0000 1660.0000 760.0000 335.0000 274.0000 650.0000 +37.8333 250.0000 2982.0000 3085.0000 1659.0000 765.0000 333.0000 273.0000 653.0000 +37.8750 250.0000 2980.0000 3082.0000 1666.0000 764.0000 334.0000 269.0000 655.0000 +37.9167 250.0000 2977.0000 3084.0000 1666.0000 773.0000 335.0000 259.0000 656.0000 +37.9583 249.0000 2972.0000 3087.0000 1666.0000 775.0000 333.0000 262.0000 656.0000 +38.0000 249.0000 2975.0000 3091.0000 1663.0000 776.0000 329.0000 259.0000 658.0000 +38.0417 249.0000 2965.0000 3087.0000 1668.0000 771.0000 331.0000 269.0000 660.0000 +38.0833 249.0000 2962.0000 3093.0000 1667.0000 768.0000 334.0000 267.0000 660.0000 +38.1250 249.0000 2965.0000 3082.0000 1665.0000 765.0000 332.0000 278.0000 664.0000 +38.1667 249.0000 2967.0000 3079.0000 1666.0000 767.0000 332.0000 274.0000 666.0000 +38.2083 248.0000 2973.0000 3071.0000 1667.0000 765.0000 334.0000 275.0000 667.0000 +38.2500 248.0000 2974.0000 3061.0000 1666.0000 763.0000 337.0000 282.0000 669.0000 +38.2917 248.0000 2976.0000 3064.0000 1665.0000 761.0000 336.0000 280.0000 670.0000 +38.3333 248.0000 2960.0000 3062.0000 1666.0000 765.0000 336.0000 290.0000 673.0000 +38.3750 248.0000 2958.0000 3049.0000 1667.0000 764.0000 336.0000 304.0000 674.0000 +38.4167 248.0000 2955.0000 3041.0000 1665.0000 761.0000 341.0000 314.0000 675.0000 +38.4583 248.0000 2939.0000 3044.0000 1664.0000 757.0000 348.0000 324.0000 676.0000 +38.5000 248.0000 2941.0000 3041.0000 1660.0000 761.0000 351.0000 322.0000 676.0000 +38.5417 248.0000 2945.0000 3042.0000 1666.0000 756.0000 352.0000 314.0000 677.0000 +38.5833 247.0000 2950.0000 3035.0000 1663.0000 756.0000 350.0000 319.0000 680.0000 +38.6250 246.0000 2937.0000 3048.0000 1655.0000 754.0000 349.0000 330.0000 681.0000 +38.6667 246.0000 2944.0000 3055.0000 1650.0000 755.0000 349.0000 319.0000 682.0000 +38.7083 246.0000 2959.0000 3050.0000 1647.0000 758.0000 345.0000 310.0000 685.0000 +38.7500 246.0000 2986.0000 3049.0000 1642.0000 758.0000 347.0000 287.0000 685.0000 +38.7917 245.0000 2992.0000 3055.0000 1643.0000 758.0000 349.0000 273.0000 685.0000 +38.8333 245.0000 2997.0000 3036.0000 1648.0000 752.0000 351.0000 286.0000 685.0000 +38.8750 245.0000 3004.0000 3028.0000 1657.0000 749.0000 352.0000 279.0000 686.0000 +38.9167 245.0000 3013.0000 3020.0000 1660.0000 747.0000 353.0000 275.0000 687.0000 +38.9583 245.0000 3020.0000 3023.0000 1647.0000 757.0000 348.0000 272.0000 688.0000 +39.0000 245.0000 3018.0000 3031.0000 1648.0000 758.0000 350.0000 262.0000 688.0000 +39.0417 245.0000 3023.0000 3020.0000 1651.0000 760.0000 354.0000 259.0000 688.0000 +39.0833 245.0000 3025.0000 3017.0000 1651.0000 758.0000 353.0000 261.0000 690.0000 +39.1250 245.0000 3012.0000 3014.0000 1653.0000 764.0000 354.0000 266.0000 692.0000 +39.1667 245.0000 3011.0000 3005.0000 1666.0000 756.0000 353.0000 269.0000 695.0000 +39.2083 245.0000 3001.0000 3018.0000 1663.0000 751.0000 357.0000 269.0000 696.0000 +39.2500 245.0000 3005.0000 3015.0000 1669.0000 751.0000 359.0000 259.0000 697.0000 +39.2917 245.0000 2992.0000 3021.0000 1663.0000 750.0000 359.0000 271.0000 699.0000 +39.3333 245.0000 2985.0000 3008.0000 1669.0000 749.0000 362.0000 282.0000 700.0000 +39.3750 245.0000 2984.0000 2999.0000 1667.0000 750.0000 360.0000 293.0000 702.0000 +39.4167 245.0000 2981.0000 2996.0000 1658.0000 748.0000 361.0000 307.0000 704.0000 +39.4583 245.0000 2985.0000 2987.0000 1655.0000 747.0000 363.0000 313.0000 705.0000 +39.5000 244.0000 2975.0000 2989.0000 1650.0000 748.0000 361.0000 326.0000 707.0000 +39.5417 244.0000 2982.0000 2980.0000 1645.0000 752.0000 361.0000 326.0000 710.0000 +39.5833 244.0000 2992.0000 2969.0000 1650.0000 754.0000 360.0000 320.0000 711.0000 +39.6250 244.0000 2983.0000 2984.0000 1647.0000 755.0000 356.0000 319.0000 712.0000 +39.6667 244.0000 2996.0000 2975.0000 1643.0000 757.0000 357.0000 314.0000 714.0000 +39.7083 244.0000 3013.0000 2972.0000 1649.0000 751.0000 358.0000 297.0000 716.0000 +39.7500 244.0000 3014.0000 2980.0000 1654.0000 750.0000 358.0000 283.0000 717.0000 +39.7917 244.0000 3030.0000 2979.0000 1644.0000 750.0000 356.0000 277.0000 720.0000 +39.8333 244.0000 3023.0000 2976.0000 1641.0000 755.0000 357.0000 284.0000 720.0000 +39.8750 244.0000 3034.0000 2969.0000 1644.0000 760.0000 359.0000 270.0000 720.0000 +39.9167 244.0000 3034.0000 2970.0000 1643.0000 759.0000 360.0000 269.0000 721.0000 +39.9583 243.0000 3039.0000 2964.0000 1648.0000 758.0000 361.0000 265.0000 722.0000 +40.0000 243.0000 3035.0000 2975.0000 1646.0000 753.0000 363.0000 262.0000 723.0000 +40.0417 243.0000 3026.0000 2961.0000 1649.0000 747.0000 365.0000 285.0000 724.0000 +40.0833 243.0000 3035.0000 2970.0000 1651.0000 743.0000 366.0000 268.0000 724.0000 +40.1250 243.0000 3033.0000 2966.0000 1653.0000 741.0000 367.0000 272.0000 725.0000 +40.1667 243.0000 3033.0000 2969.0000 1647.0000 742.0000 366.0000 274.0000 726.0000 +40.2083 243.0000 3037.0000 2962.0000 1651.0000 745.0000 363.0000 269.0000 730.0000 +40.2500 243.0000 3031.0000 2960.0000 1652.0000 741.0000 363.0000 278.0000 732.0000 +40.2917 243.0000 3027.0000 2957.0000 1653.0000 739.0000 366.0000 280.0000 735.0000 +40.3333 243.0000 3020.0000 2953.0000 1660.0000 739.0000 361.0000 284.0000 740.0000 +40.3750 243.0000 3011.0000 2943.0000 1659.0000 742.0000 358.0000 302.0000 742.0000 +40.4167 243.0000 3008.0000 2950.0000 1650.0000 742.0000 356.0000 306.0000 745.0000 +40.4583 243.0000 2996.0000 2950.0000 1650.0000 746.0000 357.0000 311.0000 747.0000 +40.5000 243.0000 2984.0000 2966.0000 1643.0000 744.0000 354.0000 318.0000 748.0000 +40.5417 243.0000 2991.0000 2964.0000 1637.0000 746.0000 350.0000 316.0000 753.0000 +40.5833 242.0000 2995.0000 2963.0000 1630.0000 745.0000 354.0000 318.0000 753.0000 +40.6250 242.0000 2982.0000 2972.0000 1635.0000 745.0000 349.0000 319.0000 756.0000 +40.6667 242.0000 2992.0000 2973.0000 1625.0000 747.0000 349.0000 316.0000 756.0000 +40.7083 242.0000 2999.0000 2972.0000 1620.0000 747.0000 353.0000 310.0000 757.0000 +40.7500 242.0000 3003.0000 2993.0000 1610.0000 742.0000 355.0000 295.0000 760.0000 +40.7917 241.0000 3019.0000 2979.0000 1607.0000 743.0000 360.0000 291.0000 760.0000 +40.8333 241.0000 3027.0000 2969.0000 1617.0000 742.0000 359.0000 284.0000 761.0000 +40.8750 241.0000 3037.0000 2966.0000 1618.0000 750.0000 357.0000 268.0000 763.0000 +40.9167 241.0000 3026.0000 2964.0000 1618.0000 753.0000 355.0000 276.0000 767.0000 +40.9583 241.0000 3022.0000 2974.0000 1604.0000 757.0000 353.0000 278.0000 771.0000 +41.0000 241.0000 3018.0000 2972.0000 1607.0000 757.0000 354.0000 280.0000 771.0000 +41.0417 241.0000 3015.0000 2978.0000 1595.0000 760.0000 352.0000 287.0000 772.0000 +41.0833 241.0000 3008.0000 2978.0000 1599.0000 764.0000 350.0000 286.0000 774.0000 +41.1250 241.0000 3012.0000 2964.0000 1597.0000 764.0000 346.0000 298.0000 778.0000 +41.1667 241.0000 3018.0000 2966.0000 1588.0000 762.0000 344.0000 299.0000 782.0000 +41.2083 241.0000 3009.0000 2974.0000 1592.0000 760.0000 345.0000 296.0000 783.0000 +41.2500 241.0000 3009.0000 2974.0000 1595.0000 759.0000 348.0000 290.0000 784.0000 +41.2917 241.0000 3001.0000 2970.0000 1598.0000 759.0000 348.0000 296.0000 787.0000 +41.3333 241.0000 2997.0000 2974.0000 1601.0000 757.0000 347.0000 293.0000 790.0000 +41.3750 241.0000 2985.0000 2973.0000 1601.0000 757.0000 345.0000 306.0000 792.0000 +41.4167 241.0000 2977.0000 2964.0000 1596.0000 755.0000 348.0000 327.0000 792.0000 +41.4583 241.0000 2978.0000 2967.0000 1600.0000 754.0000 345.0000 321.0000 794.0000 +41.5000 240.0000 2976.0000 2975.0000 1603.0000 751.0000 347.0000 313.0000 795.0000 +41.5417 240.0000 2963.0000 2971.0000 1597.0000 756.0000 345.0000 330.0000 798.0000 +41.5833 240.0000 2977.0000 2971.0000 1590.0000 760.0000 341.0000 319.0000 802.0000 +41.6250 240.0000 2961.0000 2980.0000 1588.0000 761.0000 341.0000 325.0000 804.0000 +41.6667 240.0000 2958.0000 2991.0000 1583.0000 760.0000 346.0000 318.0000 804.0000 +41.7083 240.0000 2965.0000 2990.0000 1586.0000 759.0000 345.0000 309.0000 806.0000 +41.7500 240.0000 2981.0000 2988.0000 1589.0000 758.0000 344.0000 293.0000 807.0000 +41.7917 240.0000 2989.0000 2981.0000 1595.0000 754.0000 350.0000 282.0000 809.0000 +41.8333 240.0000 2985.0000 2986.0000 1588.0000 751.0000 352.0000 288.0000 810.0000 +41.8750 240.0000 2995.0000 2984.0000 1585.0000 750.0000 352.0000 283.0000 811.0000 +41.9167 240.0000 2989.0000 2982.0000 1588.0000 752.0000 349.0000 286.0000 814.0000 +41.9583 240.0000 2999.0000 2973.0000 1574.0000 753.0000 350.0000 296.0000 815.0000 +42.0000 240.0000 2999.0000 2980.0000 1571.0000 756.0000 349.0000 289.0000 816.0000 +42.0417 240.0000 2999.0000 2988.0000 1561.0000 759.0000 345.0000 290.0000 818.0000 +42.0833 240.0000 3003.0000 2979.0000 1568.0000 758.0000 348.0000 284.0000 820.0000 +42.1250 240.0000 2989.0000 2983.0000 1570.0000 760.0000 350.0000 286.0000 822.0000 +42.1667 240.0000 2979.0000 2993.0000 1561.0000 759.0000 349.0000 296.0000 823.0000 +42.2083 240.0000 2975.0000 2994.0000 1552.0000 757.0000 351.0000 305.0000 826.0000 +42.2500 240.0000 2969.0000 2997.0000 1545.0000 757.0000 352.0000 313.0000 827.0000 +42.2917 240.0000 2969.0000 3003.0000 1540.0000 751.0000 355.0000 313.0000 829.0000 +42.3333 240.0000 2984.0000 2993.0000 1528.0000 754.0000 353.0000 318.0000 830.0000 +42.3750 240.0000 2963.0000 3009.0000 1517.0000 759.0000 355.0000 325.0000 832.0000 +42.4167 240.0000 2965.0000 3002.0000 1522.0000 754.0000 358.0000 326.0000 833.0000 +42.4583 240.0000 2968.0000 2989.0000 1534.0000 753.0000 354.0000 327.0000 835.0000 +42.5000 239.0000 2964.0000 2996.0000 1526.0000 754.0000 354.0000 331.0000 836.0000 +42.5417 239.0000 2964.0000 2993.0000 1522.0000 752.0000 351.0000 341.0000 838.0000 +42.5833 239.0000 2955.0000 3003.0000 1522.0000 749.0000 347.0000 345.0000 840.0000 +42.6250 239.0000 2950.0000 3012.0000 1527.0000 747.0000 346.0000 338.0000 841.0000 +42.6667 239.0000 2954.0000 3016.0000 1517.0000 757.0000 344.0000 331.0000 842.0000 +42.7083 239.0000 2961.0000 3014.0000 1523.0000 756.0000 342.0000 322.0000 843.0000 +42.7500 239.0000 2973.0000 3017.0000 1525.0000 757.0000 343.0000 301.0000 845.0000 +42.7917 239.0000 2990.0000 3004.0000 1519.0000 756.0000 344.0000 303.0000 845.0000 +42.8333 239.0000 2995.0000 3008.0000 1517.0000 756.0000 347.0000 293.0000 845.0000 +42.8750 239.0000 2995.0000 3014.0000 1511.0000 754.0000 348.0000 292.0000 847.0000 +42.9167 239.0000 2988.0000 3015.0000 1504.0000 752.0000 353.0000 301.0000 848.0000 +42.9583 239.0000 2990.0000 3022.0000 1501.0000 748.0000 352.0000 298.0000 850.0000 +43.0000 239.0000 2993.0000 3028.0000 1497.0000 743.0000 353.0000 297.0000 850.0000 +43.0417 239.0000 3000.0000 3028.0000 1497.0000 734.0000 353.0000 298.0000 851.0000 +43.0833 239.0000 3008.0000 3025.0000 1502.0000 729.0000 358.0000 288.0000 851.0000 +43.1250 239.0000 2995.0000 3033.0000 1497.0000 730.0000 364.0000 290.0000 852.0000 +43.1667 239.0000 2981.0000 3025.0000 1490.0000 730.0000 366.0000 316.0000 853.0000 +43.2083 239.0000 2990.0000 3012.0000 1487.0000 731.0000 368.0000 319.0000 854.0000 +43.2500 239.0000 2996.0000 3017.0000 1488.0000 723.0000 372.0000 310.0000 855.0000 +43.2917 239.0000 2976.0000 3018.0000 1494.0000 721.0000 371.0000 326.0000 855.0000 +43.3333 239.0000 2978.0000 3012.0000 1493.0000 724.0000 373.0000 325.0000 856.0000 +43.3750 239.0000 2975.0000 3013.0000 1490.0000 724.0000 374.0000 328.0000 857.0000 +43.4167 239.0000 2965.0000 3018.0000 1490.0000 724.0000 377.0000 329.0000 858.0000 +43.4583 239.0000 2957.0000 3027.0000 1492.0000 722.0000 378.0000 326.0000 859.0000 +43.5000 238.0000 2939.0000 3029.0000 1493.0000 723.0000 375.0000 342.0000 861.0000 +43.5417 238.0000 2929.0000 3032.0000 1495.0000 724.0000 374.0000 347.0000 861.0000 +43.5833 238.0000 2943.0000 3021.0000 1500.0000 719.0000 375.0000 342.0000 862.0000 +43.6250 238.0000 2930.0000 3026.0000 1504.0000 715.0000 375.0000 349.0000 863.0000 +43.6667 238.0000 2937.0000 3017.0000 1505.0000 714.0000 378.0000 347.0000 864.0000 +43.7083 237.0000 2938.0000 3027.0000 1498.0000 718.0000 376.0000 341.0000 865.0000 +43.7500 237.0000 2959.0000 3023.0000 1503.0000 711.0000 379.0000 321.0000 867.0000 +43.7917 237.0000 2975.0000 3021.0000 1506.0000 710.0000 382.0000 302.0000 867.0000 +43.8333 237.0000 2966.0000 3033.0000 1498.0000 714.0000 380.0000 303.0000 869.0000 +43.8750 237.0000 2974.0000 3015.0000 1497.0000 716.0000 385.0000 307.0000 869.0000 +43.9167 237.0000 2978.0000 3004.0000 1497.0000 714.0000 385.0000 313.0000 872.0000 +43.9583 237.0000 2995.0000 3005.0000 1501.0000 711.0000 384.0000 292.0000 875.0000 +44.0000 237.0000 2996.0000 2998.0000 1502.0000 714.0000 381.0000 296.0000 876.0000 +44.0417 237.0000 2984.0000 3010.0000 1505.0000 716.0000 381.0000 289.0000 878.0000 +44.0833 237.0000 2961.0000 3031.0000 1496.0000 716.0000 379.0000 299.0000 881.0000 +44.1250 236.0000 2965.0000 3036.0000 1490.0000 718.0000 377.0000 295.0000 883.0000 +44.1667 236.0000 2947.0000 3045.0000 1486.0000 723.0000 370.0000 307.0000 886.0000 +44.2083 236.0000 2948.0000 3039.0000 1480.0000 726.0000 366.0000 317.0000 888.0000 +44.2500 236.0000 2958.0000 3034.0000 1478.0000 731.0000 364.0000 309.0000 890.0000 +44.2917 236.0000 2957.0000 3026.0000 1484.0000 724.0000 362.0000 316.0000 895.0000 +44.3333 236.0000 2948.0000 3037.0000 1486.0000 717.0000 364.0000 315.0000 897.0000 +44.3750 236.0000 2937.0000 3041.0000 1493.0000 716.0000 365.0000 314.0000 898.0000 +44.4167 236.0000 2921.0000 3041.0000 1497.0000 711.0000 366.0000 328.0000 900.0000 +44.4583 235.0000 2921.0000 3038.0000 1487.0000 717.0000 362.0000 339.0000 901.0000 +44.5000 235.0000 2897.0000 3048.0000 1481.0000 719.0000 361.0000 356.0000 903.0000 +44.5417 235.0000 2897.0000 3050.0000 1484.0000 710.0000 363.0000 355.0000 906.0000 +44.5833 235.0000 2911.0000 3053.0000 1481.0000 713.0000 361.0000 338.0000 908.0000 +44.6250 235.0000 2903.0000 3060.0000 1480.0000 715.0000 363.0000 336.0000 908.0000 +44.6667 235.0000 2911.0000 3049.0000 1476.0000 720.0000 361.0000 338.0000 910.0000 +44.7083 234.0000 2912.0000 3057.0000 1474.0000 722.0000 357.0000 330.0000 914.0000 +44.7500 234.0000 2925.0000 3058.0000 1476.0000 724.0000 357.0000 311.0000 915.0000 +44.7917 234.0000 2934.0000 3054.0000 1475.0000 727.0000 356.0000 305.0000 915.0000 +44.8333 234.0000 2923.0000 3065.0000 1473.0000 724.0000 357.0000 305.0000 919.0000 +44.8750 234.0000 2914.0000 3065.0000 1474.0000 724.0000 355.0000 314.0000 920.0000 +44.9167 234.0000 2915.0000 3065.0000 1487.0000 725.0000 350.0000 301.0000 923.0000 +44.9583 234.0000 2914.0000 3074.0000 1486.0000 724.0000 347.0000 297.0000 924.0000 +45.0000 234.0000 2907.0000 3076.0000 1483.0000 726.0000 347.0000 303.0000 924.0000 +45.0417 233.0000 2904.0000 3074.0000 1486.0000 726.0000 344.0000 305.0000 928.0000 +45.0833 233.0000 2899.0000 3071.0000 1492.0000 722.0000 347.0000 306.0000 930.0000 +45.1250 233.0000 2896.0000 3069.0000 1499.0000 723.0000 346.0000 300.0000 934.0000 +45.1667 233.0000 2879.0000 3078.0000 1501.0000 727.0000 347.0000 301.0000 934.0000 +45.2083 233.0000 2864.0000 3078.0000 1495.0000 729.0000 346.0000 320.0000 935.0000 +45.2500 233.0000 2877.0000 3066.0000 1496.0000 727.0000 349.0000 315.0000 937.0000 +45.2917 233.0000 2879.0000 3049.0000 1501.0000 728.0000 347.0000 322.0000 941.0000 +45.3333 233.0000 2890.0000 3042.0000 1503.0000 727.0000 347.0000 317.0000 941.0000 +45.3750 233.0000 2875.0000 3047.0000 1502.0000 724.0000 348.0000 330.0000 941.0000 +45.4167 232.0000 2866.0000 3040.0000 1500.0000 727.0000 346.0000 345.0000 944.0000 +45.4583 232.0000 2866.0000 3036.0000 1494.0000 730.0000 345.0000 351.0000 946.0000 +45.5000 232.0000 2867.0000 3023.0000 1500.0000 727.0000 350.0000 355.0000 946.0000 +45.5417 232.0000 2875.0000 3007.0000 1503.0000 728.0000 350.0000 359.0000 946.0000 +45.5833 232.0000 2872.0000 3007.0000 1501.0000 733.0000 350.0000 357.0000 948.0000 +45.6250 232.0000 2853.0000 3021.0000 1501.0000 732.0000 354.0000 359.0000 948.0000 +45.6667 232.0000 2858.0000 3022.0000 1505.0000 735.0000 353.0000 347.0000 948.0000 +45.7083 232.0000 2868.0000 3032.0000 1502.0000 737.0000 352.0000 327.0000 950.0000 +45.7500 232.0000 2876.0000 3038.0000 1496.0000 732.0000 355.0000 319.0000 952.0000 +45.7917 232.0000 2882.0000 3036.0000 1497.0000 727.0000 353.0000 318.0000 955.0000 +45.8333 232.0000 2878.0000 3039.0000 1495.0000 724.0000 357.0000 318.0000 957.0000 +45.8750 232.0000 2874.0000 3038.0000 1497.0000 724.0000 355.0000 320.0000 960.0000 +45.9167 232.0000 2883.0000 3028.0000 1506.0000 718.0000 357.0000 315.0000 961.0000 +45.9583 232.0000 2882.0000 3023.0000 1499.0000 723.0000 357.0000 320.0000 964.0000 +46.0000 232.0000 2879.0000 3020.0000 1504.0000 715.0000 365.0000 321.0000 964.0000 +46.0417 232.0000 2888.0000 3014.0000 1499.0000 714.0000 362.0000 325.0000 966.0000 +46.0833 232.0000 2894.0000 3007.0000 1500.0000 713.0000 363.0000 323.0000 968.0000 +46.1250 232.0000 2899.0000 3006.0000 1499.0000 710.0000 365.0000 319.0000 970.0000 +46.1667 232.0000 2889.0000 3007.0000 1505.0000 702.0000 369.0000 326.0000 970.0000 +46.2083 231.0000 2890.0000 3001.0000 1503.0000 699.0000 366.0000 337.0000 973.0000 +46.2500 231.0000 2883.0000 3010.0000 1500.0000 699.0000 362.0000 339.0000 976.0000 +46.2917 231.0000 2884.0000 3016.0000 1505.0000 697.0000 361.0000 329.0000 977.0000 +46.3333 230.0000 2881.0000 3003.0000 1507.0000 697.0000 365.0000 340.0000 977.0000 +46.3750 230.0000 2872.0000 2996.0000 1508.0000 700.0000 361.0000 353.0000 980.0000 +46.4167 230.0000 2876.0000 2996.0000 1509.0000 697.0000 362.0000 348.0000 982.0000 +46.4583 229.0000 2864.0000 2994.0000 1509.0000 699.0000 364.0000 357.0000 984.0000 +46.5000 229.0000 2860.0000 2990.0000 1505.0000 701.0000 362.0000 368.0000 985.0000 +46.5417 228.0000 2860.0000 2995.0000 1503.0000 701.0000 359.0000 366.0000 988.0000 +46.5833 228.0000 2867.0000 3006.0000 1505.0000 696.0000 358.0000 349.0000 991.0000 +46.6250 228.0000 2864.0000 2999.0000 1499.0000 694.0000 362.0000 362.0000 992.0000 +46.6667 228.0000 2882.0000 2999.0000 1496.0000 688.0000 364.0000 351.0000 992.0000 +46.7083 228.0000 2886.0000 3009.0000 1495.0000 682.0000 365.0000 341.0000 994.0000 +46.7500 228.0000 2902.0000 3010.0000 1488.0000 688.0000 360.0000 328.0000 996.0000 +46.7917 228.0000 2912.0000 3015.0000 1484.0000 684.0000 364.0000 315.0000 998.0000 +46.8333 228.0000 2920.0000 3013.0000 1475.0000 683.0000 368.0000 313.0000 1000.0000 +46.8750 228.0000 2919.0000 3012.0000 1473.0000 682.0000 367.0000 317.0000 1002.0000 +46.9167 228.0000 2937.0000 2999.0000 1472.0000 682.0000 367.0000 312.0000 1003.0000 +46.9583 228.0000 2936.0000 2996.0000 1471.0000 683.0000 367.0000 315.0000 1004.0000 +47.0000 228.0000 2947.0000 2983.0000 1471.0000 686.0000 368.0000 313.0000 1004.0000 +47.0417 228.0000 2947.0000 2980.0000 1471.0000 688.0000 366.0000 313.0000 1007.0000 +47.0833 228.0000 2943.0000 2978.0000 1470.0000 690.0000 366.0000 317.0000 1008.0000 +47.1250 228.0000 2941.0000 2983.0000 1462.0000 691.0000 369.0000 316.0000 1010.0000 +47.1667 228.0000 2943.0000 2978.0000 1462.0000 687.0000 371.0000 320.0000 1011.0000 +47.2083 228.0000 2945.0000 2970.0000 1456.0000 691.0000 367.0000 330.0000 1013.0000 +47.2500 228.0000 2947.0000 2965.0000 1460.0000 691.0000 367.0000 328.0000 1014.0000 +47.2917 228.0000 2951.0000 2943.0000 1463.0000 699.0000 365.0000 335.0000 1016.0000 +47.3333 228.0000 2965.0000 2929.0000 1470.0000 698.0000 361.0000 331.0000 1018.0000 +47.3750 228.0000 2955.0000 2927.0000 1470.0000 696.0000 362.0000 340.0000 1022.0000 +47.4167 228.0000 2946.0000 2939.0000 1459.0000 702.0000 357.0000 343.0000 1026.0000 +47.4583 228.0000 2949.0000 2933.0000 1467.0000 701.0000 354.0000 339.0000 1029.0000 +47.5000 228.0000 2929.0000 2943.0000 1463.0000 702.0000 356.0000 348.0000 1031.0000 +47.5417 228.0000 2930.0000 2943.0000 1467.0000 701.0000 357.0000 340.0000 1034.0000 +47.5833 228.0000 2927.0000 2942.0000 1473.0000 703.0000 354.0000 337.0000 1036.0000 +47.6250 228.0000 2923.0000 2940.0000 1473.0000 703.0000 353.0000 341.0000 1039.0000 +47.6667 228.0000 2937.0000 2930.0000 1479.0000 705.0000 355.0000 327.0000 1039.0000 +47.7083 228.0000 2935.0000 2937.0000 1478.0000 701.0000 358.0000 323.0000 1040.0000 +47.7500 228.0000 2943.0000 2928.0000 1484.0000 703.0000 354.0000 318.0000 1042.0000 +47.7917 228.0000 2955.0000 2928.0000 1482.0000 699.0000 352.0000 312.0000 1044.0000 +47.8333 228.0000 2945.0000 2926.0000 1477.0000 700.0000 357.0000 321.0000 1046.0000 +47.8750 228.0000 2956.0000 2925.0000 1482.0000 698.0000 355.0000 310.0000 1046.0000 +47.9167 228.0000 2956.0000 2932.0000 1480.0000 699.0000 359.0000 299.0000 1047.0000 +47.9583 228.0000 2946.0000 2931.0000 1476.0000 699.0000 359.0000 313.0000 1048.0000 +48.0000 228.0000 2951.0000 2931.0000 1474.0000 697.0000 360.0000 307.0000 1052.0000 +48.0417 228.0000 2944.0000 2941.0000 1472.0000 692.0000 357.0000 312.0000 1054.0000 +48.0833 228.0000 2930.0000 2944.0000 1472.0000 693.0000 356.0000 322.0000 1055.0000 +48.1250 228.0000 2928.0000 2946.0000 1480.0000 696.0000 355.0000 310.0000 1057.0000 +48.1667 228.0000 2921.0000 2934.0000 1487.0000 694.0000 360.0000 318.0000 1058.0000 +48.2083 228.0000 2919.0000 2930.0000 1495.0000 691.0000 362.0000 316.0000 1059.0000 +48.2500 228.0000 2922.0000 2912.0000 1496.0000 698.0000 354.0000 328.0000 1062.0000 +48.2917 228.0000 2927.0000 2902.0000 1501.0000 701.0000 354.0000 322.0000 1065.0000 +48.3333 228.0000 2929.0000 2893.0000 1497.0000 702.0000 351.0000 334.0000 1066.0000 +48.3750 228.0000 2926.0000 2892.0000 1491.0000 710.0000 345.0000 339.0000 1069.0000 +48.4167 228.0000 2930.0000 2872.0000 1499.0000 714.0000 343.0000 345.0000 1069.0000 +48.4583 228.0000 2918.0000 2879.0000 1484.0000 714.0000 343.0000 362.0000 1072.0000 +48.5000 228.0000 2917.0000 2876.0000 1487.0000 718.0000 342.0000 359.0000 1073.0000 +48.5417 228.0000 2905.0000 2892.0000 1484.0000 720.0000 340.0000 355.0000 1076.0000 +48.5833 227.0000 2896.0000 2901.0000 1481.0000 725.0000 340.0000 353.0000 1077.0000 +48.6250 227.0000 2897.0000 2894.0000 1483.0000 724.0000 339.0000 357.0000 1079.0000 +48.6667 227.0000 2908.0000 2888.0000 1483.0000 721.0000 343.0000 351.0000 1079.0000 +48.7083 227.0000 2925.0000 2881.0000 1473.0000 726.0000 343.0000 343.0000 1082.0000 +48.7500 227.0000 2944.0000 2877.0000 1484.0000 723.0000 344.0000 316.0000 1085.0000 +48.7917 227.0000 2938.0000 2883.0000 1481.0000 722.0000 347.0000 316.0000 1086.0000 +48.8333 227.0000 2936.0000 2882.0000 1487.0000 723.0000 348.0000 311.0000 1086.0000 +48.8750 227.0000 2929.0000 2889.0000 1491.0000 720.0000 348.0000 310.0000 1086.0000 +48.9167 227.0000 2927.0000 2897.0000 1487.0000 722.0000 348.0000 304.0000 1088.0000 +48.9583 227.0000 2918.0000 2908.0000 1481.0000 716.0000 354.0000 308.0000 1088.0000 +49.0000 227.0000 2918.0000 2901.0000 1489.0000 718.0000 352.0000 307.0000 1088.0000 +49.0417 227.0000 2913.0000 2894.0000 1489.0000 723.0000 347.0000 317.0000 1090.0000 +49.0833 227.0000 2915.0000 2890.0000 1489.0000 729.0000 348.0000 312.0000 1090.0000 +49.1250 227.0000 2910.0000 2896.0000 1490.0000 717.0000 356.0000 313.0000 1091.0000 +49.1667 227.0000 2902.0000 2896.0000 1490.0000 719.0000 352.0000 320.0000 1094.0000 +49.2083 227.0000 2903.0000 2899.0000 1487.0000 717.0000 353.0000 319.0000 1095.0000 +49.2500 227.0000 2896.0000 2916.0000 1470.0000 723.0000 355.0000 316.0000 1097.0000 +49.2917 227.0000 2891.0000 2912.0000 1470.0000 728.0000 353.0000 322.0000 1097.0000 +49.3333 227.0000 2878.0000 2902.0000 1478.0000 731.0000 352.0000 332.0000 1100.0000 +49.3750 227.0000 2873.0000 2903.0000 1472.0000 740.0000 347.0000 335.0000 1103.0000 +49.4167 227.0000 2869.0000 2894.0000 1474.0000 741.0000 346.0000 345.0000 1104.0000 +49.4583 227.0000 2877.0000 2885.0000 1470.0000 742.0000 348.0000 345.0000 1106.0000 +49.5000 226.0000 2857.0000 2898.0000 1467.0000 739.0000 349.0000 355.0000 1109.0000 +49.5417 226.0000 2857.0000 2894.0000 1471.0000 741.0000 347.0000 354.0000 1110.0000 +49.5833 226.0000 2851.0000 2894.0000 1471.0000 748.0000 347.0000 352.0000 1111.0000 +49.6250 226.0000 2847.0000 2890.0000 1468.0000 751.0000 342.0000 364.0000 1112.0000 +49.6667 226.0000 2857.0000 2886.0000 1468.0000 752.0000 340.0000 357.0000 1114.0000 +49.7083 226.0000 2870.0000 2888.0000 1470.0000 751.0000 339.0000 340.0000 1116.0000 +49.7500 226.0000 2883.0000 2887.0000 1464.0000 756.0000 338.0000 327.0000 1119.0000 +49.7917 226.0000 2892.0000 2889.0000 1461.0000 754.0000 337.0000 322.0000 1119.0000 +49.8333 226.0000 2897.0000 2873.0000 1465.0000 751.0000 340.0000 328.0000 1120.0000 +49.8750 226.0000 2900.0000 2864.0000 1470.0000 752.0000 338.0000 326.0000 1124.0000 +49.9167 226.0000 2906.0000 2863.0000 1475.0000 752.0000 336.0000 317.0000 1125.0000 +49.9583 226.0000 2901.0000 2865.0000 1473.0000 748.0000 340.0000 322.0000 1125.0000 +50.0000 226.0000 2897.0000 2874.0000 1469.0000 744.0000 336.0000 325.0000 1129.0000 +50.0417 226.0000 2900.0000 2885.0000 1462.0000 744.0000 334.0000 319.0000 1130.0000 +50.0833 226.0000 2893.0000 2890.0000 1461.0000 746.0000 337.0000 317.0000 1130.0000 +50.1250 226.0000 2886.0000 2887.0000 1466.0000 747.0000 332.0000 324.0000 1132.0000 +50.1667 226.0000 2883.0000 2889.0000 1467.0000 749.0000 335.0000 319.0000 1132.0000 +50.2083 226.0000 2871.0000 2890.0000 1479.0000 748.0000 333.0000 317.0000 1136.0000 +50.2500 226.0000 2856.0000 2898.0000 1470.0000 754.0000 331.0000 328.0000 1137.0000 +50.2917 226.0000 2851.0000 2904.0000 1465.0000 753.0000 334.0000 330.0000 1137.0000 +50.3333 226.0000 2848.0000 2900.0000 1463.0000 744.0000 333.0000 346.0000 1140.0000 +50.3750 225.0000 2832.0000 2909.0000 1463.0000 738.0000 331.0000 358.0000 1144.0000 +50.4167 224.0000 2834.0000 2917.0000 1458.0000 745.0000 332.0000 346.0000 1144.0000 +50.4583 224.0000 2837.0000 2911.0000 1459.0000 744.0000 332.0000 348.0000 1145.0000 +50.5000 224.0000 2830.0000 2912.0000 1460.0000 743.0000 331.0000 353.0000 1147.0000 +50.5417 224.0000 2836.0000 2907.0000 1455.0000 746.0000 333.0000 351.0000 1148.0000 +50.5833 224.0000 2829.0000 2917.0000 1449.0000 748.0000 333.0000 351.0000 1149.0000 +50.6250 224.0000 2832.0000 2906.0000 1447.0000 749.0000 331.0000 360.0000 1151.0000 +50.6667 224.0000 2833.0000 2900.0000 1444.0000 747.0000 333.0000 368.0000 1151.0000 +50.7083 224.0000 2860.0000 2903.0000 1441.0000 745.0000 334.0000 342.0000 1151.0000 +50.7500 224.0000 2871.0000 2895.0000 1447.0000 743.0000 336.0000 331.0000 1153.0000 +50.7917 224.0000 2880.0000 2900.0000 1452.0000 744.0000 335.0000 311.0000 1154.0000 +50.8333 224.0000 2881.0000 2901.0000 1444.0000 747.0000 336.0000 313.0000 1154.0000 +50.8750 224.0000 2877.0000 2897.0000 1456.0000 744.0000 338.0000 310.0000 1154.0000 +50.9167 224.0000 2867.0000 2889.0000 1468.0000 741.0000 340.0000 314.0000 1157.0000 +50.9583 224.0000 2874.0000 2885.0000 1453.0000 744.0000 338.0000 324.0000 1158.0000 +51.0000 224.0000 2883.0000 2889.0000 1448.0000 745.0000 342.0000 310.0000 1159.0000 +51.0417 224.0000 2886.0000 2889.0000 1447.0000 739.0000 345.0000 311.0000 1159.0000 +51.0833 224.0000 2878.0000 2892.0000 1442.0000 742.0000 344.0000 318.0000 1160.0000 +51.1250 224.0000 2883.0000 2884.0000 1445.0000 744.0000 344.0000 315.0000 1161.0000 +51.1667 224.0000 2877.0000 2890.0000 1446.0000 741.0000 346.0000 313.0000 1163.0000 +51.2083 224.0000 2866.0000 2905.0000 1440.0000 746.0000 348.0000 308.0000 1163.0000 +51.2500 224.0000 2867.0000 2896.0000 1440.0000 746.0000 348.0000 313.0000 1166.0000 +51.2917 224.0000 2856.0000 2906.0000 1433.0000 744.0000 348.0000 322.0000 1167.0000 +51.3333 224.0000 2857.0000 2901.0000 1440.0000 741.0000 352.0000 317.0000 1168.0000 +51.3750 223.0000 2846.0000 2902.0000 1434.0000 743.0000 350.0000 330.0000 1172.0000 +51.4167 223.0000 2840.0000 2900.0000 1438.0000 739.0000 347.0000 338.0000 1175.0000 +51.4583 222.0000 2835.0000 2905.0000 1438.0000 734.0000 347.0000 341.0000 1178.0000 +51.5000 222.0000 2832.0000 2901.0000 1442.0000 729.0000 350.0000 344.0000 1180.0000 +51.5417 221.0000 2829.0000 2910.0000 1440.0000 727.0000 349.0000 343.0000 1181.0000 +51.5833 221.0000 2826.0000 2919.0000 1435.0000 719.0000 350.0000 347.0000 1183.0000 +51.6250 221.0000 2826.0000 2922.0000 1437.0000 711.0000 356.0000 342.0000 1185.0000 +51.6667 221.0000 2817.0000 2938.0000 1432.0000 709.0000 356.0000 341.0000 1186.0000 +51.7083 221.0000 2842.0000 2923.0000 1436.0000 713.0000 355.0000 321.0000 1189.0000 +51.7500 221.0000 2854.0000 2922.0000 1427.0000 719.0000 354.0000 312.0000 1191.0000 +51.7917 221.0000 2862.0000 2918.0000 1430.0000 714.0000 353.0000 309.0000 1193.0000 +51.8333 220.0000 2853.0000 2928.0000 1438.0000 715.0000 351.0000 300.0000 1195.0000 +51.8750 220.0000 2846.0000 2932.0000 1432.0000 719.0000 351.0000 305.0000 1195.0000 +51.9167 220.0000 2845.0000 2934.0000 1432.0000 713.0000 352.0000 305.0000 1199.0000 +51.9583 220.0000 2865.0000 2915.0000 1434.0000 715.0000 351.0000 298.0000 1202.0000 +52.0000 220.0000 2860.0000 2915.0000 1443.0000 714.0000 353.0000 293.0000 1202.0000 +52.0417 220.0000 2854.0000 2912.0000 1436.0000 720.0000 351.0000 304.0000 1203.0000 +52.0833 220.0000 2847.0000 2915.0000 1429.0000 720.0000 356.0000 309.0000 1204.0000 +52.1250 220.0000 2838.0000 2924.0000 1427.0000 723.0000 356.0000 307.0000 1205.0000 +52.1667 220.0000 2829.0000 2928.0000 1432.0000 725.0000 356.0000 303.0000 1207.0000 +52.2083 220.0000 2822.0000 2919.0000 1437.0000 724.0000 353.0000 315.0000 1210.0000 +52.2500 220.0000 2826.0000 2915.0000 1437.0000 721.0000 349.0000 318.0000 1214.0000 +52.2917 220.0000 2832.0000 2904.0000 1430.0000 719.0000 349.0000 330.0000 1216.0000 +52.3333 220.0000 2835.0000 2892.0000 1431.0000 723.0000 348.0000 334.0000 1217.0000 +52.3750 220.0000 2821.0000 2896.0000 1431.0000 726.0000 341.0000 347.0000 1218.0000 +52.4167 220.0000 2826.0000 2902.0000 1419.0000 723.0000 341.0000 350.0000 1219.0000 +52.4583 219.0000 2818.0000 2901.0000 1421.0000 725.0000 340.0000 357.0000 1219.0000 +52.5000 218.0000 2815.0000 2910.0000 1409.0000 726.0000 339.0000 361.0000 1222.0000 +52.5417 218.0000 2828.0000 2901.0000 1404.0000 722.0000 341.0000 364.0000 1222.0000 +52.5833 217.0000 2823.0000 2912.0000 1401.0000 723.0000 339.0000 361.0000 1224.0000 +52.6250 217.0000 2829.0000 2908.0000 1399.0000 724.0000 335.0000 360.0000 1228.0000 +52.6667 217.0000 2848.0000 2896.0000 1402.0000 730.0000 333.0000 342.0000 1232.0000 +52.7083 217.0000 2852.0000 2885.0000 1415.0000 729.0000 331.0000 338.0000 1233.0000 +52.7500 217.0000 2873.0000 2885.0000 1420.0000 730.0000 331.0000 311.0000 1233.0000 +52.7917 217.0000 2856.0000 2893.0000 1418.0000 732.0000 329.0000 320.0000 1235.0000 +52.8333 217.0000 2857.0000 2904.0000 1411.0000 733.0000 330.0000 313.0000 1235.0000 +52.8750 217.0000 2865.0000 2889.0000 1421.0000 725.0000 330.0000 317.0000 1236.0000 +52.9167 217.0000 2866.0000 2893.0000 1412.0000 730.0000 332.0000 313.0000 1237.0000 +52.9583 217.0000 2860.0000 2897.0000 1407.0000 734.0000 330.0000 317.0000 1238.0000 +53.0000 217.0000 2868.0000 2898.0000 1400.0000 737.0000 332.0000 310.0000 1238.0000 +53.0417 217.0000 2863.0000 2894.0000 1401.0000 733.0000 333.0000 319.0000 1240.0000 +53.0833 217.0000 2861.0000 2894.0000 1399.0000 739.0000 332.0000 318.0000 1240.0000 +53.1250 217.0000 2848.0000 2908.0000 1395.0000 737.0000 336.0000 319.0000 1240.0000 +53.1667 217.0000 2842.0000 2907.0000 1394.0000 744.0000 335.0000 319.0000 1242.0000 +53.2083 217.0000 2841.0000 2893.0000 1394.0000 747.0000 332.0000 331.0000 1245.0000 +53.2500 217.0000 2837.0000 2895.0000 1398.0000 748.0000 333.0000 326.0000 1246.0000 +53.2917 217.0000 2842.0000 2895.0000 1399.0000 747.0000 332.0000 322.0000 1246.0000 +53.3333 217.0000 2822.0000 2895.0000 1410.0000 742.0000 327.0000 339.0000 1248.0000 +53.3750 217.0000 2816.0000 2897.0000 1403.0000 743.0000 327.0000 349.0000 1248.0000 +53.4167 217.0000 2817.0000 2893.0000 1404.0000 752.0000 328.0000 339.0000 1250.0000 +53.4583 216.0000 2808.0000 2892.0000 1400.0000 754.0000 329.0000 350.0000 1251.0000 +53.5000 216.0000 2798.0000 2898.0000 1400.0000 754.0000 330.0000 352.0000 1252.0000 +53.5417 216.0000 2805.0000 2890.0000 1397.0000 752.0000 330.0000 358.0000 1252.0000 +53.5833 216.0000 2810.0000 2896.0000 1394.0000 750.0000 335.0000 347.0000 1252.0000 +53.6250 215.0000 2800.0000 2903.0000 1396.0000 753.0000 336.0000 344.0000 1253.0000 +53.6667 215.0000 2795.0000 2895.0000 1413.0000 752.0000 331.0000 345.0000 1254.0000 +53.7083 215.0000 2801.0000 2894.0000 1407.0000 750.0000 327.0000 350.0000 1256.0000 +53.7500 215.0000 2823.0000 2888.0000 1414.0000 748.0000 320.0000 330.0000 1262.0000 +53.7917 215.0000 2830.0000 2895.0000 1413.0000 747.0000 320.0000 316.0000 1264.0000 +53.8333 215.0000 2811.0000 2905.0000 1416.0000 746.0000 321.0000 322.0000 1264.0000 +53.8750 215.0000 2800.0000 2916.0000 1411.0000 748.0000 319.0000 323.0000 1268.0000 +53.9167 215.0000 2802.0000 2922.0000 1408.0000 748.0000 319.0000 316.0000 1270.0000 +53.9583 215.0000 2803.0000 2926.0000 1412.0000 746.0000 318.0000 307.0000 1273.0000 +54.0000 215.0000 2793.0000 2919.0000 1409.0000 752.0000 321.0000 317.0000 1274.0000 +54.0417 215.0000 2795.0000 2901.0000 1416.0000 749.0000 323.0000 327.0000 1274.0000 +54.0833 215.0000 2791.0000 2905.0000 1418.0000 751.0000 322.0000 321.0000 1277.0000 +54.1250 215.0000 2788.0000 2907.0000 1418.0000 750.0000 322.0000 321.0000 1279.0000 +54.1667 215.0000 2780.0000 2913.0000 1415.0000 753.0000 320.0000 322.0000 1282.0000 +54.2083 215.0000 2784.0000 2899.0000 1412.0000 762.0000 320.0000 325.0000 1283.0000 +54.2500 215.0000 2775.0000 2904.0000 1412.0000 758.0000 321.0000 331.0000 1284.0000 +54.2917 215.0000 2783.0000 2899.0000 1415.0000 757.0000 321.0000 323.0000 1287.0000 +54.3333 215.0000 2780.0000 2894.0000 1421.0000 751.0000 322.0000 329.0000 1288.0000 +54.3750 215.0000 2764.0000 2891.0000 1413.0000 755.0000 323.0000 351.0000 1288.0000 +54.4167 215.0000 2752.0000 2889.0000 1416.0000 751.0000 326.0000 361.0000 1290.0000 +54.4583 215.0000 2738.0000 2904.0000 1417.0000 746.0000 329.0000 358.0000 1293.0000 +54.5000 214.0000 2731.0000 2901.0000 1416.0000 745.0000 332.0000 368.0000 1293.0000 +54.5417 214.0000 2740.0000 2898.0000 1418.0000 749.0000 334.0000 354.0000 1293.0000 +54.5833 214.0000 2725.0000 2899.0000 1415.0000 748.0000 334.0000 370.0000 1295.0000 +54.6250 214.0000 2720.0000 2892.0000 1425.0000 743.0000 336.0000 375.0000 1295.0000 +54.6667 214.0000 2728.0000 2890.0000 1428.0000 745.0000 334.0000 364.0000 1297.0000 +54.7083 214.0000 2731.0000 2893.0000 1423.0000 753.0000 333.0000 355.0000 1298.0000 +54.7500 214.0000 2750.0000 2886.0000 1421.0000 758.0000 330.0000 341.0000 1300.0000 +54.7917 214.0000 2772.0000 2879.0000 1422.0000 762.0000 326.0000 323.0000 1302.0000 +54.8333 214.0000 2772.0000 2858.0000 1427.0000 764.0000 326.0000 336.0000 1303.0000 +54.8750 214.0000 2775.0000 2863.0000 1416.0000 761.0000 329.0000 337.0000 1305.0000 +54.9167 214.0000 2788.0000 2856.0000 1427.0000 764.0000 324.0000 319.0000 1308.0000 +54.9583 214.0000 2775.0000 2865.0000 1424.0000 771.0000 324.0000 318.0000 1309.0000 +55.0000 214.0000 2773.0000 2864.0000 1428.0000 766.0000 325.0000 318.0000 1312.0000 +55.0417 214.0000 2769.0000 2861.0000 1428.0000 778.0000 323.0000 315.0000 1312.0000 +55.0833 214.0000 2768.0000 2864.0000 1420.0000 779.0000 322.0000 319.0000 1314.0000 +55.1250 214.0000 2762.0000 2858.0000 1429.0000 776.0000 325.0000 321.0000 1315.0000 +55.1667 214.0000 2752.0000 2873.0000 1423.0000 777.0000 322.0000 321.0000 1318.0000 +55.2083 214.0000 2745.0000 2870.0000 1420.0000 772.0000 325.0000 334.0000 1320.0000 +55.2500 214.0000 2748.0000 2870.0000 1417.0000 778.0000 323.0000 328.0000 1322.0000 +55.2917 214.0000 2738.0000 2867.0000 1426.0000 772.0000 325.0000 335.0000 1323.0000 +55.3333 214.0000 2740.0000 2864.0000 1428.0000 766.0000 330.0000 334.0000 1324.0000 +55.3750 214.0000 2731.0000 2864.0000 1432.0000 769.0000 326.0000 337.0000 1327.0000 +55.4167 214.0000 2721.0000 2863.0000 1432.0000 771.0000 327.0000 345.0000 1327.0000 +55.4583 214.0000 2724.0000 2850.0000 1426.0000 778.0000 327.0000 352.0000 1329.0000 +55.5000 214.0000 2710.0000 2848.0000 1427.0000 772.0000 330.0000 369.0000 1330.0000 +55.5417 214.0000 2722.0000 2830.0000 1431.0000 771.0000 330.0000 370.0000 1332.0000 +55.5833 214.0000 2726.0000 2822.0000 1436.0000 768.0000 334.0000 367.0000 1333.0000 +55.6250 214.0000 2720.0000 2808.0000 1437.0000 767.0000 331.0000 388.0000 1335.0000 +55.6667 214.0000 2728.0000 2811.0000 1436.0000 769.0000 330.0000 377.0000 1335.0000 +55.7083 214.0000 2745.0000 2808.0000 1440.0000 771.0000 332.0000 355.0000 1335.0000 +55.7500 214.0000 2755.0000 2814.0000 1428.0000 778.0000 328.0000 345.0000 1338.0000 +55.7917 214.0000 2761.0000 2809.0000 1432.0000 779.0000 327.0000 338.0000 1340.0000 +55.8333 214.0000 2772.0000 2794.0000 1437.0000 782.0000 328.0000 332.0000 1341.0000 +55.8750 214.0000 2776.0000 2796.0000 1435.0000 783.0000 329.0000 325.0000 1342.0000 +55.9167 214.0000 2785.0000 2792.0000 1432.0000 785.0000 330.0000 320.0000 1342.0000 +55.9583 214.0000 2787.0000 2792.0000 1434.0000 781.0000 332.0000 313.0000 1347.0000 +56.0000 214.0000 2787.0000 2794.0000 1421.0000 778.0000 336.0000 323.0000 1347.0000 +56.0417 214.0000 2789.0000 2787.0000 1419.0000 782.0000 333.0000 328.0000 1348.0000 +56.0833 214.0000 2791.0000 2785.0000 1413.0000 785.0000 338.0000 326.0000 1348.0000 +56.1250 214.0000 2795.0000 2783.0000 1412.0000 785.0000 337.0000 323.0000 1351.0000 +56.1667 214.0000 2794.0000 2784.0000 1409.0000 781.0000 339.0000 327.0000 1352.0000 +56.2083 214.0000 2795.0000 2792.0000 1393.0000 783.0000 338.0000 331.0000 1354.0000 +56.2500 214.0000 2783.0000 2792.0000 1387.0000 784.0000 337.0000 347.0000 1356.0000 +56.2917 214.0000 2791.0000 2795.0000 1383.0000 782.0000 341.0000 337.0000 1357.0000 +56.3333 214.0000 2785.0000 2792.0000 1381.0000 784.0000 338.0000 346.0000 1360.0000 +56.3750 214.0000 2778.0000 2789.0000 1393.0000 778.0000 338.0000 349.0000 1361.0000 +56.4167 214.0000 2770.0000 2789.0000 1394.0000 777.0000 337.0000 358.0000 1361.0000 +56.4583 214.0000 2765.0000 2790.0000 1390.0000 780.0000 340.0000 359.0000 1362.0000 +56.5000 214.0000 2764.0000 2790.0000 1386.0000 782.0000 340.0000 361.0000 1363.0000 +56.5417 214.0000 2762.0000 2796.0000 1383.0000 783.0000 341.0000 357.0000 1364.0000 +56.5833 214.0000 2762.0000 2795.0000 1378.0000 785.0000 336.0000 359.0000 1371.0000 +56.6250 214.0000 2757.0000 2785.0000 1380.0000 788.0000 336.0000 369.0000 1371.0000 +56.6667 214.0000 2765.0000 2788.0000 1384.0000 782.0000 335.0000 360.0000 1372.0000 +56.7083 214.0000 2771.0000 2794.0000 1379.0000 782.0000 334.0000 350.0000 1376.0000 +56.7500 214.0000 2794.0000 2790.0000 1375.0000 782.0000 334.0000 332.0000 1379.0000 +56.7917 214.0000 2804.0000 2785.0000 1372.0000 780.0000 336.0000 330.0000 1379.0000 +56.8333 214.0000 2817.0000 2774.0000 1383.0000 773.0000 335.0000 320.0000 1384.0000 +56.8750 214.0000 2811.0000 2772.0000 1381.0000 778.0000 333.0000 327.0000 1384.0000 +56.9167 214.0000 2807.0000 2782.0000 1380.0000 780.0000 333.0000 317.0000 1387.0000 +56.9583 214.0000 2796.0000 2783.0000 1382.0000 784.0000 334.0000 318.0000 1389.0000 +57.0000 214.0000 2797.0000 2780.0000 1374.0000 789.0000 333.0000 323.0000 1390.0000 +57.0417 214.0000 2794.0000 2770.0000 1382.0000 788.0000 334.0000 325.0000 1393.0000 +57.0833 214.0000 2781.0000 2783.0000 1379.0000 788.0000 334.0000 328.0000 1393.0000 +57.1250 214.0000 2782.0000 2780.0000 1379.0000 787.0000 337.0000 327.0000 1394.0000 +57.1667 214.0000 2776.0000 2780.0000 1381.0000 784.0000 339.0000 331.0000 1395.0000 +57.2083 214.0000 2787.0000 2767.0000 1388.0000 784.0000 341.0000 324.0000 1395.0000 +57.2500 214.0000 2786.0000 2761.0000 1394.0000 782.0000 338.0000 328.0000 1397.0000 +57.2917 214.0000 2785.0000 2765.0000 1393.0000 784.0000 336.0000 324.0000 1399.0000 +57.3333 214.0000 2774.0000 2767.0000 1390.0000 781.0000 340.0000 334.0000 1400.0000 +57.3750 214.0000 2770.0000 2756.0000 1397.0000 776.0000 343.0000 343.0000 1401.0000 +57.4167 214.0000 2759.0000 2757.0000 1391.0000 778.0000 347.0000 353.0000 1401.0000 +57.4583 214.0000 2752.0000 2761.0000 1391.0000 778.0000 347.0000 355.0000 1402.0000 +57.5000 214.0000 2742.0000 2750.0000 1394.0000 779.0000 347.0000 371.0000 1403.0000 +57.5417 214.0000 2745.0000 2750.0000 1392.0000 778.0000 347.0000 369.0000 1405.0000 +57.5833 214.0000 2741.0000 2759.0000 1394.0000 772.0000 349.0000 365.0000 1406.0000 +57.6250 214.0000 2735.0000 2767.0000 1394.0000 772.0000 350.0000 360.0000 1408.0000 +57.6667 214.0000 2745.0000 2766.0000 1393.0000 776.0000 347.0000 350.0000 1409.0000 +57.7083 214.0000 2751.0000 2763.0000 1396.0000 773.0000 348.0000 346.0000 1409.0000 +57.7500 214.0000 2769.0000 2760.0000 1397.0000 771.0000 351.0000 328.0000 1410.0000 +57.7917 214.0000 2771.0000 2761.0000 1402.0000 772.0000 351.0000 317.0000 1412.0000 +57.8333 214.0000 2766.0000 2765.0000 1398.0000 769.0000 355.0000 320.0000 1413.0000 +57.8750 214.0000 2770.0000 2769.0000 1394.0000 771.0000 354.0000 313.0000 1415.0000 +57.9167 214.0000 2766.0000 2768.0000 1393.0000 773.0000 353.0000 316.0000 1417.0000 +57.9583 214.0000 2769.0000 2771.0000 1381.0000 778.0000 350.0000 315.0000 1422.0000 +58.0000 214.0000 2747.0000 2791.0000 1378.0000 778.0000 349.0000 321.0000 1422.0000 +58.0417 214.0000 2750.0000 2788.0000 1370.0000 777.0000 354.0000 323.0000 1424.0000 +58.0833 214.0000 2748.0000 2783.0000 1376.0000 775.0000 348.0000 327.0000 1429.0000 +58.1250 214.0000 2746.0000 2774.0000 1378.0000 776.0000 350.0000 331.0000 1431.0000 +58.1667 214.0000 2749.0000 2776.0000 1378.0000 772.0000 350.0000 328.0000 1433.0000 +58.2083 214.0000 2738.0000 2778.0000 1376.0000 771.0000 351.0000 336.0000 1436.0000 +58.2500 214.0000 2736.0000 2784.0000 1372.0000 775.0000 351.0000 332.0000 1436.0000 +58.2917 214.0000 2731.0000 2776.0000 1369.0000 776.0000 350.0000 346.0000 1438.0000 +58.3333 214.0000 2738.0000 2781.0000 1365.0000 779.0000 349.0000 335.0000 1439.0000 +58.3750 214.0000 2731.0000 2781.0000 1363.0000 778.0000 350.0000 342.0000 1441.0000 +58.4167 214.0000 2727.0000 2783.0000 1366.0000 776.0000 350.0000 342.0000 1442.0000 +58.4583 214.0000 2724.0000 2776.0000 1357.0000 774.0000 349.0000 362.0000 1444.0000 +58.5000 214.0000 2717.0000 2780.0000 1355.0000 769.0000 352.0000 367.0000 1446.0000 +58.5417 214.0000 2727.0000 2788.0000 1353.0000 760.0000 352.0000 360.0000 1446.0000 +58.5833 214.0000 2734.0000 2785.0000 1354.0000 756.0000 354.0000 355.0000 1448.0000 +58.6250 214.0000 2745.0000 2780.0000 1354.0000 751.0000 354.0000 353.0000 1449.0000 +58.6667 214.0000 2742.0000 2795.0000 1353.0000 748.0000 353.0000 343.0000 1452.0000 +58.7083 214.0000 2741.0000 2803.0000 1356.0000 743.0000 356.0000 334.0000 1453.0000 +58.7500 214.0000 2758.0000 2806.0000 1353.0000 744.0000 350.0000 319.0000 1456.0000 +58.7917 214.0000 2764.0000 2809.0000 1355.0000 744.0000 352.0000 305.0000 1457.0000 +58.8333 214.0000 2742.0000 2825.0000 1344.0000 751.0000 353.0000 313.0000 1458.0000 +58.8750 214.0000 2741.0000 2824.0000 1339.0000 754.0000 354.0000 315.0000 1459.0000 +58.9167 214.0000 2749.0000 2818.0000 1332.0000 762.0000 353.0000 312.0000 1460.0000 +58.9583 214.0000 2750.0000 2817.0000 1331.0000 765.0000 358.0000 304.0000 1461.0000 +59.0000 214.0000 2746.0000 2821.0000 1330.0000 763.0000 359.0000 306.0000 1461.0000 +59.0417 214.0000 2737.0000 2824.0000 1326.0000 765.0000 356.0000 316.0000 1462.0000 +59.0833 214.0000 2730.0000 2832.0000 1318.0000 767.0000 355.0000 319.0000 1465.0000 +59.1250 214.0000 2723.0000 2842.0000 1321.0000 766.0000 358.0000 310.0000 1466.0000 +59.1667 214.0000 2714.0000 2844.0000 1315.0000 768.0000 354.0000 321.0000 1470.0000 +59.2083 214.0000 2708.0000 2847.0000 1312.0000 768.0000 354.0000 323.0000 1474.0000 +59.2500 214.0000 2700.0000 2861.0000 1311.0000 770.0000 352.0000 315.0000 1477.0000 +59.2917 214.0000 2682.0000 2865.0000 1306.0000 768.0000 354.0000 333.0000 1478.0000 +59.3333 214.0000 2682.0000 2868.0000 1299.0000 772.0000 353.0000 330.0000 1482.0000 +59.3750 214.0000 2684.0000 2860.0000 1306.0000 764.0000 354.0000 336.0000 1482.0000 +59.4167 214.0000 2669.0000 2857.0000 1308.0000 758.0000 356.0000 352.0000 1486.0000 +59.4583 214.0000 2660.0000 2859.0000 1313.0000 756.0000 355.0000 355.0000 1488.0000 +59.5000 214.0000 2655.0000 2858.0000 1311.0000 756.0000 356.0000 361.0000 1489.0000 +59.5417 214.0000 2659.0000 2858.0000 1313.0000 756.0000 357.0000 353.0000 1490.0000 +59.5833 214.0000 2660.0000 2853.0000 1315.0000 759.0000 361.0000 347.0000 1491.0000 +59.6250 214.0000 2652.0000 2834.0000 1325.0000 765.0000 358.0000 358.0000 1494.0000 +59.6667 214.0000 2663.0000 2819.0000 1330.0000 760.0000 358.0000 360.0000 1496.0000 +59.7083 212.0000 2670.0000 2821.0000 1331.0000 755.0000 356.0000 355.0000 1500.0000 +59.7500 212.0000 2702.0000 2820.0000 1328.0000 753.0000 357.0000 328.0000 1500.0000 +59.7917 211.0000 2723.0000 2812.0000 1321.0000 758.0000 357.0000 316.0000 1502.0000 +59.8333 211.0000 2721.0000 2806.0000 1317.0000 760.0000 356.0000 325.0000 1504.0000 +59.8750 211.0000 2723.0000 2805.0000 1312.0000 758.0000 359.0000 326.0000 1506.0000 +59.9167 210.0000 2732.0000 2798.0000 1305.0000 757.0000 356.0000 333.0000 1509.0000 +59.9583 210.0000 2737.0000 2808.0000 1307.0000 755.0000 357.0000 317.0000 1509.0000 +60.0000 210.0000 2734.0000 2803.0000 1310.0000 754.0000 355.0000 322.0000 1512.0000 diff --git a/pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_1.txt b/pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_1.txt new file mode 100644 index 0000000000..020d49c58c --- /dev/null +++ b/pycode/memilio-epidata/memilio/epidata/folder_run_bs/run_1.txt @@ -0,0 +1,1442 @@ +Time S E I_NS I_Sy I_Sev I_Crit R D + 0.0000 9480.0000 506.0000 6.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.0417 9412.0000 574.0000 6.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.0833 9354.0000 632.0000 6.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.1250 9294.0000 691.0000 7.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.1667 9232.0000 753.0000 7.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.2083 9168.0000 816.0000 8.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.2500 9103.0000 879.0000 10.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.2917 9039.0000 941.0000 12.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.3333 8988.0000 991.0000 13.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.3750 8958.0000 1016.0000 18.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.4167 8947.0000 1021.0000 24.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.4583 8934.0000 1025.0000 33.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.5000 8921.0000 1035.0000 36.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.5417 8910.0000 1040.0000 42.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.5833 8873.0000 1064.0000 55.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.6250 8846.0000 1083.0000 63.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.6667 8819.0000 1098.0000 75.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.7083 8784.0000 1125.0000 83.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.7500 8755.0000 1144.0000 93.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.7917 8742.0000 1144.0000 106.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.8333 8702.0000 1175.0000 115.0000 3.0000 0.0000 5.0000 0.0000 0.0000 + 0.8750 8655.0000 1207.0000 129.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 0.9167 8613.0000 1238.0000 140.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 0.9583 8538.0000 1299.0000 154.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 1.0000 8445.0000 1382.0000 164.0000 4.0000 0.0000 5.0000 0.0000 0.0000 + 1.0417 8344.0000 1474.0000 171.0000 6.0000 0.0000 5.0000 0.0000 0.0000 + 1.0833 8229.0000 1576.0000 183.0000 7.0000 0.0000 5.0000 0.0000 0.0000 + 1.1250 8118.0000 1673.0000 195.0000 7.0000 0.0000 5.0000 2.0000 0.0000 + 1.1667 8004.0000 1775.0000 206.0000 7.0000 0.0000 4.0000 3.0000 1.0000 + 1.2083 7887.0000 1882.0000 216.0000 7.0000 0.0000 4.0000 3.0000 1.0000 + 1.2500 7786.0000 1966.0000 232.0000 7.0000 0.0000 4.0000 4.0000 1.0000 + 1.2917 7656.0000 2079.0000 247.0000 8.0000 0.0000 4.0000 5.0000 1.0000 + 1.3333 7533.0000 2187.0000 258.0000 11.0000 0.0000 4.0000 6.0000 1.0000 + 1.3750 7464.0000 2237.0000 276.0000 12.0000 0.0000 4.0000 6.0000 1.0000 + 1.4167 7426.0000 2262.0000 289.0000 12.0000 0.0000 4.0000 6.0000 1.0000 + 1.4583 7403.0000 2268.0000 304.0000 13.0000 0.0000 4.0000 7.0000 1.0000 + 1.5000 7380.0000 2274.0000 319.0000 14.0000 0.0000 3.0000 8.0000 2.0000 + 1.5417 7350.0000 2291.0000 330.0000 14.0000 0.0000 3.0000 10.0000 2.0000 + 1.5833 7280.0000 2338.0000 350.0000 15.0000 0.0000 3.0000 12.0000 2.0000 + 1.6250 7200.0000 2402.0000 364.0000 16.0000 0.0000 3.0000 13.0000 2.0000 + 1.6667 7082.0000 2493.0000 388.0000 17.0000 0.0000 3.0000 15.0000 2.0000 + 1.7083 6985.0000 2570.0000 405.0000 17.0000 0.0000 3.0000 18.0000 2.0000 + 1.7500 6840.0000 2694.0000 425.0000 18.0000 0.0000 3.0000 18.0000 2.0000 + 1.7917 6673.0000 2843.0000 438.0000 20.0000 0.0000 3.0000 21.0000 2.0000 + 1.8333 6498.0000 2994.0000 461.0000 20.0000 0.0000 3.0000 22.0000 2.0000 + 1.8750 6304.0000 3167.0000 478.0000 21.0000 0.0000 3.0000 25.0000 2.0000 + 1.9167 6057.0000 3392.0000 498.0000 22.0000 0.0000 3.0000 26.0000 2.0000 + 1.9583 5767.0000 3656.0000 522.0000 24.0000 0.0000 3.0000 26.0000 2.0000 + 2.0000 5434.0000 3967.0000 541.0000 25.0000 0.0000 3.0000 28.0000 2.0000 + 2.0417 5137.0000 4229.0000 573.0000 27.0000 0.0000 3.0000 29.0000 2.0000 + 2.0833 4795.0000 4547.0000 593.0000 30.0000 0.0000 3.0000 30.0000 2.0000 + 2.1250 4507.0000 4800.0000 624.0000 33.0000 0.0000 3.0000 31.0000 2.0000 + 2.1667 4200.0000 5076.0000 656.0000 34.0000 0.0000 3.0000 29.0000 2.0000 + 2.2083 3925.0000 5313.0000 690.0000 40.0000 0.0000 3.0000 27.0000 2.0000 + 2.2500 3639.0000 5557.0000 730.0000 43.0000 0.0000 3.0000 26.0000 2.0000 + 2.2917 3406.0000 5758.0000 753.0000 52.0000 0.0000 2.0000 26.0000 3.0000 + 2.3333 3234.0000 5892.0000 792.0000 53.0000 0.0000 2.0000 24.0000 3.0000 + 2.3750 3117.0000 5955.0000 842.0000 55.0000 0.0000 2.0000 26.0000 3.0000 + 2.4167 3048.0000 5992.0000 864.0000 58.0000 0.0000 2.0000 33.0000 3.0000 + 2.4583 3006.0000 5982.0000 912.0000 59.0000 0.0000 2.0000 36.0000 3.0000 + 2.5000 2967.0000 5973.0000 952.0000 60.0000 0.0000 2.0000 43.0000 3.0000 + 2.5417 2886.0000 6009.0000 992.0000 59.0000 0.0000 2.0000 49.0000 3.0000 + 2.5833 2787.0000 6049.0000 1042.0000 65.0000 0.0000 2.0000 52.0000 3.0000 + 2.6250 2691.0000 6091.0000 1091.0000 69.0000 0.0000 2.0000 53.0000 3.0000 + 2.6667 2505.0000 6222.0000 1145.0000 72.0000 0.0000 2.0000 51.0000 3.0000 + 2.7083 2344.0000 6327.0000 1193.0000 81.0000 0.0000 2.0000 50.0000 3.0000 + 2.7500 2145.0000 6478.0000 1241.0000 87.0000 0.0000 2.0000 44.0000 3.0000 + 2.7917 1972.0000 6603.0000 1282.0000 97.0000 0.0000 2.0000 41.0000 3.0000 + 2.8333 1837.0000 6679.0000 1342.0000 101.0000 0.0000 2.0000 36.0000 3.0000 + 2.8750 1742.0000 6721.0000 1390.0000 111.0000 0.0000 2.0000 31.0000 3.0000 + 2.9167 1664.0000 6740.0000 1445.0000 121.0000 0.0000 2.0000 25.0000 3.0000 + 2.9583 1594.0000 6743.0000 1508.0000 125.0000 0.0000 2.0000 25.0000 3.0000 + 3.0000 1540.0000 6737.0000 1568.0000 126.0000 0.0000 2.0000 24.0000 3.0000 + 3.0417 1509.0000 6699.0000 1633.0000 130.0000 0.0000 2.0000 24.0000 3.0000 + 3.0833 1497.0000 6637.0000 1702.0000 134.0000 0.0000 2.0000 25.0000 3.0000 + 3.1250 1486.0000 6574.0000 1773.0000 139.0000 0.0000 2.0000 23.0000 3.0000 + 3.1667 1482.0000 6527.0000 1823.0000 143.0000 0.0000 2.0000 20.0000 3.0000 + 3.2083 1478.0000 6473.0000 1874.0000 150.0000 0.0000 2.0000 20.0000 3.0000 + 3.2500 1475.0000 6421.0000 1920.0000 158.0000 0.0000 2.0000 21.0000 3.0000 + 3.2917 1474.0000 6361.0000 1978.0000 161.0000 0.0000 2.0000 21.0000 3.0000 + 3.3333 1468.0000 6303.0000 2033.0000 171.0000 0.0000 2.0000 20.0000 3.0000 + 3.3750 1465.0000 6250.0000 2069.0000 177.0000 0.0000 2.0000 34.0000 3.0000 + 3.4167 1446.0000 6212.0000 2120.0000 181.0000 0.0000 2.0000 36.0000 3.0000 + 3.4583 1425.0000 6171.0000 2171.0000 189.0000 0.0000 2.0000 39.0000 3.0000 + 3.5000 1406.0000 6120.0000 2223.0000 201.0000 0.0000 2.0000 45.0000 3.0000 + 3.5417 1370.0000 6090.0000 2278.0000 209.0000 0.0000 2.0000 48.0000 3.0000 + 3.5833 1313.0000 6086.0000 2328.0000 210.0000 0.0000 2.0000 58.0000 3.0000 + 3.6250 1285.0000 6052.0000 2370.0000 224.0000 0.0000 2.0000 64.0000 3.0000 + 3.6667 1180.0000 6095.0000 2428.0000 233.0000 0.0000 2.0000 59.0000 3.0000 + 3.7083 1109.0000 6104.0000 2485.0000 240.0000 0.0000 2.0000 57.0000 3.0000 + 3.7500 1040.0000 6119.0000 2540.0000 247.0000 0.0000 2.0000 49.0000 3.0000 + 3.7917 1010.0000 6108.0000 2582.0000 258.0000 0.0000 2.0000 37.0000 3.0000 + 3.8333 1002.0000 6050.0000 2638.0000 267.0000 0.0000 2.0000 38.0000 3.0000 + 3.8750 997.0000 6011.0000 2679.0000 279.0000 0.0000 2.0000 29.0000 3.0000 + 3.9167 997.0000 5944.0000 2738.0000 284.0000 0.0000 2.0000 32.0000 3.0000 + 3.9583 997.0000 5891.0000 2786.0000 292.0000 0.0000 2.0000 29.0000 3.0000 + 4.0000 992.0000 5844.0000 2830.0000 303.0000 0.0000 2.0000 26.0000 3.0000 + 4.0417 991.0000 5791.0000 2867.0000 317.0000 0.0000 2.0000 29.0000 3.0000 + 4.0833 988.0000 5748.0000 2905.0000 326.0000 0.0000 2.0000 28.0000 3.0000 + 4.1250 987.0000 5692.0000 2949.0000 338.0000 0.0000 2.0000 29.0000 3.0000 + 4.1667 986.0000 5646.0000 2977.0000 349.0000 0.0000 2.0000 37.0000 3.0000 + 4.2083 982.0000 5591.0000 3023.0000 360.0000 0.0000 2.0000 39.0000 3.0000 + 4.2500 980.0000 5547.0000 3064.0000 373.0000 0.0000 2.0000 31.0000 3.0000 + 4.2917 978.0000 5484.0000 3107.0000 385.0000 0.0000 2.0000 41.0000 3.0000 + 4.3333 975.0000 5451.0000 3136.0000 393.0000 0.0000 2.0000 40.0000 3.0000 + 4.3750 972.0000 5396.0000 3160.0000 418.0000 0.0000 2.0000 49.0000 3.0000 + 4.4167 969.0000 5348.0000 3194.0000 431.0000 0.0000 2.0000 53.0000 3.0000 + 4.4583 953.0000 5304.0000 3233.0000 435.0000 0.0000 2.0000 70.0000 3.0000 + 4.5000 946.0000 5263.0000 3257.0000 446.0000 0.0000 2.0000 83.0000 3.0000 + 4.5417 936.0000 5221.0000 3292.0000 461.0000 0.0000 2.0000 85.0000 3.0000 + 4.5833 914.0000 5192.0000 3328.0000 475.0000 0.0000 2.0000 86.0000 3.0000 + 4.6250 910.0000 5151.0000 3359.0000 486.0000 0.0000 2.0000 89.0000 3.0000 + 4.6667 899.0000 5143.0000 3362.0000 498.0000 0.0000 2.0000 93.0000 3.0000 + 4.7083 886.0000 5145.0000 3365.0000 515.0000 0.0000 2.0000 84.0000 3.0000 + 4.7500 867.0000 5150.0000 3393.0000 522.0000 0.0000 2.0000 63.0000 3.0000 + 4.7917 865.0000 5125.0000 3409.0000 534.0000 0.0000 2.0000 62.0000 3.0000 + 4.8333 862.0000 5095.0000 3439.0000 543.0000 0.0000 2.0000 56.0000 3.0000 + 4.8750 862.0000 5055.0000 3467.0000 550.0000 0.0000 2.0000 61.0000 3.0000 + 4.9167 862.0000 5019.0000 3489.0000 565.0000 1.0000 2.0000 59.0000 3.0000 + 4.9583 861.0000 4986.0000 3515.0000 582.0000 1.0000 2.0000 50.0000 3.0000 + 5.0000 861.0000 4934.0000 3555.0000 597.0000 1.0000 2.0000 47.0000 3.0000 + 5.0417 861.0000 4898.0000 3565.0000 615.0000 1.0000 2.0000 55.0000 3.0000 + 5.0833 859.0000 4875.0000 3572.0000 626.0000 1.0000 2.0000 62.0000 3.0000 + 5.1250 859.0000 4853.0000 3590.0000 631.0000 2.0000 2.0000 60.0000 3.0000 + 5.1667 856.0000 4821.0000 3620.0000 636.0000 2.0000 2.0000 60.0000 3.0000 + 5.2083 855.0000 4795.0000 3620.0000 651.0000 2.0000 2.0000 72.0000 3.0000 + 5.2500 853.0000 4772.0000 3632.0000 670.0000 2.0000 2.0000 66.0000 3.0000 + 5.2917 851.0000 4743.0000 3636.0000 689.0000 2.0000 2.0000 74.0000 3.0000 + 5.3333 850.0000 4717.0000 3651.0000 701.0000 2.0000 2.0000 74.0000 3.0000 + 5.3750 843.0000 4692.0000 3672.0000 716.0000 2.0000 2.0000 70.0000 3.0000 + 5.4167 836.0000 4654.0000 3697.0000 723.0000 2.0000 2.0000 83.0000 3.0000 + 5.4583 825.0000 4632.0000 3710.0000 737.0000 2.0000 2.0000 89.0000 3.0000 + 5.5000 821.0000 4616.0000 3715.0000 745.0000 2.0000 2.0000 96.0000 3.0000 + 5.5417 815.0000 4595.0000 3734.0000 754.0000 2.0000 2.0000 95.0000 3.0000 + 5.5833 811.0000 4572.0000 3740.0000 767.0000 2.0000 2.0000 103.0000 3.0000 + 5.6250 807.0000 4557.0000 3745.0000 778.0000 2.0000 2.0000 106.0000 3.0000 + 5.6667 803.0000 4536.0000 3760.0000 789.0000 2.0000 2.0000 105.0000 3.0000 + 5.7083 802.0000 4528.0000 3775.0000 800.0000 2.0000 2.0000 88.0000 3.0000 + 5.7500 801.0000 4529.0000 3777.0000 816.0000 2.0000 2.0000 70.0000 3.0000 + 5.7917 795.0000 4517.0000 3783.0000 830.0000 2.0000 2.0000 68.0000 3.0000 + 5.8333 795.0000 4491.0000 3794.0000 842.0000 2.0000 2.0000 71.0000 3.0000 + 5.8750 795.0000 4478.0000 3788.0000 864.0000 2.0000 2.0000 68.0000 3.0000 + 5.9167 794.0000 4455.0000 3798.0000 877.0000 2.0000 2.0000 69.0000 3.0000 + 5.9583 792.0000 4448.0000 3801.0000 891.0000 2.0000 2.0000 61.0000 3.0000 + 6.0000 791.0000 4430.0000 3808.0000 906.0000 2.0000 2.0000 58.0000 3.0000 + 6.0417 791.0000 4409.0000 3807.0000 923.0000 2.0000 2.0000 63.0000 3.0000 + 6.0833 791.0000 4404.0000 3803.0000 932.0000 2.0000 2.0000 63.0000 3.0000 + 6.1250 791.0000 4391.0000 3798.0000 944.0000 2.0000 2.0000 69.0000 3.0000 + 6.1667 789.0000 4368.0000 3807.0000 962.0000 2.0000 2.0000 67.0000 3.0000 + 6.2083 789.0000 4353.0000 3802.0000 977.0000 2.0000 2.0000 72.0000 3.0000 + 6.2500 787.0000 4336.0000 3804.0000 982.0000 2.0000 2.0000 84.0000 3.0000 + 6.2917 786.0000 4324.0000 3812.0000 993.0000 2.0000 2.0000 78.0000 3.0000 + 6.3333 784.0000 4309.0000 3809.0000 1002.0000 2.0000 2.0000 89.0000 3.0000 + 6.3750 783.0000 4286.0000 3802.0000 1011.0000 2.0000 2.0000 111.0000 3.0000 + 6.4167 782.0000 4258.0000 3813.0000 1018.0000 2.0000 2.0000 122.0000 3.0000 + 6.4583 778.0000 4245.0000 3813.0000 1028.0000 2.0000 2.0000 129.0000 3.0000 + 6.5000 768.0000 4219.0000 3847.0000 1033.0000 2.0000 2.0000 126.0000 3.0000 + 6.5417 764.0000 4202.0000 3845.0000 1043.0000 2.0000 2.0000 139.0000 3.0000 + 6.5833 760.0000 4195.0000 3841.0000 1051.0000 2.0000 2.0000 146.0000 3.0000 + 6.6250 755.0000 4185.0000 3844.0000 1062.0000 2.0000 2.0000 147.0000 3.0000 + 6.6667 752.0000 4190.0000 3851.0000 1068.0000 3.0000 2.0000 131.0000 3.0000 + 6.7083 749.0000 4195.0000 3845.0000 1084.0000 3.0000 2.0000 119.0000 3.0000 + 6.7500 749.0000 4216.0000 3838.0000 1098.0000 4.0000 2.0000 90.0000 3.0000 + 6.7917 748.0000 4212.0000 3844.0000 1110.0000 4.0000 2.0000 77.0000 3.0000 + 6.8333 746.0000 4193.0000 3852.0000 1124.0000 4.0000 2.0000 76.0000 3.0000 + 6.8750 745.0000 4189.0000 3849.0000 1136.0000 4.0000 2.0000 72.0000 3.0000 + 6.9167 744.0000 4189.0000 3833.0000 1147.0000 7.0000 2.0000 75.0000 3.0000 + 6.9583 742.0000 4188.0000 3836.0000 1156.0000 6.0000 3.0000 66.0000 3.0000 + 7.0000 741.0000 4182.0000 3830.0000 1165.0000 7.0000 3.0000 69.0000 3.0000 + 7.0417 740.0000 4171.0000 3829.0000 1176.0000 6.0000 3.0000 72.0000 3.0000 + 7.0833 739.0000 4165.0000 3830.0000 1182.0000 7.0000 3.0000 71.0000 3.0000 + 7.1250 739.0000 4146.0000 3835.0000 1181.0000 7.0000 3.0000 86.0000 3.0000 + 7.1667 738.0000 4140.0000 3842.0000 1181.0000 7.0000 3.0000 86.0000 3.0000 + 7.2083 737.0000 4139.0000 3842.0000 1193.0000 7.0000 3.0000 76.0000 3.0000 + 7.2500 735.0000 4114.0000 3848.0000 1204.0000 7.0000 3.0000 86.0000 3.0000 + 7.2917 735.0000 4098.0000 3852.0000 1210.0000 8.0000 3.0000 91.0000 3.0000 + 7.3333 734.0000 4090.0000 3849.0000 1226.0000 8.0000 3.0000 87.0000 3.0000 + 7.3750 733.0000 4053.0000 3854.0000 1241.0000 7.0000 4.0000 105.0000 3.0000 + 7.4167 730.0000 4047.0000 3840.0000 1251.0000 7.0000 4.0000 118.0000 3.0000 + 7.4583 724.0000 4039.0000 3837.0000 1261.0000 6.0000 4.0000 126.0000 3.0000 + 7.5000 717.0000 4028.0000 3835.0000 1274.0000 6.0000 4.0000 133.0000 3.0000 + 7.5417 715.0000 4020.0000 3839.0000 1272.0000 6.0000 4.0000 141.0000 3.0000 + 7.5833 712.0000 4018.0000 3842.0000 1275.0000 5.0000 3.0000 142.0000 3.0000 + 7.6250 711.0000 4008.0000 3837.0000 1291.0000 5.0000 3.0000 142.0000 3.0000 + 7.6667 709.0000 4012.0000 3836.0000 1306.0000 5.0000 3.0000 126.0000 3.0000 + 7.7083 703.0000 4006.0000 3849.0000 1309.0000 6.0000 3.0000 121.0000 3.0000 + 7.7500 702.0000 4017.0000 3841.0000 1313.0000 7.0000 3.0000 114.0000 3.0000 + 7.7917 700.0000 4022.0000 3857.0000 1308.0000 7.0000 3.0000 100.0000 3.0000 + 7.8333 699.0000 4019.0000 3855.0000 1311.0000 6.0000 3.0000 104.0000 3.0000 + 7.8750 695.0000 4012.0000 3859.0000 1316.0000 6.0000 3.0000 106.0000 3.0000 + 7.9167 691.0000 4003.0000 3852.0000 1336.0000 6.0000 3.0000 106.0000 3.0000 + 7.9583 690.0000 4008.0000 3858.0000 1349.0000 7.0000 3.0000 82.0000 3.0000 + 8.0000 689.0000 4008.0000 3840.0000 1363.0000 8.0000 3.0000 86.0000 3.0000 + 8.0417 689.0000 3985.0000 3860.0000 1366.0000 9.0000 3.0000 85.0000 3.0000 + 8.0833 689.0000 3976.0000 3857.0000 1369.0000 10.0000 3.0000 93.0000 3.0000 + 8.1250 688.0000 3974.0000 3860.0000 1374.0000 10.0000 3.0000 88.0000 3.0000 + 8.1667 687.0000 3955.0000 3855.0000 1386.0000 10.0000 3.0000 101.0000 3.0000 + 8.2083 685.0000 3945.0000 3865.0000 1392.0000 10.0000 3.0000 97.0000 3.0000 + 8.2500 684.0000 3926.0000 3874.0000 1396.0000 10.0000 3.0000 104.0000 3.0000 + 8.2917 683.0000 3916.0000 3878.0000 1394.0000 11.0000 3.0000 112.0000 3.0000 + 8.3333 682.0000 3899.0000 3893.0000 1398.0000 11.0000 3.0000 111.0000 3.0000 + 8.3750 679.0000 3885.0000 3895.0000 1407.0000 11.0000 3.0000 117.0000 3.0000 + 8.4167 676.0000 3869.0000 3906.0000 1408.0000 11.0000 3.0000 124.0000 3.0000 + 8.4583 673.0000 3861.0000 3904.0000 1407.0000 11.0000 3.0000 138.0000 3.0000 + 8.5000 665.0000 3854.0000 3908.0000 1410.0000 11.0000 3.0000 146.0000 3.0000 + 8.5417 662.0000 3849.0000 3901.0000 1413.0000 11.0000 3.0000 158.0000 3.0000 + 8.5833 660.0000 3854.0000 3885.0000 1429.0000 11.0000 3.0000 155.0000 3.0000 + 8.6250 657.0000 3845.0000 3888.0000 1430.0000 11.0000 3.0000 163.0000 3.0000 + 8.6667 655.0000 3851.0000 3900.0000 1434.0000 11.0000 4.0000 142.0000 3.0000 + 8.7083 652.0000 3863.0000 3903.0000 1434.0000 12.0000 4.0000 129.0000 3.0000 + 8.7500 650.0000 3881.0000 3890.0000 1431.0000 12.0000 4.0000 129.0000 3.0000 + 8.7917 648.0000 3907.0000 3888.0000 1433.0000 12.0000 4.0000 105.0000 3.0000 + 8.8333 645.0000 3900.0000 3880.0000 1444.0000 12.0000 4.0000 112.0000 3.0000 + 8.8750 643.0000 3899.0000 3871.0000 1452.0000 12.0000 4.0000 116.0000 3.0000 + 8.9167 642.0000 3895.0000 3879.0000 1450.0000 14.0000 4.0000 113.0000 3.0000 + 8.9583 642.0000 3912.0000 3867.0000 1466.0000 14.0000 4.0000 92.0000 3.0000 + 9.0000 642.0000 3904.0000 3872.0000 1467.0000 15.0000 4.0000 93.0000 3.0000 + 9.0417 640.0000 3899.0000 3867.0000 1478.0000 17.0000 4.0000 92.0000 3.0000 + 9.0833 640.0000 3884.0000 3869.0000 1485.0000 18.0000 4.0000 97.0000 3.0000 + 9.1250 640.0000 3871.0000 3865.0000 1499.0000 20.0000 4.0000 98.0000 3.0000 + 9.1667 638.0000 3860.0000 3861.0000 1510.0000 20.0000 4.0000 104.0000 3.0000 + 9.2083 637.0000 3852.0000 3846.0000 1523.0000 21.0000 4.0000 114.0000 3.0000 + 9.2500 637.0000 3853.0000 3831.0000 1532.0000 21.0000 4.0000 119.0000 3.0000 + 9.2917 637.0000 3841.0000 3837.0000 1536.0000 21.0000 4.0000 121.0000 3.0000 + 9.3333 636.0000 3824.0000 3848.0000 1529.0000 25.0000 4.0000 131.0000 3.0000 + 9.3750 635.0000 3805.0000 3854.0000 1534.0000 24.0000 5.0000 140.0000 3.0000 + 9.4167 629.0000 3799.0000 3856.0000 1533.0000 24.0000 5.0000 151.0000 3.0000 + 9.4583 627.0000 3797.0000 3838.0000 1541.0000 25.0000 5.0000 164.0000 3.0000 + 9.5000 620.0000 3778.0000 3850.0000 1542.0000 26.0000 5.0000 176.0000 3.0000 + 9.5417 618.0000 3788.0000 3842.0000 1547.0000 28.0000 5.0000 169.0000 3.0000 + 9.5833 615.0000 3791.0000 3849.0000 1546.0000 28.0000 5.0000 163.0000 3.0000 + 9.6250 613.0000 3789.0000 3839.0000 1549.0000 28.0000 5.0000 174.0000 3.0000 + 9.6667 612.0000 3798.0000 3836.0000 1547.0000 31.0000 5.0000 168.0000 3.0000 + 9.7083 609.0000 3809.0000 3841.0000 1552.0000 30.0000 5.0000 151.0000 3.0000 + 9.7500 607.0000 3825.0000 3837.0000 1550.0000 31.0000 4.0000 143.0000 3.0000 + 9.7917 605.0000 3850.0000 3831.0000 1556.0000 31.0000 4.0000 120.0000 3.0000 + 9.8333 604.0000 3839.0000 3846.0000 1551.0000 32.0000 4.0000 121.0000 3.0000 + 9.8750 604.0000 3848.0000 3845.0000 1560.0000 35.0000 4.0000 101.0000 3.0000 + 9.9167 604.0000 3836.0000 3848.0000 1557.0000 34.0000 5.0000 113.0000 3.0000 + 9.9583 603.0000 3852.0000 3842.0000 1556.0000 32.0000 7.0000 105.0000 3.0000 +10.0000 603.0000 3850.0000 3841.0000 1564.0000 33.0000 7.0000 99.0000 3.0000 +10.0417 602.0000 3849.0000 3832.0000 1562.0000 32.0000 8.0000 112.0000 3.0000 +10.0833 601.0000 3855.0000 3824.0000 1566.0000 35.0000 8.0000 108.0000 3.0000 +10.1250 600.0000 3843.0000 3829.0000 1565.0000 35.0000 8.0000 117.0000 3.0000 +10.1667 600.0000 3847.0000 3833.0000 1561.0000 36.0000 8.0000 112.0000 3.0000 +10.2083 599.0000 3829.0000 3844.0000 1567.0000 36.0000 8.0000 114.0000 3.0000 +10.2500 599.0000 3811.0000 3846.0000 1564.0000 37.0000 9.0000 131.0000 3.0000 +10.2917 599.0000 3793.0000 3862.0000 1573.0000 41.0000 9.0000 120.0000 3.0000 +10.3333 597.0000 3791.0000 3857.0000 1577.0000 42.0000 9.0000 124.0000 3.0000 +10.3750 597.0000 3783.0000 3847.0000 1574.0000 45.0000 9.0000 142.0000 3.0000 +10.4167 596.0000 3791.0000 3830.0000 1575.0000 48.0000 9.0000 148.0000 3.0000 +10.4583 592.0000 3782.0000 3845.0000 1575.0000 50.0000 10.0000 143.0000 3.0000 +10.5000 585.0000 3771.0000 3865.0000 1571.0000 52.0000 10.0000 143.0000 3.0000 +10.5417 583.0000 3762.0000 3861.0000 1577.0000 52.0000 11.0000 151.0000 3.0000 +10.5833 583.0000 3764.0000 3857.0000 1575.0000 54.0000 11.0000 153.0000 3.0000 +10.6250 583.0000 3763.0000 3844.0000 1575.0000 57.0000 11.0000 164.0000 3.0000 +10.6667 582.0000 3766.0000 3842.0000 1576.0000 56.0000 11.0000 164.0000 3.0000 +10.7083 581.0000 3766.0000 3836.0000 1589.0000 61.0000 11.0000 153.0000 3.0000 +10.7500 581.0000 3791.0000 3849.0000 1587.0000 62.0000 11.0000 116.0000 3.0000 +10.7917 578.0000 3800.0000 3856.0000 1588.0000 64.0000 11.0000 100.0000 3.0000 +10.8333 576.0000 3790.0000 3867.0000 1579.0000 65.0000 11.0000 109.0000 3.0000 +10.8750 573.0000 3787.0000 3872.0000 1573.0000 66.0000 11.0000 115.0000 3.0000 +10.9167 572.0000 3799.0000 3869.0000 1580.0000 66.0000 11.0000 100.0000 3.0000 +10.9583 572.0000 3798.0000 3867.0000 1585.0000 66.0000 11.0000 98.0000 3.0000 +11.0000 572.0000 3799.0000 3866.0000 1588.0000 66.0000 12.0000 94.0000 3.0000 +11.0417 571.0000 3785.0000 3861.0000 1590.0000 70.0000 12.0000 108.0000 3.0000 +11.0833 567.0000 3786.0000 3861.0000 1586.0000 71.0000 15.0000 111.0000 3.0000 +11.1250 567.0000 3788.0000 3848.0000 1594.0000 69.0000 15.0000 116.0000 3.0000 +11.1667 566.0000 3795.0000 3840.0000 1597.0000 70.0000 15.0000 114.0000 3.0000 +11.2083 565.0000 3786.0000 3828.0000 1604.0000 72.0000 15.0000 127.0000 3.0000 +11.2500 565.0000 3777.0000 3830.0000 1604.0000 74.0000 15.0000 132.0000 3.0000 +11.2917 565.0000 3764.0000 3838.0000 1607.0000 74.0000 15.0000 134.0000 3.0000 +11.3333 564.0000 3747.0000 3842.0000 1612.0000 77.0000 15.0000 140.0000 3.0000 +11.3750 564.0000 3737.0000 3843.0000 1616.0000 78.0000 15.0000 144.0000 3.0000 +11.4167 563.0000 3738.0000 3823.0000 1620.0000 76.0000 16.0000 161.0000 3.0000 +11.4583 561.0000 3729.0000 3822.0000 1631.0000 76.0000 17.0000 160.0000 4.0000 +11.5000 557.0000 3722.0000 3835.0000 1624.0000 78.0000 15.0000 164.0000 5.0000 +11.5417 557.0000 3717.0000 3842.0000 1619.0000 81.0000 15.0000 164.0000 5.0000 +11.5833 556.0000 3700.0000 3840.0000 1618.0000 83.0000 15.0000 183.0000 5.0000 +11.6250 555.0000 3698.0000 3837.0000 1614.0000 86.0000 16.0000 189.0000 5.0000 +11.6667 553.0000 3708.0000 3848.0000 1615.0000 87.0000 16.0000 168.0000 5.0000 +11.7083 552.0000 3733.0000 3821.0000 1628.0000 87.0000 17.0000 157.0000 5.0000 +11.7500 552.0000 3761.0000 3818.0000 1627.0000 90.0000 17.0000 130.0000 5.0000 +11.7917 552.0000 3786.0000 3801.0000 1633.0000 93.0000 17.0000 113.0000 5.0000 +11.8333 551.0000 3791.0000 3786.0000 1630.0000 95.0000 17.0000 125.0000 5.0000 +11.8750 549.0000 3798.0000 3785.0000 1632.0000 95.0000 18.0000 118.0000 5.0000 +11.9167 549.0000 3799.0000 3783.0000 1632.0000 98.0000 18.0000 116.0000 5.0000 +11.9583 549.0000 3808.0000 3771.0000 1630.0000 100.0000 17.0000 120.0000 5.0000 +12.0000 549.0000 3801.0000 3787.0000 1630.0000 100.0000 18.0000 110.0000 5.0000 +12.0417 548.0000 3790.0000 3792.0000 1634.0000 100.0000 18.0000 113.0000 5.0000 +12.0833 547.0000 3784.0000 3778.0000 1647.0000 100.0000 18.0000 121.0000 5.0000 +12.1250 546.0000 3787.0000 3774.0000 1652.0000 104.0000 17.0000 114.0000 6.0000 +12.1667 544.0000 3776.0000 3774.0000 1661.0000 104.0000 18.0000 117.0000 6.0000 +12.2083 544.0000 3762.0000 3752.0000 1677.0000 102.0000 21.0000 136.0000 6.0000 +12.2500 544.0000 3765.0000 3744.0000 1678.0000 105.0000 21.0000 137.0000 6.0000 +12.2917 544.0000 3764.0000 3736.0000 1684.0000 106.0000 20.0000 140.0000 6.0000 +12.3333 544.0000 3759.0000 3731.0000 1686.0000 111.0000 20.0000 143.0000 6.0000 +12.3750 544.0000 3743.0000 3735.0000 1682.0000 112.0000 21.0000 157.0000 6.0000 +12.4167 544.0000 3737.0000 3745.0000 1680.0000 113.0000 23.0000 152.0000 6.0000 +12.4583 542.0000 3730.0000 3742.0000 1679.0000 115.0000 23.0000 163.0000 6.0000 +12.5000 539.0000 3717.0000 3741.0000 1675.0000 118.0000 23.0000 181.0000 6.0000 +12.5417 538.0000 3715.0000 3736.0000 1680.0000 119.0000 24.0000 182.0000 6.0000 +12.5833 535.0000 3718.0000 3734.0000 1678.0000 123.0000 25.0000 181.0000 6.0000 +12.6250 533.0000 3704.0000 3740.0000 1682.0000 126.0000 25.0000 184.0000 6.0000 +12.6667 530.0000 3709.0000 3739.0000 1672.0000 127.0000 26.0000 191.0000 6.0000 +12.7083 529.0000 3730.0000 3738.0000 1679.0000 125.0000 29.0000 164.0000 6.0000 +12.7500 528.0000 3759.0000 3725.0000 1682.0000 128.0000 29.0000 143.0000 6.0000 +12.7917 527.0000 3767.0000 3744.0000 1676.0000 132.0000 29.0000 119.0000 6.0000 +12.8333 527.0000 3747.0000 3749.0000 1685.0000 136.0000 29.0000 121.0000 6.0000 +12.8750 525.0000 3740.0000 3756.0000 1683.0000 138.0000 31.0000 121.0000 6.0000 +12.9167 525.0000 3734.0000 3751.0000 1695.0000 140.0000 32.0000 117.0000 6.0000 +12.9583 525.0000 3738.0000 3746.0000 1693.0000 139.0000 34.0000 119.0000 6.0000 +13.0000 525.0000 3733.0000 3743.0000 1697.0000 142.0000 34.0000 120.0000 6.0000 +13.0417 524.0000 3725.0000 3749.0000 1693.0000 145.0000 35.0000 123.0000 6.0000 +13.0833 523.0000 3719.0000 3753.0000 1697.0000 145.0000 36.0000 121.0000 6.0000 +13.1250 523.0000 3714.0000 3751.0000 1700.0000 148.0000 37.0000 121.0000 6.0000 +13.1667 523.0000 3712.0000 3741.0000 1704.0000 149.0000 38.0000 127.0000 6.0000 +13.2083 523.0000 3711.0000 3735.0000 1712.0000 150.0000 39.0000 124.0000 6.0000 +13.2500 521.0000 3702.0000 3737.0000 1708.0000 151.0000 39.0000 136.0000 6.0000 +13.2917 521.0000 3693.0000 3743.0000 1712.0000 154.0000 37.0000 134.0000 6.0000 +13.3333 519.0000 3683.0000 3749.0000 1712.0000 155.0000 38.0000 138.0000 6.0000 +13.3750 519.0000 3671.0000 3746.0000 1706.0000 160.0000 38.0000 154.0000 6.0000 +13.4167 518.0000 3651.0000 3759.0000 1706.0000 163.0000 40.0000 157.0000 6.0000 +13.4583 515.0000 3637.0000 3749.0000 1709.0000 167.0000 39.0000 177.0000 7.0000 +13.5000 514.0000 3638.0000 3742.0000 1714.0000 168.0000 39.0000 177.0000 8.0000 +13.5417 512.0000 3632.0000 3739.0000 1718.0000 170.0000 40.0000 181.0000 8.0000 +13.5833 510.0000 3620.0000 3750.0000 1721.0000 173.0000 40.0000 178.0000 8.0000 +13.6250 508.0000 3612.0000 3751.0000 1723.0000 174.0000 41.0000 183.0000 8.0000 +13.6667 508.0000 3625.0000 3745.0000 1727.0000 178.0000 42.0000 167.0000 8.0000 +13.7083 508.0000 3628.0000 3737.0000 1733.0000 176.0000 44.0000 166.0000 8.0000 +13.7500 505.0000 3649.0000 3740.0000 1730.0000 174.0000 45.0000 149.0000 8.0000 +13.7917 505.0000 3665.0000 3736.0000 1723.0000 177.0000 45.0000 141.0000 8.0000 +13.8333 503.0000 3666.0000 3719.0000 1723.0000 182.0000 46.0000 153.0000 8.0000 +13.8750 503.0000 3681.0000 3714.0000 1733.0000 180.0000 48.0000 133.0000 8.0000 +13.9167 503.0000 3674.0000 3700.0000 1726.0000 184.0000 48.0000 157.0000 8.0000 +13.9583 503.0000 3688.0000 3705.0000 1730.0000 182.0000 52.0000 132.0000 8.0000 +14.0000 503.0000 3668.0000 3710.0000 1723.0000 183.0000 51.0000 154.0000 8.0000 +14.0417 502.0000 3679.0000 3703.0000 1713.0000 182.0000 52.0000 161.0000 8.0000 +14.0833 501.0000 3675.0000 3709.0000 1716.0000 183.0000 55.0000 153.0000 8.0000 +14.1250 501.0000 3664.0000 3709.0000 1716.0000 184.0000 56.0000 162.0000 8.0000 +14.1667 501.0000 3653.0000 3717.0000 1716.0000 186.0000 55.0000 164.0000 8.0000 +14.2083 500.0000 3651.0000 3719.0000 1709.0000 186.0000 54.0000 171.0000 10.0000 +14.2500 500.0000 3654.0000 3708.0000 1716.0000 188.0000 54.0000 170.0000 10.0000 +14.2917 500.0000 3654.0000 3698.0000 1716.0000 191.0000 55.0000 176.0000 10.0000 +14.3333 499.0000 3659.0000 3699.0000 1711.0000 195.0000 55.0000 172.0000 10.0000 +14.3750 498.0000 3648.0000 3699.0000 1704.0000 201.0000 55.0000 185.0000 10.0000 +14.4167 493.0000 3651.0000 3696.0000 1704.0000 205.0000 55.0000 186.0000 10.0000 +14.4583 490.0000 3648.0000 3692.0000 1703.0000 207.0000 54.0000 195.0000 11.0000 +14.5000 487.0000 3642.0000 3700.0000 1693.0000 209.0000 54.0000 204.0000 11.0000 +14.5417 486.0000 3643.0000 3694.0000 1696.0000 210.0000 54.0000 206.0000 11.0000 +14.5833 485.0000 3637.0000 3697.0000 1697.0000 212.0000 53.0000 207.0000 12.0000 +14.6250 482.0000 3627.0000 3703.0000 1699.0000 215.0000 54.0000 208.0000 12.0000 +14.6667 481.0000 3644.0000 3703.0000 1696.0000 214.0000 53.0000 197.0000 12.0000 +14.7083 481.0000 3650.0000 3697.0000 1702.0000 215.0000 53.0000 190.0000 12.0000 +14.7500 480.0000 3681.0000 3693.0000 1701.0000 217.0000 52.0000 164.0000 12.0000 +14.7917 480.0000 3698.0000 3686.0000 1699.0000 219.0000 52.0000 153.0000 13.0000 +14.8333 479.0000 3694.0000 3684.0000 1703.0000 224.0000 51.0000 151.0000 14.0000 +14.8750 478.0000 3682.0000 3673.0000 1710.0000 225.0000 51.0000 166.0000 15.0000 +14.9167 478.0000 3677.0000 3682.0000 1713.0000 225.0000 52.0000 158.0000 15.0000 +14.9583 478.0000 3680.0000 3683.0000 1719.0000 228.0000 52.0000 145.0000 15.0000 +15.0000 478.0000 3682.0000 3680.0000 1713.0000 232.0000 52.0000 148.0000 15.0000 +15.0417 478.0000 3674.0000 3681.0000 1704.0000 237.0000 51.0000 159.0000 16.0000 +15.0833 478.0000 3673.0000 3684.0000 1695.0000 242.0000 51.0000 161.0000 16.0000 +15.1250 478.0000 3650.0000 3717.0000 1687.0000 244.0000 52.0000 155.0000 17.0000 +15.1667 477.0000 3653.0000 3709.0000 1683.0000 246.0000 52.0000 162.0000 18.0000 +15.2083 477.0000 3651.0000 3704.0000 1678.0000 245.0000 54.0000 172.0000 19.0000 +15.2500 477.0000 3647.0000 3716.0000 1678.0000 244.0000 55.0000 164.0000 19.0000 +15.2917 477.0000 3635.0000 3722.0000 1673.0000 248.0000 54.0000 172.0000 19.0000 +15.3333 477.0000 3630.0000 3722.0000 1669.0000 250.0000 55.0000 178.0000 19.0000 +15.3750 476.0000 3609.0000 3724.0000 1665.0000 257.0000 57.0000 193.0000 19.0000 +15.4167 475.0000 3604.0000 3706.0000 1670.0000 259.0000 57.0000 210.0000 19.0000 +15.4583 474.0000 3604.0000 3705.0000 1673.0000 258.0000 59.0000 208.0000 19.0000 +15.5000 474.0000 3599.0000 3695.0000 1679.0000 257.0000 60.0000 217.0000 19.0000 +15.5417 474.0000 3592.0000 3702.0000 1674.0000 257.0000 61.0000 221.0000 19.0000 +15.5833 473.0000 3592.0000 3712.0000 1677.0000 259.0000 62.0000 206.0000 19.0000 +15.6250 472.0000 3580.0000 3709.0000 1679.0000 265.0000 61.0000 215.0000 19.0000 +15.6667 471.0000 3600.0000 3711.0000 1680.0000 266.0000 60.0000 192.0000 20.0000 +15.7083 471.0000 3614.0000 3691.0000 1688.0000 266.0000 62.0000 188.0000 20.0000 +15.7500 471.0000 3626.0000 3694.0000 1684.0000 269.0000 62.0000 174.0000 20.0000 +15.7917 471.0000 3631.0000 3692.0000 1691.0000 272.0000 62.0000 160.0000 21.0000 +15.8333 468.0000 3615.0000 3697.0000 1690.0000 270.0000 64.0000 175.0000 21.0000 +15.8750 467.0000 3616.0000 3707.0000 1687.0000 272.0000 65.0000 165.0000 21.0000 +15.9167 467.0000 3614.0000 3693.0000 1696.0000 271.0000 69.0000 169.0000 21.0000 +15.9583 467.0000 3622.0000 3703.0000 1688.0000 273.0000 71.0000 155.0000 21.0000 +16.0000 467.0000 3622.0000 3695.0000 1695.0000 274.0000 70.0000 155.0000 22.0000 +16.0417 466.0000 3612.0000 3695.0000 1695.0000 278.0000 70.0000 162.0000 22.0000 +16.0833 464.0000 3609.0000 3693.0000 1693.0000 279.0000 71.0000 169.0000 22.0000 +16.1250 464.0000 3610.0000 3692.0000 1689.0000 280.0000 72.0000 171.0000 22.0000 +16.1667 464.0000 3610.0000 3678.0000 1688.0000 284.0000 71.0000 182.0000 23.0000 +16.2083 463.0000 3622.0000 3664.0000 1691.0000 286.0000 73.0000 178.0000 23.0000 +16.2500 463.0000 3614.0000 3667.0000 1685.0000 285.0000 77.0000 186.0000 23.0000 +16.2917 463.0000 3604.0000 3667.0000 1689.0000 285.0000 79.0000 189.0000 24.0000 +16.3333 463.0000 3598.0000 3667.0000 1684.0000 289.0000 80.0000 194.0000 25.0000 +16.3750 463.0000 3588.0000 3655.0000 1692.0000 290.0000 81.0000 206.0000 25.0000 +16.4167 463.0000 3568.0000 3666.0000 1691.0000 290.0000 82.0000 215.0000 25.0000 +16.4583 461.0000 3561.0000 3670.0000 1689.0000 295.0000 83.0000 216.0000 25.0000 +16.5000 457.0000 3547.0000 3670.0000 1691.0000 296.0000 85.0000 229.0000 25.0000 +16.5417 456.0000 3539.0000 3679.0000 1687.0000 298.0000 86.0000 230.0000 25.0000 +16.5833 455.0000 3533.0000 3679.0000 1679.0000 300.0000 86.0000 243.0000 25.0000 +16.6250 454.0000 3534.0000 3674.0000 1672.0000 307.0000 86.0000 248.0000 25.0000 +16.6667 453.0000 3556.0000 3668.0000 1678.0000 310.0000 86.0000 224.0000 25.0000 +16.7083 452.0000 3575.0000 3650.0000 1680.0000 313.0000 88.0000 217.0000 25.0000 +16.7500 451.0000 3568.0000 3675.0000 1690.0000 313.0000 88.0000 190.0000 25.0000 +16.7917 451.0000 3580.0000 3673.0000 1684.0000 320.0000 88.0000 178.0000 26.0000 +16.8333 451.0000 3574.0000 3664.0000 1687.0000 320.0000 90.0000 188.0000 26.0000 +16.8750 451.0000 3580.0000 3672.0000 1686.0000 321.0000 91.0000 173.0000 26.0000 +16.9167 450.0000 3571.0000 3672.0000 1686.0000 318.0000 94.0000 182.0000 27.0000 +16.9583 450.0000 3575.0000 3680.0000 1680.0000 320.0000 97.0000 171.0000 27.0000 +17.0000 450.0000 3562.0000 3680.0000 1682.0000 328.0000 97.0000 174.0000 27.0000 +17.0417 450.0000 3551.0000 3679.0000 1687.0000 327.0000 101.0000 178.0000 27.0000 +17.0833 449.0000 3542.0000 3672.0000 1683.0000 335.0000 101.0000 191.0000 27.0000 +17.1250 448.0000 3544.0000 3682.0000 1678.0000 334.0000 102.0000 184.0000 28.0000 +17.1667 448.0000 3539.0000 3687.0000 1670.0000 337.0000 103.0000 188.0000 28.0000 +17.2083 448.0000 3535.0000 3690.0000 1670.0000 336.0000 103.0000 189.0000 29.0000 +17.2500 447.0000 3540.0000 3676.0000 1663.0000 333.0000 108.0000 204.0000 29.0000 +17.2917 447.0000 3545.0000 3674.0000 1668.0000 336.0000 109.0000 192.0000 29.0000 +17.3333 447.0000 3547.0000 3661.0000 1671.0000 337.0000 108.0000 198.0000 31.0000 +17.3750 446.0000 3543.0000 3652.0000 1674.0000 333.0000 108.0000 213.0000 31.0000 +17.4167 445.0000 3538.0000 3646.0000 1678.0000 331.0000 110.0000 221.0000 31.0000 +17.4583 443.0000 3530.0000 3652.0000 1670.0000 335.0000 110.0000 229.0000 31.0000 +17.5000 439.0000 3522.0000 3647.0000 1674.0000 329.0000 116.0000 242.0000 31.0000 +17.5417 438.0000 3513.0000 3651.0000 1678.0000 324.0000 122.0000 243.0000 31.0000 +17.5833 436.0000 3512.0000 3655.0000 1681.0000 324.0000 122.0000 239.0000 31.0000 +17.6250 435.0000 3507.0000 3649.0000 1676.0000 329.0000 121.0000 252.0000 31.0000 +17.6667 434.0000 3514.0000 3652.0000 1682.0000 324.0000 123.0000 239.0000 32.0000 +17.7083 434.0000 3524.0000 3650.0000 1682.0000 323.0000 125.0000 229.0000 33.0000 +17.7500 434.0000 3559.0000 3637.0000 1683.0000 329.0000 126.0000 199.0000 33.0000 +17.7917 433.0000 3575.0000 3629.0000 1690.0000 329.0000 123.0000 186.0000 35.0000 +17.8333 430.0000 3583.0000 3618.0000 1689.0000 328.0000 120.0000 196.0000 36.0000 +17.8750 429.0000 3579.0000 3621.0000 1697.0000 326.0000 121.0000 190.0000 37.0000 +17.9167 429.0000 3573.0000 3627.0000 1700.0000 331.0000 117.0000 182.0000 41.0000 +17.9583 429.0000 3567.0000 3626.0000 1705.0000 333.0000 116.0000 182.0000 42.0000 +18.0000 429.0000 3568.0000 3627.0000 1703.0000 338.0000 116.0000 176.0000 43.0000 +18.0417 429.0000 3560.0000 3617.0000 1709.0000 338.0000 117.0000 186.0000 44.0000 +18.0833 429.0000 3548.0000 3618.0000 1712.0000 341.0000 117.0000 191.0000 44.0000 +18.1250 429.0000 3550.0000 3623.0000 1711.0000 345.0000 117.0000 181.0000 44.0000 +18.1667 429.0000 3546.0000 3618.0000 1721.0000 342.0000 117.0000 183.0000 44.0000 +18.2083 429.0000 3547.0000 3612.0000 1714.0000 345.0000 116.0000 192.0000 45.0000 +18.2500 429.0000 3535.0000 3619.0000 1713.0000 345.0000 119.0000 194.0000 46.0000 +18.2917 426.0000 3526.0000 3625.0000 1710.0000 344.0000 120.0000 203.0000 46.0000 +18.3333 426.0000 3530.0000 3615.0000 1714.0000 349.0000 118.0000 202.0000 46.0000 +18.3750 423.0000 3515.0000 3615.0000 1722.0000 353.0000 118.0000 208.0000 46.0000 +18.4167 422.0000 3504.0000 3619.0000 1716.0000 358.0000 118.0000 216.0000 47.0000 +18.4583 422.0000 3505.0000 3601.0000 1731.0000 359.0000 118.0000 216.0000 48.0000 +18.5000 418.0000 3497.0000 3595.0000 1740.0000 354.0000 121.0000 227.0000 48.0000 +18.5417 418.0000 3488.0000 3604.0000 1742.0000 356.0000 121.0000 222.0000 49.0000 +18.5833 418.0000 3490.0000 3580.0000 1754.0000 352.0000 123.0000 232.0000 51.0000 +18.6250 417.0000 3470.0000 3597.0000 1749.0000 354.0000 124.0000 238.0000 51.0000 +18.6667 416.0000 3483.0000 3588.0000 1747.0000 357.0000 124.0000 233.0000 52.0000 +18.7083 415.0000 3483.0000 3592.0000 1752.0000 354.0000 126.0000 225.0000 53.0000 +18.7500 415.0000 3502.0000 3577.0000 1758.0000 355.0000 128.0000 212.0000 53.0000 +18.7917 414.0000 3511.0000 3582.0000 1760.0000 356.0000 127.0000 195.0000 55.0000 +18.8333 411.0000 3503.0000 3578.0000 1771.0000 358.0000 125.0000 197.0000 57.0000 +18.8750 409.0000 3498.0000 3574.0000 1778.0000 356.0000 125.0000 202.0000 58.0000 +18.9167 409.0000 3497.0000 3573.0000 1774.0000 357.0000 129.0000 203.0000 58.0000 +18.9583 409.0000 3501.0000 3573.0000 1775.0000 357.0000 130.0000 196.0000 59.0000 +19.0000 409.0000 3490.0000 3573.0000 1782.0000 359.0000 131.0000 197.0000 59.0000 +19.0417 409.0000 3491.0000 3566.0000 1784.0000 360.0000 132.0000 199.0000 59.0000 +19.0833 409.0000 3484.0000 3569.0000 1776.0000 363.0000 134.0000 206.0000 59.0000 +19.1250 407.0000 3489.0000 3559.0000 1786.0000 366.0000 134.0000 200.0000 59.0000 +19.1667 407.0000 3470.0000 3551.0000 1788.0000 370.0000 133.0000 220.0000 61.0000 +19.2083 407.0000 3485.0000 3549.0000 1779.0000 373.0000 132.0000 214.0000 61.0000 +19.2500 406.0000 3486.0000 3545.0000 1789.0000 377.0000 134.0000 202.0000 61.0000 +19.2917 405.0000 3478.0000 3549.0000 1785.0000 382.0000 137.0000 203.0000 61.0000 +19.3333 405.0000 3468.0000 3539.0000 1790.0000 382.0000 136.0000 219.0000 61.0000 +19.3750 404.0000 3460.0000 3521.0000 1794.0000 379.0000 135.0000 244.0000 63.0000 +19.4167 404.0000 3463.0000 3524.0000 1795.0000 380.0000 135.0000 235.0000 64.0000 +19.4583 402.0000 3461.0000 3516.0000 1795.0000 384.0000 136.0000 242.0000 64.0000 +19.5000 400.0000 3445.0000 3529.0000 1782.0000 389.0000 136.0000 254.0000 65.0000 +19.5417 400.0000 3430.0000 3523.0000 1780.0000 393.0000 140.0000 268.0000 66.0000 +19.5833 398.0000 3426.0000 3529.0000 1779.0000 396.0000 140.0000 265.0000 67.0000 +19.6250 396.0000 3413.0000 3534.0000 1784.0000 397.0000 141.0000 268.0000 67.0000 +19.6667 395.0000 3426.0000 3531.0000 1782.0000 400.0000 140.0000 258.0000 68.0000 +19.7083 395.0000 3437.0000 3534.0000 1773.0000 401.0000 145.0000 246.0000 69.0000 +19.7500 395.0000 3455.0000 3527.0000 1777.0000 401.0000 148.0000 228.0000 69.0000 +19.7917 393.0000 3482.0000 3521.0000 1771.0000 402.0000 147.0000 211.0000 73.0000 +19.8333 392.0000 3479.0000 3531.0000 1765.0000 402.0000 148.0000 210.0000 73.0000 +19.8750 392.0000 3485.0000 3532.0000 1758.0000 401.0000 152.0000 206.0000 74.0000 +19.9167 392.0000 3486.0000 3533.0000 1760.0000 401.0000 153.0000 201.0000 74.0000 +19.9583 391.0000 3487.0000 3525.0000 1764.0000 403.0000 153.0000 202.0000 75.0000 +20.0000 390.0000 3493.0000 3526.0000 1758.0000 408.0000 152.0000 198.0000 75.0000 +20.0417 390.0000 3485.0000 3526.0000 1765.0000 409.0000 158.0000 192.0000 75.0000 +20.0833 389.0000 3466.0000 3535.0000 1763.0000 408.0000 163.0000 201.0000 75.0000 +20.1250 388.0000 3455.0000 3538.0000 1763.0000 408.0000 162.0000 210.0000 76.0000 +20.1667 388.0000 3448.0000 3530.0000 1760.0000 410.0000 163.0000 224.0000 77.0000 +20.2083 387.0000 3446.0000 3522.0000 1765.0000 415.0000 163.0000 224.0000 78.0000 +20.2500 387.0000 3431.0000 3530.0000 1772.0000 419.0000 165.0000 218.0000 78.0000 +20.2917 386.0000 3419.0000 3533.0000 1770.0000 420.0000 164.0000 229.0000 79.0000 +20.3333 386.0000 3405.0000 3532.0000 1770.0000 421.0000 166.0000 239.0000 81.0000 +20.3750 386.0000 3396.0000 3524.0000 1765.0000 422.0000 165.0000 260.0000 82.0000 +20.4167 383.0000 3398.0000 3520.0000 1765.0000 421.0000 165.0000 265.0000 83.0000 +20.4583 379.0000 3401.0000 3511.0000 1763.0000 425.0000 163.0000 274.0000 84.0000 +20.5000 378.0000 3390.0000 3514.0000 1766.0000 425.0000 162.0000 281.0000 84.0000 +20.5417 377.0000 3395.0000 3516.0000 1764.0000 426.0000 163.0000 275.0000 84.0000 +20.5833 375.0000 3399.0000 3521.0000 1757.0000 423.0000 164.0000 276.0000 85.0000 +20.6250 375.0000 3397.0000 3523.0000 1759.0000 418.0000 164.0000 278.0000 86.0000 +20.6667 374.0000 3405.0000 3532.0000 1750.0000 411.0000 168.0000 274.0000 86.0000 +20.7083 374.0000 3422.0000 3533.0000 1745.0000 411.0000 173.0000 256.0000 86.0000 +20.7500 372.0000 3431.0000 3534.0000 1741.0000 415.0000 173.0000 247.0000 87.0000 +20.7917 372.0000 3458.0000 3532.0000 1740.0000 410.0000 175.0000 225.0000 88.0000 +20.8333 371.0000 3459.0000 3530.0000 1747.0000 413.0000 173.0000 217.0000 90.0000 +20.8750 371.0000 3461.0000 3534.0000 1747.0000 407.0000 175.0000 215.0000 90.0000 +20.9167 371.0000 3458.0000 3532.0000 1746.0000 406.0000 180.0000 216.0000 91.0000 +20.9583 370.0000 3451.0000 3531.0000 1746.0000 408.0000 181.0000 222.0000 91.0000 +21.0000 370.0000 3447.0000 3538.0000 1741.0000 413.0000 184.0000 215.0000 92.0000 +21.0417 369.0000 3436.0000 3541.0000 1742.0000 418.0000 183.0000 217.0000 94.0000 +21.0833 369.0000 3426.0000 3539.0000 1745.0000 418.0000 185.0000 223.0000 95.0000 +21.1250 368.0000 3431.0000 3536.0000 1739.0000 420.0000 187.0000 223.0000 96.0000 +21.1667 368.0000 3422.0000 3550.0000 1736.0000 425.0000 186.0000 216.0000 97.0000 +21.2083 368.0000 3400.0000 3555.0000 1736.0000 431.0000 186.0000 227.0000 97.0000 +21.2500 368.0000 3395.0000 3552.0000 1735.0000 431.0000 185.0000 237.0000 97.0000 +21.2917 368.0000 3402.0000 3549.0000 1724.0000 440.0000 185.0000 234.0000 98.0000 +21.3333 367.0000 3394.0000 3540.0000 1722.0000 442.0000 185.0000 250.0000 100.0000 +21.3750 367.0000 3393.0000 3520.0000 1721.0000 448.0000 187.0000 263.0000 101.0000 +21.4167 367.0000 3391.0000 3522.0000 1723.0000 447.0000 189.0000 260.0000 101.0000 +21.4583 366.0000 3385.0000 3525.0000 1724.0000 450.0000 189.0000 260.0000 101.0000 +21.5000 363.0000 3371.0000 3521.0000 1737.0000 449.0000 190.0000 266.0000 103.0000 +21.5417 363.0000 3373.0000 3520.0000 1733.0000 452.0000 191.0000 265.0000 103.0000 +21.5833 363.0000 3369.0000 3512.0000 1734.0000 455.0000 191.0000 272.0000 104.0000 +21.6250 362.0000 3357.0000 3514.0000 1738.0000 453.0000 191.0000 281.0000 104.0000 +21.6667 362.0000 3363.0000 3522.0000 1732.0000 453.0000 193.0000 271.0000 104.0000 +21.7083 360.0000 3367.0000 3515.0000 1748.0000 456.0000 194.0000 256.0000 104.0000 +21.7500 360.0000 3396.0000 3495.0000 1767.0000 453.0000 197.0000 228.0000 104.0000 +21.7917 360.0000 3390.0000 3507.0000 1756.0000 456.0000 196.0000 230.0000 105.0000 +21.8333 360.0000 3386.0000 3508.0000 1754.0000 459.0000 193.0000 232.0000 108.0000 +21.8750 360.0000 3392.0000 3509.0000 1749.0000 457.0000 193.0000 231.0000 109.0000 +21.9167 359.0000 3390.0000 3498.0000 1748.0000 462.0000 193.0000 239.0000 111.0000 +21.9583 359.0000 3406.0000 3489.0000 1743.0000 467.0000 194.0000 231.0000 111.0000 +22.0000 358.0000 3411.0000 3493.0000 1738.0000 470.0000 196.0000 223.0000 111.0000 +22.0417 358.0000 3411.0000 3485.0000 1742.0000 472.0000 192.0000 228.0000 112.0000 +22.0833 357.0000 3393.0000 3504.0000 1733.0000 474.0000 192.0000 235.0000 112.0000 +22.1250 357.0000 3392.0000 3489.0000 1738.0000 476.0000 190.0000 243.0000 115.0000 +22.1667 357.0000 3397.0000 3481.0000 1747.0000 479.0000 192.0000 231.0000 116.0000 +22.2083 357.0000 3388.0000 3482.0000 1751.0000 476.0000 197.0000 233.0000 116.0000 +22.2500 357.0000 3378.0000 3480.0000 1749.0000 477.0000 196.0000 247.0000 116.0000 +22.2917 356.0000 3375.0000 3482.0000 1749.0000 480.0000 194.0000 247.0000 117.0000 +22.3333 356.0000 3377.0000 3479.0000 1747.0000 483.0000 196.0000 243.0000 119.0000 +22.3750 356.0000 3376.0000 3459.0000 1747.0000 482.0000 195.0000 265.0000 120.0000 +22.4167 356.0000 3377.0000 3459.0000 1743.0000 488.0000 195.0000 262.0000 120.0000 +22.4583 354.0000 3380.0000 3461.0000 1743.0000 486.0000 195.0000 260.0000 121.0000 +22.5000 353.0000 3375.0000 3459.0000 1748.0000 481.0000 199.0000 263.0000 122.0000 +22.5417 353.0000 3367.0000 3461.0000 1742.0000 483.0000 199.0000 271.0000 124.0000 +22.5833 352.0000 3364.0000 3455.0000 1751.0000 482.0000 201.0000 271.0000 124.0000 +22.6250 352.0000 3363.0000 3458.0000 1742.0000 486.0000 200.0000 274.0000 125.0000 +22.6667 351.0000 3363.0000 3456.0000 1744.0000 494.0000 199.0000 268.0000 125.0000 +22.7083 349.0000 3376.0000 3454.0000 1745.0000 496.0000 200.0000 254.0000 126.0000 +22.7500 348.0000 3383.0000 3462.0000 1751.0000 497.0000 200.0000 232.0000 127.0000 +22.7917 347.0000 3390.0000 3458.0000 1746.0000 499.0000 201.0000 231.0000 128.0000 +22.8333 346.0000 3401.0000 3452.0000 1747.0000 501.0000 200.0000 223.0000 130.0000 +22.8750 346.0000 3401.0000 3447.0000 1744.0000 501.0000 203.0000 228.0000 130.0000 +22.9167 346.0000 3406.0000 3453.0000 1738.0000 509.0000 202.0000 213.0000 133.0000 +22.9583 345.0000 3407.0000 3445.0000 1745.0000 507.0000 199.0000 217.0000 135.0000 +23.0000 345.0000 3409.0000 3432.0000 1758.0000 503.0000 200.0000 218.0000 135.0000 +23.0417 344.0000 3413.0000 3420.0000 1763.0000 509.0000 201.0000 214.0000 136.0000 +23.0833 344.0000 3406.0000 3411.0000 1763.0000 510.0000 201.0000 226.0000 139.0000 +23.1250 344.0000 3397.0000 3425.0000 1757.0000 512.0000 201.0000 224.0000 140.0000 +23.1667 344.0000 3386.0000 3429.0000 1754.0000 518.0000 198.0000 230.0000 141.0000 +23.2083 344.0000 3380.0000 3426.0000 1752.0000 520.0000 198.0000 238.0000 142.0000 +23.2500 344.0000 3387.0000 3421.0000 1752.0000 520.0000 197.0000 236.0000 143.0000 +23.2917 344.0000 3379.0000 3429.0000 1754.0000 516.0000 198.0000 236.0000 144.0000 +23.3333 344.0000 3370.0000 3421.0000 1762.0000 511.0000 199.0000 249.0000 144.0000 +23.3750 343.0000 3369.0000 3403.0000 1771.0000 508.0000 201.0000 261.0000 144.0000 +23.4167 343.0000 3351.0000 3397.0000 1767.0000 510.0000 202.0000 285.0000 145.0000 +23.4583 340.0000 3360.0000 3392.0000 1764.0000 517.0000 201.0000 281.0000 145.0000 +23.5000 339.0000 3361.0000 3384.0000 1746.0000 527.0000 201.0000 296.0000 146.0000 +23.5417 338.0000 3361.0000 3388.0000 1743.0000 530.0000 198.0000 294.0000 148.0000 +23.5833 337.0000 3363.0000 3377.0000 1753.0000 533.0000 196.0000 292.0000 149.0000 +23.6250 336.0000 3332.0000 3400.0000 1745.0000 537.0000 196.0000 304.0000 150.0000 +23.6667 336.0000 3346.0000 3404.0000 1752.0000 535.0000 195.0000 281.0000 151.0000 +23.7083 335.0000 3353.0000 3413.0000 1741.0000 543.0000 198.0000 266.0000 151.0000 +23.7500 333.0000 3380.0000 3402.0000 1744.0000 549.0000 195.0000 243.0000 154.0000 +23.7917 333.0000 3398.0000 3404.0000 1742.0000 554.0000 197.0000 217.0000 155.0000 +23.8333 333.0000 3378.0000 3409.0000 1740.0000 556.0000 197.0000 231.0000 156.0000 +23.8750 333.0000 3378.0000 3416.0000 1741.0000 554.0000 201.0000 221.0000 156.0000 +23.9167 333.0000 3382.0000 3410.0000 1741.0000 561.0000 202.0000 215.0000 156.0000 +23.9583 331.0000 3386.0000 3403.0000 1748.0000 558.0000 202.0000 215.0000 157.0000 +24.0000 331.0000 3388.0000 3406.0000 1744.0000 556.0000 202.0000 214.0000 159.0000 +24.0417 330.0000 3380.0000 3402.0000 1752.0000 548.0000 202.0000 224.0000 162.0000 +24.0833 330.0000 3386.0000 3407.0000 1749.0000 551.0000 202.0000 212.0000 163.0000 +24.1250 330.0000 3369.0000 3408.0000 1750.0000 545.0000 205.0000 229.0000 164.0000 +24.1667 330.0000 3365.0000 3409.0000 1750.0000 548.0000 205.0000 228.0000 165.0000 +24.2083 330.0000 3359.0000 3398.0000 1756.0000 547.0000 205.0000 240.0000 165.0000 +24.2500 328.0000 3359.0000 3395.0000 1759.0000 552.0000 206.0000 235.0000 166.0000 +24.2917 327.0000 3346.0000 3400.0000 1754.0000 551.0000 206.0000 248.0000 168.0000 +24.3333 327.0000 3342.0000 3409.0000 1756.0000 547.0000 205.0000 246.0000 168.0000 +24.3750 325.0000 3333.0000 3417.0000 1753.0000 547.0000 204.0000 253.0000 168.0000 +24.4167 324.0000 3326.0000 3402.0000 1758.0000 547.0000 205.0000 270.0000 168.0000 +24.4583 321.0000 3327.0000 3390.0000 1753.0000 553.0000 201.0000 284.0000 171.0000 +24.5000 320.0000 3322.0000 3393.0000 1756.0000 549.0000 207.0000 282.0000 171.0000 +24.5417 320.0000 3318.0000 3393.0000 1762.0000 550.0000 209.0000 277.0000 171.0000 +24.5833 320.0000 3311.0000 3402.0000 1762.0000 551.0000 210.0000 272.0000 172.0000 +24.6250 320.0000 3301.0000 3398.0000 1772.0000 546.0000 211.0000 279.0000 173.0000 +24.6667 320.0000 3309.0000 3394.0000 1772.0000 543.0000 212.0000 276.0000 174.0000 +24.7083 320.0000 3323.0000 3387.0000 1778.0000 542.0000 216.0000 259.0000 175.0000 +24.7500 319.0000 3356.0000 3380.0000 1780.0000 548.0000 216.0000 225.0000 176.0000 +24.7917 319.0000 3358.0000 3385.0000 1785.0000 551.0000 217.0000 209.0000 176.0000 +24.8333 319.0000 3348.0000 3376.0000 1784.0000 547.0000 219.0000 228.0000 179.0000 +24.8750 318.0000 3343.0000 3376.0000 1785.0000 549.0000 222.0000 227.0000 180.0000 +24.9167 318.0000 3336.0000 3381.0000 1790.0000 550.0000 224.0000 220.0000 181.0000 +24.9583 318.0000 3331.0000 3394.0000 1788.0000 547.0000 225.0000 215.0000 182.0000 +25.0000 318.0000 3331.0000 3389.0000 1790.0000 547.0000 226.0000 216.0000 183.0000 +25.0417 318.0000 3330.0000 3384.0000 1783.0000 554.0000 224.0000 223.0000 184.0000 +25.0833 318.0000 3324.0000 3378.0000 1783.0000 557.0000 226.0000 229.0000 185.0000 +25.1250 318.0000 3320.0000 3378.0000 1780.0000 557.0000 226.0000 234.0000 187.0000 +25.1667 318.0000 3323.0000 3366.0000 1784.0000 561.0000 226.0000 234.0000 188.0000 +25.2083 317.0000 3315.0000 3366.0000 1779.0000 565.0000 225.0000 245.0000 188.0000 +25.2500 317.0000 3310.0000 3375.0000 1777.0000 569.0000 223.0000 241.0000 188.0000 +25.2917 317.0000 3299.0000 3377.0000 1780.0000 567.0000 222.0000 248.0000 190.0000 +25.3333 315.0000 3300.0000 3378.0000 1779.0000 567.0000 218.0000 252.0000 191.0000 +25.3750 314.0000 3305.0000 3361.0000 1781.0000 567.0000 218.0000 262.0000 192.0000 +25.4167 314.0000 3304.0000 3368.0000 1770.0000 570.0000 222.0000 260.0000 192.0000 +25.4583 312.0000 3300.0000 3362.0000 1772.0000 569.0000 223.0000 269.0000 193.0000 +25.5000 307.0000 3306.0000 3352.0000 1766.0000 575.0000 223.0000 276.0000 195.0000 +25.5417 307.0000 3312.0000 3355.0000 1760.0000 578.0000 221.0000 272.0000 195.0000 +25.5833 306.0000 3322.0000 3338.0000 1760.0000 578.0000 228.0000 273.0000 195.0000 +25.6250 306.0000 3309.0000 3346.0000 1765.0000 579.0000 228.0000 270.0000 197.0000 +25.6667 306.0000 3317.0000 3332.0000 1767.0000 587.0000 228.0000 264.0000 199.0000 +25.7083 306.0000 3326.0000 3332.0000 1756.0000 591.0000 229.0000 261.0000 199.0000 +25.7500 306.0000 3345.0000 3324.0000 1758.0000 591.0000 230.0000 247.0000 199.0000 +25.7917 306.0000 3358.0000 3319.0000 1760.0000 591.0000 235.0000 231.0000 200.0000 +25.8333 306.0000 3348.0000 3327.0000 1751.0000 598.0000 234.0000 235.0000 201.0000 +25.8750 306.0000 3360.0000 3314.0000 1752.0000 601.0000 234.0000 231.0000 202.0000 +25.9167 306.0000 3359.0000 3311.0000 1746.0000 605.0000 230.0000 241.0000 202.0000 +25.9583 306.0000 3375.0000 3296.0000 1754.0000 608.0000 229.0000 229.0000 203.0000 +26.0000 306.0000 3368.0000 3302.0000 1750.0000 611.0000 228.0000 231.0000 204.0000 +26.0417 306.0000 3361.0000 3297.0000 1758.0000 605.0000 232.0000 236.0000 205.0000 +26.0833 306.0000 3361.0000 3295.0000 1763.0000 605.0000 231.0000 232.0000 207.0000 +26.1250 306.0000 3359.0000 3290.0000 1767.0000 606.0000 229.0000 232.0000 211.0000 +26.1667 306.0000 3361.0000 3281.0000 1769.0000 604.0000 230.0000 237.0000 212.0000 +26.2083 306.0000 3351.0000 3281.0000 1775.0000 607.0000 228.0000 237.0000 215.0000 +26.2500 306.0000 3338.0000 3287.0000 1775.0000 604.0000 227.0000 247.0000 216.0000 +26.2917 306.0000 3332.0000 3290.0000 1770.0000 612.0000 230.0000 244.0000 216.0000 +26.3333 306.0000 3336.0000 3271.0000 1766.0000 609.0000 234.0000 261.0000 217.0000 +26.3750 306.0000 3325.0000 3273.0000 1768.0000 609.0000 234.0000 266.0000 219.0000 +26.4167 306.0000 3307.0000 3284.0000 1767.0000 602.0000 237.0000 278.0000 219.0000 +26.4583 305.0000 3299.0000 3275.0000 1782.0000 602.0000 238.0000 278.0000 221.0000 +26.5000 304.0000 3285.0000 3266.0000 1777.0000 597.0000 245.0000 305.0000 221.0000 +26.5417 304.0000 3290.0000 3260.0000 1774.0000 597.0000 249.0000 304.0000 222.0000 +26.5833 304.0000 3290.0000 3263.0000 1776.0000 597.0000 248.0000 298.0000 224.0000 +26.6250 304.0000 3286.0000 3262.0000 1779.0000 601.0000 249.0000 294.0000 225.0000 +26.6667 304.0000 3306.0000 3248.0000 1788.0000 598.0000 255.0000 276.0000 225.0000 +26.7083 304.0000 3311.0000 3243.0000 1786.0000 596.0000 256.0000 278.0000 226.0000 +26.7500 302.0000 3336.0000 3252.0000 1774.0000 594.0000 258.0000 256.0000 228.0000 +26.7917 301.0000 3335.0000 3267.0000 1767.0000 592.0000 260.0000 248.0000 230.0000 +26.8333 301.0000 3337.0000 3261.0000 1773.0000 593.0000 258.0000 244.0000 233.0000 +26.8750 301.0000 3335.0000 3257.0000 1768.0000 598.0000 257.0000 250.0000 234.0000 +26.9167 301.0000 3340.0000 3252.0000 1777.0000 598.0000 258.0000 239.0000 235.0000 +26.9583 301.0000 3341.0000 3255.0000 1783.0000 597.0000 257.0000 230.0000 236.0000 +27.0000 301.0000 3328.0000 3265.0000 1779.0000 605.0000 254.0000 231.0000 237.0000 +27.0417 300.0000 3317.0000 3280.0000 1774.0000 601.0000 254.0000 234.0000 240.0000 +27.0833 300.0000 3308.0000 3281.0000 1780.0000 594.0000 257.0000 240.0000 240.0000 +27.1250 299.0000 3309.0000 3289.0000 1778.0000 593.0000 257.0000 234.0000 241.0000 +27.1667 299.0000 3297.0000 3294.0000 1772.0000 595.0000 255.0000 244.0000 244.0000 +27.2083 299.0000 3298.0000 3284.0000 1775.0000 598.0000 257.0000 242.0000 247.0000 +27.2500 298.0000 3291.0000 3288.0000 1771.0000 600.0000 257.0000 246.0000 249.0000 +27.2917 297.0000 3288.0000 3292.0000 1759.0000 602.0000 259.0000 254.0000 249.0000 +27.3333 295.0000 3277.0000 3297.0000 1755.0000 602.0000 261.0000 264.0000 249.0000 +27.3750 295.0000 3269.0000 3294.0000 1761.0000 598.0000 261.0000 270.0000 252.0000 +27.4167 294.0000 3265.0000 3310.0000 1753.0000 604.0000 261.0000 260.0000 253.0000 +27.4583 294.0000 3252.0000 3308.0000 1752.0000 608.0000 259.0000 273.0000 254.0000 +27.5000 292.0000 3247.0000 3311.0000 1754.0000 603.0000 263.0000 276.0000 254.0000 +27.5417 292.0000 3239.0000 3314.0000 1756.0000 607.0000 260.0000 275.0000 257.0000 +27.5833 292.0000 3232.0000 3310.0000 1765.0000 602.0000 258.0000 282.0000 259.0000 +27.6250 292.0000 3219.0000 3321.0000 1762.0000 604.0000 257.0000 284.0000 261.0000 +27.6667 292.0000 3240.0000 3314.0000 1765.0000 603.0000 257.0000 266.0000 263.0000 +27.7083 292.0000 3243.0000 3322.0000 1758.0000 607.0000 253.0000 259.0000 266.0000 +27.7500 292.0000 3253.0000 3318.0000 1754.0000 612.0000 255.0000 250.0000 266.0000 +27.7917 292.0000 3252.0000 3311.0000 1752.0000 616.0000 256.0000 253.0000 268.0000 +27.8333 291.0000 3257.0000 3310.0000 1759.0000 617.0000 255.0000 242.0000 269.0000 +27.8750 291.0000 3255.0000 3301.0000 1763.0000 621.0000 255.0000 244.0000 270.0000 +27.9167 290.0000 3246.0000 3300.0000 1770.0000 619.0000 259.0000 246.0000 270.0000 +27.9583 290.0000 3244.0000 3301.0000 1770.0000 616.0000 264.0000 244.0000 271.0000 +28.0000 290.0000 3245.0000 3282.0000 1785.0000 618.0000 263.0000 244.0000 273.0000 +28.0417 290.0000 3240.0000 3281.0000 1786.0000 619.0000 262.0000 245.0000 277.0000 +28.0833 289.0000 3233.0000 3279.0000 1782.0000 619.0000 263.0000 257.0000 278.0000 +28.1250 289.0000 3234.0000 3273.0000 1783.0000 619.0000 264.0000 260.0000 278.0000 +28.1667 289.0000 3234.0000 3270.0000 1779.0000 622.0000 264.0000 263.0000 279.0000 +28.2083 289.0000 3230.0000 3275.0000 1785.0000 621.0000 264.0000 255.0000 281.0000 +28.2500 289.0000 3220.0000 3282.0000 1776.0000 627.0000 262.0000 260.0000 284.0000 +28.2917 288.0000 3222.0000 3275.0000 1775.0000 624.0000 264.0000 267.0000 285.0000 +28.3333 288.0000 3218.0000 3281.0000 1770.0000 625.0000 265.0000 266.0000 287.0000 +28.3750 288.0000 3207.0000 3272.0000 1777.0000 626.0000 265.0000 276.0000 289.0000 +28.4167 288.0000 3190.0000 3283.0000 1775.0000 619.0000 267.0000 288.0000 290.0000 +28.4583 288.0000 3188.0000 3286.0000 1770.0000 623.0000 272.0000 282.0000 291.0000 +28.5000 287.0000 3173.0000 3299.0000 1772.0000 627.0000 270.0000 280.0000 292.0000 +28.5417 287.0000 3173.0000 3300.0000 1771.0000 630.0000 270.0000 276.0000 293.0000 +28.5833 287.0000 3167.0000 3305.0000 1781.0000 625.0000 271.0000 270.0000 294.0000 +28.6250 287.0000 3151.0000 3301.0000 1781.0000 629.0000 272.0000 284.0000 295.0000 +28.6667 287.0000 3161.0000 3298.0000 1782.0000 630.0000 272.0000 273.0000 297.0000 +28.7083 287.0000 3173.0000 3286.0000 1786.0000 634.0000 274.0000 261.0000 299.0000 +28.7500 287.0000 3194.0000 3268.0000 1790.0000 634.0000 277.0000 250.0000 300.0000 +28.7917 287.0000 3190.0000 3277.0000 1792.0000 635.0000 274.0000 241.0000 304.0000 +28.8333 287.0000 3182.0000 3285.0000 1788.0000 637.0000 274.0000 243.0000 304.0000 +28.8750 287.0000 3186.0000 3282.0000 1785.0000 639.0000 276.0000 239.0000 306.0000 +28.9167 287.0000 3188.0000 3276.0000 1787.0000 644.0000 276.0000 235.0000 307.0000 +28.9583 287.0000 3192.0000 3275.0000 1785.0000 646.0000 276.0000 229.0000 310.0000 +29.0000 287.0000 3186.0000 3276.0000 1786.0000 649.0000 277.0000 229.0000 310.0000 +29.0417 286.0000 3186.0000 3274.0000 1781.0000 652.0000 274.0000 234.0000 313.0000 +29.0833 286.0000 3182.0000 3273.0000 1775.0000 658.0000 276.0000 237.0000 313.0000 +29.1250 286.0000 3169.0000 3275.0000 1775.0000 661.0000 274.0000 247.0000 313.0000 +29.1667 286.0000 3164.0000 3285.0000 1770.0000 660.0000 275.0000 246.0000 314.0000 +29.2083 285.0000 3155.0000 3298.0000 1764.0000 663.0000 272.0000 247.0000 316.0000 +29.2500 285.0000 3152.0000 3291.0000 1753.0000 673.0000 274.0000 256.0000 316.0000 +29.2917 285.0000 3154.0000 3292.0000 1759.0000 670.0000 276.0000 247.0000 317.0000 +29.3333 285.0000 3134.0000 3291.0000 1758.0000 671.0000 278.0000 265.0000 318.0000 +29.3750 284.0000 3123.0000 3276.0000 1760.0000 676.0000 276.0000 286.0000 319.0000 +29.4167 284.0000 3120.0000 3264.0000 1763.0000 668.0000 283.0000 299.0000 319.0000 +29.4583 283.0000 3125.0000 3265.0000 1753.0000 668.0000 282.0000 302.0000 322.0000 +29.5000 282.0000 3120.0000 3270.0000 1753.0000 665.0000 283.0000 305.0000 322.0000 +29.5417 282.0000 3116.0000 3270.0000 1752.0000 662.0000 285.0000 311.0000 322.0000 +29.5833 282.0000 3107.0000 3277.0000 1753.0000 662.0000 282.0000 313.0000 324.0000 +29.6250 282.0000 3107.0000 3276.0000 1756.0000 660.0000 285.0000 309.0000 325.0000 +29.6667 282.0000 3129.0000 3261.0000 1760.0000 665.0000 286.0000 291.0000 326.0000 +29.7083 280.0000 3135.0000 3261.0000 1764.0000 666.0000 286.0000 281.0000 327.0000 +29.7500 278.0000 3147.0000 3265.0000 1756.0000 664.0000 284.0000 276.0000 330.0000 +29.7917 277.0000 3169.0000 3266.0000 1745.0000 670.0000 283.0000 258.0000 332.0000 +29.8333 277.0000 3169.0000 3266.0000 1747.0000 666.0000 280.0000 261.0000 334.0000 +29.8750 277.0000 3182.0000 3255.0000 1758.0000 665.0000 280.0000 248.0000 335.0000 +29.9167 277.0000 3189.0000 3253.0000 1763.0000 663.0000 279.0000 238.0000 338.0000 +29.9583 277.0000 3190.0000 3245.0000 1770.0000 665.0000 279.0000 233.0000 341.0000 +30.0000 277.0000 3196.0000 3231.0000 1765.0000 661.0000 280.0000 247.0000 343.0000 +30.0417 277.0000 3216.0000 3197.0000 1772.0000 662.0000 281.0000 250.0000 345.0000 +30.0833 277.0000 3235.0000 3172.0000 1783.0000 660.0000 281.0000 245.0000 347.0000 +30.1250 277.0000 3232.0000 3170.0000 1797.0000 654.0000 285.0000 238.0000 347.0000 +30.1667 277.0000 3230.0000 3167.0000 1788.0000 657.0000 286.0000 248.0000 347.0000 +30.2083 276.0000 3227.0000 3160.0000 1786.0000 652.0000 286.0000 266.0000 347.0000 +30.2500 275.0000 3238.0000 3152.0000 1786.0000 655.0000 285.0000 261.0000 348.0000 +30.2917 275.0000 3231.0000 3150.0000 1787.0000 653.0000 283.0000 271.0000 350.0000 +30.3333 275.0000 3228.0000 3145.0000 1786.0000 655.0000 283.0000 276.0000 352.0000 +30.3750 275.0000 3222.0000 3139.0000 1783.0000 660.0000 281.0000 287.0000 353.0000 +30.4167 274.0000 3221.0000 3131.0000 1787.0000 656.0000 283.0000 294.0000 354.0000 +30.4583 274.0000 3208.0000 3147.0000 1791.0000 656.0000 283.0000 286.0000 355.0000 +30.5000 273.0000 3199.0000 3137.0000 1799.0000 655.0000 288.0000 294.0000 355.0000 +30.5417 272.0000 3196.0000 3133.0000 1798.0000 663.0000 287.0000 295.0000 356.0000 +30.5833 270.0000 3186.0000 3133.0000 1799.0000 660.0000 293.0000 303.0000 356.0000 +30.6250 269.0000 3180.0000 3135.0000 1791.0000 666.0000 294.0000 309.0000 356.0000 +30.6667 268.0000 3190.0000 3130.0000 1783.0000 678.0000 290.0000 301.0000 360.0000 +30.7083 268.0000 3203.0000 3124.0000 1785.0000 681.0000 289.0000 289.0000 361.0000 +30.7500 268.0000 3215.0000 3134.0000 1784.0000 685.0000 292.0000 261.0000 361.0000 +30.7917 268.0000 3223.0000 3131.0000 1781.0000 692.0000 290.0000 252.0000 363.0000 +30.8333 268.0000 3225.0000 3104.0000 1782.0000 697.0000 290.0000 271.0000 363.0000 +30.8750 268.0000 3233.0000 3113.0000 1786.0000 696.0000 288.0000 250.0000 366.0000 +30.9167 268.0000 3223.0000 3122.0000 1781.0000 695.0000 290.0000 253.0000 368.0000 +30.9583 268.0000 3228.0000 3103.0000 1791.0000 696.0000 292.0000 254.0000 368.0000 +31.0000 268.0000 3230.0000 3098.0000 1792.0000 696.0000 293.0000 255.0000 368.0000 +31.0417 268.0000 3212.0000 3105.0000 1795.0000 696.0000 297.0000 259.0000 368.0000 +31.0833 268.0000 3206.0000 3113.0000 1784.0000 703.0000 298.0000 259.0000 369.0000 +31.1250 268.0000 3208.0000 3111.0000 1784.0000 704.0000 301.0000 255.0000 369.0000 +31.1667 268.0000 3201.0000 3107.0000 1786.0000 704.0000 300.0000 262.0000 372.0000 +31.2083 268.0000 3197.0000 3112.0000 1781.0000 701.0000 300.0000 267.0000 374.0000 +31.2500 268.0000 3181.0000 3110.0000 1780.0000 703.0000 301.0000 281.0000 376.0000 +31.2917 268.0000 3181.0000 3113.0000 1782.0000 707.0000 302.0000 269.0000 378.0000 +31.3333 268.0000 3162.0000 3117.0000 1791.0000 699.0000 304.0000 278.0000 381.0000 +31.3750 268.0000 3154.0000 3123.0000 1796.0000 695.0000 305.0000 276.0000 383.0000 +31.4167 268.0000 3147.0000 3118.0000 1808.0000 693.0000 306.0000 275.0000 385.0000 +31.4583 268.0000 3133.0000 3120.0000 1813.0000 690.0000 307.0000 282.0000 387.0000 +31.5000 268.0000 3109.0000 3125.0000 1808.0000 690.0000 305.0000 304.0000 391.0000 +31.5417 268.0000 3115.0000 3129.0000 1800.0000 690.0000 304.0000 302.0000 392.0000 +31.5833 267.0000 3127.0000 3108.0000 1802.0000 689.0000 302.0000 311.0000 394.0000 +31.6250 267.0000 3135.0000 3101.0000 1807.0000 679.0000 304.0000 313.0000 394.0000 +31.6667 267.0000 3144.0000 3104.0000 1801.0000 671.0000 308.0000 310.0000 395.0000 +31.7083 267.0000 3157.0000 3111.0000 1797.0000 665.0000 314.0000 293.0000 396.0000 +31.7500 267.0000 3174.0000 3098.0000 1797.0000 663.0000 314.0000 290.0000 397.0000 +31.7917 267.0000 3187.0000 3098.0000 1792.0000 665.0000 315.0000 278.0000 398.0000 +31.8333 267.0000 3181.0000 3096.0000 1786.0000 670.0000 316.0000 283.0000 401.0000 +31.8750 267.0000 3188.0000 3101.0000 1788.0000 672.0000 317.0000 265.0000 402.0000 +31.9167 267.0000 3192.0000 3102.0000 1782.0000 672.0000 319.0000 262.0000 404.0000 +31.9583 267.0000 3200.0000 3087.0000 1788.0000 668.0000 323.0000 262.0000 405.0000 +32.0000 267.0000 3197.0000 3092.0000 1785.0000 671.0000 326.0000 256.0000 406.0000 +32.0417 267.0000 3193.0000 3094.0000 1783.0000 675.0000 322.0000 257.0000 409.0000 +32.0833 266.0000 3182.0000 3097.0000 1789.0000 670.0000 322.0000 263.0000 411.0000 +32.1250 266.0000 3178.0000 3091.0000 1788.0000 669.0000 321.0000 275.0000 412.0000 +32.1667 266.0000 3184.0000 3085.0000 1788.0000 678.0000 318.0000 266.0000 415.0000 +32.2083 266.0000 3183.0000 3085.0000 1783.0000 677.0000 316.0000 271.0000 419.0000 +32.2500 265.0000 3185.0000 3081.0000 1778.0000 676.0000 318.0000 278.0000 419.0000 +32.2917 265.0000 3187.0000 3068.0000 1777.0000 677.0000 319.0000 287.0000 420.0000 +32.3333 264.0000 3195.0000 3067.0000 1772.0000 679.0000 318.0000 284.0000 421.0000 +32.3750 264.0000 3188.0000 3066.0000 1767.0000 680.0000 317.0000 295.0000 423.0000 +32.4167 264.0000 3168.0000 3085.0000 1753.0000 681.0000 319.0000 305.0000 425.0000 +32.4583 262.0000 3168.0000 3083.0000 1749.0000 685.0000 323.0000 304.0000 426.0000 +32.5000 262.0000 3163.0000 3077.0000 1747.0000 691.0000 323.0000 309.0000 428.0000 +32.5417 262.0000 3153.0000 3083.0000 1748.0000 691.0000 318.0000 313.0000 432.0000 +32.5833 262.0000 3150.0000 3078.0000 1752.0000 700.0000 320.0000 305.0000 433.0000 +32.6250 262.0000 3135.0000 3092.0000 1749.0000 695.0000 319.0000 315.0000 433.0000 +32.6667 262.0000 3153.0000 3083.0000 1749.0000 697.0000 314.0000 304.0000 438.0000 +32.7083 262.0000 3159.0000 3098.0000 1747.0000 700.0000 314.0000 280.0000 440.0000 +32.7500 262.0000 3171.0000 3089.0000 1745.0000 696.0000 314.0000 280.0000 443.0000 +32.7917 262.0000 3176.0000 3093.0000 1747.0000 694.0000 316.0000 268.0000 444.0000 +32.8333 261.0000 3166.0000 3097.0000 1739.0000 697.0000 316.0000 278.0000 446.0000 +32.8750 261.0000 3160.0000 3104.0000 1743.0000 694.0000 314.0000 275.0000 449.0000 +32.9167 261.0000 3160.0000 3109.0000 1738.0000 693.0000 310.0000 278.0000 451.0000 +32.9583 261.0000 3167.0000 3113.0000 1735.0000 694.0000 308.0000 269.0000 453.0000 +33.0000 261.0000 3169.0000 3110.0000 1728.0000 695.0000 313.0000 271.0000 453.0000 +33.0417 261.0000 3168.0000 3120.0000 1728.0000 701.0000 312.0000 254.0000 456.0000 +33.0833 261.0000 3164.0000 3112.0000 1731.0000 697.0000 313.0000 264.0000 458.0000 +33.1250 261.0000 3154.0000 3112.0000 1739.0000 694.0000 313.0000 266.0000 461.0000 +33.1667 261.0000 3145.0000 3106.0000 1735.0000 700.0000 313.0000 276.0000 464.0000 +33.2083 261.0000 3145.0000 3100.0000 1745.0000 695.0000 317.0000 273.0000 464.0000 +33.2500 261.0000 3149.0000 3096.0000 1739.0000 698.0000 310.0000 278.0000 469.0000 +33.2917 261.0000 3148.0000 3091.0000 1742.0000 694.0000 309.0000 285.0000 470.0000 +33.3333 261.0000 3151.0000 3084.0000 1733.0000 697.0000 310.0000 293.0000 471.0000 +33.3750 261.0000 3142.0000 3096.0000 1728.0000 698.0000 310.0000 293.0000 472.0000 +33.4167 261.0000 3130.0000 3090.0000 1727.0000 699.0000 309.0000 312.0000 472.0000 +33.4583 258.0000 3126.0000 3089.0000 1727.0000 700.0000 310.0000 316.0000 474.0000 +33.5000 258.0000 3128.0000 3088.0000 1723.0000 701.0000 314.0000 314.0000 474.0000 +33.5417 258.0000 3120.0000 3094.0000 1724.0000 697.0000 317.0000 315.0000 475.0000 +33.5833 258.0000 3116.0000 3093.0000 1722.0000 699.0000 318.0000 318.0000 476.0000 +33.6250 257.0000 3116.0000 3088.0000 1719.0000 699.0000 318.0000 325.0000 478.0000 +33.6667 257.0000 3124.0000 3090.0000 1721.0000 699.0000 321.0000 310.0000 478.0000 +33.7083 257.0000 3132.0000 3091.0000 1722.0000 704.0000 322.0000 294.0000 478.0000 +33.7500 257.0000 3155.0000 3074.0000 1729.0000 711.0000 317.0000 275.0000 482.0000 +33.7917 257.0000 3171.0000 3071.0000 1735.0000 707.0000 319.0000 256.0000 484.0000 +33.8333 257.0000 3175.0000 3067.0000 1735.0000 710.0000 320.0000 252.0000 484.0000 +33.8750 256.0000 3173.0000 3062.0000 1739.0000 709.0000 318.0000 256.0000 487.0000 +33.9167 256.0000 3177.0000 3055.0000 1735.0000 717.0000 317.0000 255.0000 488.0000 +33.9583 256.0000 3181.0000 3067.0000 1726.0000 718.0000 316.0000 246.0000 490.0000 +34.0000 256.0000 3175.0000 3067.0000 1719.0000 719.0000 316.0000 257.0000 491.0000 +34.0417 256.0000 3180.0000 3065.0000 1712.0000 723.0000 317.0000 256.0000 491.0000 +34.0833 256.0000 3178.0000 3056.0000 1713.0000 724.0000 319.0000 261.0000 493.0000 +34.1250 256.0000 3178.0000 3059.0000 1707.0000 729.0000 319.0000 257.0000 495.0000 +34.1667 256.0000 3171.0000 3066.0000 1703.0000 729.0000 321.0000 258.0000 496.0000 +34.2083 256.0000 3169.0000 3066.0000 1699.0000 739.0000 323.0000 252.0000 496.0000 +34.2500 256.0000 3155.0000 3069.0000 1701.0000 744.0000 322.0000 257.0000 496.0000 +34.2917 255.0000 3156.0000 3058.0000 1698.0000 740.0000 322.0000 273.0000 498.0000 +34.3333 255.0000 3160.0000 3056.0000 1701.0000 738.0000 324.0000 266.0000 500.0000 +34.3750 255.0000 3163.0000 3050.0000 1701.0000 735.0000 322.0000 272.0000 502.0000 +34.4167 255.0000 3159.0000 3056.0000 1703.0000 735.0000 321.0000 269.0000 502.0000 +34.4583 255.0000 3152.0000 3063.0000 1701.0000 739.0000 318.0000 267.0000 505.0000 +34.5000 254.0000 3122.0000 3080.0000 1704.0000 739.0000 318.0000 278.0000 505.0000 +34.5417 254.0000 3109.0000 3094.0000 1700.0000 741.0000 317.0000 277.0000 508.0000 +34.5833 254.0000 3097.0000 3100.0000 1703.0000 735.0000 321.0000 281.0000 509.0000 +34.6250 254.0000 3087.0000 3099.0000 1699.0000 733.0000 323.0000 296.0000 509.0000 +34.6667 254.0000 3089.0000 3116.0000 1695.0000 736.0000 320.0000 277.0000 513.0000 +34.7083 254.0000 3093.0000 3110.0000 1692.0000 735.0000 321.0000 278.0000 517.0000 +34.7500 254.0000 3105.0000 3117.0000 1692.0000 737.0000 322.0000 256.0000 517.0000 +34.7917 253.0000 3101.0000 3121.0000 1686.0000 743.0000 322.0000 254.0000 520.0000 +34.8333 253.0000 3097.0000 3127.0000 1680.0000 746.0000 321.0000 252.0000 524.0000 +34.8750 253.0000 3097.0000 3115.0000 1687.0000 743.0000 325.0000 255.0000 525.0000 +34.9167 253.0000 3087.0000 3112.0000 1680.0000 750.0000 329.0000 264.0000 525.0000 +34.9583 253.0000 3093.0000 3105.0000 1679.0000 756.0000 326.0000 262.0000 526.0000 +35.0000 253.0000 3108.0000 3098.0000 1680.0000 757.0000 324.0000 251.0000 529.0000 +35.0417 253.0000 3103.0000 3100.0000 1677.0000 757.0000 322.0000 257.0000 531.0000 +35.0833 253.0000 3111.0000 3091.0000 1677.0000 760.0000 318.0000 257.0000 533.0000 +35.1250 253.0000 3103.0000 3090.0000 1674.0000 761.0000 319.0000 267.0000 533.0000 +35.1667 253.0000 3096.0000 3095.0000 1680.0000 754.0000 326.0000 262.0000 534.0000 +35.2083 253.0000 3089.0000 3099.0000 1680.0000 758.0000 327.0000 259.0000 535.0000 +35.2500 253.0000 3074.0000 3102.0000 1675.0000 764.0000 322.0000 271.0000 539.0000 +35.2917 253.0000 3082.0000 3092.0000 1672.0000 764.0000 325.0000 272.0000 540.0000 +35.3333 253.0000 3086.0000 3086.0000 1674.0000 759.0000 326.0000 274.0000 542.0000 +35.3750 253.0000 3075.0000 3078.0000 1685.0000 757.0000 326.0000 281.0000 545.0000 +35.4167 252.0000 3062.0000 3083.0000 1680.0000 762.0000 323.0000 290.0000 548.0000 +35.4583 251.0000 3054.0000 3086.0000 1669.0000 766.0000 326.0000 300.0000 548.0000 +35.5000 251.0000 3046.0000 3087.0000 1677.0000 758.0000 330.0000 302.0000 549.0000 +35.5417 251.0000 3039.0000 3091.0000 1675.0000 756.0000 330.0000 307.0000 551.0000 +35.5833 251.0000 3051.0000 3086.0000 1674.0000 759.0000 325.0000 301.0000 553.0000 +35.6250 251.0000 3044.0000 3080.0000 1671.0000 765.0000 319.0000 312.0000 558.0000 +35.6667 251.0000 3045.0000 3093.0000 1670.0000 765.0000 321.0000 297.0000 558.0000 +35.7083 251.0000 3043.0000 3107.0000 1671.0000 763.0000 317.0000 289.0000 559.0000 +35.7500 251.0000 3061.0000 3104.0000 1679.0000 756.0000 318.0000 271.0000 560.0000 +35.7917 251.0000 3081.0000 3111.0000 1678.0000 753.0000 320.0000 244.0000 562.0000 +35.8333 251.0000 3066.0000 3112.0000 1679.0000 757.0000 320.0000 250.0000 565.0000 +35.8750 251.0000 3066.0000 3095.0000 1684.0000 758.0000 325.0000 256.0000 565.0000 +35.9167 251.0000 3067.0000 3095.0000 1683.0000 758.0000 323.0000 255.0000 568.0000 +35.9583 251.0000 3067.0000 3088.0000 1687.0000 762.0000 322.0000 253.0000 570.0000 +36.0000 251.0000 3059.0000 3092.0000 1686.0000 764.0000 318.0000 256.0000 574.0000 +36.0417 251.0000 3052.0000 3097.0000 1688.0000 758.0000 317.0000 261.0000 576.0000 +36.0833 251.0000 3047.0000 3113.0000 1683.0000 759.0000 321.0000 249.0000 577.0000 +36.1250 251.0000 3028.0000 3121.0000 1685.0000 763.0000 320.0000 254.0000 578.0000 +36.1667 251.0000 3013.0000 3124.0000 1694.0000 758.0000 320.0000 259.0000 581.0000 +36.2083 251.0000 3000.0000 3130.0000 1690.0000 755.0000 321.0000 270.0000 583.0000 +36.2500 251.0000 2996.0000 3131.0000 1690.0000 758.0000 319.0000 272.0000 583.0000 +36.2917 251.0000 2994.0000 3133.0000 1682.0000 758.0000 319.0000 278.0000 585.0000 +36.3333 251.0000 2999.0000 3119.0000 1702.0000 755.0000 319.0000 268.0000 587.0000 +36.3750 251.0000 2991.0000 3118.0000 1706.0000 754.0000 323.0000 270.0000 587.0000 +36.4167 251.0000 2983.0000 3118.0000 1699.0000 760.0000 322.0000 279.0000 588.0000 +36.4583 251.0000 2975.0000 3108.0000 1700.0000 761.0000 322.0000 293.0000 590.0000 +36.5000 251.0000 2979.0000 3104.0000 1689.0000 766.0000 321.0000 298.0000 592.0000 +36.5417 251.0000 2968.0000 3111.0000 1690.0000 769.0000 320.0000 297.0000 594.0000 +36.5833 251.0000 2965.0000 3116.0000 1687.0000 766.0000 322.0000 295.0000 598.0000 +36.6250 251.0000 2961.0000 3121.0000 1688.0000 759.0000 324.0000 295.0000 601.0000 +36.6667 251.0000 2965.0000 3111.0000 1690.0000 760.0000 326.0000 296.0000 601.0000 +36.7083 251.0000 2981.0000 3113.0000 1690.0000 755.0000 330.0000 279.0000 601.0000 +36.7500 251.0000 3000.0000 3107.0000 1684.0000 756.0000 329.0000 272.0000 601.0000 +36.7917 251.0000 3014.0000 3109.0000 1684.0000 758.0000 328.0000 254.0000 602.0000 +36.8333 250.0000 3004.0000 3110.0000 1689.0000 757.0000 327.0000 259.0000 604.0000 +36.8750 250.0000 3003.0000 3110.0000 1686.0000 752.0000 331.0000 262.0000 606.0000 +36.9167 250.0000 2994.0000 3123.0000 1680.0000 753.0000 326.0000 264.0000 610.0000 +36.9583 250.0000 3007.0000 3120.0000 1677.0000 752.0000 322.0000 257.0000 615.0000 +37.0000 250.0000 3014.0000 3111.0000 1669.0000 754.0000 324.0000 259.0000 619.0000 +37.0417 250.0000 3016.0000 3110.0000 1664.0000 752.0000 329.0000 259.0000 620.0000 +37.0833 250.0000 3007.0000 3111.0000 1662.0000 755.0000 332.0000 263.0000 620.0000 +37.1250 250.0000 3002.0000 3099.0000 1677.0000 750.0000 335.0000 266.0000 621.0000 +37.1667 250.0000 2988.0000 3101.0000 1668.0000 758.0000 338.0000 276.0000 621.0000 +37.2083 250.0000 2988.0000 3091.0000 1662.0000 763.0000 338.0000 285.0000 623.0000 +37.2500 250.0000 2996.0000 3072.0000 1668.0000 758.0000 334.0000 292.0000 630.0000 +37.2917 250.0000 3001.0000 3072.0000 1664.0000 760.0000 332.0000 290.0000 631.0000 +37.3333 250.0000 3006.0000 3063.0000 1670.0000 759.0000 335.0000 284.0000 633.0000 +37.3750 250.0000 2986.0000 3073.0000 1667.0000 762.0000 333.0000 294.0000 635.0000 +37.4167 250.0000 2978.0000 3069.0000 1661.0000 767.0000 331.0000 306.0000 638.0000 +37.4583 250.0000 2957.0000 3072.0000 1664.0000 766.0000 329.0000 321.0000 641.0000 +37.5000 250.0000 2947.0000 3081.0000 1661.0000 761.0000 332.0000 327.0000 641.0000 +37.5417 250.0000 2940.0000 3090.0000 1653.0000 757.0000 337.0000 332.0000 641.0000 +37.5833 250.0000 2936.0000 3080.0000 1660.0000 759.0000 336.0000 338.0000 641.0000 +37.6250 250.0000 2925.0000 3084.0000 1662.0000 760.0000 338.0000 339.0000 642.0000 +37.6667 250.0000 2949.0000 3087.0000 1656.0000 762.0000 337.0000 316.0000 643.0000 +37.7083 250.0000 2957.0000 3071.0000 1670.0000 756.0000 337.0000 314.0000 645.0000 +37.7500 250.0000 2972.0000 3086.0000 1666.0000 755.0000 338.0000 286.0000 647.0000 +37.7917 250.0000 2983.0000 3088.0000 1660.0000 760.0000 335.0000 274.0000 650.0000 +37.8333 250.0000 2982.0000 3085.0000 1659.0000 765.0000 333.0000 273.0000 653.0000 +37.8750 250.0000 2980.0000 3082.0000 1666.0000 764.0000 334.0000 269.0000 655.0000 +37.9167 250.0000 2977.0000 3084.0000 1666.0000 773.0000 335.0000 259.0000 656.0000 +37.9583 249.0000 2972.0000 3087.0000 1666.0000 775.0000 333.0000 262.0000 656.0000 +38.0000 249.0000 2975.0000 3091.0000 1663.0000 776.0000 329.0000 259.0000 658.0000 +38.0417 249.0000 2965.0000 3087.0000 1668.0000 771.0000 331.0000 269.0000 660.0000 +38.0833 249.0000 2962.0000 3093.0000 1667.0000 768.0000 334.0000 267.0000 660.0000 +38.1250 249.0000 2965.0000 3082.0000 1665.0000 765.0000 332.0000 278.0000 664.0000 +38.1667 249.0000 2967.0000 3079.0000 1666.0000 767.0000 332.0000 274.0000 666.0000 +38.2083 248.0000 2973.0000 3071.0000 1667.0000 765.0000 334.0000 275.0000 667.0000 +38.2500 248.0000 2974.0000 3061.0000 1666.0000 763.0000 337.0000 282.0000 669.0000 +38.2917 248.0000 2976.0000 3064.0000 1665.0000 761.0000 336.0000 280.0000 670.0000 +38.3333 248.0000 2960.0000 3062.0000 1666.0000 765.0000 336.0000 290.0000 673.0000 +38.3750 248.0000 2958.0000 3049.0000 1667.0000 764.0000 336.0000 304.0000 674.0000 +38.4167 248.0000 2955.0000 3041.0000 1665.0000 761.0000 341.0000 314.0000 675.0000 +38.4583 248.0000 2939.0000 3044.0000 1664.0000 757.0000 348.0000 324.0000 676.0000 +38.5000 248.0000 2941.0000 3041.0000 1660.0000 761.0000 351.0000 322.0000 676.0000 +38.5417 248.0000 2945.0000 3042.0000 1666.0000 756.0000 352.0000 314.0000 677.0000 +38.5833 247.0000 2950.0000 3035.0000 1663.0000 756.0000 350.0000 319.0000 680.0000 +38.6250 246.0000 2937.0000 3048.0000 1655.0000 754.0000 349.0000 330.0000 681.0000 +38.6667 246.0000 2944.0000 3055.0000 1650.0000 755.0000 349.0000 319.0000 682.0000 +38.7083 246.0000 2959.0000 3050.0000 1647.0000 758.0000 345.0000 310.0000 685.0000 +38.7500 246.0000 2986.0000 3049.0000 1642.0000 758.0000 347.0000 287.0000 685.0000 +38.7917 245.0000 2992.0000 3055.0000 1643.0000 758.0000 349.0000 273.0000 685.0000 +38.8333 245.0000 2997.0000 3036.0000 1648.0000 752.0000 351.0000 286.0000 685.0000 +38.8750 245.0000 3004.0000 3028.0000 1657.0000 749.0000 352.0000 279.0000 686.0000 +38.9167 245.0000 3013.0000 3020.0000 1660.0000 747.0000 353.0000 275.0000 687.0000 +38.9583 245.0000 3020.0000 3023.0000 1647.0000 757.0000 348.0000 272.0000 688.0000 +39.0000 245.0000 3018.0000 3031.0000 1648.0000 758.0000 350.0000 262.0000 688.0000 +39.0417 245.0000 3023.0000 3020.0000 1651.0000 760.0000 354.0000 259.0000 688.0000 +39.0833 245.0000 3025.0000 3017.0000 1651.0000 758.0000 353.0000 261.0000 690.0000 +39.1250 245.0000 3012.0000 3014.0000 1653.0000 764.0000 354.0000 266.0000 692.0000 +39.1667 245.0000 3011.0000 3005.0000 1666.0000 756.0000 353.0000 269.0000 695.0000 +39.2083 245.0000 3001.0000 3018.0000 1663.0000 751.0000 357.0000 269.0000 696.0000 +39.2500 245.0000 3005.0000 3015.0000 1669.0000 751.0000 359.0000 259.0000 697.0000 +39.2917 245.0000 2992.0000 3021.0000 1663.0000 750.0000 359.0000 271.0000 699.0000 +39.3333 245.0000 2985.0000 3008.0000 1669.0000 749.0000 362.0000 282.0000 700.0000 +39.3750 245.0000 2984.0000 2999.0000 1667.0000 750.0000 360.0000 293.0000 702.0000 +39.4167 245.0000 2981.0000 2996.0000 1658.0000 748.0000 361.0000 307.0000 704.0000 +39.4583 245.0000 2985.0000 2987.0000 1655.0000 747.0000 363.0000 313.0000 705.0000 +39.5000 244.0000 2975.0000 2989.0000 1650.0000 748.0000 361.0000 326.0000 707.0000 +39.5417 244.0000 2982.0000 2980.0000 1645.0000 752.0000 361.0000 326.0000 710.0000 +39.5833 244.0000 2992.0000 2969.0000 1650.0000 754.0000 360.0000 320.0000 711.0000 +39.6250 244.0000 2983.0000 2984.0000 1647.0000 755.0000 356.0000 319.0000 712.0000 +39.6667 244.0000 2996.0000 2975.0000 1643.0000 757.0000 357.0000 314.0000 714.0000 +39.7083 244.0000 3013.0000 2972.0000 1649.0000 751.0000 358.0000 297.0000 716.0000 +39.7500 244.0000 3014.0000 2980.0000 1654.0000 750.0000 358.0000 283.0000 717.0000 +39.7917 244.0000 3030.0000 2979.0000 1644.0000 750.0000 356.0000 277.0000 720.0000 +39.8333 244.0000 3023.0000 2976.0000 1641.0000 755.0000 357.0000 284.0000 720.0000 +39.8750 244.0000 3034.0000 2969.0000 1644.0000 760.0000 359.0000 270.0000 720.0000 +39.9167 244.0000 3034.0000 2970.0000 1643.0000 759.0000 360.0000 269.0000 721.0000 +39.9583 243.0000 3039.0000 2964.0000 1648.0000 758.0000 361.0000 265.0000 722.0000 +40.0000 243.0000 3035.0000 2975.0000 1646.0000 753.0000 363.0000 262.0000 723.0000 +40.0417 243.0000 3026.0000 2961.0000 1649.0000 747.0000 365.0000 285.0000 724.0000 +40.0833 243.0000 3035.0000 2970.0000 1651.0000 743.0000 366.0000 268.0000 724.0000 +40.1250 243.0000 3033.0000 2966.0000 1653.0000 741.0000 367.0000 272.0000 725.0000 +40.1667 243.0000 3033.0000 2969.0000 1647.0000 742.0000 366.0000 274.0000 726.0000 +40.2083 243.0000 3037.0000 2962.0000 1651.0000 745.0000 363.0000 269.0000 730.0000 +40.2500 243.0000 3031.0000 2960.0000 1652.0000 741.0000 363.0000 278.0000 732.0000 +40.2917 243.0000 3027.0000 2957.0000 1653.0000 739.0000 366.0000 280.0000 735.0000 +40.3333 243.0000 3020.0000 2953.0000 1660.0000 739.0000 361.0000 284.0000 740.0000 +40.3750 243.0000 3011.0000 2943.0000 1659.0000 742.0000 358.0000 302.0000 742.0000 +40.4167 243.0000 3008.0000 2950.0000 1650.0000 742.0000 356.0000 306.0000 745.0000 +40.4583 243.0000 2996.0000 2950.0000 1650.0000 746.0000 357.0000 311.0000 747.0000 +40.5000 243.0000 2984.0000 2966.0000 1643.0000 744.0000 354.0000 318.0000 748.0000 +40.5417 243.0000 2991.0000 2964.0000 1637.0000 746.0000 350.0000 316.0000 753.0000 +40.5833 242.0000 2995.0000 2963.0000 1630.0000 745.0000 354.0000 318.0000 753.0000 +40.6250 242.0000 2982.0000 2972.0000 1635.0000 745.0000 349.0000 319.0000 756.0000 +40.6667 242.0000 2992.0000 2973.0000 1625.0000 747.0000 349.0000 316.0000 756.0000 +40.7083 242.0000 2999.0000 2972.0000 1620.0000 747.0000 353.0000 310.0000 757.0000 +40.7500 242.0000 3003.0000 2993.0000 1610.0000 742.0000 355.0000 295.0000 760.0000 +40.7917 241.0000 3019.0000 2979.0000 1607.0000 743.0000 360.0000 291.0000 760.0000 +40.8333 241.0000 3027.0000 2969.0000 1617.0000 742.0000 359.0000 284.0000 761.0000 +40.8750 241.0000 3037.0000 2966.0000 1618.0000 750.0000 357.0000 268.0000 763.0000 +40.9167 241.0000 3026.0000 2964.0000 1618.0000 753.0000 355.0000 276.0000 767.0000 +40.9583 241.0000 3022.0000 2974.0000 1604.0000 757.0000 353.0000 278.0000 771.0000 +41.0000 241.0000 3018.0000 2972.0000 1607.0000 757.0000 354.0000 280.0000 771.0000 +41.0417 241.0000 3015.0000 2978.0000 1595.0000 760.0000 352.0000 287.0000 772.0000 +41.0833 241.0000 3008.0000 2978.0000 1599.0000 764.0000 350.0000 286.0000 774.0000 +41.1250 241.0000 3012.0000 2964.0000 1597.0000 764.0000 346.0000 298.0000 778.0000 +41.1667 241.0000 3018.0000 2966.0000 1588.0000 762.0000 344.0000 299.0000 782.0000 +41.2083 241.0000 3009.0000 2974.0000 1592.0000 760.0000 345.0000 296.0000 783.0000 +41.2500 241.0000 3009.0000 2974.0000 1595.0000 759.0000 348.0000 290.0000 784.0000 +41.2917 241.0000 3001.0000 2970.0000 1598.0000 759.0000 348.0000 296.0000 787.0000 +41.3333 241.0000 2997.0000 2974.0000 1601.0000 757.0000 347.0000 293.0000 790.0000 +41.3750 241.0000 2985.0000 2973.0000 1601.0000 757.0000 345.0000 306.0000 792.0000 +41.4167 241.0000 2977.0000 2964.0000 1596.0000 755.0000 348.0000 327.0000 792.0000 +41.4583 241.0000 2978.0000 2967.0000 1600.0000 754.0000 345.0000 321.0000 794.0000 +41.5000 240.0000 2976.0000 2975.0000 1603.0000 751.0000 347.0000 313.0000 795.0000 +41.5417 240.0000 2963.0000 2971.0000 1597.0000 756.0000 345.0000 330.0000 798.0000 +41.5833 240.0000 2977.0000 2971.0000 1590.0000 760.0000 341.0000 319.0000 802.0000 +41.6250 240.0000 2961.0000 2980.0000 1588.0000 761.0000 341.0000 325.0000 804.0000 +41.6667 240.0000 2958.0000 2991.0000 1583.0000 760.0000 346.0000 318.0000 804.0000 +41.7083 240.0000 2965.0000 2990.0000 1586.0000 759.0000 345.0000 309.0000 806.0000 +41.7500 240.0000 2981.0000 2988.0000 1589.0000 758.0000 344.0000 293.0000 807.0000 +41.7917 240.0000 2989.0000 2981.0000 1595.0000 754.0000 350.0000 282.0000 809.0000 +41.8333 240.0000 2985.0000 2986.0000 1588.0000 751.0000 352.0000 288.0000 810.0000 +41.8750 240.0000 2995.0000 2984.0000 1585.0000 750.0000 352.0000 283.0000 811.0000 +41.9167 240.0000 2989.0000 2982.0000 1588.0000 752.0000 349.0000 286.0000 814.0000 +41.9583 240.0000 2999.0000 2973.0000 1574.0000 753.0000 350.0000 296.0000 815.0000 +42.0000 240.0000 2999.0000 2980.0000 1571.0000 756.0000 349.0000 289.0000 816.0000 +42.0417 240.0000 2999.0000 2988.0000 1561.0000 759.0000 345.0000 290.0000 818.0000 +42.0833 240.0000 3003.0000 2979.0000 1568.0000 758.0000 348.0000 284.0000 820.0000 +42.1250 240.0000 2989.0000 2983.0000 1570.0000 760.0000 350.0000 286.0000 822.0000 +42.1667 240.0000 2979.0000 2993.0000 1561.0000 759.0000 349.0000 296.0000 823.0000 +42.2083 240.0000 2975.0000 2994.0000 1552.0000 757.0000 351.0000 305.0000 826.0000 +42.2500 240.0000 2969.0000 2997.0000 1545.0000 757.0000 352.0000 313.0000 827.0000 +42.2917 240.0000 2969.0000 3003.0000 1540.0000 751.0000 355.0000 313.0000 829.0000 +42.3333 240.0000 2984.0000 2993.0000 1528.0000 754.0000 353.0000 318.0000 830.0000 +42.3750 240.0000 2963.0000 3009.0000 1517.0000 759.0000 355.0000 325.0000 832.0000 +42.4167 240.0000 2965.0000 3002.0000 1522.0000 754.0000 358.0000 326.0000 833.0000 +42.4583 240.0000 2968.0000 2989.0000 1534.0000 753.0000 354.0000 327.0000 835.0000 +42.5000 239.0000 2964.0000 2996.0000 1526.0000 754.0000 354.0000 331.0000 836.0000 +42.5417 239.0000 2964.0000 2993.0000 1522.0000 752.0000 351.0000 341.0000 838.0000 +42.5833 239.0000 2955.0000 3003.0000 1522.0000 749.0000 347.0000 345.0000 840.0000 +42.6250 239.0000 2950.0000 3012.0000 1527.0000 747.0000 346.0000 338.0000 841.0000 +42.6667 239.0000 2954.0000 3016.0000 1517.0000 757.0000 344.0000 331.0000 842.0000 +42.7083 239.0000 2961.0000 3014.0000 1523.0000 756.0000 342.0000 322.0000 843.0000 +42.7500 239.0000 2973.0000 3017.0000 1525.0000 757.0000 343.0000 301.0000 845.0000 +42.7917 239.0000 2990.0000 3004.0000 1519.0000 756.0000 344.0000 303.0000 845.0000 +42.8333 239.0000 2995.0000 3008.0000 1517.0000 756.0000 347.0000 293.0000 845.0000 +42.8750 239.0000 2995.0000 3014.0000 1511.0000 754.0000 348.0000 292.0000 847.0000 +42.9167 239.0000 2988.0000 3015.0000 1504.0000 752.0000 353.0000 301.0000 848.0000 +42.9583 239.0000 2990.0000 3022.0000 1501.0000 748.0000 352.0000 298.0000 850.0000 +43.0000 239.0000 2993.0000 3028.0000 1497.0000 743.0000 353.0000 297.0000 850.0000 +43.0417 239.0000 3000.0000 3028.0000 1497.0000 734.0000 353.0000 298.0000 851.0000 +43.0833 239.0000 3008.0000 3025.0000 1502.0000 729.0000 358.0000 288.0000 851.0000 +43.1250 239.0000 2995.0000 3033.0000 1497.0000 730.0000 364.0000 290.0000 852.0000 +43.1667 239.0000 2981.0000 3025.0000 1490.0000 730.0000 366.0000 316.0000 853.0000 +43.2083 239.0000 2990.0000 3012.0000 1487.0000 731.0000 368.0000 319.0000 854.0000 +43.2500 239.0000 2996.0000 3017.0000 1488.0000 723.0000 372.0000 310.0000 855.0000 +43.2917 239.0000 2976.0000 3018.0000 1494.0000 721.0000 371.0000 326.0000 855.0000 +43.3333 239.0000 2978.0000 3012.0000 1493.0000 724.0000 373.0000 325.0000 856.0000 +43.3750 239.0000 2975.0000 3013.0000 1490.0000 724.0000 374.0000 328.0000 857.0000 +43.4167 239.0000 2965.0000 3018.0000 1490.0000 724.0000 377.0000 329.0000 858.0000 +43.4583 239.0000 2957.0000 3027.0000 1492.0000 722.0000 378.0000 326.0000 859.0000 +43.5000 238.0000 2939.0000 3029.0000 1493.0000 723.0000 375.0000 342.0000 861.0000 +43.5417 238.0000 2929.0000 3032.0000 1495.0000 724.0000 374.0000 347.0000 861.0000 +43.5833 238.0000 2943.0000 3021.0000 1500.0000 719.0000 375.0000 342.0000 862.0000 +43.6250 238.0000 2930.0000 3026.0000 1504.0000 715.0000 375.0000 349.0000 863.0000 +43.6667 238.0000 2937.0000 3017.0000 1505.0000 714.0000 378.0000 347.0000 864.0000 +43.7083 237.0000 2938.0000 3027.0000 1498.0000 718.0000 376.0000 341.0000 865.0000 +43.7500 237.0000 2959.0000 3023.0000 1503.0000 711.0000 379.0000 321.0000 867.0000 +43.7917 237.0000 2975.0000 3021.0000 1506.0000 710.0000 382.0000 302.0000 867.0000 +43.8333 237.0000 2966.0000 3033.0000 1498.0000 714.0000 380.0000 303.0000 869.0000 +43.8750 237.0000 2974.0000 3015.0000 1497.0000 716.0000 385.0000 307.0000 869.0000 +43.9167 237.0000 2978.0000 3004.0000 1497.0000 714.0000 385.0000 313.0000 872.0000 +43.9583 237.0000 2995.0000 3005.0000 1501.0000 711.0000 384.0000 292.0000 875.0000 +44.0000 237.0000 2996.0000 2998.0000 1502.0000 714.0000 381.0000 296.0000 876.0000 +44.0417 237.0000 2984.0000 3010.0000 1505.0000 716.0000 381.0000 289.0000 878.0000 +44.0833 237.0000 2961.0000 3031.0000 1496.0000 716.0000 379.0000 299.0000 881.0000 +44.1250 236.0000 2965.0000 3036.0000 1490.0000 718.0000 377.0000 295.0000 883.0000 +44.1667 236.0000 2947.0000 3045.0000 1486.0000 723.0000 370.0000 307.0000 886.0000 +44.2083 236.0000 2948.0000 3039.0000 1480.0000 726.0000 366.0000 317.0000 888.0000 +44.2500 236.0000 2958.0000 3034.0000 1478.0000 731.0000 364.0000 309.0000 890.0000 +44.2917 236.0000 2957.0000 3026.0000 1484.0000 724.0000 362.0000 316.0000 895.0000 +44.3333 236.0000 2948.0000 3037.0000 1486.0000 717.0000 364.0000 315.0000 897.0000 +44.3750 236.0000 2937.0000 3041.0000 1493.0000 716.0000 365.0000 314.0000 898.0000 +44.4167 236.0000 2921.0000 3041.0000 1497.0000 711.0000 366.0000 328.0000 900.0000 +44.4583 235.0000 2921.0000 3038.0000 1487.0000 717.0000 362.0000 339.0000 901.0000 +44.5000 235.0000 2897.0000 3048.0000 1481.0000 719.0000 361.0000 356.0000 903.0000 +44.5417 235.0000 2897.0000 3050.0000 1484.0000 710.0000 363.0000 355.0000 906.0000 +44.5833 235.0000 2911.0000 3053.0000 1481.0000 713.0000 361.0000 338.0000 908.0000 +44.6250 235.0000 2903.0000 3060.0000 1480.0000 715.0000 363.0000 336.0000 908.0000 +44.6667 235.0000 2911.0000 3049.0000 1476.0000 720.0000 361.0000 338.0000 910.0000 +44.7083 234.0000 2912.0000 3057.0000 1474.0000 722.0000 357.0000 330.0000 914.0000 +44.7500 234.0000 2925.0000 3058.0000 1476.0000 724.0000 357.0000 311.0000 915.0000 +44.7917 234.0000 2934.0000 3054.0000 1475.0000 727.0000 356.0000 305.0000 915.0000 +44.8333 234.0000 2923.0000 3065.0000 1473.0000 724.0000 357.0000 305.0000 919.0000 +44.8750 234.0000 2914.0000 3065.0000 1474.0000 724.0000 355.0000 314.0000 920.0000 +44.9167 234.0000 2915.0000 3065.0000 1487.0000 725.0000 350.0000 301.0000 923.0000 +44.9583 234.0000 2914.0000 3074.0000 1486.0000 724.0000 347.0000 297.0000 924.0000 +45.0000 234.0000 2907.0000 3076.0000 1483.0000 726.0000 347.0000 303.0000 924.0000 +45.0417 233.0000 2904.0000 3074.0000 1486.0000 726.0000 344.0000 305.0000 928.0000 +45.0833 233.0000 2899.0000 3071.0000 1492.0000 722.0000 347.0000 306.0000 930.0000 +45.1250 233.0000 2896.0000 3069.0000 1499.0000 723.0000 346.0000 300.0000 934.0000 +45.1667 233.0000 2879.0000 3078.0000 1501.0000 727.0000 347.0000 301.0000 934.0000 +45.2083 233.0000 2864.0000 3078.0000 1495.0000 729.0000 346.0000 320.0000 935.0000 +45.2500 233.0000 2877.0000 3066.0000 1496.0000 727.0000 349.0000 315.0000 937.0000 +45.2917 233.0000 2879.0000 3049.0000 1501.0000 728.0000 347.0000 322.0000 941.0000 +45.3333 233.0000 2890.0000 3042.0000 1503.0000 727.0000 347.0000 317.0000 941.0000 +45.3750 233.0000 2875.0000 3047.0000 1502.0000 724.0000 348.0000 330.0000 941.0000 +45.4167 232.0000 2866.0000 3040.0000 1500.0000 727.0000 346.0000 345.0000 944.0000 +45.4583 232.0000 2866.0000 3036.0000 1494.0000 730.0000 345.0000 351.0000 946.0000 +45.5000 232.0000 2867.0000 3023.0000 1500.0000 727.0000 350.0000 355.0000 946.0000 +45.5417 232.0000 2875.0000 3007.0000 1503.0000 728.0000 350.0000 359.0000 946.0000 +45.5833 232.0000 2872.0000 3007.0000 1501.0000 733.0000 350.0000 357.0000 948.0000 +45.6250 232.0000 2853.0000 3021.0000 1501.0000 732.0000 354.0000 359.0000 948.0000 +45.6667 232.0000 2858.0000 3022.0000 1505.0000 735.0000 353.0000 347.0000 948.0000 +45.7083 232.0000 2868.0000 3032.0000 1502.0000 737.0000 352.0000 327.0000 950.0000 +45.7500 232.0000 2876.0000 3038.0000 1496.0000 732.0000 355.0000 319.0000 952.0000 +45.7917 232.0000 2882.0000 3036.0000 1497.0000 727.0000 353.0000 318.0000 955.0000 +45.8333 232.0000 2878.0000 3039.0000 1495.0000 724.0000 357.0000 318.0000 957.0000 +45.8750 232.0000 2874.0000 3038.0000 1497.0000 724.0000 355.0000 320.0000 960.0000 +45.9167 232.0000 2883.0000 3028.0000 1506.0000 718.0000 357.0000 315.0000 961.0000 +45.9583 232.0000 2882.0000 3023.0000 1499.0000 723.0000 357.0000 320.0000 964.0000 +46.0000 232.0000 2879.0000 3020.0000 1504.0000 715.0000 365.0000 321.0000 964.0000 +46.0417 232.0000 2888.0000 3014.0000 1499.0000 714.0000 362.0000 325.0000 966.0000 +46.0833 232.0000 2894.0000 3007.0000 1500.0000 713.0000 363.0000 323.0000 968.0000 +46.1250 232.0000 2899.0000 3006.0000 1499.0000 710.0000 365.0000 319.0000 970.0000 +46.1667 232.0000 2889.0000 3007.0000 1505.0000 702.0000 369.0000 326.0000 970.0000 +46.2083 231.0000 2890.0000 3001.0000 1503.0000 699.0000 366.0000 337.0000 973.0000 +46.2500 231.0000 2883.0000 3010.0000 1500.0000 699.0000 362.0000 339.0000 976.0000 +46.2917 231.0000 2884.0000 3016.0000 1505.0000 697.0000 361.0000 329.0000 977.0000 +46.3333 230.0000 2881.0000 3003.0000 1507.0000 697.0000 365.0000 340.0000 977.0000 +46.3750 230.0000 2872.0000 2996.0000 1508.0000 700.0000 361.0000 353.0000 980.0000 +46.4167 230.0000 2876.0000 2996.0000 1509.0000 697.0000 362.0000 348.0000 982.0000 +46.4583 229.0000 2864.0000 2994.0000 1509.0000 699.0000 364.0000 357.0000 984.0000 +46.5000 229.0000 2860.0000 2990.0000 1505.0000 701.0000 362.0000 368.0000 985.0000 +46.5417 228.0000 2860.0000 2995.0000 1503.0000 701.0000 359.0000 366.0000 988.0000 +46.5833 228.0000 2867.0000 3006.0000 1505.0000 696.0000 358.0000 349.0000 991.0000 +46.6250 228.0000 2864.0000 2999.0000 1499.0000 694.0000 362.0000 362.0000 992.0000 +46.6667 228.0000 2882.0000 2999.0000 1496.0000 688.0000 364.0000 351.0000 992.0000 +46.7083 228.0000 2886.0000 3009.0000 1495.0000 682.0000 365.0000 341.0000 994.0000 +46.7500 228.0000 2902.0000 3010.0000 1488.0000 688.0000 360.0000 328.0000 996.0000 +46.7917 228.0000 2912.0000 3015.0000 1484.0000 684.0000 364.0000 315.0000 998.0000 +46.8333 228.0000 2920.0000 3013.0000 1475.0000 683.0000 368.0000 313.0000 1000.0000 +46.8750 228.0000 2919.0000 3012.0000 1473.0000 682.0000 367.0000 317.0000 1002.0000 +46.9167 228.0000 2937.0000 2999.0000 1472.0000 682.0000 367.0000 312.0000 1003.0000 +46.9583 228.0000 2936.0000 2996.0000 1471.0000 683.0000 367.0000 315.0000 1004.0000 +47.0000 228.0000 2947.0000 2983.0000 1471.0000 686.0000 368.0000 313.0000 1004.0000 +47.0417 228.0000 2947.0000 2980.0000 1471.0000 688.0000 366.0000 313.0000 1007.0000 +47.0833 228.0000 2943.0000 2978.0000 1470.0000 690.0000 366.0000 317.0000 1008.0000 +47.1250 228.0000 2941.0000 2983.0000 1462.0000 691.0000 369.0000 316.0000 1010.0000 +47.1667 228.0000 2943.0000 2978.0000 1462.0000 687.0000 371.0000 320.0000 1011.0000 +47.2083 228.0000 2945.0000 2970.0000 1456.0000 691.0000 367.0000 330.0000 1013.0000 +47.2500 228.0000 2947.0000 2965.0000 1460.0000 691.0000 367.0000 328.0000 1014.0000 +47.2917 228.0000 2951.0000 2943.0000 1463.0000 699.0000 365.0000 335.0000 1016.0000 +47.3333 228.0000 2965.0000 2929.0000 1470.0000 698.0000 361.0000 331.0000 1018.0000 +47.3750 228.0000 2955.0000 2927.0000 1470.0000 696.0000 362.0000 340.0000 1022.0000 +47.4167 228.0000 2946.0000 2939.0000 1459.0000 702.0000 357.0000 343.0000 1026.0000 +47.4583 228.0000 2949.0000 2933.0000 1467.0000 701.0000 354.0000 339.0000 1029.0000 +47.5000 228.0000 2929.0000 2943.0000 1463.0000 702.0000 356.0000 348.0000 1031.0000 +47.5417 228.0000 2930.0000 2943.0000 1467.0000 701.0000 357.0000 340.0000 1034.0000 +47.5833 228.0000 2927.0000 2942.0000 1473.0000 703.0000 354.0000 337.0000 1036.0000 +47.6250 228.0000 2923.0000 2940.0000 1473.0000 703.0000 353.0000 341.0000 1039.0000 +47.6667 228.0000 2937.0000 2930.0000 1479.0000 705.0000 355.0000 327.0000 1039.0000 +47.7083 228.0000 2935.0000 2937.0000 1478.0000 701.0000 358.0000 323.0000 1040.0000 +47.7500 228.0000 2943.0000 2928.0000 1484.0000 703.0000 354.0000 318.0000 1042.0000 +47.7917 228.0000 2955.0000 2928.0000 1482.0000 699.0000 352.0000 312.0000 1044.0000 +47.8333 228.0000 2945.0000 2926.0000 1477.0000 700.0000 357.0000 321.0000 1046.0000 +47.8750 228.0000 2956.0000 2925.0000 1482.0000 698.0000 355.0000 310.0000 1046.0000 +47.9167 228.0000 2956.0000 2932.0000 1480.0000 699.0000 359.0000 299.0000 1047.0000 +47.9583 228.0000 2946.0000 2931.0000 1476.0000 699.0000 359.0000 313.0000 1048.0000 +48.0000 228.0000 2951.0000 2931.0000 1474.0000 697.0000 360.0000 307.0000 1052.0000 +48.0417 228.0000 2944.0000 2941.0000 1472.0000 692.0000 357.0000 312.0000 1054.0000 +48.0833 228.0000 2930.0000 2944.0000 1472.0000 693.0000 356.0000 322.0000 1055.0000 +48.1250 228.0000 2928.0000 2946.0000 1480.0000 696.0000 355.0000 310.0000 1057.0000 +48.1667 228.0000 2921.0000 2934.0000 1487.0000 694.0000 360.0000 318.0000 1058.0000 +48.2083 228.0000 2919.0000 2930.0000 1495.0000 691.0000 362.0000 316.0000 1059.0000 +48.2500 228.0000 2922.0000 2912.0000 1496.0000 698.0000 354.0000 328.0000 1062.0000 +48.2917 228.0000 2927.0000 2902.0000 1501.0000 701.0000 354.0000 322.0000 1065.0000 +48.3333 228.0000 2929.0000 2893.0000 1497.0000 702.0000 351.0000 334.0000 1066.0000 +48.3750 228.0000 2926.0000 2892.0000 1491.0000 710.0000 345.0000 339.0000 1069.0000 +48.4167 228.0000 2930.0000 2872.0000 1499.0000 714.0000 343.0000 345.0000 1069.0000 +48.4583 228.0000 2918.0000 2879.0000 1484.0000 714.0000 343.0000 362.0000 1072.0000 +48.5000 228.0000 2917.0000 2876.0000 1487.0000 718.0000 342.0000 359.0000 1073.0000 +48.5417 228.0000 2905.0000 2892.0000 1484.0000 720.0000 340.0000 355.0000 1076.0000 +48.5833 227.0000 2896.0000 2901.0000 1481.0000 725.0000 340.0000 353.0000 1077.0000 +48.6250 227.0000 2897.0000 2894.0000 1483.0000 724.0000 339.0000 357.0000 1079.0000 +48.6667 227.0000 2908.0000 2888.0000 1483.0000 721.0000 343.0000 351.0000 1079.0000 +48.7083 227.0000 2925.0000 2881.0000 1473.0000 726.0000 343.0000 343.0000 1082.0000 +48.7500 227.0000 2944.0000 2877.0000 1484.0000 723.0000 344.0000 316.0000 1085.0000 +48.7917 227.0000 2938.0000 2883.0000 1481.0000 722.0000 347.0000 316.0000 1086.0000 +48.8333 227.0000 2936.0000 2882.0000 1487.0000 723.0000 348.0000 311.0000 1086.0000 +48.8750 227.0000 2929.0000 2889.0000 1491.0000 720.0000 348.0000 310.0000 1086.0000 +48.9167 227.0000 2927.0000 2897.0000 1487.0000 722.0000 348.0000 304.0000 1088.0000 +48.9583 227.0000 2918.0000 2908.0000 1481.0000 716.0000 354.0000 308.0000 1088.0000 +49.0000 227.0000 2918.0000 2901.0000 1489.0000 718.0000 352.0000 307.0000 1088.0000 +49.0417 227.0000 2913.0000 2894.0000 1489.0000 723.0000 347.0000 317.0000 1090.0000 +49.0833 227.0000 2915.0000 2890.0000 1489.0000 729.0000 348.0000 312.0000 1090.0000 +49.1250 227.0000 2910.0000 2896.0000 1490.0000 717.0000 356.0000 313.0000 1091.0000 +49.1667 227.0000 2902.0000 2896.0000 1490.0000 719.0000 352.0000 320.0000 1094.0000 +49.2083 227.0000 2903.0000 2899.0000 1487.0000 717.0000 353.0000 319.0000 1095.0000 +49.2500 227.0000 2896.0000 2916.0000 1470.0000 723.0000 355.0000 316.0000 1097.0000 +49.2917 227.0000 2891.0000 2912.0000 1470.0000 728.0000 353.0000 322.0000 1097.0000 +49.3333 227.0000 2878.0000 2902.0000 1478.0000 731.0000 352.0000 332.0000 1100.0000 +49.3750 227.0000 2873.0000 2903.0000 1472.0000 740.0000 347.0000 335.0000 1103.0000 +49.4167 227.0000 2869.0000 2894.0000 1474.0000 741.0000 346.0000 345.0000 1104.0000 +49.4583 227.0000 2877.0000 2885.0000 1470.0000 742.0000 348.0000 345.0000 1106.0000 +49.5000 226.0000 2857.0000 2898.0000 1467.0000 739.0000 349.0000 355.0000 1109.0000 +49.5417 226.0000 2857.0000 2894.0000 1471.0000 741.0000 347.0000 354.0000 1110.0000 +49.5833 226.0000 2851.0000 2894.0000 1471.0000 748.0000 347.0000 352.0000 1111.0000 +49.6250 226.0000 2847.0000 2890.0000 1468.0000 751.0000 342.0000 364.0000 1112.0000 +49.6667 226.0000 2857.0000 2886.0000 1468.0000 752.0000 340.0000 357.0000 1114.0000 +49.7083 226.0000 2870.0000 2888.0000 1470.0000 751.0000 339.0000 340.0000 1116.0000 +49.7500 226.0000 2883.0000 2887.0000 1464.0000 756.0000 338.0000 327.0000 1119.0000 +49.7917 226.0000 2892.0000 2889.0000 1461.0000 754.0000 337.0000 322.0000 1119.0000 +49.8333 226.0000 2897.0000 2873.0000 1465.0000 751.0000 340.0000 328.0000 1120.0000 +49.8750 226.0000 2900.0000 2864.0000 1470.0000 752.0000 338.0000 326.0000 1124.0000 +49.9167 226.0000 2906.0000 2863.0000 1475.0000 752.0000 336.0000 317.0000 1125.0000 +49.9583 226.0000 2901.0000 2865.0000 1473.0000 748.0000 340.0000 322.0000 1125.0000 +50.0000 226.0000 2897.0000 2874.0000 1469.0000 744.0000 336.0000 325.0000 1129.0000 +50.0417 226.0000 2900.0000 2885.0000 1462.0000 744.0000 334.0000 319.0000 1130.0000 +50.0833 226.0000 2893.0000 2890.0000 1461.0000 746.0000 337.0000 317.0000 1130.0000 +50.1250 226.0000 2886.0000 2887.0000 1466.0000 747.0000 332.0000 324.0000 1132.0000 +50.1667 226.0000 2883.0000 2889.0000 1467.0000 749.0000 335.0000 319.0000 1132.0000 +50.2083 226.0000 2871.0000 2890.0000 1479.0000 748.0000 333.0000 317.0000 1136.0000 +50.2500 226.0000 2856.0000 2898.0000 1470.0000 754.0000 331.0000 328.0000 1137.0000 +50.2917 226.0000 2851.0000 2904.0000 1465.0000 753.0000 334.0000 330.0000 1137.0000 +50.3333 226.0000 2848.0000 2900.0000 1463.0000 744.0000 333.0000 346.0000 1140.0000 +50.3750 225.0000 2832.0000 2909.0000 1463.0000 738.0000 331.0000 358.0000 1144.0000 +50.4167 224.0000 2834.0000 2917.0000 1458.0000 745.0000 332.0000 346.0000 1144.0000 +50.4583 224.0000 2837.0000 2911.0000 1459.0000 744.0000 332.0000 348.0000 1145.0000 +50.5000 224.0000 2830.0000 2912.0000 1460.0000 743.0000 331.0000 353.0000 1147.0000 +50.5417 224.0000 2836.0000 2907.0000 1455.0000 746.0000 333.0000 351.0000 1148.0000 +50.5833 224.0000 2829.0000 2917.0000 1449.0000 748.0000 333.0000 351.0000 1149.0000 +50.6250 224.0000 2832.0000 2906.0000 1447.0000 749.0000 331.0000 360.0000 1151.0000 +50.6667 224.0000 2833.0000 2900.0000 1444.0000 747.0000 333.0000 368.0000 1151.0000 +50.7083 224.0000 2860.0000 2903.0000 1441.0000 745.0000 334.0000 342.0000 1151.0000 +50.7500 224.0000 2871.0000 2895.0000 1447.0000 743.0000 336.0000 331.0000 1153.0000 +50.7917 224.0000 2880.0000 2900.0000 1452.0000 744.0000 335.0000 311.0000 1154.0000 +50.8333 224.0000 2881.0000 2901.0000 1444.0000 747.0000 336.0000 313.0000 1154.0000 +50.8750 224.0000 2877.0000 2897.0000 1456.0000 744.0000 338.0000 310.0000 1154.0000 +50.9167 224.0000 2867.0000 2889.0000 1468.0000 741.0000 340.0000 314.0000 1157.0000 +50.9583 224.0000 2874.0000 2885.0000 1453.0000 744.0000 338.0000 324.0000 1158.0000 +51.0000 224.0000 2883.0000 2889.0000 1448.0000 745.0000 342.0000 310.0000 1159.0000 +51.0417 224.0000 2886.0000 2889.0000 1447.0000 739.0000 345.0000 311.0000 1159.0000 +51.0833 224.0000 2878.0000 2892.0000 1442.0000 742.0000 344.0000 318.0000 1160.0000 +51.1250 224.0000 2883.0000 2884.0000 1445.0000 744.0000 344.0000 315.0000 1161.0000 +51.1667 224.0000 2877.0000 2890.0000 1446.0000 741.0000 346.0000 313.0000 1163.0000 +51.2083 224.0000 2866.0000 2905.0000 1440.0000 746.0000 348.0000 308.0000 1163.0000 +51.2500 224.0000 2867.0000 2896.0000 1440.0000 746.0000 348.0000 313.0000 1166.0000 +51.2917 224.0000 2856.0000 2906.0000 1433.0000 744.0000 348.0000 322.0000 1167.0000 +51.3333 224.0000 2857.0000 2901.0000 1440.0000 741.0000 352.0000 317.0000 1168.0000 +51.3750 223.0000 2846.0000 2902.0000 1434.0000 743.0000 350.0000 330.0000 1172.0000 +51.4167 223.0000 2840.0000 2900.0000 1438.0000 739.0000 347.0000 338.0000 1175.0000 +51.4583 222.0000 2835.0000 2905.0000 1438.0000 734.0000 347.0000 341.0000 1178.0000 +51.5000 222.0000 2832.0000 2901.0000 1442.0000 729.0000 350.0000 344.0000 1180.0000 +51.5417 221.0000 2829.0000 2910.0000 1440.0000 727.0000 349.0000 343.0000 1181.0000 +51.5833 221.0000 2826.0000 2919.0000 1435.0000 719.0000 350.0000 347.0000 1183.0000 +51.6250 221.0000 2826.0000 2922.0000 1437.0000 711.0000 356.0000 342.0000 1185.0000 +51.6667 221.0000 2817.0000 2938.0000 1432.0000 709.0000 356.0000 341.0000 1186.0000 +51.7083 221.0000 2842.0000 2923.0000 1436.0000 713.0000 355.0000 321.0000 1189.0000 +51.7500 221.0000 2854.0000 2922.0000 1427.0000 719.0000 354.0000 312.0000 1191.0000 +51.7917 221.0000 2862.0000 2918.0000 1430.0000 714.0000 353.0000 309.0000 1193.0000 +51.8333 220.0000 2853.0000 2928.0000 1438.0000 715.0000 351.0000 300.0000 1195.0000 +51.8750 220.0000 2846.0000 2932.0000 1432.0000 719.0000 351.0000 305.0000 1195.0000 +51.9167 220.0000 2845.0000 2934.0000 1432.0000 713.0000 352.0000 305.0000 1199.0000 +51.9583 220.0000 2865.0000 2915.0000 1434.0000 715.0000 351.0000 298.0000 1202.0000 +52.0000 220.0000 2860.0000 2915.0000 1443.0000 714.0000 353.0000 293.0000 1202.0000 +52.0417 220.0000 2854.0000 2912.0000 1436.0000 720.0000 351.0000 304.0000 1203.0000 +52.0833 220.0000 2847.0000 2915.0000 1429.0000 720.0000 356.0000 309.0000 1204.0000 +52.1250 220.0000 2838.0000 2924.0000 1427.0000 723.0000 356.0000 307.0000 1205.0000 +52.1667 220.0000 2829.0000 2928.0000 1432.0000 725.0000 356.0000 303.0000 1207.0000 +52.2083 220.0000 2822.0000 2919.0000 1437.0000 724.0000 353.0000 315.0000 1210.0000 +52.2500 220.0000 2826.0000 2915.0000 1437.0000 721.0000 349.0000 318.0000 1214.0000 +52.2917 220.0000 2832.0000 2904.0000 1430.0000 719.0000 349.0000 330.0000 1216.0000 +52.3333 220.0000 2835.0000 2892.0000 1431.0000 723.0000 348.0000 334.0000 1217.0000 +52.3750 220.0000 2821.0000 2896.0000 1431.0000 726.0000 341.0000 347.0000 1218.0000 +52.4167 220.0000 2826.0000 2902.0000 1419.0000 723.0000 341.0000 350.0000 1219.0000 +52.4583 219.0000 2818.0000 2901.0000 1421.0000 725.0000 340.0000 357.0000 1219.0000 +52.5000 218.0000 2815.0000 2910.0000 1409.0000 726.0000 339.0000 361.0000 1222.0000 +52.5417 218.0000 2828.0000 2901.0000 1404.0000 722.0000 341.0000 364.0000 1222.0000 +52.5833 217.0000 2823.0000 2912.0000 1401.0000 723.0000 339.0000 361.0000 1224.0000 +52.6250 217.0000 2829.0000 2908.0000 1399.0000 724.0000 335.0000 360.0000 1228.0000 +52.6667 217.0000 2848.0000 2896.0000 1402.0000 730.0000 333.0000 342.0000 1232.0000 +52.7083 217.0000 2852.0000 2885.0000 1415.0000 729.0000 331.0000 338.0000 1233.0000 +52.7500 217.0000 2873.0000 2885.0000 1420.0000 730.0000 331.0000 311.0000 1233.0000 +52.7917 217.0000 2856.0000 2893.0000 1418.0000 732.0000 329.0000 320.0000 1235.0000 +52.8333 217.0000 2857.0000 2904.0000 1411.0000 733.0000 330.0000 313.0000 1235.0000 +52.8750 217.0000 2865.0000 2889.0000 1421.0000 725.0000 330.0000 317.0000 1236.0000 +52.9167 217.0000 2866.0000 2893.0000 1412.0000 730.0000 332.0000 313.0000 1237.0000 +52.9583 217.0000 2860.0000 2897.0000 1407.0000 734.0000 330.0000 317.0000 1238.0000 +53.0000 217.0000 2868.0000 2898.0000 1400.0000 737.0000 332.0000 310.0000 1238.0000 +53.0417 217.0000 2863.0000 2894.0000 1401.0000 733.0000 333.0000 319.0000 1240.0000 +53.0833 217.0000 2861.0000 2894.0000 1399.0000 739.0000 332.0000 318.0000 1240.0000 +53.1250 217.0000 2848.0000 2908.0000 1395.0000 737.0000 336.0000 319.0000 1240.0000 +53.1667 217.0000 2842.0000 2907.0000 1394.0000 744.0000 335.0000 319.0000 1242.0000 +53.2083 217.0000 2841.0000 2893.0000 1394.0000 747.0000 332.0000 331.0000 1245.0000 +53.2500 217.0000 2837.0000 2895.0000 1398.0000 748.0000 333.0000 326.0000 1246.0000 +53.2917 217.0000 2842.0000 2895.0000 1399.0000 747.0000 332.0000 322.0000 1246.0000 +53.3333 217.0000 2822.0000 2895.0000 1410.0000 742.0000 327.0000 339.0000 1248.0000 +53.3750 217.0000 2816.0000 2897.0000 1403.0000 743.0000 327.0000 349.0000 1248.0000 +53.4167 217.0000 2817.0000 2893.0000 1404.0000 752.0000 328.0000 339.0000 1250.0000 +53.4583 216.0000 2808.0000 2892.0000 1400.0000 754.0000 329.0000 350.0000 1251.0000 +53.5000 216.0000 2798.0000 2898.0000 1400.0000 754.0000 330.0000 352.0000 1252.0000 +53.5417 216.0000 2805.0000 2890.0000 1397.0000 752.0000 330.0000 358.0000 1252.0000 +53.5833 216.0000 2810.0000 2896.0000 1394.0000 750.0000 335.0000 347.0000 1252.0000 +53.6250 215.0000 2800.0000 2903.0000 1396.0000 753.0000 336.0000 344.0000 1253.0000 +53.6667 215.0000 2795.0000 2895.0000 1413.0000 752.0000 331.0000 345.0000 1254.0000 +53.7083 215.0000 2801.0000 2894.0000 1407.0000 750.0000 327.0000 350.0000 1256.0000 +53.7500 215.0000 2823.0000 2888.0000 1414.0000 748.0000 320.0000 330.0000 1262.0000 +53.7917 215.0000 2830.0000 2895.0000 1413.0000 747.0000 320.0000 316.0000 1264.0000 +53.8333 215.0000 2811.0000 2905.0000 1416.0000 746.0000 321.0000 322.0000 1264.0000 +53.8750 215.0000 2800.0000 2916.0000 1411.0000 748.0000 319.0000 323.0000 1268.0000 +53.9167 215.0000 2802.0000 2922.0000 1408.0000 748.0000 319.0000 316.0000 1270.0000 +53.9583 215.0000 2803.0000 2926.0000 1412.0000 746.0000 318.0000 307.0000 1273.0000 +54.0000 215.0000 2793.0000 2919.0000 1409.0000 752.0000 321.0000 317.0000 1274.0000 +54.0417 215.0000 2795.0000 2901.0000 1416.0000 749.0000 323.0000 327.0000 1274.0000 +54.0833 215.0000 2791.0000 2905.0000 1418.0000 751.0000 322.0000 321.0000 1277.0000 +54.1250 215.0000 2788.0000 2907.0000 1418.0000 750.0000 322.0000 321.0000 1279.0000 +54.1667 215.0000 2780.0000 2913.0000 1415.0000 753.0000 320.0000 322.0000 1282.0000 +54.2083 215.0000 2784.0000 2899.0000 1412.0000 762.0000 320.0000 325.0000 1283.0000 +54.2500 215.0000 2775.0000 2904.0000 1412.0000 758.0000 321.0000 331.0000 1284.0000 +54.2917 215.0000 2783.0000 2899.0000 1415.0000 757.0000 321.0000 323.0000 1287.0000 +54.3333 215.0000 2780.0000 2894.0000 1421.0000 751.0000 322.0000 329.0000 1288.0000 +54.3750 215.0000 2764.0000 2891.0000 1413.0000 755.0000 323.0000 351.0000 1288.0000 +54.4167 215.0000 2752.0000 2889.0000 1416.0000 751.0000 326.0000 361.0000 1290.0000 +54.4583 215.0000 2738.0000 2904.0000 1417.0000 746.0000 329.0000 358.0000 1293.0000 +54.5000 214.0000 2731.0000 2901.0000 1416.0000 745.0000 332.0000 368.0000 1293.0000 +54.5417 214.0000 2740.0000 2898.0000 1418.0000 749.0000 334.0000 354.0000 1293.0000 +54.5833 214.0000 2725.0000 2899.0000 1415.0000 748.0000 334.0000 370.0000 1295.0000 +54.6250 214.0000 2720.0000 2892.0000 1425.0000 743.0000 336.0000 375.0000 1295.0000 +54.6667 214.0000 2728.0000 2890.0000 1428.0000 745.0000 334.0000 364.0000 1297.0000 +54.7083 214.0000 2731.0000 2893.0000 1423.0000 753.0000 333.0000 355.0000 1298.0000 +54.7500 214.0000 2750.0000 2886.0000 1421.0000 758.0000 330.0000 341.0000 1300.0000 +54.7917 214.0000 2772.0000 2879.0000 1422.0000 762.0000 326.0000 323.0000 1302.0000 +54.8333 214.0000 2772.0000 2858.0000 1427.0000 764.0000 326.0000 336.0000 1303.0000 +54.8750 214.0000 2775.0000 2863.0000 1416.0000 761.0000 329.0000 337.0000 1305.0000 +54.9167 214.0000 2788.0000 2856.0000 1427.0000 764.0000 324.0000 319.0000 1308.0000 +54.9583 214.0000 2775.0000 2865.0000 1424.0000 771.0000 324.0000 318.0000 1309.0000 +55.0000 214.0000 2773.0000 2864.0000 1428.0000 766.0000 325.0000 318.0000 1312.0000 +55.0417 214.0000 2769.0000 2861.0000 1428.0000 778.0000 323.0000 315.0000 1312.0000 +55.0833 214.0000 2768.0000 2864.0000 1420.0000 779.0000 322.0000 319.0000 1314.0000 +55.1250 214.0000 2762.0000 2858.0000 1429.0000 776.0000 325.0000 321.0000 1315.0000 +55.1667 214.0000 2752.0000 2873.0000 1423.0000 777.0000 322.0000 321.0000 1318.0000 +55.2083 214.0000 2745.0000 2870.0000 1420.0000 772.0000 325.0000 334.0000 1320.0000 +55.2500 214.0000 2748.0000 2870.0000 1417.0000 778.0000 323.0000 328.0000 1322.0000 +55.2917 214.0000 2738.0000 2867.0000 1426.0000 772.0000 325.0000 335.0000 1323.0000 +55.3333 214.0000 2740.0000 2864.0000 1428.0000 766.0000 330.0000 334.0000 1324.0000 +55.3750 214.0000 2731.0000 2864.0000 1432.0000 769.0000 326.0000 337.0000 1327.0000 +55.4167 214.0000 2721.0000 2863.0000 1432.0000 771.0000 327.0000 345.0000 1327.0000 +55.4583 214.0000 2724.0000 2850.0000 1426.0000 778.0000 327.0000 352.0000 1329.0000 +55.5000 214.0000 2710.0000 2848.0000 1427.0000 772.0000 330.0000 369.0000 1330.0000 +55.5417 214.0000 2722.0000 2830.0000 1431.0000 771.0000 330.0000 370.0000 1332.0000 +55.5833 214.0000 2726.0000 2822.0000 1436.0000 768.0000 334.0000 367.0000 1333.0000 +55.6250 214.0000 2720.0000 2808.0000 1437.0000 767.0000 331.0000 388.0000 1335.0000 +55.6667 214.0000 2728.0000 2811.0000 1436.0000 769.0000 330.0000 377.0000 1335.0000 +55.7083 214.0000 2745.0000 2808.0000 1440.0000 771.0000 332.0000 355.0000 1335.0000 +55.7500 214.0000 2755.0000 2814.0000 1428.0000 778.0000 328.0000 345.0000 1338.0000 +55.7917 214.0000 2761.0000 2809.0000 1432.0000 779.0000 327.0000 338.0000 1340.0000 +55.8333 214.0000 2772.0000 2794.0000 1437.0000 782.0000 328.0000 332.0000 1341.0000 +55.8750 214.0000 2776.0000 2796.0000 1435.0000 783.0000 329.0000 325.0000 1342.0000 +55.9167 214.0000 2785.0000 2792.0000 1432.0000 785.0000 330.0000 320.0000 1342.0000 +55.9583 214.0000 2787.0000 2792.0000 1434.0000 781.0000 332.0000 313.0000 1347.0000 +56.0000 214.0000 2787.0000 2794.0000 1421.0000 778.0000 336.0000 323.0000 1347.0000 +56.0417 214.0000 2789.0000 2787.0000 1419.0000 782.0000 333.0000 328.0000 1348.0000 +56.0833 214.0000 2791.0000 2785.0000 1413.0000 785.0000 338.0000 326.0000 1348.0000 +56.1250 214.0000 2795.0000 2783.0000 1412.0000 785.0000 337.0000 323.0000 1351.0000 +56.1667 214.0000 2794.0000 2784.0000 1409.0000 781.0000 339.0000 327.0000 1352.0000 +56.2083 214.0000 2795.0000 2792.0000 1393.0000 783.0000 338.0000 331.0000 1354.0000 +56.2500 214.0000 2783.0000 2792.0000 1387.0000 784.0000 337.0000 347.0000 1356.0000 +56.2917 214.0000 2791.0000 2795.0000 1383.0000 782.0000 341.0000 337.0000 1357.0000 +56.3333 214.0000 2785.0000 2792.0000 1381.0000 784.0000 338.0000 346.0000 1360.0000 +56.3750 214.0000 2778.0000 2789.0000 1393.0000 778.0000 338.0000 349.0000 1361.0000 +56.4167 214.0000 2770.0000 2789.0000 1394.0000 777.0000 337.0000 358.0000 1361.0000 +56.4583 214.0000 2765.0000 2790.0000 1390.0000 780.0000 340.0000 359.0000 1362.0000 +56.5000 214.0000 2764.0000 2790.0000 1386.0000 782.0000 340.0000 361.0000 1363.0000 +56.5417 214.0000 2762.0000 2796.0000 1383.0000 783.0000 341.0000 357.0000 1364.0000 +56.5833 214.0000 2762.0000 2795.0000 1378.0000 785.0000 336.0000 359.0000 1371.0000 +56.6250 214.0000 2757.0000 2785.0000 1380.0000 788.0000 336.0000 369.0000 1371.0000 +56.6667 214.0000 2765.0000 2788.0000 1384.0000 782.0000 335.0000 360.0000 1372.0000 +56.7083 214.0000 2771.0000 2794.0000 1379.0000 782.0000 334.0000 350.0000 1376.0000 +56.7500 214.0000 2794.0000 2790.0000 1375.0000 782.0000 334.0000 332.0000 1379.0000 +56.7917 214.0000 2804.0000 2785.0000 1372.0000 780.0000 336.0000 330.0000 1379.0000 +56.8333 214.0000 2817.0000 2774.0000 1383.0000 773.0000 335.0000 320.0000 1384.0000 +56.8750 214.0000 2811.0000 2772.0000 1381.0000 778.0000 333.0000 327.0000 1384.0000 +56.9167 214.0000 2807.0000 2782.0000 1380.0000 780.0000 333.0000 317.0000 1387.0000 +56.9583 214.0000 2796.0000 2783.0000 1382.0000 784.0000 334.0000 318.0000 1389.0000 +57.0000 214.0000 2797.0000 2780.0000 1374.0000 789.0000 333.0000 323.0000 1390.0000 +57.0417 214.0000 2794.0000 2770.0000 1382.0000 788.0000 334.0000 325.0000 1393.0000 +57.0833 214.0000 2781.0000 2783.0000 1379.0000 788.0000 334.0000 328.0000 1393.0000 +57.1250 214.0000 2782.0000 2780.0000 1379.0000 787.0000 337.0000 327.0000 1394.0000 +57.1667 214.0000 2776.0000 2780.0000 1381.0000 784.0000 339.0000 331.0000 1395.0000 +57.2083 214.0000 2787.0000 2767.0000 1388.0000 784.0000 341.0000 324.0000 1395.0000 +57.2500 214.0000 2786.0000 2761.0000 1394.0000 782.0000 338.0000 328.0000 1397.0000 +57.2917 214.0000 2785.0000 2765.0000 1393.0000 784.0000 336.0000 324.0000 1399.0000 +57.3333 214.0000 2774.0000 2767.0000 1390.0000 781.0000 340.0000 334.0000 1400.0000 +57.3750 214.0000 2770.0000 2756.0000 1397.0000 776.0000 343.0000 343.0000 1401.0000 +57.4167 214.0000 2759.0000 2757.0000 1391.0000 778.0000 347.0000 353.0000 1401.0000 +57.4583 214.0000 2752.0000 2761.0000 1391.0000 778.0000 347.0000 355.0000 1402.0000 +57.5000 214.0000 2742.0000 2750.0000 1394.0000 779.0000 347.0000 371.0000 1403.0000 +57.5417 214.0000 2745.0000 2750.0000 1392.0000 778.0000 347.0000 369.0000 1405.0000 +57.5833 214.0000 2741.0000 2759.0000 1394.0000 772.0000 349.0000 365.0000 1406.0000 +57.6250 214.0000 2735.0000 2767.0000 1394.0000 772.0000 350.0000 360.0000 1408.0000 +57.6667 214.0000 2745.0000 2766.0000 1393.0000 776.0000 347.0000 350.0000 1409.0000 +57.7083 214.0000 2751.0000 2763.0000 1396.0000 773.0000 348.0000 346.0000 1409.0000 +57.7500 214.0000 2769.0000 2760.0000 1397.0000 771.0000 351.0000 328.0000 1410.0000 +57.7917 214.0000 2771.0000 2761.0000 1402.0000 772.0000 351.0000 317.0000 1412.0000 +57.8333 214.0000 2766.0000 2765.0000 1398.0000 769.0000 355.0000 320.0000 1413.0000 +57.8750 214.0000 2770.0000 2769.0000 1394.0000 771.0000 354.0000 313.0000 1415.0000 +57.9167 214.0000 2766.0000 2768.0000 1393.0000 773.0000 353.0000 316.0000 1417.0000 +57.9583 214.0000 2769.0000 2771.0000 1381.0000 778.0000 350.0000 315.0000 1422.0000 +58.0000 214.0000 2747.0000 2791.0000 1378.0000 778.0000 349.0000 321.0000 1422.0000 +58.0417 214.0000 2750.0000 2788.0000 1370.0000 777.0000 354.0000 323.0000 1424.0000 +58.0833 214.0000 2748.0000 2783.0000 1376.0000 775.0000 348.0000 327.0000 1429.0000 +58.1250 214.0000 2746.0000 2774.0000 1378.0000 776.0000 350.0000 331.0000 1431.0000 +58.1667 214.0000 2749.0000 2776.0000 1378.0000 772.0000 350.0000 328.0000 1433.0000 +58.2083 214.0000 2738.0000 2778.0000 1376.0000 771.0000 351.0000 336.0000 1436.0000 +58.2500 214.0000 2736.0000 2784.0000 1372.0000 775.0000 351.0000 332.0000 1436.0000 +58.2917 214.0000 2731.0000 2776.0000 1369.0000 776.0000 350.0000 346.0000 1438.0000 +58.3333 214.0000 2738.0000 2781.0000 1365.0000 779.0000 349.0000 335.0000 1439.0000 +58.3750 214.0000 2731.0000 2781.0000 1363.0000 778.0000 350.0000 342.0000 1441.0000 +58.4167 214.0000 2727.0000 2783.0000 1366.0000 776.0000 350.0000 342.0000 1442.0000 +58.4583 214.0000 2724.0000 2776.0000 1357.0000 774.0000 349.0000 362.0000 1444.0000 +58.5000 214.0000 2717.0000 2780.0000 1355.0000 769.0000 352.0000 367.0000 1446.0000 +58.5417 214.0000 2727.0000 2788.0000 1353.0000 760.0000 352.0000 360.0000 1446.0000 +58.5833 214.0000 2734.0000 2785.0000 1354.0000 756.0000 354.0000 355.0000 1448.0000 +58.6250 214.0000 2745.0000 2780.0000 1354.0000 751.0000 354.0000 353.0000 1449.0000 +58.6667 214.0000 2742.0000 2795.0000 1353.0000 748.0000 353.0000 343.0000 1452.0000 +58.7083 214.0000 2741.0000 2803.0000 1356.0000 743.0000 356.0000 334.0000 1453.0000 +58.7500 214.0000 2758.0000 2806.0000 1353.0000 744.0000 350.0000 319.0000 1456.0000 +58.7917 214.0000 2764.0000 2809.0000 1355.0000 744.0000 352.0000 305.0000 1457.0000 +58.8333 214.0000 2742.0000 2825.0000 1344.0000 751.0000 353.0000 313.0000 1458.0000 +58.8750 214.0000 2741.0000 2824.0000 1339.0000 754.0000 354.0000 315.0000 1459.0000 +58.9167 214.0000 2749.0000 2818.0000 1332.0000 762.0000 353.0000 312.0000 1460.0000 +58.9583 214.0000 2750.0000 2817.0000 1331.0000 765.0000 358.0000 304.0000 1461.0000 +59.0000 214.0000 2746.0000 2821.0000 1330.0000 763.0000 359.0000 306.0000 1461.0000 +59.0417 214.0000 2737.0000 2824.0000 1326.0000 765.0000 356.0000 316.0000 1462.0000 +59.0833 214.0000 2730.0000 2832.0000 1318.0000 767.0000 355.0000 319.0000 1465.0000 +59.1250 214.0000 2723.0000 2842.0000 1321.0000 766.0000 358.0000 310.0000 1466.0000 +59.1667 214.0000 2714.0000 2844.0000 1315.0000 768.0000 354.0000 321.0000 1470.0000 +59.2083 214.0000 2708.0000 2847.0000 1312.0000 768.0000 354.0000 323.0000 1474.0000 +59.2500 214.0000 2700.0000 2861.0000 1311.0000 770.0000 352.0000 315.0000 1477.0000 +59.2917 214.0000 2682.0000 2865.0000 1306.0000 768.0000 354.0000 333.0000 1478.0000 +59.3333 214.0000 2682.0000 2868.0000 1299.0000 772.0000 353.0000 330.0000 1482.0000 +59.3750 214.0000 2684.0000 2860.0000 1306.0000 764.0000 354.0000 336.0000 1482.0000 +59.4167 214.0000 2669.0000 2857.0000 1308.0000 758.0000 356.0000 352.0000 1486.0000 +59.4583 214.0000 2660.0000 2859.0000 1313.0000 756.0000 355.0000 355.0000 1488.0000 +59.5000 214.0000 2655.0000 2858.0000 1311.0000 756.0000 356.0000 361.0000 1489.0000 +59.5417 214.0000 2659.0000 2858.0000 1313.0000 756.0000 357.0000 353.0000 1490.0000 +59.5833 214.0000 2660.0000 2853.0000 1315.0000 759.0000 361.0000 347.0000 1491.0000 +59.6250 214.0000 2652.0000 2834.0000 1325.0000 765.0000 358.0000 358.0000 1494.0000 +59.6667 214.0000 2663.0000 2819.0000 1330.0000 760.0000 358.0000 360.0000 1496.0000 +59.7083 212.0000 2670.0000 2821.0000 1331.0000 755.0000 356.0000 355.0000 1500.0000 +59.7500 212.0000 2702.0000 2820.0000 1328.0000 753.0000 357.0000 328.0000 1500.0000 +59.7917 211.0000 2723.0000 2812.0000 1321.0000 758.0000 357.0000 316.0000 1502.0000 +59.8333 211.0000 2721.0000 2806.0000 1317.0000 760.0000 356.0000 325.0000 1504.0000 +59.8750 211.0000 2723.0000 2805.0000 1312.0000 758.0000 359.0000 326.0000 1506.0000 +59.9167 210.0000 2732.0000 2798.0000 1305.0000 757.0000 356.0000 333.0000 1509.0000 +59.9583 210.0000 2737.0000 2808.0000 1307.0000 755.0000 357.0000 317.0000 1509.0000 +60.0000 210.0000 2734.0000 2803.0000 1310.0000 754.0000 355.0000 322.0000 1512.0000 From 75116caf3f63845cb54d7083c0c7a01044258e8c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 15 Feb 2024 08:11:19 +0100 Subject: [PATCH 026/488] quick important fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 60 ++++++++++++++---------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 24fef2c0ef..fd0ec1f6b6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -386,7 +386,7 @@ std::pair get_my_and_sigma(std::pair mean_and_st return {my, sigma}; } -void set_parameters(mio::abm::Parameters params) +void set_parameters(mio::abm::Parameters& params) { mio::RandomNumberGenerator rng; @@ -440,30 +440,28 @@ void set_parameters(mio::abm::Parameters params) {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); }; - // Set protection level from low viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 - // params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, - // mio::abm::VirusVariant::Wildtype}] = - // [](ScalarType days) -> ScalarType { - // return mio::linear_interpolation_of_data_set({{0, 0.967}, - // {30, 0.975}, - // {60, 0.977}, - // {90, 0.974}, - // {120, 0.963}, - // {150, 0.947}, - // {180, 0.93}, - // {210, 0.929}, - // {240, 0.923}, - // {270, 0.908}, - // {300, 0.893}, - // {330, 0.887}, - // {360, 0.887}, - // {360, 0.5}}, - // days); - // }; + // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 + params.get() = [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.967}, + {30, 0.975}, + {60, 0.977}, + {90, 0.974}, + {120, 0.963}, + {150, 0.947}, + {180, 0.93}, + {210, 0.929}, + {240, 0.923}, + {270, 0.908}, + {300, 0.893}, + {330, 0.887}, + {360, 0.887}, + {360, 0.5}}, + days); + }; //Set other parameters - params.get() = 0.5; - params.get() = 1.0; + params.get() = 0.66; + params.get() = 0.0; } /** @@ -474,7 +472,7 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co int max_num_persons) { // Assumed percentage of infection state at the beginning of the simulation. - ScalarType exposed_prob = 0.05, infected_no_symptoms_prob = 0.001, infected_symptoms_prob = 0.001, + ScalarType exposed_prob = 0.08, infected_no_symptoms_prob = 0.001, infected_symptoms_prob = 0.001, recovered_prob = 0.0; //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -489,7 +487,7 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co // Assign an infection state to each person. assign_infection_state(world, t0, exposed_prob, infected_no_symptoms_prob, infected_symptoms_prob, recovered_prob); - auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(1); + auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); // During the lockdown, 25% of people work from home and schools are closed for 90% of students. // Social events are very rare. @@ -614,7 +612,17 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di ensemble_results.reserve(size_t(num_runs)); auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 10000; + auto max_num_persons = 5000; + + int tid = -1; +#pragma omp parallel private(tid) // Start of parallel region: forks threads + { + tid = omp_get_thread_num(); // default is number of CPUs on machine + printf("Hello from Thread %d\n", tid); + if (tid == 0) { + printf("Number of threads = %d\n", omp_get_num_threads()); + } + } // ** end of the the parallel: joins threads // Loop over a number of runs while (run_idx <= num_runs) { From cf5bf929dab39e92791bf5b156b20879b56f39e3 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 15 Feb 2024 14:49:39 +0100 Subject: [PATCH 027/488] Add structures in the abm models to check if a Person has a home in Braunschweig --- cpp/models/abm/common_abm_loggers.h | 6 +- cpp/models/abm/location.cpp | 5 +- cpp/models/abm/person.cpp | 4 +- cpp/models/abm/person.h | 17 +- cpp/models/abm/world.cpp | 5 +- cpp/models/abm/world.h | 3 +- cpp/simulations/abm_braunschweig.cpp | 196 ++++++++++++------ .../memilio/epidata/check_bs_data.py | 27 +-- 8 files changed, 174 insertions(+), 89 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index 085a0511a8..dbe6a7d602 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -199,7 +199,8 @@ struct LogInfectionPerLocationType : mio::LogAlways { auto curr_time = sim.get_time(); PRAGMA_OMP(for) for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + if (person.is_home_in_bs() && + (person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { sum[(int)(person.get_location().get_type())] += 1; } @@ -225,7 +226,8 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { auto curr_time = sim.get_time(); PRAGMA_OMP(for) for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + if (person.is_home_in_bs() && + (person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { sum[(size_t)(person.get_age())] += 1; } diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index a24cd2a724..81c605b598 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -213,7 +213,10 @@ size_t Cell::get_subpopulation(TimePoint t, InfectionState state) const size_t Location::get_subpopulation(TimePoint t, InfectionState state) const { return count_if(m_persons.begin(), m_persons.end(), [&](observer_ptr p) { - return p->get_infection_state(t) == state; + if (p->is_home_in_bs()) { + return p->get_infection_state(t) == state; + } + return false; }); } diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index fa06b3a6d7..5119de98de 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -32,7 +32,8 @@ namespace mio namespace abm { -Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t person_id) +Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t person_id, + bool is_home_in_bs) : m_location(&location) , m_assigned_locations((uint32_t)LocationType::Count, INVALID_LOCATION_INDEX) , m_quarantine_start(TimePoint(-(std::numeric_limits::max() / 2))) @@ -45,6 +46,7 @@ Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age , m_person_id(person_id) , m_cells{0} , m_last_transport_mode(TransportMode::Unknown) + , m_is_home_in_bs(is_home_in_bs) { m_random_workgroup = UniformDistribution::get_instance()(rng); m_random_schoolgroup = UniformDistribution::get_instance()(rng); diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index b80430a1b0..0128ba403a 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -127,9 +127,10 @@ class Person * @param[in, out] location Initial Location of the Person. * @param[in] age The AgeGroup of the Person. * @param[in] person_id Index of the Person. + * @param[in] is_home_in_bs Whether the Person has a home in Braunschweig. */ explicit Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, - uint32_t person_id = INVALID_PERSON_ID); + uint32_t person_id = INVALID_PERSON_ID, bool is_home_in_bs = true); /** * @brief Create a copy of this #Person object with a new Location. @@ -329,7 +330,7 @@ class Person { return t < m_quarantine_start + params.get(); } - + /** * @brief Removes the quarantine status of the Person. */ @@ -505,6 +506,15 @@ class Person loc, age, id); } + /** + * @brief Whether the Person has a home in Braunschweig. + * @return Whether the Person has a home in Braunschweig. + */ + bool is_home_in_bs() + { + return m_is_home_in_bs; + } + private: observer_ptr m_location; ///< Current Location of the Person. std::vector m_assigned_locations; /**! Vector with the indices of the assigned Locations so that the @@ -525,7 +535,8 @@ class Person uint32_t m_person_id; ///< Id of the Person. std::vector m_cells; ///< Vector with all Cell%s the Person visits at its current Location. mio::abm::TransportMode m_last_transport_mode; ///< TransportMode the Person used to get to its current Location. - Counter m_rng_counter{0}; ///< counter for RandomNumberGenerator + Counter m_rng_counter{0}; ///< counter for RandomNumberGenerator. + bool m_is_home_in_bs; ///< Whether the Person has a home in Braunschweig. }; } // namespace abm diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 859b93320e..dc02e47e4b 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -43,11 +43,12 @@ LocationId World::add_location(LocationType type, uint32_t num_cells) return id; } -Person& World::add_person(const LocationId id, AgeGroup age) +Person& World::add_person(const LocationId id, AgeGroup age, bool is_home_in_bs) { assert(age.get() < parameters.get_num_groups()); uint32_t person_id = static_cast(m_persons.size()); - m_persons.push_back(std::make_unique(m_rng, get_individualized_location(id), age, person_id)); + m_persons.push_back( + std::make_unique(m_rng, get_individualized_location(id), age, person_id, is_home_in_bs)); auto& person = *m_persons.back(); person.set_assigned_location(m_cemetery_id); get_individualized_location(id).add_person(person); diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index 8aa65ac5de..70270f273a 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -174,9 +174,10 @@ class World * @brief Add a Person to the World. * @param[in] id Index and type of the initial Location of the Person. * @param[in] age AgeGroup of the person. + * @param[in] is_home_in_bs Whether the Person has a home in Braunschweig. * @return Reference to the newly created Person. */ - Person& add_person(const LocationId id, AgeGroup age); + Person& add_person(const LocationId id, AgeGroup age, bool is_home_in_bs = false); /** * @brief Get a range of all Location%s in the World. diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index 711b7851bc..5f7f63855d 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -310,6 +310,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, locations.insert({home_id, home}); mio::abm::GeographicalLocation location_long_lat_home = {(double)row[index["lon_start"]] / 1e+5, (double)row[index["lat_start"]] / 1e+5}; + world.get_individualized_location(home).set_geographical_location(location_long_lat_home); } else { @@ -327,10 +328,20 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, world.get_individualized_location(location).set_geographical_location(location_long_lat); } } + fin.clear(); fin.seekg(0); std::getline(fin, line); // Skip header row + // Check if the input file has a column 'in_bs' + bool has_column_in_bs; + if (index.find("in_bs") == index.end()) { + has_column_in_bs = false; + } + else { + has_column_in_bs = true; + } + // Add the persons and trips while (std::getline(fin, line)) { row.clear(); @@ -364,12 +375,24 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, } auto first_location_id = it_first_location_id->second.first; auto first_location = locations.find(first_location_id)->second; - auto& person = world.add_person(first_location, determine_age_group(age)); auto home = locations.find(home_id)->second; - person.set_assigned_location(home); - person.set_assigned_location(hospital); - person.set_assigned_location(icu); - persons.insert({person_id, person}); + // If the a column 'in_bs' in the input, assign Person accordingly + if (has_column_in_bs) { + uint32_t home_in_bs = row[index["in_bs"]]; + auto& person = world.add_person(first_location, determine_age_group(age), home_in_bs == 1); + person.set_assigned_location(home); + person.set_assigned_location(hospital); + person.set_assigned_location(icu); + persons.insert({person_id, person}); + } + // Treat all the Person as they have a home in Braunschweig (default) + else { + auto& person = world.add_person(first_location, determine_age_group(age)); + person.set_assigned_location(home); + person.set_assigned_location(hospital); + person.set_assigned_location(icu); + persons.insert({person_id, person}); + } it_person = persons.find(person_id); } @@ -416,12 +439,15 @@ void set_parameters(mio::abm::Parameters params) 0.276; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.092; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; //15-34 params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = @@ -445,49 +471,65 @@ void set_parameters(mio::abm::Parameters params) 0.315; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; //60-79 params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.315; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.123; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.024; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.123; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.024; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; //80+ params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.315; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.079; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.115; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.033; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.115; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.033; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; // Set each parameter for vaccinated people including personal infection and vaccine protection levels. // Summary: https://doi.org/10.1038/s41577-021-00550-x, //0-4 - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.161; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = + 0.161; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = + 0.132; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.001; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_0_to_4, @@ -549,12 +591,15 @@ void set_parameters(mio::abm::Parameters params) 0.161; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.132; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.186; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.143; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.186; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.015; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = + 0.143; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.001; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_5_to_14, @@ -615,12 +660,17 @@ void set_parameters(mio::abm::Parameters params) 0.179; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.142; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.001; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.157; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.013; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.021; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.142; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.001; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.157; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.013; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = + 0.126; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.021; // Set up personal infection and vaccine protection levels, based on: https://doi.org/10.1038/s41577-021-00550-x, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_15_to_34, mio::abm::VirusVariant::Wildtype}] = @@ -680,12 +730,16 @@ void set_parameters(mio::abm::Parameters params) 0.179; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.141; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.003; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.113; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.141; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.003; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.113; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.008; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_35_to_59, @@ -746,12 +800,17 @@ void set_parameters(mio::abm::Parameters params) 0.179; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.136; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.009; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.083; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.136; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.009; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.083; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.023; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_60_to_79, @@ -812,12 +871,15 @@ void set_parameters(mio::abm::Parameters params) 0.179; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.126; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.133; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.012; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.035; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.133; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.012; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.036; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = + 0.035; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.052; // Protection of reinfection is the same for all age-groups, based on: // https://doi.org/10.1016/S0140-6736(22)02465-5, https://doi.org/10.1038/s41591-021-01377-8 params.get()[{mio::abm::ExposureType::NaturalInfection, age_group_80_plus, diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py index 7d04852f6d..1445ab341d 100644 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -510,15 +510,18 @@ ### draft to add collumn to check if the location in Braunschweig # pip install geopy # from geopy.geocoders import Nominatim -# geolocator = Nominatim(user_agent="MEmilio") -# longitude = bd['loCe'] -# latitude = bd['laCe'] -# coordination = str(longitude) + "," + str(latitude) -# location = geolocator.reverse(coordination) -# loc_dict = location.raw -# print(loc_dict['address']['city']) -# if loc_dict['address']['city'] == 'Braunschweig' : -# bd['in_bs'] = 1 -# else: -# bd['in_bs'] = 0 -# bd.to_csv('modified_input.csv', index=False) +# from geopy.extra.rate_limiter import RateLimiter +# geolocator = Nominatim(user_agent="MEmilio")bd['in_bs'] = 0 +# reverse = RateLimiter(geolocator.reverse, min_delay_seconds=1) +# # Loop through each row of the data +# for index, row in bd.iterrows(): +# # Check if the end location is in Braunschweig and homeID is the same as loc_id_end, i.e. the Person ends with a trip in Braunschweig +# location = reverse(str(row['loCe']) + "," + str(row['laCe'])).raw +# if location['address']['city'] == 'Braunschweig' and row['loc_id_end'] == row['hhID'] : +# bd.at[index,'in_bs'] = 1 +# next +# # Check if the end location is in Braunschweig and homeID is the same as loc_id_start, i.e. the Person starts with a trip in Braunschweig +# location = reverse(str(row['loCs']) + "," + str(row['laCs'])).raw +# if location['address']['city'] == 'Braunschweig' and row['loc_id_start'] == row['hhID'] : +# bd.at[index,'in_bs'] = 1 +# bd.to_csv('modified_input.csv', index=False) \ No newline at end of file From 287014e4b63799437490978b55d987faf74ea7d0 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Wed, 21 Feb 2024 15:39:52 +0100 Subject: [PATCH 028/488] Modify the name of column in_bs in the input data --- cpp/simulations/abm_braunschweig.cpp | 17 ++++++-------- .../memilio/epidata/check_bs_data.py | 22 +++++-------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index 5f7f63855d..eac72bfb05 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -333,13 +333,10 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, fin.seekg(0); std::getline(fin, line); // Skip header row - // Check if the input file has a column 'in_bs' - bool has_column_in_bs; - if (index.find("in_bs") == index.end()) { - has_column_in_bs = false; - } - else { - has_column_in_bs = true; + // Check if the input file has a column 'home_in_bs' + bool has_column_home_in_bs = false; + if (index.find("home_in_bs") != index.end()) { + has_column_home_in_bs = true; } // Add the persons and trips @@ -376,9 +373,9 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, auto first_location_id = it_first_location_id->second.first; auto first_location = locations.find(first_location_id)->second; auto home = locations.find(home_id)->second; - // If the a column 'in_bs' in the input, assign Person accordingly - if (has_column_in_bs) { - uint32_t home_in_bs = row[index["in_bs"]]; + // If the a column 'home_in_bs' in the input, assign Person accordingly + if (has_column_home_in_bs) { + uint32_t home_in_bs = row[index["home_in_bs"]]; auto& person = world.add_person(first_location, determine_age_group(age), home_in_bs == 1); person.set_assigned_location(home); person.set_assigned_location(hospital); diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py index 1445ab341d..8281c18551 100644 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -508,20 +508,8 @@ x = 42 ### draft to add collumn to check if the location in Braunschweig -# pip install geopy -# from geopy.geocoders import Nominatim -# from geopy.extra.rate_limiter import RateLimiter -# geolocator = Nominatim(user_agent="MEmilio")bd['in_bs'] = 0 -# reverse = RateLimiter(geolocator.reverse, min_delay_seconds=1) -# # Loop through each row of the data -# for index, row in bd.iterrows(): -# # Check if the end location is in Braunschweig and homeID is the same as loc_id_end, i.e. the Person ends with a trip in Braunschweig -# location = reverse(str(row['loCe']) + "," + str(row['laCe'])).raw -# if location['address']['city'] == 'Braunschweig' and row['loc_id_end'] == row['hhID'] : -# bd.at[index,'in_bs'] = 1 -# next -# # Check if the end location is in Braunschweig and homeID is the same as loc_id_start, i.e. the Person starts with a trip in Braunschweig -# location = reverse(str(row['loCs']) + "," + str(row['laCs'])).raw -# if location['address']['city'] == 'Braunschweig' and row['loc_id_start'] == row['hhID'] : -# bd.at[index,'in_bs'] = 1 -# bd.to_csv('modified_input.csv', index=False) \ No newline at end of file +#bd['home_in_bs'] = 0 +#for index, row in bd.iterrows(): +# if ((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): +# bd.at[index,'home_in_bs'] = 1 +#bd.to_csv('modified_braunschweig_result.csv', index=False) \ No newline at end of file From 145549ff893b114ad6a769e5b4864c40ce15d205 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Feb 2024 11:00:46 +0100 Subject: [PATCH 029/488] push local par Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fd0ec1f6b6..c6893c9742 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -464,6 +464,43 @@ void set_parameters(mio::abm::Parameters& params) params.get() = 0.0; } +// set location specific parameters +void set_local_parameters(mio::abm::World& world) +{ + const int n_age_groups = world.parameters.get_num_groups(); + // const Eigen::MatrixXd contacts_home{ + // {0.4413, 0.4504, 1.2383, 0.8033, 0.0494, 0.0017}, {0.0485, 0.7616, 0.6532, 1.1614, 0.0256, 0.0013}, + // {0.1800, 0.1795, 0.8806, 0.6413, 0.0429, 0.0032}, {0.0495, 0.2639, 0.5189, 0.8277, 0.0679, 0.0014}, + // {0.0087, 0.0394, 0.1417, 0.3834, 0.7064, 0.0447}, {0.0292, 0.0648, 0.1248, 0.4179, 0.3497, 0.1544}}; + + // Eigen::MatrixXi a{ + // // construct a 2x2 matrix + // {1, 2}, // first row + // {3, 4} // second row + // }; + + Eigen::Matrix b{ + {2, 3, 4}, + {5, 6, 7}, + }; + + const Eigen::Matrix asb{1, 1.0}; + + for (auto& loc : world.get_locations()) { + switch (loc.get_type()) { + case mio::abm::LocationType::Home: + loc.get_infection_parameters().get().array() = contacts_home; + break; + case mio::abm::LocationType::School: + break; + case mio::abm::LocationType::Work: + break; + default: + break; + } + } +} + /** * Create a sampled simulation with start time t0. * @param t0 The start time of the Simulation. @@ -479,6 +516,7 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co auto world = mio::abm::World(num_age_groups); set_parameters(world.parameters); + set_local_parameters(world); // Create the world object from statistical data. create_world_from_data(world, input_file, t0, max_num_persons); From 003d0fdb7829433dbfc53d12173d57b86c9c444b Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Mon, 26 Feb 2024 12:16:06 +0100 Subject: [PATCH 030/488] Add h5 outputs for infections per loction types and age groups in abm_braunschweig --- cpp/simulations/abm_braunschweig.cpp | 50 ++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index eac72bfb05..87dbaee8a3 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -1067,10 +1067,17 @@ void write_log_to_file_infection_per_age_group(const T& history) mio::IOResult run(const std::string& input_file, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(2); // End time per simulation - auto ensemble_results = std::vector>>{}; // Vector of collected results - ensemble_results.reserve(size_t(num_runs)); + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(2); // End time per simulation + auto ensemble_results_infections_per_type = + std::vector>>{}; // Vector of collected results of infections per type + auto ensemble_results_infections_per_loc = std::vector< + std::vector>>{}; // Vector of collected results of infections per location type + auto ensemble_results_infections_per_age = std::vector< + std::vector>>{}; // Vector of collected results of infections per age group + ensemble_results_infections_per_type.reserve(size_t(num_runs)); + ensemble_results_infections_per_loc.reserve(size_t(num_runs)); + ensemble_results_infections_per_age.reserve(size_t(num_runs)); auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations auto max_num_persons = 1000; @@ -1096,22 +1103,45 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di for (auto& location : sim.get_world().get_locations()) { loc_ids.push_back(location.get_index()); } + // Collect the location types indexes. + std::vector loc_type_ids; + for (int loc_type_id = 0; loc_type_id < static_cast(mio::abm::LocationType::Count); loc_type_id++) { + loc_type_ids.push_back(loc_type_id); + } + // Collect the age groups indexes. + std::vector age_group_ids; + for (size_t age_group_id = 0; age_group_id < num_age_groups; age_group_id++) { + age_group_ids.push_back(age_group_id); + } // Advance the world to tmax sim.advance(tmax, historyPersonInf, historyTimeSeries, historyInfectionPerLocationType, historyInfectionPerAgeGroup, historyPersonInfDelta); // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_result = std::vector>{std::get<0>(historyTimeSeries.get_log())}; + auto temp_sim_result_infection_per_type = + std::vector>{std::get<0>(historyTimeSeries.get_log())}; + auto temp_sim_result_infection_per_loc = + std::vector>{std::get<0>(historyTimeSeries.get_log())}; + auto temp_sim_result_infection_per_age = + std::vector>{std::get<0>(historyTimeSeries.get_log())}; // Push result of the simulation back to the result vector - ensemble_results.push_back(temp_sim_result); + ensemble_results_infections_per_type.push_back(temp_sim_result_infection_per_type); + ensemble_results_infections_per_loc.push_back(temp_sim_result_infection_per_loc); + ensemble_results_infections_per_age.push_back(temp_sim_result_infection_per_age); // Option to save the current run result to file if (save_result_result && save_single_runs) { - auto result_dir_run = result_dir / ("abm_result_run_" + std::to_string(run_idx) + ".h5"); - BOOST_OUTCOME_TRY(save_result(ensemble_results.back(), loc_ids, 1, result_dir_run.string())); + auto result_dir_run = + result_dir / ("abm_result_infections_per_type_run_" + std::to_string(run_idx) + ".h5"); + BOOST_OUTCOME_TRY( + save_result(ensemble_results_infections_per_type.back(), loc_ids, 1, result_dir_run.string())); + result_dir_run = result_dir / ("abm_result_infections_per_loc_run_" + std::to_string(run_idx) + ".h5"); + BOOST_OUTCOME_TRY( + save_result(ensemble_results_infections_per_loc.back(), loc_type_ids, 1, result_dir_run.string())); + result_dir_run = result_dir / ("abm_result_infections_per_age_run_" + std::to_string(run_idx) + ".h5"); + BOOST_OUTCOME_TRY( + save_result(ensemble_results_infections_per_age.back(), age_group_ids, 1, result_dir_run.string())); } write_log_to_file_person_and_location_data(historyPersonInf); write_log_to_file_trip_data(historyPersonInfDelta); - write_log_to_file_infection_per_location_type(historyInfectionPerLocationType); - write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup); ++run_idx; } From 706d8808a23977bd8657080f90d89a5bfa1e08b4 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:08:49 +0100 Subject: [PATCH 031/488] Add location contact matrices. Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 211 +++++++++++++++++++++-- 1 file changed, 194 insertions(+), 17 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c6893c9742..2bec6d9802 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -468,34 +468,211 @@ void set_parameters(mio::abm::Parameters& params) void set_local_parameters(mio::abm::World& world) { const int n_age_groups = world.parameters.get_num_groups(); - // const Eigen::MatrixXd contacts_home{ - // {0.4413, 0.4504, 1.2383, 0.8033, 0.0494, 0.0017}, {0.0485, 0.7616, 0.6532, 1.1614, 0.0256, 0.0013}, - // {0.1800, 0.1795, 0.8806, 0.6413, 0.0429, 0.0032}, {0.0495, 0.2639, 0.5189, 0.8277, 0.0679, 0.0014}, - // {0.0087, 0.0394, 0.1417, 0.3834, 0.7064, 0.0447}, {0.0292, 0.0648, 0.1248, 0.4179, 0.3497, 0.1544}}; - - // Eigen::MatrixXi a{ - // // construct a 2x2 matrix - // {1, 2}, // first row - // {3, 4} // second row - // }; - - Eigen::Matrix b{ - {2, 3, 4}, - {5, 6, 7}, - }; - const Eigen::Matrix asb{1, 1.0}; + // setting this up in matrix-form would be much nicer, + // but we somehow can't construct Eigen object with initializer lists + /* baseline_home + 0.4413 0.4504 1.2383 0.8033 0.0494 0.0017 + 0.0485 0.7616 0.6532 1.1614 0.0256 0.0013 + 0.1800 0.1795 0.8806 0.6413 0.0429 0.0032 + 0.0495 0.2639 0.5189 0.8277 0.0679 0.0014 + 0.0087 0.0394 0.1417 0.3834 0.7064 0.0447 + 0.0292 0.0648 0.1248 0.4179 0.3497 0.1544 + */ + mio::CustomIndexArray contacts_home( + {mio::AgeGroup(n_age_groups), mio::AgeGroup(n_age_groups)}, 0.); + contacts_home[{age_group_0_to_4, age_group_0_to_4}] = 0.4413; + contacts_home[{age_group_0_to_4, age_group_5_to_14}] = 0.0504; + contacts_home[{age_group_0_to_4, age_group_15_to_34}] = 1.2383; + contacts_home[{age_group_0_to_4, age_group_35_to_59}] = 0.8033; + contacts_home[{age_group_0_to_4, age_group_60_to_79}] = 0.0494; + contacts_home[{age_group_0_to_4, age_group_80_plus}] = 0.0017; + contacts_home[{age_group_5_to_14, age_group_0_to_4}] = 0.0485; + contacts_home[{age_group_5_to_14, age_group_5_to_14}] = 0.7616; + contacts_home[{age_group_5_to_14, age_group_15_to_34}] = 0.6532; + contacts_home[{age_group_5_to_14, age_group_35_to_59}] = 1.1614; + contacts_home[{age_group_5_to_14, age_group_60_to_79}] = 0.0256; + contacts_home[{age_group_5_to_14, age_group_80_plus}] = 0.0013; + contacts_home[{age_group_15_to_34, age_group_0_to_4}] = 0.1800; + contacts_home[{age_group_15_to_34, age_group_5_to_14}] = 0.1795; + contacts_home[{age_group_15_to_34, age_group_15_to_34}] = 0.8806; + contacts_home[{age_group_15_to_34, age_group_35_to_59}] = 0.6413; + contacts_home[{age_group_15_to_34, age_group_60_to_79}] = 0.0429; + contacts_home[{age_group_15_to_34, age_group_80_plus}] = 0.0032; + contacts_home[{age_group_35_to_59, age_group_0_to_4}] = 0.0495; + contacts_home[{age_group_35_to_59, age_group_5_to_14}] = 0.2639; + contacts_home[{age_group_35_to_59, age_group_15_to_34}] = 0.5189; + contacts_home[{age_group_35_to_59, age_group_35_to_59}] = 0.8277; + contacts_home[{age_group_35_to_59, age_group_60_to_79}] = 0.0679; + contacts_home[{age_group_35_to_59, age_group_80_plus}] = 0.0014; + contacts_home[{age_group_60_to_79, age_group_0_to_4}] = 0.0087; + contacts_home[{age_group_60_to_79, age_group_5_to_14}] = 0.0394; + contacts_home[{age_group_60_to_79, age_group_15_to_34}] = 0.1417; + contacts_home[{age_group_60_to_79, age_group_35_to_59}] = 0.3834; + contacts_home[{age_group_60_to_79, age_group_60_to_79}] = 0.7064; + contacts_home[{age_group_60_to_79, age_group_80_plus}] = 0.0447; + contacts_home[{age_group_80_plus, age_group_0_to_4}] = 0.0292; + contacts_home[{age_group_80_plus, age_group_5_to_14}] = 0.0648; + contacts_home[{age_group_80_plus, age_group_15_to_34}] = 0.1248; + contacts_home[{age_group_80_plus, age_group_35_to_59}] = 0.4179; + contacts_home[{age_group_80_plus, age_group_60_to_79}] = 0.3497; + contacts_home[{age_group_80_plus, age_group_80_plus}] = 0.1544; + + /* baseline_school + 1.1165 0.2741 0.2235 0.1028 0.0007 0.0000 + 0.1627 1.9412 0.2431 0.1780 0.0130 0.0000 + 0.0148 0.1646 1.1266 0.0923 0.0074 0.0000 + 0.0367 0.1843 0.3265 0.0502 0.0021 0.0005 + 0.0004 0.0370 0.0115 0.0014 0.0039 0.0000 + 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 + */ + mio::CustomIndexArray contacts_school( + {mio::AgeGroup(n_age_groups), mio::AgeGroup(n_age_groups)}, 0.); + contacts_school[{age_group_0_to_4, age_group_0_to_4}] = 1.1165; + contacts_school[{age_group_0_to_4, age_group_5_to_14}] = 0.2741; + contacts_school[{age_group_0_to_4, age_group_15_to_34}] = 0.2235; + contacts_school[{age_group_0_to_4, age_group_35_to_59}] = 0.1028; + contacts_school[{age_group_0_to_4, age_group_60_to_79}] = 0.0007; + contacts_school[{age_group_0_to_4, age_group_80_plus}] = 0.0000; + contacts_school[{age_group_5_to_14, age_group_0_to_4}] = 0.1627; + contacts_school[{age_group_5_to_14, age_group_5_to_14}] = 1.9412; + contacts_school[{age_group_5_to_14, age_group_15_to_34}] = 0.2431; + contacts_school[{age_group_5_to_14, age_group_35_to_59}] = 0.1780; + contacts_school[{age_group_5_to_14, age_group_60_to_79}] = 0.0130; + contacts_school[{age_group_5_to_14, age_group_80_plus}] = 0.0000; + contacts_school[{age_group_15_to_34, age_group_0_to_4}] = 0.0148; + contacts_school[{age_group_15_to_34, age_group_5_to_14}] = 0.1646; + contacts_school[{age_group_15_to_34, age_group_15_to_34}] = 1.1266; + contacts_school[{age_group_15_to_34, age_group_35_to_59}] = 0.0923; + contacts_school[{age_group_15_to_34, age_group_60_to_79}] = 0.0074; + contacts_school[{age_group_15_to_34, age_group_80_plus}] = 0.0000; + contacts_school[{age_group_35_to_59, age_group_0_to_4}] = 0.0367; + contacts_school[{age_group_35_to_59, age_group_5_to_14}] = 0.1843; + contacts_school[{age_group_35_to_59, age_group_15_to_34}] = 0.3265; + contacts_school[{age_group_35_to_59, age_group_35_to_59}] = 0.0502; + contacts_school[{age_group_35_to_59, age_group_60_to_79}] = 0.0021; + contacts_school[{age_group_35_to_59, age_group_80_plus}] = 0.0005; + contacts_school[{age_group_60_to_79, age_group_0_to_4}] = 0.0004; + contacts_school[{age_group_60_to_79, age_group_5_to_14}] = 0.0370; + contacts_school[{age_group_60_to_79, age_group_15_to_34}] = 0.0115; + contacts_school[{age_group_60_to_79, age_group_35_to_59}] = 0.0014; + contacts_school[{age_group_60_to_79, age_group_60_to_79}] = 0.0039; + contacts_school[{age_group_60_to_79, age_group_80_plus}] = 0.0000; + contacts_school[{age_group_80_plus, age_group_0_to_4}] = 0.0000; + contacts_school[{age_group_80_plus, age_group_5_to_14}] = 0.0000; + contacts_school[{age_group_80_plus, age_group_15_to_34}] = 0.0000; + contacts_school[{age_group_80_plus, age_group_35_to_59}] = 0.0000; + contacts_school[{age_group_80_plus, age_group_60_to_79}] = 0.0000; + contacts_school[{age_group_80_plus, age_group_80_plus}] = 0.0000; + + /* baseline_work + 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 + 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 + 0.0000 0.0127 1.7570 1.6050 0.0133 0.0000 + 0.0000 0.0020 1.0311 2.3166 0.0098 0.0000 + 0.0000 0.0002 0.0194 0.0325 0.0003 0.0000 + 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 + */ + mio::CustomIndexArray contacts_work( + {mio::AgeGroup(n_age_groups), mio::AgeGroup(n_age_groups)}, 0.); + contacts_work[{age_group_0_to_4, age_group_0_to_4}] = 0.0000; + contacts_work[{age_group_0_to_4, age_group_5_to_14}] = 0.0000; + contacts_work[{age_group_0_to_4, age_group_15_to_34}] = 0.0000; + contacts_work[{age_group_0_to_4, age_group_35_to_59}] = 0.0000; + contacts_work[{age_group_0_to_4, age_group_60_to_79}] = 0.0000; + contacts_work[{age_group_0_to_4, age_group_80_plus}] = 0.0000; + contacts_work[{age_group_5_to_14, age_group_0_to_4}] = 0.0000; + contacts_work[{age_group_5_to_14, age_group_5_to_14}] = 0.0000; + contacts_work[{age_group_5_to_14, age_group_15_to_34}] = 0.0000; + contacts_work[{age_group_5_to_14, age_group_35_to_59}] = 0.0000; + contacts_work[{age_group_5_to_14, age_group_60_to_79}] = 0.0000; + contacts_work[{age_group_5_to_14, age_group_80_plus}] = 0.0000; + contacts_work[{age_group_15_to_34, age_group_0_to_4}] = 0.0000; + contacts_work[{age_group_15_to_34, age_group_5_to_14}] = 0.0127; + contacts_work[{age_group_15_to_34, age_group_15_to_34}] = 1.7570; + contacts_work[{age_group_15_to_34, age_group_35_to_59}] = 1.6050; + contacts_work[{age_group_15_to_34, age_group_60_to_79}] = 0.0133; + contacts_work[{age_group_15_to_34, age_group_80_plus}] = 0.0000; + contacts_work[{age_group_35_to_59, age_group_0_to_4}] = 0.0000; + contacts_work[{age_group_35_to_59, age_group_5_to_14}] = 0.0020; + contacts_work[{age_group_35_to_59, age_group_15_to_34}] = 1.0311; + contacts_work[{age_group_35_to_59, age_group_35_to_59}] = 2.3166; + contacts_work[{age_group_35_to_59, age_group_60_to_79}] = 0.0098; + contacts_work[{age_group_35_to_59, age_group_80_plus}] = 0.0000; + contacts_work[{age_group_60_to_79, age_group_0_to_4}] = 0.0000; + contacts_work[{age_group_60_to_79, age_group_5_to_14}] = 0.0002; + contacts_work[{age_group_60_to_79, age_group_15_to_34}] = 0.0194; + contacts_work[{age_group_60_to_79, age_group_35_to_59}] = 0.0325; + contacts_work[{age_group_60_to_79, age_group_60_to_79}] = 0.0003; + contacts_work[{age_group_60_to_79, age_group_80_plus}] = 0.0000; + contacts_work[{age_group_80_plus, age_group_0_to_4}] = 0.0000; + contacts_work[{age_group_80_plus, age_group_5_to_14}] = 0.0000; + contacts_work[{age_group_80_plus, age_group_15_to_34}] = 0.0000; + contacts_work[{age_group_80_plus, age_group_35_to_59}] = 0.0000; + contacts_work[{age_group_80_plus, age_group_60_to_79}] = 0.0000; + contacts_work[{age_group_80_plus, age_group_80_plus}] = 0.0000; + + /* baseline_other + 0.5170 0.3997 0.7957 0.9958 0.3239 0.0428 + 0.0632 0.9121 0.3254 0.4731 0.2355 0.0148 + 0.0336 0.1604 1.7529 0.8622 0.1440 0.0077 + 0.0204 0.1444 0.5738 1.2127 0.3433 0.0178 + 0.0371 0.0393 0.4171 0.9666 0.7495 0.0257 + 0.0791 0.0800 0.3480 0.5588 0.2769 0.0180 + + */ + mio::CustomIndexArray contacts_other( + {mio::AgeGroup(n_age_groups), mio::AgeGroup(n_age_groups)}, 0.); + contacts_other[{age_group_0_to_4, age_group_0_to_4}] = 0.5170; + contacts_other[{age_group_0_to_4, age_group_5_to_14}] = 0.3997; + contacts_other[{age_group_0_to_4, age_group_15_to_34}] = 0.7957; + contacts_other[{age_group_0_to_4, age_group_35_to_59}] = 0.9958; + contacts_other[{age_group_0_to_4, age_group_60_to_79}] = 0.3239; + contacts_other[{age_group_0_to_4, age_group_80_plus}] = 0.0428; + contacts_other[{age_group_5_to_14, age_group_0_to_4}] = 0.0632; + contacts_other[{age_group_5_to_14, age_group_5_to_14}] = 0.9121; + contacts_other[{age_group_5_to_14, age_group_15_to_34}] = 0.3254; + contacts_other[{age_group_5_to_14, age_group_35_to_59}] = 0.4731; + contacts_other[{age_group_5_to_14, age_group_60_to_79}] = 0.2355; + contacts_other[{age_group_5_to_14, age_group_80_plus}] = 0.0148; + contacts_other[{age_group_15_to_34, age_group_0_to_4}] = 0.0336; + contacts_other[{age_group_15_to_34, age_group_5_to_14}] = 0.1604; + contacts_other[{age_group_15_to_34, age_group_15_to_34}] = 1.7529; + contacts_other[{age_group_15_to_34, age_group_35_to_59}] = 0.8622; + contacts_other[{age_group_15_to_34, age_group_60_to_79}] = 0.1440; + contacts_other[{age_group_15_to_34, age_group_80_plus}] = 0.0077; + contacts_other[{age_group_35_to_59, age_group_0_to_4}] = 0.0204; + contacts_other[{age_group_35_to_59, age_group_5_to_14}] = 0.1444; + contacts_other[{age_group_35_to_59, age_group_15_to_34}] = 0.5738; + contacts_other[{age_group_35_to_59, age_group_35_to_59}] = 1.2127; + contacts_other[{age_group_35_to_59, age_group_60_to_79}] = 0.3433; + contacts_other[{age_group_35_to_59, age_group_80_plus}] = 0.0178; + contacts_other[{age_group_60_to_79, age_group_0_to_4}] = 0.0371; + contacts_other[{age_group_60_to_79, age_group_5_to_14}] = 0.0393; + contacts_other[{age_group_60_to_79, age_group_15_to_34}] = 0.4171; + contacts_other[{age_group_60_to_79, age_group_35_to_59}] = 0.9666; + contacts_other[{age_group_60_to_79, age_group_60_to_79}] = 0.7495; + contacts_other[{age_group_60_to_79, age_group_80_plus}] = 0.0257; + contacts_other[{age_group_80_plus, age_group_0_to_4}] = 0.0791; + contacts_other[{age_group_80_plus, age_group_5_to_14}] = 0.0800; + contacts_other[{age_group_80_plus, age_group_15_to_34}] = 0.3480; + contacts_other[{age_group_80_plus, age_group_35_to_59}] = 0.5588; + contacts_other[{age_group_80_plus, age_group_60_to_79}] = 0.2769; + contacts_other[{age_group_80_plus, age_group_80_plus}] = 0.0180; for (auto& loc : world.get_locations()) { switch (loc.get_type()) { case mio::abm::LocationType::Home: - loc.get_infection_parameters().get().array() = contacts_home; + loc.get_infection_parameters().get() = contacts_home; break; case mio::abm::LocationType::School: + loc.get_infection_parameters().get() = contacts_work; break; case mio::abm::LocationType::Work: + loc.get_infection_parameters().get() = contacts_work; break; default: + loc.get_infection_parameters().get() = contacts_other; break; } } From 18f34d84d99bcb7fbfc4a39a0a3befc58fcc62ce Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Tue, 27 Feb 2024 11:51:02 +0100 Subject: [PATCH 032/488] Add check if a Person is in bs in Location's get_subpopulation --- cpp/models/abm/location.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 81c605b598..7ff78c8250 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -206,17 +206,14 @@ ScalarType Cell::compute_space_per_person_relative() size_t Cell::get_subpopulation(TimePoint t, InfectionState state) const { return count_if(m_persons.begin(), m_persons.end(), [&](observer_ptr p) { - return p->get_infection_state(t) == state; + return p->get_infection_state(t) == state && p->is_home_in_bs(); }); } size_t Location::get_subpopulation(TimePoint t, InfectionState state) const { return count_if(m_persons.begin(), m_persons.end(), [&](observer_ptr p) { - if (p->is_home_in_bs()) { - return p->get_infection_state(t) == state; - } - return false; + return p->get_infection_state(t) == state && p->is_home_in_bs(); }); } From a26f72e7b3a5b709bd78c1d01d16fd5f42e73208 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Tue, 27 Feb 2024 13:49:42 +0100 Subject: [PATCH 033/488] Begin of initialization Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/simulations/CMakeLists.txt | 2 +- cpp/simulations/generate_graph_from_data.cpp | 282 +++++++++++++++++++ cpp/simulations/paper_abm_bs_testing.cpp | 27 +- 3 files changed, 305 insertions(+), 6 deletions(-) create mode 100644 cpp/simulations/generate_graph_from_data.cpp diff --git a/cpp/simulations/CMakeLists.txt b/cpp/simulations/CMakeLists.txt index 3a04021edf..7376116d0d 100644 --- a/cpp/simulations/CMakeLists.txt +++ b/cpp/simulations/CMakeLists.txt @@ -20,6 +20,6 @@ if(MEMILIO_HAS_JSONCPP AND MEMILIO_HAS_HDF5) target_compile_options(abm_braunschweig PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) add_executable(paper_abm_bs_testing paper_abm_bs_testing.cpp) - target_link_libraries(paper_abm_bs_testing PRIVATE memilio abm Boost::filesystem ${HDF5_C_LIBRARIES}) + target_link_libraries(paper_abm_bs_testing PRIVATE memilio ode_secir abm Boost::filesystem ${HDF5_C_LIBRARIES}) target_compile_options(paper_abm_bs_testing PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) endif() diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp new file mode 100644 index 0000000000..3987e5bb62 --- /dev/null +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -0,0 +1,282 @@ +/* +* Copyright (C) 2020-2023 German Aerospace Center (DLR-SC) +* +* Authors: Daniel Abele, Wadim Koslow, Martin Kühn, David Kerkmann +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include "memilio/compartments/parameter_studies.h" +#include "memilio/geography/regions.h" +#include "memilio/io/epi_data.h" +#include "memilio/io/result_io.h" +#include "memilio/io/mobility_io.h" +#include "memilio/utils/date.h" +#include "memilio/utils/miompi.h" +#include "memilio/utils/random_number_generator.h" +#include "ode_secir/parameters_io.h" +#include "ode_secir/parameter_space.h" +#include "memilio/mobility/metapopulation_mobility_instant.h" +#include "memilio/utils/stl_util.h" +#include "boost/filesystem.hpp" +#include +#include + +namespace fs = boost::filesystem; + +/** + * indices of contact matrix corresponding to locations where contacts occur. + */ +enum class ContactLocation +{ + Home = 0, + School, + Work, + Other, + Count, +}; + +/** + * Set a value and distribution of an UncertainValue. + * Assigns average of min and max as a value and UNIFORM(min, max) as a distribution. + * @param p uncertain value to set. + * @param min minimum of distribution. + * @param max minimum of distribution. + */ +void assign_uniform_distribution(mio::UncertainValue& p, double min, double max) +{ + p = mio::UncertainValue(0.5 * (max + min)); + p.set_distribution(mio::ParameterDistributionUniform(min, max)); +} + +/** + * Set a value and distribution of an array of UncertainValues. + * Assigns average of min[i] and max[i] as a value and UNIFORM(min[i], max[i]) as a distribution for + * each element i of the array. + * @param array array of UncertainValues to set. + * @param min minimum of distribution for each element of array. + * @param max minimum of distribution for each element of array. + */ +template +void array_assign_uniform_distribution(mio::CustomIndexArray& array, + const double (&min)[N], const double (&max)[N]) +{ + assert(N == array.numel()); + for (auto i = mio::AgeGroup(0); i < mio::AgeGroup(N); ++i) { + assign_uniform_distribution(array[i], min[size_t(i)], max[size_t(i)]); + } +} + +/** + * Set a value and distribution of an array of UncertainValues. + * Assigns average of min and max as a value and UNIFORM(min, max) as a distribution to every element of the array. + * @param array array of UncertainValues to set. + * @param min minimum of distribution. + * @param max minimum of distribution. + */ +void array_assign_uniform_distribution(mio::CustomIndexArray& array, double min, + double max) +{ + for (auto i = mio::AgeGroup(0); i < array.size(); ++i) { + assign_uniform_distribution(array[i], min, max); + } +} + +/** + * Set epidemiological parameters of Sars-CoV-2 for a immune-naive + * population and wild type variant. + * @param params Object that the parameters will be added to. + * @returns Currently generates no errors. + */ +mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) +{ + //times + const double incubationTime = 5.2; + const double serialIntervalMin = 0.5 * 2.67 + 0.5 * 5.2; + const double serialIntervalMax = 0.5 * 4.00 + 0.5 * 5.2; + const double timeInfectedSymptomsMin[] = {5.6255, 5.6255, 5.6646, 5.5631, 5.501, 5.465}; + const double timeInfectedSymptomsMax[] = {8.427, 8.427, 8.4684, 8.3139, 8.169, 8.085}; + const double timeInfectedSevereMin[] = {3.925, 3.925, 4.85, 6.4, 7.2, 9.}; + const double timeInfectedSevereMax[] = {6.075, 6.075, 7., 8.7, 9.8, 13.}; + const double timeInfectedCriticalMin[] = {4.95, 4.95, 4.86, 14.14, 14.4, 10.}; + const double timeInfectedCriticalMax[] = {8.95, 8.95, 8.86, 20.58, 19.8, 13.2}; + + array_assign_uniform_distribution(params.get(), incubationTime, incubationTime); + array_assign_uniform_distribution(params.get(), serialIntervalMin, serialIntervalMax); + array_assign_uniform_distribution(params.get(), timeInfectedSymptomsMin, + timeInfectedSymptomsMax); + array_assign_uniform_distribution(params.get(), timeInfectedSevereMin, + timeInfectedSevereMax); + array_assign_uniform_distribution(params.get(), timeInfectedCriticalMin, + timeInfectedCriticalMax); + + //probabilities + const double transmissionProbabilityOnContactMin[] = {0.02, 0.05, 0.05, 0.05, 0.08, 0.15}; + const double transmissionProbabilityOnContactMax[] = {0.04, 0.07, 0.07, 0.07, 0.10, 0.20}; + const double relativeTransmissionNoSymptomsMin = 1; + const double relativeTransmissionNoSymptomsMax = 1; + // The precise value between Risk* (situation under control) and MaxRisk* (situation not under control) + // depends on incidence and test and trace capacity + const double riskOfInfectionFromSymptomaticMin = 0.1; + const double riskOfInfectionFromSymptomaticMax = 0.3; + const double maxRiskOfInfectionFromSymptomaticMin = 0.3; + const double maxRiskOfInfectionFromSymptomaticMax = 0.5; + const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; + const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.20}; + const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.18, 0.25}; + const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; + const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; + const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; + const double deathsPerCriticalMax[] = {0.10, 0.10, 0.18, 0.18, 0.50, 0.7}; + + array_assign_uniform_distribution(params.get(), + transmissionProbabilityOnContactMin, transmissionProbabilityOnContactMax); + array_assign_uniform_distribution(params.get(), + relativeTransmissionNoSymptomsMin, relativeTransmissionNoSymptomsMax); + array_assign_uniform_distribution(params.get(), + riskOfInfectionFromSymptomaticMin, riskOfInfectionFromSymptomaticMax); + array_assign_uniform_distribution(params.get(), + maxRiskOfInfectionFromSymptomaticMin, maxRiskOfInfectionFromSymptomaticMax); + array_assign_uniform_distribution(params.get(), + recoveredPerInfectedNoSymptomsMin, recoveredPerInfectedNoSymptomsMax); + array_assign_uniform_distribution(params.get(), + severePerInfectedSymptomsMin, severePerInfectedSymptomsMax); + array_assign_uniform_distribution(params.get(), criticalPerSevereMin, + criticalPerSevereMax); + array_assign_uniform_distribution(params.get(), deathsPerCriticalMin, + deathsPerCriticalMax); + + //sasonality + const double seasonality_min = 0.1; + const double seasonality_max = 0.3; + + assign_uniform_distribution(params.get(), seasonality_min, seasonality_max); + + return mio::success(); +} + +static const std::map contact_locations = {{ContactLocation::Home, "home"}, + {ContactLocation::School, "school_pf_eig"}, + {ContactLocation::Work, "work"}, + {ContactLocation::Other, "other"}}; + +/** + * Set contact matrices. + * Reads contact matrices from files in the data directory. + * @param data_dir data directory. + * @param params Object that the contact matrices will be added to. + * @returns any io errors that happen during reading of the files. + */ +mio::IOResult set_contact_matrices(const fs::path& data_dir, mio::osecir::Parameters& params) +{ + //TODO: io error handling + auto contact_matrices = mio::ContactMatrixGroup(contact_locations.size(), size_t(params.get_num_groups())); + for (auto&& contact_location : contact_locations) { + BOOST_OUTCOME_TRY(baseline, + mio::read_mobility_plain( + (data_dir / "contacts" / ("baseline_" + contact_location.second + ".txt")).string())); + BOOST_OUTCOME_TRY(minimum, + mio::read_mobility_plain( + (data_dir / "contacts" / ("minimum_" + contact_location.second + ".txt")).string())); + contact_matrices[size_t(contact_location.first)].get_baseline() = baseline; + contact_matrices[size_t(contact_location.first)].get_minimum() = minimum; + } + params.get() = mio::UncertainContactMatrix(contact_matrices); + + return mio::success(); +} + +/** + * Create the input graph for the parameter study. + * Reads files from the data directory. + * @param start_date start date of the simulation. + * @param end_date end date of the simulation. + * @param data_dir data directory. + * @returns created graph or any io errors that happen during reading of the files. + */ +mio::IOResult> get_graph(mio::Date start_date, const int num_days, + const fs::path& data_dir) +{ + + // global parameters + const int num_groups = 6; + mio::osecir::Parameters params(num_groups); + params.get() = mio::get_day_in_year(start_date); + BOOST_OUTCOME_TRY(set_covid_parameters(params)); + BOOST_OUTCOME_TRY(set_contact_matrices(data_dir, params)); + + auto population_data_path = + mio::path_join((data_dir / "pydata" / "Germany").string(), "county_current_population.json"); + + BOOST_OUTCOME_TRY(node_ids, mio::get_node_ids(population_data_path, true)); + std::vector nodes(node_ids.size(), mio::osecir::Model(num_groups)); + for (auto& node : nodes) { + node.parameters = params; + } + auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 1.0); + auto scaling_factor_icu = 1.0; + + const auto& read_function_nodes = mio::osecir::read_input_data_county; + BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, + data_dir.string(), num_days, false)); + return mio::success(nodes); +} + +/* +int main(int argc, char** argv) +{ + + mio::set_log_level(mio::LogLevel::warn); + mio::mpi::init(); + + std::string data_dir; + mio::Date start_date = mio::Date(2023, 6, 1); + double num_days_sim = 90.0; + + if (argc == 1) { + data_dir = "../../data"; + } + else if (argc == 2) { + data_dir = argv[1]; + } + else if (argc == 6) { + data_dir = argv[1]; + start_date = mio::Date(std::atoi(argv[2]), std::atoi(argv[3]), std::atoi(argv[4])); + num_days_sim = std::atoi(argv[5]); + } + else { + mio::mpi::finalize(); + return 0; + } + + //mio::thread_local_rng().seed( + // {114381446, 2427727386, 806223567, 832414962, 4121923627, 1581162203}); //set seeds, e.g., for debugging + mio::thread_local_rng().synchronize(); + if (mio::mpi::is_root()) { + printf("Seeds: "); + for (auto s : mio::thread_local_rng().get_seeds()) { + printf("%u, ", s); + } + printf("\n"); + } + + //create or load graph + auto create_extrapolated_data = get_graph(start_date, num_days_sim, data_dir); + + mio::mpi::finalize(); + return 0; +} +*/ \ No newline at end of file diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2bec6d9802..04f6ec9e10 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -29,6 +29,7 @@ #include "boost/algorithm/string/classification.hpp" #include "abm/vaccine.h" #include "abm/common_abm_loggers.h" +#include "generate_graph_from_data.cpp" namespace fs = boost::filesystem; @@ -77,6 +78,26 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t, doubl world.parameters, t, infection_state)); } } + +void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint /*t*/) +{ + // estimate intial population by ODE compartiments + auto initial_graph = get_graph(mio::Date(2020, 03, 01), 15, "pydata/Germany/"); + + //mio::CustomIndexArray infection_probs{{6}, 1.}; + //auto population_data_path = + // mio::path_join((data_dir / "pydata" / "Germany").string(), "county_current_population.json"); + + //auto node_ids = mio::get_node_ids(population_data_path, true); + //initial_graph[] + + // convert initial population to ABM initial infection probabilities + for (auto& person : world.get_persons()) { + if (person.get_age() == age_group_0_to_4) { + } + } +} + int stringToMinutes(const std::string& input) { size_t colonPos = input.find(":"); @@ -685,10 +706,6 @@ void set_local_parameters(mio::abm::World& world) mio::abm::Simulation create_sampled_simulation(const std::string& input_file, const mio::abm::TimePoint& t0, int max_num_persons) { - // Assumed percentage of infection state at the beginning of the simulation. - ScalarType exposed_prob = 0.08, infected_no_symptoms_prob = 0.001, infected_symptoms_prob = 0.001, - recovered_prob = 0.0; - //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world auto world = mio::abm::World(num_age_groups); @@ -700,7 +717,7 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co world.use_migration_rules(false); // Assign an infection state to each person. - assign_infection_state(world, t0, exposed_prob, infected_no_symptoms_prob, infected_symptoms_prob, recovered_prob); + //assign_infection_state(world, t0); auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); From 57aac7d850aa19bb60906269b271ee2253d960fe Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Tue, 27 Feb 2024 17:27:07 +0100 Subject: [PATCH 034/488] Finish graph initialisation Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 04f6ec9e10..ad36593b04 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -82,15 +82,12 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t, doubl void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint /*t*/) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(mio::Date(2020, 03, 01), 15, "pydata/Germany/"); - - //mio::CustomIndexArray infection_probs{{6}, 1.}; - //auto population_data_path = - // mio::path_join((data_dir / "pydata" / "Germany").string(), "county_current_population.json"); - - //auto node_ids = mio::get_node_ids(population_data_path, true); - //initial_graph[] + auto initial_graph = get_graph(mio::Date(2020, 03, 01), 1, "/Users/david/Documents/HZI/memilio/data/"); + size_t braunschweig_id = 0; // TODO: Find correct ID for Braunschweig + auto braunschweig_node = initial_graph.value()[braunschweig_id]; + // TODO: Collect number of infected agents and assign randomly to the population + // convert initial population to ABM initial infection probabilities for (auto& person : world.get_persons()) { if (person.get_age() == age_group_0_to_4) { @@ -717,7 +714,7 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co world.use_migration_rules(false); // Assign an infection state to each person. - //assign_infection_state(world, t0); + assign_infection_state(world, t0); auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); From 717846519787f9589f7a236c17315f1628b72488 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Feb 2024 14:45:36 +0100 Subject: [PATCH 035/488] fix bs flag Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- .../memilio/epidata/check_bs_data.py | 987 +++++++++--------- 1 file changed, 510 insertions(+), 477 deletions(-) diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py index 8281c18551..44a3f87960 100644 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -14,7 +14,7 @@ ####### minimal sanity check on data ####### -bd = pd.read_csv(r'', header=None, skiprows=1) +bd = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/pycode/memilio-epidata/memilio/epidata/bs_und_umgebung.csv', header=None, skiprows=1) # setup dictionary for the leisure activities, and vehicle choice and column names # bd.rename( @@ -33,483 +33,516 @@ dict_vehicle = {1: 'bicyle', 2: 'car_driver', 3: 'car_codriver', 4: 'public transport', 5: 'walk'} -# check if people do the same trip more than once -trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] -duplicate_trips = trips.duplicated() -if (duplicate_trips.any()): - print('Error: The Person does the "same" trip more than once (or dos 2 things in 5 mins). Number of duplicate trips: ' + str(duplicate_trips[duplicate_trips==True].size)) - # if (~bd[['tripID']].duplicated().any()): - # print('There are no duplicate TripIDs. There are multiple TripIDs for the same Trip. \n') -activities_after_duplicate_trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime', 'ActivityAfter']].loc[trips.duplicated(keep=False)] -if (~activities_after_duplicate_trips.duplicated(keep=False).all()): - print('Error: Multiple activities after the same trip. \n') - -# check if persons have more than one home -person_homes = bd[['personID', 'loc_id_end', 'ActivityAfter']].loc[bd['ActivityAfter']==7] -person_homes = person_homes.drop_duplicates().groupby(['personID']).size().reset_index(name='counts') -person_homes.drop(person_homes.loc[person_homes['counts']<2].index, inplace=True) -if(person_homes.size > 0): - print('Error: There are people that have more than one home. \n') - -# check if the proportion of single-person-households is too high -households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) - -# check if the proportion of single-person-households is too high -if (households.loc[households['counts']==1]['counts'].size)/(households['counts'].size) > 0.5: - print("Error: The proportion of single-person-households is too high: " + - str((households.loc[households['counts']==1]['counts'].size)/(households['counts'].size))) - -# check if there are invalid entries -# if not bd['idTrafficZone'].ge(30000000).all(): -# print('Error: There is an entry in "tripID" that is not assignable. \n') +# # check if people do the same trip more than once +# trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] +# duplicate_trips = trips.duplicated() +# if (duplicate_trips.any()): +# print('Error: The Person does the "same" trip more than once (or dos 2 things in 5 mins). Number of duplicate trips: ' + str(duplicate_trips[duplicate_trips==True].size)) +# # if (~bd[['tripID']].duplicated().any()): +# # print('There are no duplicate TripIDs. There are multiple TripIDs for the same Trip. \n') +# activities_after_duplicate_trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime', 'ActivityAfter']].loc[trips.duplicated(keep=False)] +# if (~activities_after_duplicate_trips.duplicated(keep=False).all()): +# print('Error: Multiple activities after the same trip. \n') + +# # check if persons have more than one home +# person_homes = bd[['personID', 'loc_id_end', 'ActivityAfter']].loc[bd['ActivityAfter']==7] +# person_homes = person_homes.drop_duplicates().groupby(['personID']).size().reset_index(name='counts') +# person_homes.drop(person_homes.loc[person_homes['counts']<2].index, inplace=True) +# if(person_homes.size > 0): +# print('Error: There are people that have more than one home. \n') + +# # check if the proportion of single-person-households is too high +# households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) + +# # check if the proportion of single-person-households is too high +# if (households.loc[households['counts']==1]['counts'].size)/(households['counts'].size) > 0.5: +# print("Error: The proportion of single-person-households is too high: " + +# str((households.loc[households['counts']==1]['counts'].size)/(households['counts'].size))) + +# # check if there are invalid entries +# # if not bd['idTrafficZone'].ge(30000000).all(): +# # print('Error: There is an entry in "tripID" that is not assignable. \n') +# # # number of entries that are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripID'].ge(30000000)].size) + '. \n') +# if not bd['personID'].ge(100000000).all(): +# print('Error: There is an entry in "personID" that is not assignable. \n') # # number of entries that are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripID'].ge(30000000)].size) + '. \n') -if not bd['personID'].ge(100000000).all(): - print('Error: There is an entry in "personID" that is not assignable. \n') - # number of entries that are not assignable - print('Number of entries that are not assignable: ' + str(bd.loc[~bd['personID'].ge(100000000)].size) + '. \n') -# if not bd['tripChain'].between(1, 100).all(): -# print('Error: There is an entry in "tripChain" that is not assignable. \n') -# # number of entries that are not assignable - # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripChain'].between(1, 100)].size) + '. \n') - # # max assigned value - # print('Max assigned value: ' + str(bd['tripChain'].max()) + '. \n') -# if not bd['countyStart'].ge(30000000).all(): -# print('Error: There is an entry in "countyStart" that is not assignable. \n') -# # which ones are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyStart'].ge(30000000)].size) + '. \n') -# if not bd['countyEnd'].ge(30000000).all(): -# print('Error: There is an entry in "countyEnd" that is not assignable. \n') -# # which ones are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyEnd'].ge(30000000)].size) + '. \n') -# if not bd['hhID'].ge(100000000).all(): -# print('Error: There is an entry in "hhID" that is not assignable. \n') -# if not bd['tripChainID'].between(-1, -1).all(): -# print('Error: There is an entry in "tripChainID" that is not assignable. \n') -if not bd['vehicleChoice'].between(1, 5).all(): - print('Error: There is an entry in "vehicleChoice" that is not assignable. \n') - #print number of entries that are not assignable - print('Number of entries that are not assignable: ' + str(bd.loc[~bd['vehicleChoice'].between(1, 5)].size) + '. \n') -if not bd['ActivityAfter'].between(0, 7).all(): - print('Error: There is an entry in "ActivityAfter" that is not assignable. \n') - #print number of entries that are not assignable - print('Number of entries that are not assignable: ' + str(bd.loc[~bd['ActivityAfter'].between(0, 7)].size) + '. \n') - -# check if there are empty cells -for header in bd.columns: - if (bd[header].isna().any()): - print('Error: ' + str(len(bd[bd[header].isna()])) + ' empty entries in column' + str(header) + '. \n') - -# check age groups with schools -number_of_people = bd[['personID']].drop_duplicates().size -print(str(number_of_people) + ' are people. \n') - -# number_of_trips = bd[['tripID']].drop_duplicates().size -# print(str(number_of_trips) + ' trips. \n') - - -students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] -print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') -print(str(students.loc[students['age'] > 20].size) + ' trips of ' + str(students.size) + ' trips going to school are in a higher age group than 10. \n') - -children = bd[['personID','ActivityAfter']].loc[(bd['age']<=16) & (bd['age']>=7)] -number_of_children = children['personID'].drop_duplicates().size -number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size -print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') - - -workers = bd[['personID','ActivityAfter']].loc[(bd['age']>30)] -number_of_workers = workers['personID'].drop_duplicates().size -number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size -print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' workers do not go to work. \n') - - - -############################################### - - -####### visual check on values in data frame ####### - -# def get_trip_chain_activity_after(person_id): -# bd_persons_trip_chain_activity_after = bd.loc[bd['personID'] == person_id, [ -# 'tripChain', 'ActivityAfter']] -# bd_persons_trip_chain_activity_after = bd_persons_trip_chain_activity_after.sort_values( -# by=['tripChain'], ascending=True, ignore_index=True) -# bd_persons_trip_chain_activity_after['ActivityAfter'] = bd_persons_trip_chain_activity_after['ActivityAfter'].map( -# dict_leisure) -# # and vehicle choice -# bd_persons_trip_chain_vehicle_choice = bd.loc[bd['personID'] == person_id, [ -# 'tripChain', 'vehicleChoice']] -# bd_persons_trip_chain_vehicle_choice = bd_persons_trip_chain_vehicle_choice.sort_values( -# by=['tripChain'], ascending=True, ignore_index=True) -# bd_persons_trip_chain_vehicle_choice['vehicleChoice'] = bd_persons_trip_chain_vehicle_choice['vehicleChoice'].map( -# dict_vehicle) -# return bd_persons_trip_chain_activity_after, bd_persons_trip_chain_vehicle_choice - - -# read in the data -if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'figs_bs_data')): - os.makedirs(os.path.join(os.path.dirname( - os.path.abspath(__file__)), 'figs_bs_data')) -figs_path = os.path.join(os.path.dirname( - os.path.abspath(__file__)), 'figs_bs_data') - -# check whether first start location is the last end location -first_trip = bd[['personID','loc_id_start']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) -last_trip = bd[['personID', 'loc_id_end']].drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) -print("Number of persons where first start location is home: " + str(first_trip.loc[first_trip['loc_id_start']==-1]['loc_id_start'].size)+ ".") -print("Number of persons where last end location is home: " + str(last_trip.loc[last_trip['loc_id_end']==-1]['loc_id_end'].size)+ ".") - -# check what persons are doing which only do one trip -# location_types = last_trip.groupby(['ActivityAfter']).size() - -# location_types.plot(kind='bar') -# plt.xlabel('Activity') +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['personID'].ge(100000000)].size) + '. \n') +# # if not bd['tripChain'].between(1, 100).all(): +# # print('Error: There is an entry in "tripChain" that is not assignable. \n') +# # # number of entries that are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripChain'].between(1, 100)].size) + '. \n') +# # # max assigned value +# # print('Max assigned value: ' + str(bd['tripChain'].max()) + '. \n') +# # if not bd['countyStart'].ge(30000000).all(): +# # print('Error: There is an entry in "countyStart" that is not assignable. \n') +# # # which ones are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyStart'].ge(30000000)].size) + '. \n') +# # if not bd['countyEnd'].ge(30000000).all(): +# # print('Error: There is an entry in "countyEnd" that is not assignable. \n') +# # # which ones are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyEnd'].ge(30000000)].size) + '. \n') +# # if not bd['hhID'].ge(100000000).all(): +# # print('Error: There is an entry in "hhID" that is not assignable. \n') +# # if not bd['tripChainID'].between(-1, -1).all(): +# # print('Error: There is an entry in "tripChainID" that is not assignable. \n') +# if not bd['vehicleChoice'].between(1, 5).all(): +# print('Error: There is an entry in "vehicleChoice" that is not assignable. \n') +# #print number of entries that are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['vehicleChoice'].between(1, 5)].size) + '. \n') +# if not bd['ActivityAfter'].between(0, 7).all(): +# print('Error: There is an entry in "ActivityAfter" that is not assignable. \n') +# #print number of entries that are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['ActivityAfter'].between(0, 7)].size) + '. \n') + +# # check if there are empty cells +# for header in bd.columns: +# if (bd[header].isna().any()): +# print('Error: ' + str(len(bd[bd[header].isna()])) + ' empty entries in column' + str(header) + '. \n') + +# # check age groups with schools +# number_of_people = bd[['personID']].drop_duplicates().size +# print(str(number_of_people) + ' are people. \n') + +# # number_of_trips = bd[['tripID']].drop_duplicates().size +# # print(str(number_of_trips) + ' trips. \n') + + +# students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] +# print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') +# print(str(students.loc[students['age'] > 20].size) + ' trips of ' + str(students.size) + ' trips going to school are in a higher age group than 10. \n') + +# children = bd[['personID','ActivityAfter']].loc[(bd['age']<=16) & (bd['age']>=7)] +# number_of_children = children['personID'].drop_duplicates().size +# number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size +# print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') + + +# workers = bd[['personID','ActivityAfter']].loc[(bd['age']>30)] +# number_of_workers = workers['personID'].drop_duplicates().size +# number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size +# print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' workers do not go to work. \n') + + + +# ############################################### + + +# ####### visual check on values in data frame ####### + +# # def get_trip_chain_activity_after(person_id): +# # bd_persons_trip_chain_activity_after = bd.loc[bd['personID'] == person_id, [ +# # 'tripChain', 'ActivityAfter']] +# # bd_persons_trip_chain_activity_after = bd_persons_trip_chain_activity_after.sort_values( +# # by=['tripChain'], ascending=True, ignore_index=True) +# # bd_persons_trip_chain_activity_after['ActivityAfter'] = bd_persons_trip_chain_activity_after['ActivityAfter'].map( +# # dict_leisure) +# # # and vehicle choice +# # bd_persons_trip_chain_vehicle_choice = bd.loc[bd['personID'] == person_id, [ +# # 'tripChain', 'vehicleChoice']] +# # bd_persons_trip_chain_vehicle_choice = bd_persons_trip_chain_vehicle_choice.sort_values( +# # by=['tripChain'], ascending=True, ignore_index=True) +# # bd_persons_trip_chain_vehicle_choice['vehicleChoice'] = bd_persons_trip_chain_vehicle_choice['vehicleChoice'].map( +# # dict_vehicle) +# # return bd_persons_trip_chain_activity_after, bd_persons_trip_chain_vehicle_choice + + +# # read in the data +# if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'figs_bs_data')): +# os.makedirs(os.path.join(os.path.dirname( +# os.path.abspath(__file__)), 'figs_bs_data')) +# figs_path = os.path.join(os.path.dirname( +# os.path.abspath(__file__)), 'figs_bs_data') + +# # check whether first start location is the last end location +# first_trip = bd[['personID','loc_id_start']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) +# last_trip = bd[['personID', 'loc_id_end']].drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) +# print("Number of persons where first start location is home: " + str(first_trip.loc[first_trip['loc_id_start']==-1]['loc_id_start'].size)+ ".") +# print("Number of persons where last end location is home: " + str(last_trip.loc[last_trip['loc_id_end']==-1]['loc_id_end'].size)+ ".") + +# # check what persons are doing which only do one trip +# # location_types = last_trip.groupby(['ActivityAfter']).size() + +# # location_types.plot(kind='bar') +# # plt.xlabel('Activity') +# # plt.ylabel('Number of persons') +# # plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) + +# # probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located +# # bd_tz_bs = bd.groupby(['idTrafficZone']).size().reset_index( +# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # # Count traffic zones where person is residing and longitude and latuitude of this in "EPSG:3035" format +# # bd_traffic_zones_persons = bd.groupby(['idTrafficZone']).size().reset_index( +# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # for row in bd_traffic_zones_persons.iterrows(): +# # bd_traffic_zones_persons.loc[row[0], ['longitude', 'latitude'] +# # ] = bd.loc[bd_traffic_zones_persons.loc[row[0], 'idTrafficZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +# # print(bd_traffic_zones_persons) + +# #### Counting people #### +# bd_persons = bd.groupby(['personID']).size().reset_index( +# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # Get the frequency of each number in the 'numbers' column +# bd_personss = bd_persons['counts'].value_counts().sort_index() +# # Plot the frequency of each number +# bd_personss.plot(kind='bar') +# plt.xlabel('Number of trips per day') # plt.ylabel('Number of persons') -# plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) - -# probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located -# bd_tz_bs = bd.groupby(['idTrafficZone']).size().reset_index( +# plt.title('Number of trips per person tripcount (Braunschweig)') +# plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) + +# bd_persons_ages = bd[['personID', 'age']].drop_duplicates() +# bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ +# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# bd_persons_ages_cohorts = bd_persons_ages.groupby( +# ['AgeCohort']).size().reset_index(name='counts') +# bd_persons_ages_cohorts.index = bd_persons_ages_cohorts['AgeCohort'].to_list() +# bd_persons_ages_cohorts.plot.bar(figsize=( +# 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) +# plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) + +# # get the id with the persons with the highest number and print them +# # [id_person_max_trips, id_person_max_1_trips] = [ +# # bd_persons['personID'][0], bd_persons['personID'][1]] +# # print(get_trip_chain_activity_after(id_person_max_trips)) + +# # select internal and external trips (from/to Braunschweig) +# # bd_persons_inside_bs = bd.loc[bd['startZone'].isin( +# # bd_tz_bs['idTrafficZone']) & bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] +# # bd_persons_outside_bs = bd.loc[~bd['startZone'].isin( +# # bd_tz_bs['idTrafficZone']) & ~bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] + +# # check how many trips are in the same traffic zone +# bd_taz_start = bd.groupby('startZone').size().reset_index(name='counts') +# #bd_same_taz = bd.loc[bd['startZone'] == bd['destZone']] +# bd_different_taz = bd.loc[bd['startZone'] != bd['destZone']] +# #bd_same_taz = bd_same_taz.groupby(['startZone']).size().reset_index(name='counts') +# bd_different_taz = bd_different_taz.groupby( +# ['startZone']).size().reset_index(name='counts') +# #bd_same_taz['percentage'] = bd_same_taz['counts']/bd_taz_start['counts'] +# bd_different_taz['complement_counts'] = bd_taz_start['counts'] - \ +# bd_different_taz['counts'] +# bd_different_taz['total_counts'] = bd_taz_start['counts'] +# bd_different_taz = (bd_different_taz.sort_values( +# by='total_counts', ascending=False, ignore_index=True)) +# plt.figure() +# plt.plot(bd_different_taz['counts']) +# plt.plot(bd_different_taz['complement_counts']) +# plt.legend(['different TAZ', 'same TAZ']) +# plt.xlabel('Traffic analysis zones') +# plt.ylabel('Amount of trips inside/outside a TAZ') +# plt.savefig(os.path.join(figs_path, 'TAZ_distribution.png'), dpi=300) + +# # which age takes which mode of transport +# bd_persons_age_vehicle_choice = bd.loc[:, ['personID', 'age', 'vehicleChoice']].sort_values( +# by=['age'], ascending=True, ignore_index=True) +# bd_persons_age_vehicle_choice['vehicleChoice'] = bd_persons_age_vehicle_choice['vehicleChoice'].map( +# dict_vehicle) +# # accumulate the number of trips per age and vehicle choice +# bd_persons_age_vehicle_choice = bd_persons_age_vehicle_choice.groupby( +# ['age', 'vehicleChoice']).size().reset_index( +# name='counts').sort_values( +# by=['age'], +# ascending=True, ignore_index=True) +# # assign each age to an age cohort +# bd_persons_age_vehicle_choice['ageCohort'] = pd.cut(bd_persons_age_vehicle_choice['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ +# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# # plot a cake chart for each age cohort +# bd_persons_age_vehicle_choice_cake = bd_persons_age_vehicle_choice.groupby( +# ['ageCohort', 'vehicleChoice']).sum().reset_index() +# bd_persons_age_vehicle_choice_cake_age_veh = bd_persons_age_vehicle_choice_cake.pivot( +# index='ageCohort', columns='vehicleChoice', values='counts') +# bd_persons_age_vehicle_choice_cake_age_veh.plot.pie(subplots=True, layout=(3, 2), figsize=( +# 10, 10), title=bd_persons_age_vehicle_choice_cake_age_veh.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'vehicle_choice_per_age.png'), dpi=300) + +# # switch age cohort and vehicle choice +# bd_persons_age_vehicle_choice_cake_veh_age = bd_persons_age_vehicle_choice_cake.pivot( +# index='vehicleChoice', columns='ageCohort', values='counts') +# bd_persons_age_vehicle_choice_cake_veh_age.plot.pie(subplots=True, layout=(3, 3), figsize=( +# 20, 10), title=bd_persons_age_vehicle_choice_cake_veh_age.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'vehicle_choice_reversed.png'), dpi=300) + +# # Analyse trip purposes per age cohort +# bd_persons_age_purpose = bd.loc[:, ['personID', 'age', 'ActivityAfter']] +# bd_persons_age_purpose['ActivityAfter'] = bd_persons_age_purpose['ActivityAfter'].map( +# dict_leisure) +# bd_persons_age_purpose['ageCohort'] = pd.cut(bd_persons_age_purpose['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ +# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# bd_persons_age_purpose_acc = bd_persons_age_purpose.groupby( +# ['ActivityAfter', 'ageCohort']).size().reset_index(name='counts') +# bd_persons_age_purpose_cake = bd_persons_age_purpose_acc.pivot( +# index='ageCohort', columns='ActivityAfter', values='counts') +# bd_persons_age_purpose_cake.plot.pie(subplots=True, layout=(2, 4), figsize=( +# 15, 5), title=bd_persons_age_purpose_cake.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'trip_purpose.png'), dpi=300) + +# # switch age cohorts and purpose +# bd_persons_age_purpose_cake_reversed = bd_persons_age_purpose_acc.pivot( +# index='ActivityAfter', columns='ageCohort', values='counts') +# bd_persons_age_purpose_cake_reversed.plot.pie(subplots=True, layout=(2, 5), figsize=( +# 15, 5), title=bd_persons_age_purpose_cake_reversed.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'trip_purpose_reversed.png'), dpi=300) + +# # Count traffic zones where people are starting their trips +# bd_traffic_zones_start = bd.groupby(['startZone']).size().reset_index( # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# # Count traffic zones where person is residing and longitude and latuitude of this in "EPSG:3035" format -# bd_traffic_zones_persons = bd.groupby(['idTrafficZone']).size().reset_index( +# for row in bd_traffic_zones_start.iterrows(): +# bd_traffic_zones_start.loc[row[0], ['longitude', 'latitude'] +# ] = bd.loc[bd_traffic_zones_start.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +# print(bd_traffic_zones_start) + +# # plot longitude and latitude of traffic zones +# bd_traffic_zones_start.plot( +# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_start['counts'] / 100, figsize=(10, 15), +# title='Traffic zones where people are starting their trips (Braunschweig)') +# plt.savefig(os.path.join(figs_path, 'traffic_zones_start.png'), dpi=300) + +# # Count traffic zones where people are going and leaving +# bd_traffic_zones_end = bd.groupby(['destZone']).size().reset_index( # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# for row in bd_traffic_zones_persons.iterrows(): -# bd_traffic_zones_persons.loc[row[0], ['longitude', 'latitude'] -# ] = bd.loc[bd_traffic_zones_persons.loc[row[0], 'idTrafficZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] -# print(bd_traffic_zones_persons) - -#### Counting people #### -bd_persons = bd.groupby(['personID']).size().reset_index( - name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# Get the frequency of each number in the 'numbers' column -bd_personss = bd_persons['counts'].value_counts().sort_index() -# Plot the frequency of each number -bd_personss.plot(kind='bar') -plt.xlabel('Number of trips per day') -plt.ylabel('Number of persons') -plt.title('Number of trips per person tripcount (Braunschweig)') -plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) - -bd_persons_ages = bd[['personID', 'age']].drop_duplicates() -bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ - '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -bd_persons_ages_cohorts = bd_persons_ages.groupby( - ['AgeCohort']).size().reset_index(name='counts') -bd_persons_ages_cohorts.index = bd_persons_ages_cohorts['AgeCohort'].to_list() -bd_persons_ages_cohorts.plot.bar(figsize=( - 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) -plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) - -# get the id with the persons with the highest number and print them -# [id_person_max_trips, id_person_max_1_trips] = [ -# bd_persons['personID'][0], bd_persons['personID'][1]] -# print(get_trip_chain_activity_after(id_person_max_trips)) - -# select internal and external trips (from/to Braunschweig) -# bd_persons_inside_bs = bd.loc[bd['startZone'].isin( -# bd_tz_bs['idTrafficZone']) & bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] -# bd_persons_outside_bs = bd.loc[~bd['startZone'].isin( -# bd_tz_bs['idTrafficZone']) & ~bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] - -# check how many trips are in the same traffic zone -bd_taz_start = bd.groupby('startZone').size().reset_index(name='counts') -#bd_same_taz = bd.loc[bd['startZone'] == bd['destZone']] -bd_different_taz = bd.loc[bd['startZone'] != bd['destZone']] -#bd_same_taz = bd_same_taz.groupby(['startZone']).size().reset_index(name='counts') -bd_different_taz = bd_different_taz.groupby( - ['startZone']).size().reset_index(name='counts') -#bd_same_taz['percentage'] = bd_same_taz['counts']/bd_taz_start['counts'] -bd_different_taz['complement_counts'] = bd_taz_start['counts'] - \ - bd_different_taz['counts'] -bd_different_taz['total_counts'] = bd_taz_start['counts'] -bd_different_taz = (bd_different_taz.sort_values( - by='total_counts', ascending=False, ignore_index=True)) -plt.figure() -plt.plot(bd_different_taz['counts']) -plt.plot(bd_different_taz['complement_counts']) -plt.legend(['different TAZ', 'same TAZ']) -plt.xlabel('Traffic analysis zones') -plt.ylabel('Amount of trips inside/outside a TAZ') -plt.savefig(os.path.join(figs_path, 'TAZ_distribution.png'), dpi=300) - -# which age takes which mode of transport -bd_persons_age_vehicle_choice = bd.loc[:, ['personID', 'age', 'vehicleChoice']].sort_values( - by=['age'], ascending=True, ignore_index=True) -bd_persons_age_vehicle_choice['vehicleChoice'] = bd_persons_age_vehicle_choice['vehicleChoice'].map( - dict_vehicle) -# accumulate the number of trips per age and vehicle choice -bd_persons_age_vehicle_choice = bd_persons_age_vehicle_choice.groupby( - ['age', 'vehicleChoice']).size().reset_index( - name='counts').sort_values( - by=['age'], - ascending=True, ignore_index=True) -# assign each age to an age cohort -bd_persons_age_vehicle_choice['ageCohort'] = pd.cut(bd_persons_age_vehicle_choice['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ - '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -# plot a cake chart for each age cohort -bd_persons_age_vehicle_choice_cake = bd_persons_age_vehicle_choice.groupby( - ['ageCohort', 'vehicleChoice']).sum().reset_index() -bd_persons_age_vehicle_choice_cake_age_veh = bd_persons_age_vehicle_choice_cake.pivot( - index='ageCohort', columns='vehicleChoice', values='counts') -bd_persons_age_vehicle_choice_cake_age_veh.plot.pie(subplots=True, layout=(3, 2), figsize=( - 10, 10), title=bd_persons_age_vehicle_choice_cake_age_veh.columns.to_list(), legend=False, ylabel='') -plt.savefig(os.path.join(figs_path, 'vehicle_choice_per_age.png'), dpi=300) - -# switch age cohort and vehicle choice -bd_persons_age_vehicle_choice_cake_veh_age = bd_persons_age_vehicle_choice_cake.pivot( - index='vehicleChoice', columns='ageCohort', values='counts') -bd_persons_age_vehicle_choice_cake_veh_age.plot.pie(subplots=True, layout=(3, 3), figsize=( - 20, 10), title=bd_persons_age_vehicle_choice_cake_veh_age.columns.to_list(), legend=False, ylabel='') -plt.savefig(os.path.join(figs_path, 'vehicle_choice_reversed.png'), dpi=300) - -# Analyse trip purposes per age cohort -bd_persons_age_purpose = bd.loc[:, ['personID', 'age', 'ActivityAfter']] -bd_persons_age_purpose['ActivityAfter'] = bd_persons_age_purpose['ActivityAfter'].map( - dict_leisure) -bd_persons_age_purpose['ageCohort'] = pd.cut(bd_persons_age_purpose['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ - '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -bd_persons_age_purpose_acc = bd_persons_age_purpose.groupby( - ['ActivityAfter', 'ageCohort']).size().reset_index(name='counts') -bd_persons_age_purpose_cake = bd_persons_age_purpose_acc.pivot( - index='ageCohort', columns='ActivityAfter', values='counts') -bd_persons_age_purpose_cake.plot.pie(subplots=True, layout=(2, 4), figsize=( - 15, 5), title=bd_persons_age_purpose_cake.columns.to_list(), legend=False, ylabel='') -plt.savefig(os.path.join(figs_path, 'trip_purpose.png'), dpi=300) - -# switch age cohorts and purpose -bd_persons_age_purpose_cake_reversed = bd_persons_age_purpose_acc.pivot( - index='ActivityAfter', columns='ageCohort', values='counts') -bd_persons_age_purpose_cake_reversed.plot.pie(subplots=True, layout=(2, 5), figsize=( - 15, 5), title=bd_persons_age_purpose_cake_reversed.columns.to_list(), legend=False, ylabel='') -plt.savefig(os.path.join(figs_path, 'trip_purpose_reversed.png'), dpi=300) - -# Count traffic zones where people are starting their trips -bd_traffic_zones_start = bd.groupby(['startZone']).size().reset_index( - name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -for row in bd_traffic_zones_start.iterrows(): - bd_traffic_zones_start.loc[row[0], ['longitude', 'latitude'] - ] = bd.loc[bd_traffic_zones_start.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] -print(bd_traffic_zones_start) - -# plot longitude and latitude of traffic zones -bd_traffic_zones_start.plot( - kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_start['counts'] / 100, figsize=(10, 15), - title='Traffic zones where people are starting their trips (Braunschweig)') -plt.savefig(os.path.join(figs_path, 'traffic_zones_start.png'), dpi=300) - -# Count traffic zones where people are going and leaving -bd_traffic_zones_end = bd.groupby(['destZone']).size().reset_index( - name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -for row in bd_traffic_zones_end.iterrows(): - bd_traffic_zones_end.loc[row[0], ['longitude', 'latitude'] - ] = bd.loc[bd_traffic_zones_end.loc[row[0], 'destZone'] == bd['destZone'], ['loCs', 'laCs']].values[0] -print(bd_traffic_zones_end) - -# plot longitude and latitude of traffic zones -bd_traffic_zones_end.plot( - kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_end['counts'] / 100, figsize=(10, 10), - title='Traffic zones where people are ending their trips (Braunschweig)') -plt.savefig(os.path.join(figs_path, 'traffic_zones_end.png'), dpi=300) - -# Time analyzing -# Time of day -bd_time = bd.groupby(['startTime']).size().reset_index(name='counts') -print(bd_time) -bd_time.plot(kind='line', x='startTime', y='counts') -plt.xlabel('Time of day') -plt.ylabel('Number of trips') -plt.title('Time of day (Braunschweig)' + ' (n = ' + str(len(bd)) + ' trips)') -plt.savefig(os.path.join(figs_path, 'time_of_day.png'), dpi=300) - -# time of day rolling average -bd_time['rolling_mean'] = bd_time['counts'].rolling(window=7).mean() -bd_time.plot(kind='line', x='startTime', y='rolling_mean') -plt.xlabel('Time of day') -plt.ylabel('Number of trips') -plt.title('Time of day (Braunschweig)' + ' (n = ' + - str(len(bd)) + ' trips), rolling mean with window size 7') -plt.savefig(os.path.join(figs_path, 'time_of_day_rolling.png'), dpi=300) - -# Frequency matrix of trips between traffic zones -matrix_freq = pd.crosstab(bd['startZone'], bd['destZone']) -nnz_matrix_freq = np.count_nonzero(matrix_freq) -subset_matrix_freq = matrix_freq.iloc[0:30, 0:30] -nnz_sub_matrix_freq = np.count_nonzero(subset_matrix_freq) -sns.heatmap(subset_matrix_freq, cmap="Blues", vmin=0) -plt.xlabel('Destination traffic zone') -plt.ylabel('Start traffic zone') -plt.title('Number of non-zero entries in frequency matrix: ' + str(nnz_sub_matrix_freq) + ' out of ' + str(subset_matrix_freq.size) + ' entries (' + - str(round(nnz_sub_matrix_freq / subset_matrix_freq.size * 100, 2)) + '%)') -plt.savefig(os.path.join(figs_path, 'heatmap.png'), dpi=300) - -# frequency matrix of trips from which leisure activity to which leisure activity - -# check if all activities of bd activity before are in the dictionary -if bd['ActivityBefore'].isin(dict_leisure.keys()).all(): - print('All activities in dictionary') -# check if there is a activity missing that is in the dictionary -if not set(dict_leisure.keys()).issubset(set(bd['ActivityBefore'].unique())): - print('There is an activity missing that is in the dictionary:') - for key in (set(dict_leisure.keys()).difference(set(bd['ActivityBefore'].unique()))): - print(key, dict_leisure[key]) - - -matrix_frqu_leisure = pd.crosstab( - bd['ActivityBefore'], - bd['ActivityAfter'], - normalize='index') -sns.heatmap(matrix_frqu_leisure, vmin=0, xticklabels=dict_leisure.values(), - yticklabels=dict_leisure.values()) -plt.xlabel('Leisure activity after trip') -plt.ylabel('Leisure activity before trip') -plt.title('Frequency of trips from which leisure activity to which leisure activity') -plt.savefig(os.path.join(figs_path, 'heatmap_leisure.png'), dpi=300) - - -# quick check if a data point in the matrix is correct -check = bd.loc[(bd['startZone'] == 31010011) & ( - bd['destZone'] == 31010011), 'startZone'].count() - - -# plotting the duration of trips -fig, axs = plt.subplots(2) -axs[0].hist(bd['travelTime']/60/60, bins=100, - range=(0, max(bd['travelTime'])*1.2/60/60)) -axs[0].set_title('Trip duration (Braunschweig)' + - ' (n = ' + str(len(bd)) + ' trips)') -axs[0].set_xlabel('Trip duration in hours') -axs[0].set_ylabel('Number of trips') -axs[1].hist(bd['travelTime']/60/60, bins=100, - range=(0, max(bd['travelTime'])*1.2/60/60)) -axs[1].set_yscale('log') -axs[1].set_title('Trip duration (Braunschweig)' + - ' (n = ' + str(len(bd)) + ' trips) log scale') -axs[1].set_xlabel('Trip duration in hours') -axs[1].set_ylabel('Number of trips') - -# same thing with the distance of the trips -fig2, axs2 = plt.subplots(2) -axs2[0].hist(bd['tripDistance'], bins=100, - range=(0, max(bd['tripDistance'])*1.2,)) -axs2[0].set_title('Trip distance (Braunschweig)' + - ' (n = ' + str(len(bd)) + ' trips)') -axs2[0].set_xlabel('Trip distance in Kilometers') -axs2[0].set_ylabel('Number of trips') -axs2[1].hist(bd['tripDistance'], bins=100, - range=(0, max(bd['tripDistance'])*1.2,)) -axs2[1].set_yscale('log') -axs2[1].set_title('Trip distance (Braunschweig)' + - ' (n = ' + str(len(bd)) + ' trips) log scale') -axs2[1].set_xlabel('Trip distance in Kilometers') -axs2[1].set_ylabel('Number of trips') - - -# analyze age distribution with age cohorts -bd_persons_id_and_age = bd[['personID', 'age']].drop_duplicates() -bd_age_cohorts = pd.cut( - bd_persons_id_and_age['age'], - bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95, 106], - labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95', '96-105']).reset_index( - name='age_cohort').groupby( - ['age_cohort']).size().reset_index( - name='counts') -bd_age_cohorts.plot(kind='bar', x='age_cohort', y='counts') -plt.xlabel('Age cohort') -plt.ylabel('Number of persons') -plt.title('Age distribution of persons in Braunschweig in age cohorts, number ') -plt.savefig(os.path.join(figs_path, 'age_cohorts.png'), dpi=300) - -# relation between age and trip duration in minutes and hours -bd_age_duration = bd.groupby(['age']).mean().reset_index() -bd_age_duration['travelTime'] = bd_age_duration['travelTime'] / 60 -bd_age_duration.plot(kind='bar', x='age', y='travelTime') - -# also do this for trip distance -bd_age_distance = bd.groupby(['age']).mean().reset_index() -bd_age_distance.plot(kind='bar', x='age', y='tripDistance') - -# analyze trip distance in distance cohort -bd_trip_distance_cohorts = pd.cut( - bd['tripDistance'], - bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], - labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( - name='trip_distance_cohort').groupby( - ['trip_distance_cohort']).size().reset_index( - name='counts') -bd_trip_distance_cohorts.plot(kind='bar', x='trip_distance_cohort', y='counts') -plt.xlabel('Trip distance cohort in km') -plt.ylabel('Number of trips') -plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + str(len(bd))) -plt.savefig(os.path.join(figs_path, 'trip_distance_cohorts.png'), dpi=300) - -# pie diagram of trip distance cohorts for each age cohort -bd_trip_distance_cohorts_vehicle = pd.cut( - bd['tripDistance'], - bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], - labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( - name='trip_distance_cohort') -bd_age_cohorts = pd.cut(bd['age'], - bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95], - labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95']).reset_index( - name='age_cohort') -# attach the age cohort to the dataframe -bd_trip_distance_cohorts_vehicle = pd.concat( - [bd_trip_distance_cohorts_vehicle['trip_distance_cohort'], bd_age_cohorts['age_cohort']], axis=1) -# group by age cohort and distance cohort -bd_trip_distance_cohorts_vehicle = bd_trip_distance_cohorts_vehicle.groupby( - ['trip_distance_cohort', 'age_cohort']).size().reset_index(name='counts') -# plot a pie chart for each age cohort -for age_cohort in bd_trip_distance_cohorts_vehicle['age_cohort'].unique(): - bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort].plot( - kind='pie', y='counts', labels=bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort]['trip_distance_cohort'], autopct='%1.1f%%', startangle=90) - plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + - str(len(bd)) + ' for age cohort ' + age_cohort) - plt.savefig(os.path.join( - figs_path, 'trip_distance_cohorts_' + age_cohort + '.png'), dpi=300) - -# now the same for trip duration vs vehicle type -bd_trip_duration_cohorts_vehicle = pd.cut( - bd['travelTime'], - bins=[-1, 500, 1000, 5000, 10000, 423789798324], - labels=['0-500', '500-1000', '1000-5000', '5000-10000', '10000+']).reset_index( - name='trip_duration_cohort') -bd_vehicle_type = bd['vehicleChoice'].reset_index(name='vehicleChoice') -# attach the age cohort to the dataframe -bd_trip_duration_cohorts_vehicle = pd.concat( - [bd_trip_duration_cohorts_vehicle['trip_duration_cohort'], bd_vehicle_type['vehicleChoice']], axis=1) -# group by age cohort and distance cohort -bd_trip_duration_cohorts_vehicle = bd_trip_duration_cohorts_vehicle.groupby( - ['trip_duration_cohort', 'vehicleChoice']).size().reset_index(name='counts') -# plot a pie chart for each age cohort -for vehicle_type in bd_trip_duration_cohorts_vehicle['vehicleChoice'].unique(): - bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type].plot( - kind='pie', y='counts', labels=bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type]['trip_duration_cohort'], autopct='%1.1f%%', startangle=90) - plt.title('Trip duration distribution in Braunschweig in trip duration cohorts, in minutes. Number of trips: ' + str(len(bd) - ) + ' for vehicle type ' + str(dict_vehicle[vehicle_type])) - plt.savefig(os.path.join(figs_path, 'trip_duration_cohorts_' + - str(dict_vehicle[vehicle_type]) + '.png'), dpi=300) - - -# also do a scatter plot of trip duration and trip distance with a regression line -bd_age_distance.plot(kind='scatter', x='age', y='tripDistance') -plt.plot(np.unique(bd_age_distance['age']), np.poly1d(np.polyfit(bd_age_distance['age'], - bd_age_distance['tripDistance'], 1))(np.unique(bd_age_distance['age']))) -bd_age_duration.plot(kind='scatter', x='age', y='travelTime') -plt.plot(np.unique(bd_age_duration['age']), np.poly1d(np.polyfit( - bd_age_duration['age'], bd_age_duration['travelTime'], 1))(np.unique(bd_age_duration['age']))) -plt.show() - -### draft to compute number of locations of type 6? -x = bd[bd.ActivityAfter==6].loc[:, 'loc_id_end'].nunique() -# downscaling of locations of type 6 to 2000 agents -x / (bd['personID'].nunique()/2000) - -x = 42 - -### draft to add collumn to check if the location in Braunschweig -#bd['home_in_bs'] = 0 -#for index, row in bd.iterrows(): -# if ((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): -# bd.at[index,'home_in_bs'] = 1 -#bd.to_csv('modified_braunschweig_result.csv', index=False) \ No newline at end of file +# for row in bd_traffic_zones_end.iterrows(): +# bd_traffic_zones_end.loc[row[0], ['longitude', 'latitude'] +# ] = bd.loc[bd_traffic_zones_end.loc[row[0], 'destZone'] == bd['destZone'], ['loCs', 'laCs']].values[0] +# print(bd_traffic_zones_end) + +# # plot longitude and latitude of traffic zones +# bd_traffic_zones_end.plot( +# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_end['counts'] / 100, figsize=(10, 10), +# title='Traffic zones where people are ending their trips (Braunschweig)') +# plt.savefig(os.path.join(figs_path, 'traffic_zones_end.png'), dpi=300) + +# # Time analyzing +# # Time of day +# bd_time = bd.groupby(['startTime']).size().reset_index(name='counts') +# print(bd_time) +# bd_time.plot(kind='line', x='startTime', y='counts') +# plt.xlabel('Time of day') +# plt.ylabel('Number of trips') +# plt.title('Time of day (Braunschweig)' + ' (n = ' + str(len(bd)) + ' trips)') +# plt.savefig(os.path.join(figs_path, 'time_of_day.png'), dpi=300) + +# # time of day rolling average +# bd_time['rolling_mean'] = bd_time['counts'].rolling(window=7).mean() +# bd_time.plot(kind='line', x='startTime', y='rolling_mean') +# plt.xlabel('Time of day') +# plt.ylabel('Number of trips') +# plt.title('Time of day (Braunschweig)' + ' (n = ' + +# str(len(bd)) + ' trips), rolling mean with window size 7') +# plt.savefig(os.path.join(figs_path, 'time_of_day_rolling.png'), dpi=300) + +# # Frequency matrix of trips between traffic zones +# matrix_freq = pd.crosstab(bd['startZone'], bd['destZone']) +# nnz_matrix_freq = np.count_nonzero(matrix_freq) +# subset_matrix_freq = matrix_freq.iloc[0:30, 0:30] +# nnz_sub_matrix_freq = np.count_nonzero(subset_matrix_freq) +# sns.heatmap(subset_matrix_freq, cmap="Blues", vmin=0) +# plt.xlabel('Destination traffic zone') +# plt.ylabel('Start traffic zone') +# plt.title('Number of non-zero entries in frequency matrix: ' + str(nnz_sub_matrix_freq) + ' out of ' + str(subset_matrix_freq.size) + ' entries (' + +# str(round(nnz_sub_matrix_freq / subset_matrix_freq.size * 100, 2)) + '%)') +# plt.savefig(os.path.join(figs_path, 'heatmap.png'), dpi=300) + +# # frequency matrix of trips from which leisure activity to which leisure activity + +# # check if all activities of bd activity before are in the dictionary +# if bd['ActivityBefore'].isin(dict_leisure.keys()).all(): +# print('All activities in dictionary') +# # check if there is a activity missing that is in the dictionary +# if not set(dict_leisure.keys()).issubset(set(bd['ActivityBefore'].unique())): +# print('There is an activity missing that is in the dictionary:') +# for key in (set(dict_leisure.keys()).difference(set(bd['ActivityBefore'].unique()))): +# print(key, dict_leisure[key]) + + +# matrix_frqu_leisure = pd.crosstab( +# bd['ActivityBefore'], +# bd['ActivityAfter'], +# normalize='index') +# sns.heatmap(matrix_frqu_leisure, vmin=0, xticklabels=dict_leisure.values(), +# yticklabels=dict_leisure.values()) +# plt.xlabel('Leisure activity after trip') +# plt.ylabel('Leisure activity before trip') +# plt.title('Frequency of trips from which leisure activity to which leisure activity') +# plt.savefig(os.path.join(figs_path, 'heatmap_leisure.png'), dpi=300) + + +# # quick check if a data point in the matrix is correct +# check = bd.loc[(bd['startZone'] == 31010011) & ( +# bd['destZone'] == 31010011), 'startZone'].count() + + +# # plotting the duration of trips +# fig, axs = plt.subplots(2) +# axs[0].hist(bd['travelTime']/60/60, bins=100, +# range=(0, max(bd['travelTime'])*1.2/60/60)) +# axs[0].set_title('Trip duration (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips)') +# axs[0].set_xlabel('Trip duration in hours') +# axs[0].set_ylabel('Number of trips') +# axs[1].hist(bd['travelTime']/60/60, bins=100, +# range=(0, max(bd['travelTime'])*1.2/60/60)) +# axs[1].set_yscale('log') +# axs[1].set_title('Trip duration (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips) log scale') +# axs[1].set_xlabel('Trip duration in hours') +# axs[1].set_ylabel('Number of trips') + +# # same thing with the distance of the trips +# fig2, axs2 = plt.subplots(2) +# axs2[0].hist(bd['tripDistance'], bins=100, +# range=(0, max(bd['tripDistance'])*1.2,)) +# axs2[0].set_title('Trip distance (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips)') +# axs2[0].set_xlabel('Trip distance in Kilometers') +# axs2[0].set_ylabel('Number of trips') +# axs2[1].hist(bd['tripDistance'], bins=100, +# range=(0, max(bd['tripDistance'])*1.2,)) +# axs2[1].set_yscale('log') +# axs2[1].set_title('Trip distance (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips) log scale') +# axs2[1].set_xlabel('Trip distance in Kilometers') +# axs2[1].set_ylabel('Number of trips') + + +# # analyze age distribution with age cohorts +# bd_persons_id_and_age = bd[['personID', 'age']].drop_duplicates() +# bd_age_cohorts = pd.cut( +# bd_persons_id_and_age['age'], +# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95, 106], +# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95', '96-105']).reset_index( +# name='age_cohort').groupby( +# ['age_cohort']).size().reset_index( +# name='counts') +# bd_age_cohorts.plot(kind='bar', x='age_cohort', y='counts') +# plt.xlabel('Age cohort') +# plt.ylabel('Number of persons') +# plt.title('Age distribution of persons in Braunschweig in age cohorts, number ') +# plt.savefig(os.path.join(figs_path, 'age_cohorts.png'), dpi=300) + +# # relation between age and trip duration in minutes and hours +# bd_age_duration = bd.groupby(['age']).mean().reset_index() +# bd_age_duration['travelTime'] = bd_age_duration['travelTime'] / 60 +# bd_age_duration.plot(kind='bar', x='age', y='travelTime') + +# # also do this for trip distance +# bd_age_distance = bd.groupby(['age']).mean().reset_index() +# bd_age_distance.plot(kind='bar', x='age', y='tripDistance') + +# # analyze trip distance in distance cohort +# bd_trip_distance_cohorts = pd.cut( +# bd['tripDistance'], +# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], +# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( +# name='trip_distance_cohort').groupby( +# ['trip_distance_cohort']).size().reset_index( +# name='counts') +# bd_trip_distance_cohorts.plot(kind='bar', x='trip_distance_cohort', y='counts') +# plt.xlabel('Trip distance cohort in km') +# plt.ylabel('Number of trips') +# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + str(len(bd))) +# plt.savefig(os.path.join(figs_path, 'trip_distance_cohorts.png'), dpi=300) + +# # pie diagram of trip distance cohorts for each age cohort +# bd_trip_distance_cohorts_vehicle = pd.cut( +# bd['tripDistance'], +# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], +# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( +# name='trip_distance_cohort') +# bd_age_cohorts = pd.cut(bd['age'], +# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95], +# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95']).reset_index( +# name='age_cohort') +# # attach the age cohort to the dataframe +# bd_trip_distance_cohorts_vehicle = pd.concat( +# [bd_trip_distance_cohorts_vehicle['trip_distance_cohort'], bd_age_cohorts['age_cohort']], axis=1) +# # group by age cohort and distance cohort +# bd_trip_distance_cohorts_vehicle = bd_trip_distance_cohorts_vehicle.groupby( +# ['trip_distance_cohort', 'age_cohort']).size().reset_index(name='counts') +# # plot a pie chart for each age cohort +# for age_cohort in bd_trip_distance_cohorts_vehicle['age_cohort'].unique(): +# bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort].plot( +# kind='pie', y='counts', labels=bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort]['trip_distance_cohort'], autopct='%1.1f%%', startangle=90) +# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + +# str(len(bd)) + ' for age cohort ' + age_cohort) +# plt.savefig(os.path.join( +# figs_path, 'trip_distance_cohorts_' + age_cohort + '.png'), dpi=300) + +# # now the same for trip duration vs vehicle type +# bd_trip_duration_cohorts_vehicle = pd.cut( +# bd['travelTime'], +# bins=[-1, 500, 1000, 5000, 10000, 423789798324], +# labels=['0-500', '500-1000', '1000-5000', '5000-10000', '10000+']).reset_index( +# name='trip_duration_cohort') +# bd_vehicle_type = bd['vehicleChoice'].reset_index(name='vehicleChoice') +# # attach the age cohort to the dataframe +# bd_trip_duration_cohorts_vehicle = pd.concat( +# [bd_trip_duration_cohorts_vehicle['trip_duration_cohort'], bd_vehicle_type['vehicleChoice']], axis=1) +# # group by age cohort and distance cohort +# bd_trip_duration_cohorts_vehicle = bd_trip_duration_cohorts_vehicle.groupby( +# ['trip_duration_cohort', 'vehicleChoice']).size().reset_index(name='counts') +# # plot a pie chart for each age cohort +# for vehicle_type in bd_trip_duration_cohorts_vehicle['vehicleChoice'].unique(): +# bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type].plot( +# kind='pie', y='counts', labels=bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type]['trip_duration_cohort'], autopct='%1.1f%%', startangle=90) +# plt.title('Trip duration distribution in Braunschweig in trip duration cohorts, in minutes. Number of trips: ' + str(len(bd) +# ) + ' for vehicle type ' + str(dict_vehicle[vehicle_type])) +# plt.savefig(os.path.join(figs_path, 'trip_duration_cohorts_' + +# str(dict_vehicle[vehicle_type]) + '.png'), dpi=300) + + +# # also do a scatter plot of trip duration and trip distance with a regression line +# bd_age_distance.plot(kind='scatter', x='age', y='tripDistance') +# plt.plot(np.unique(bd_age_distance['age']), np.poly1d(np.polyfit(bd_age_distance['age'], +# bd_age_distance['tripDistance'], 1))(np.unique(bd_age_distance['age']))) +# bd_age_duration.plot(kind='scatter', x='age', y='travelTime') +# plt.plot(np.unique(bd_age_duration['age']), np.poly1d(np.polyfit( +# bd_age_duration['age'], bd_age_duration['travelTime'], 1))(np.unique(bd_age_duration['age']))) +# plt.show() + +# ### draft to compute number of locations of type 6? +# x = bd[bd.ActivityAfter==6].loc[:, 'loc_id_end'].nunique() +# # downscaling of locations of type 6 to 2000 agents +# x / (bd['personID'].nunique()/2000) + +# x = 42 + + + + +## draft to add collumn to check if the location in Braunschweig +bd['home_in_bs'] = 0 +#list of persons who are in braunschweig +list_person_in_bs = np.array([]) +for index, row in bd.iterrows(): + if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): + list_person_in_bs = np.append(list_person_in_bs, row['personID']) + # bd.loc[bd['personID']==row['personID'],'home_in_bs'] = 1 +#drop duplicates +list_person_in_bs = np.unique(list_person_in_bs) +for index, row in bd.iterrows(): + if row['personID'] in list_person_in_bs: + bd.at[index, 'home_in_bs'] = 1 + + +bd.to_csv('modified_braunschweig_result.csv', index=False) + +#count number of trips which are in braunschweig +# bs_trip_count = 0 +# for index, row in bd.iterrows(): +# if ((row['countyStart']==3101) or (row['countyEnd']==3101 )): +# bs_trip_count = bs_trip_count+1 + +# #percentage of trips in braunschweigx +# bs_trip_count/len(bd)*100 + +# count how many persons are in braunschweig +bs_person_count = 0 +# collapse all persons to one trip and check if the trip is in braunschweig +persons_in_bs = bd[['personID', 'home_in_bs']].drop_duplicates().groupby(['personID']).aggregate('sum').reset_index() +# percentage number of persons in braunschweig is persons with not zero home_in_bs / all persons +persons_in_bs.loc[persons_in_bs['home_in_bs']==0].size/persons_in_bs.size*100 + + + +x=1 From c1308d8ea91a8de7d2d16b3b9c2e8b0c0ad98c10 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Feb 2024 14:46:13 +0100 Subject: [PATCH 036/488] number 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- pycode/memilio-epidata/memilio/epidata/check_bs_data.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py index 44a3f87960..8dbcf183b5 100644 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py @@ -517,7 +517,6 @@ for index, row in bd.iterrows(): if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): list_person_in_bs = np.append(list_person_in_bs, row['personID']) - # bd.loc[bd['personID']==row['personID'],'home_in_bs'] = 1 #drop duplicates list_person_in_bs = np.unique(list_person_in_bs) for index, row in bd.iterrows(): From cf62c5f705896db31cad0749c9348c3c7f0c2bdb Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:16:17 +0100 Subject: [PATCH 037/488] Finish infection state initialization. Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/models/abm/infection.h | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 81 +++++++++++------------- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/cpp/models/abm/infection.h b/cpp/models/abm/infection.h index 0e2cc2ce40..6133da13a3 100644 --- a/cpp/models/abm/infection.h +++ b/cpp/models/abm/infection.h @@ -63,7 +63,7 @@ class Infection * @param[in] detected [Default: false] If the Infection is detected. */ Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, AgeGroup age, const Parameters& params, - TimePoint start_date, InfectionState start_state = InfectionState::Exposed, + TimePoint init_date, InfectionState init_state = InfectionState::Exposed, std::pair latest_exposure = {ExposureType::NoProtection, TimePoint(0)}, bool detected = false); diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ad36593b04..1d18fdce26 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -42,55 +42,49 @@ const auto age_group_35_to_59 = mio::AgeGroup(3); const auto age_group_60_to_79 = mio::AgeGroup(4); const auto age_group_80_plus = mio::AgeGroup(5); -/** - * Determine the infection state of a person at the beginning of the simulation. - * The infection states are chosen randomly. They are distributed according to the probabilites set in the example. - * @return random infection state - */ -mio::abm::InfectionState determine_infection_state(mio::abm::Person::RandomNumberGenerator& rng, ScalarType exposed, - ScalarType infected_no_symptoms, ScalarType infected_symptoms, - ScalarType recovered) -{ - ScalarType susceptible = 1 - exposed - infected_no_symptoms - infected_symptoms - recovered; - std::vector weights = { - susceptible, exposed, infected_no_symptoms, infected_symptoms / 3, infected_symptoms / 3, - infected_symptoms / 3, recovered}; - if (weights.size() != (size_t)mio::abm::InfectionState::Count - 1) { - mio::log_error("Initialization in ABM wrong, please correct vector length."); - } - auto state = mio::DiscreteDistribution::get_instance()(rng, weights); - return (mio::abm::InfectionState)state; -} +const std::map infection_state_map{ + {mio::osecir::InfectionState::Susceptible, mio::abm::InfectionState::Susceptible}, + {mio::osecir::InfectionState::Exposed, mio::abm::InfectionState::Exposed}, + {mio::osecir::InfectionState::InfectedNoSymptoms, mio::abm::InfectionState::InfectedNoSymptoms}, + {mio::osecir::InfectionState::InfectedNoSymptomsConfirmed, mio::abm::InfectionState::InfectedNoSymptoms}, + {mio::osecir::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedSymptoms}, + {mio::osecir::InfectionState::InfectedSymptomsConfirmed, mio::abm::InfectionState::InfectedSymptoms}, + {mio::osecir::InfectionState::InfectedSevere, mio::abm::InfectionState::InfectedSevere}, + {mio::osecir::InfectionState::InfectedCritical, mio::abm::InfectionState::InfectedCritical}, + {mio::osecir::InfectionState::Recovered, mio::abm::InfectionState::Recovered}, + {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; /** - * Assign an infection state to each person. + * Assign an infection state to each person according to real world data read in through the ODE secir model. */ -void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t, double exposed_prob, - double infected_no_symptoms_prob, double infected_symptoms_prob, double recovered_prob) -{ - auto persons = world.get_persons(); - for (auto& person : persons) { - auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); - auto infection_state = determine_infection_state(rng, exposed_prob, infected_no_symptoms_prob, - infected_symptoms_prob, recovered_prob); - if (infection_state != mio::abm::InfectionState::Susceptible) - person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), - world.parameters, t, infection_state)); - } -} - -void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint /*t*/) +void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) { // estimate intial population by ODE compartiments auto initial_graph = get_graph(mio::Date(2020, 03, 01), 1, "/Users/david/Documents/HZI/memilio/data/"); - size_t braunschweig_id = 0; // TODO: Find correct ID for Braunschweig + size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; + mio::CustomIndexArray initial_values{ + {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.}; + initial_values.array() = braunschweig_node.populations.array().cast(); + std::cout << initial_values.array() << std::endl; + + //Eigen::Array iv_slice = initial_values.slice(age_group_0_to_4).as_array().array(); - // TODO: Collect number of infected agents and assign randomly to the population - - // convert initial population to ABM initial infection probabilities + // convert initial population to ABM initial infections for (auto& person : world.get_persons()) { - if (person.get_age() == age_group_0_to_4) { + auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); + + auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( + rng, initial_values.slice(person.get_age()).as_array().array())); + + //bool detected = false; + if (infection_state != mio::osecir::InfectionState::Susceptible) { + //if (infection_state == mio::osecir::InfectionState::InfectedNoSymptomsConfirmed || + // infection_state == mio::osecir::InfectionState::InfectedSymptomsConfirmed) { + // detected = true; + //} + person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), + world.parameters, t, infection_state_map.at(infection_state))); } } } @@ -836,12 +830,12 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di bool save_single_runs = true) { auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation auto ensemble_results = std::vector>>{}; // Vector of collected results ensemble_results.reserve(size_t(num_runs)); auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 5000; + auto max_num_persons = 500; int tid = -1; #pragma omp parallel private(tid) // Start of parallel region: forks threads @@ -897,8 +891,7 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_file = - "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/bs_und_umgebung.csv"; + std::string input_file = "/Users/david/Documents/HZI/memilio/data/mobility/braunschweig_result.csv"; size_t num_runs; bool save_single_runs = true; From 92bfa493d124808d97df86729fd67b4cb27c536c Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 28 Feb 2024 16:19:00 +0100 Subject: [PATCH 038/488] remove cout Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1d18fdce26..214f59036a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -66,9 +66,7 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) mio::CustomIndexArray initial_values{ {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.}; initial_values.array() = braunschweig_node.populations.array().cast(); - std::cout << initial_values.array() << std::endl; - - //Eigen::Array iv_slice = initial_values.slice(age_group_0_to_4).as_array().array(); + //std::cout << initial_values.array() << std::endl; // convert initial population to ABM initial infections for (auto& person : world.get_persons()) { From d3b6bfc3bfcaa34bf88ff835d7dd26b4054fa23a Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 28 Feb 2024 17:31:39 +0100 Subject: [PATCH 039/488] Change input_dir to be adaptable faster. Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 214f59036a..5fd7d4fdb0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -57,10 +57,10 @@ const std::map infection_ /** * Assign an infection state to each person according to real world data read in through the ODE secir model. */ -void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) +void assign_infection_state(mio::abm::World& world, const fs::path& input_dir, mio::abm::TimePoint t) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(mio::Date(2020, 03, 01), 1, "/Users/david/Documents/HZI/memilio/data/"); + auto initial_graph = get_graph(mio::Date(2020, 03, 01), 1, input_dir); size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; mio::CustomIndexArray initial_values{ @@ -692,7 +692,7 @@ void set_local_parameters(mio::abm::World& world) * Create a sampled simulation with start time t0. * @param t0 The start time of the Simulation. */ -mio::abm::Simulation create_sampled_simulation(const std::string& input_file, const mio::abm::TimePoint& t0, +mio::abm::Simulation create_sampled_simulation(const fs::path& input_dir, const mio::abm::TimePoint& t0, int max_num_persons) { //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -702,11 +702,12 @@ mio::abm::Simulation create_sampled_simulation(const std::string& input_file, co set_local_parameters(world); // Create the world object from statistical data. - create_world_from_data(world, input_file, t0, max_num_persons); + create_world_from_data(world, (input_dir / "mobility/braunschweig_result.csv").generic_string(), t0, + max_num_persons); world.use_migration_rules(false); // Assign an infection state to each person. - assign_infection_state(world, t0); + assign_infection_state(world, input_dir, t0); auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); @@ -824,7 +825,7 @@ void write_txt_file_for_graphical_compartment_output(std::vector run(const std::string& input_file, const fs::path& result_dir, size_t num_runs, +mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { auto t0 = mio::abm::TimePoint(0); // Start time per simulation @@ -849,7 +850,7 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di while (run_idx <= num_runs) { // Create the sampled simulation with start time t0. - auto sim = create_sampled_simulation(input_file, t0, max_num_persons); + auto sim = create_sampled_simulation(input_dir, t0, max_num_persons); //output object mio::History @@ -889,7 +890,7 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_file = "/Users/david/Documents/HZI/memilio/data/mobility/braunschweig_result.csv"; + std::string input_dir = "/Users/david/Documents/HZI/memilio/data/"; size_t num_runs; bool save_single_runs = true; @@ -924,7 +925,7 @@ int main(int argc, char** argv) //} //printf("\n"); - auto result = run(input_file, result_dir, num_runs, save_single_runs); + auto result = run(input_dir, result_dir, num_runs, save_single_runs); if (!result) { printf("%s\n", result.error().formatted_message().c_str()); return -1; From 1e077e15101277ed494cd1bbe5923442e109229e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 29 Feb 2024 17:41:27 +0100 Subject: [PATCH 040/488] push age and infection state save Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/abm.h | 1 + cpp/models/abm/location.cpp | 8 + cpp/models/abm/location.h | 9 + cpp/simulations/abm_braunschweig.cpp | 6 +- cpp/simulations/analyze_bs_run.py | 128 ++++++ cpp/simulations/check_bs_data.py | 547 +++++++++++++++++++++++ cpp/simulations/paper_abm_bs_testing.cpp | 83 +++- 7 files changed, 770 insertions(+), 12 deletions(-) create mode 100644 cpp/simulations/analyze_bs_run.py create mode 100644 cpp/simulations/check_bs_data.py diff --git a/cpp/models/abm/abm.h b/cpp/models/abm/abm.h index aa24659a1f..7094d6cd30 100644 --- a/cpp/models/abm/abm.h +++ b/cpp/models/abm/abm.h @@ -38,5 +38,6 @@ #include "abm/vaccine.h" #include "abm/household.h" #include "abm/lockdown_rules.h" +#include "abm/analyze_result.h" #endif diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 7ff78c8250..e806e1c138 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -217,5 +217,13 @@ size_t Location::get_subpopulation(TimePoint t, InfectionState state) const }); } +size_t Location::get_subpopulation_per_age_group(TimePoint t, InfectionState state, AgeGroup age_group) const +{ + mio::unused(age_group); + return count_if(m_persons.begin(), m_persons.end(), [&](observer_ptr p) { + return p->get_infection_state(t) == state && p->is_home_in_bs() && p->get_age() == age_group; + }); +} + } // namespace abm } // namespace mio diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index 04bf941f73..df633218fc 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -383,6 +383,15 @@ class Location */ size_t get_subpopulation(TimePoint t, InfectionState state) const; + /** + * @brief Get the number of Person%s of a particular #InfectionState for all Cell%s. + * @param[in] t TimePoint of querry. + * @param[in] state #InfectionState of interest. + * @param[in] age_group AgeGroup of interest. + * @return Amount of Person%s of the #InfectionState in all Cell%s. + */ + size_t get_subpopulation_per_age_group(TimePoint t, InfectionState state, AgeGroup age_group) const; + /** * @brief Get the geographical location of the Location. * @return The geographical location of the Location. diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index 87dbaee8a3..60b04d21ee 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -1118,11 +1118,11 @@ mio::IOResult run(const std::string& input_file, const fs::path& result_di historyInfectionPerAgeGroup, historyPersonInfDelta); // TODO: update result of the simulation to be a vector of location result. auto temp_sim_result_infection_per_type = - std::vector>{std::get<0>(historyTimeSeries.get_log())}; + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; auto temp_sim_result_infection_per_loc = - std::vector>{std::get<0>(historyTimeSeries.get_log())}; + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; auto temp_sim_result_infection_per_age = - std::vector>{std::get<0>(historyTimeSeries.get_log())}; + std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; // Push result of the simulation back to the result vector ensemble_results_infections_per_type.push_back(temp_sim_result_infection_per_type); ensemble_results_infections_per_loc.push_back(temp_sim_result_infection_per_loc); diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py new file mode 100644 index 0000000000..a9d9621655 --- /dev/null +++ b/cpp/simulations/analyze_bs_run.py @@ -0,0 +1,128 @@ +# Python script to analyze bs runs +# input is a bs run folder with the following structure: +# bs_run_folder has a txt file for each bs run +# each txt file has a line for each time step +# each line has a column for each compartment as well as the timestep +# each column has the number of individuals in that compartment +# the first line of each txt file is the header + +import sys +import argparse +import os +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import matplotlib +import matplotlib.colors as colors +import matplotlib.cm as cmx +import matplotlib.patches as mpatches +import matplotlib.lines as mlines +import h5py + +def main(n_runs): + # read in folder and convert txt files to numpy arrays + # folder path + folder_path = "memilio/epidata/folder_run_bs" + + # get first_file in folder + first_file = os.listdir(folder_path)[0] + file_path = os.path.join(folder_path, first_file) + # read in txt file + df = pd.read_csv(file_path, delim_whitespace=True) + # convert to numpy array + df_np = df.to_numpy() + # get the number of rows and columns + num_rows = df_np.shape[0] + num_cols = df_np.shape[1] + # get the number of compartments + num_compartments = num_cols - 1 + # get the number of time steps + num_time_steps = num_rows-1 + # get the compartment names + compartment_names = df.columns[1:] + # get the time steps + time_steps = df_np[:, 0] + + # get number of files in folder + num_files = len([entry for entry in os.listdir(folder_path)]) + # read in each txt file and convert to numpy array + df_np_3d = np.empty((num_rows, num_cols, n_runs)) + for (file, i) in zip(os.listdir(folder_path), range(n_runs)): + file_path = os.path.join(folder_path, file) + # read in txt file + df = pd.read_csv(file_path, delim_whitespace=True) + if file.startswith("infection_per_location_type"): + plot_infection_per_location_type(df) + if file.startswith("infection_per_age_group"): + plot_infection_per_age_group(df) + if file.startswith("run_"): + # convert to numpy array + df_np = df.to_numpy() + # attach to array + df_np_3d[:, :, i] = df_np + plot_mean_and_std(df_np_3d) + + +def plot_infection_per_location_type(df): + df.plot(x='Time', y=['Home', 'Work', 'School', 'SocialEvent', 'BasicsShop', 'Hospital', + 'ICU', 'Car', 'PublicTransport', 'TransportWithoutContact', 'Cemetery'], figsize=(10, 6)) + plt.show() + + +def plot_infection_per_age_group(df): + df.plot(x='Time', y=['0_to_4', '5_to_14', '15_to_34', + '35_to_59', '60_to_79', '80_plus'], figsize=(10, 6)) + plt.show() + +def plot_results(path): + # df = pd.read_hdf(os.path.join(path, 'infection_course/p50/Results_sum.h5')) + f = h5py.File("/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/build/bin/infection_state_per_age_group/p50/Results.h5", 'r') + + # Get the HDF5 group; key needs to be a group name from above + group = f['0'] + + # This assumes group[some_key_inside_the_group] is a dataset, + # and returns a np.array: + # time = group['Time'][()] + total = group['Total'][()] + group1 = group['Group1'][()] + group2 = group['Group2'][()] + + comp_simulated = np.sum(total[:, comp], axis=1) + + # After you are done + f.close() + + return comp_simulated[:] + # print(df.head()) + +def plot_mean_and_std(Y): + + x_plot = Y[:, 0, 0] + compartments = Y[:,1:,1:] + # average value + compartments_avg = np.mean(compartments,axis=2) + #plot average + for i in range(compartments_avg.shape[1]): + plt.plot(x_plot,compartments_avg[:,i]) + + #plt.plot(x_plot,compartments_avg) + #legend + plt.legend(['S', 'E', 'I_NS', 'I_Sy', 'I_Sev', 'I_Crit', 'R', 'D']) + plt.show() + # standard deviation + # compartments_std = np.std(compartments,axis=2) + # plt.plot(x_plot,compartments_avg + compartments_std) + # plt.plot(x_plot,compartments_avg - compartments_std) + # plt.show() + + +if __name__ == "__main__": + if (len(sys.argv) > 1): + n_runs = sys.argv[1] + else: + folder_path = "build/bin" + n_runs = len([entry for entry in os.listdir(folder_path) + if os.path.isfile(os.path.join(folder_path, entry))]) + #main(n_runs) + plot_results('build/bin/') diff --git a/cpp/simulations/check_bs_data.py b/cpp/simulations/check_bs_data.py new file mode 100644 index 0000000000..8dbcf183b5 --- /dev/null +++ b/cpp/simulations/check_bs_data.py @@ -0,0 +1,547 @@ +import pandas as pd +import matplotlib +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import os + +import sys +if sys.version_info[0] == 3: + import tkinter as tk +else: + import Tkinter as tk + + +####### minimal sanity check on data ####### +bd = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/pycode/memilio-epidata/memilio/epidata/bs_und_umgebung.csv', header=None, skiprows=1) + +# setup dictionary for the leisure activities, and vehicle choice and column names +# bd.rename( +# columns={0: 'idTrafficZone', 1: 'tripID', 2: 'personID', 3: 'tripChain', 4: 'startZone', 5: 'destZone', 6: 'loc_id_start', 7: 'loc_id_end', +# 8: 'countyStart', 9: 'countyEnd', 10: 'hhID', 11: 'tripChainID', 12: 'tripDistance', 13: 'startTime', 14: 'travelTime', 19: 'vehicleChoice', 20: +# 'ActivityBefore', 21: 'ActivityAfter', 15: 'loCs', 16: 'laCs', 17: 'loCe', 18: 'laCe', 22: 'age'}, +# inplace=True) +bd.rename( + columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', + 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', 10: 'travelTime' , 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', 16: + 'ActivityBefore', 17: 'ActivityAfter', 18: 'age'}, + inplace=True) + +dict_leisure = {1: 'work', 2: 'education', 3: 'Shopping', 4: 'free time', + 5: 'private matters', 6: 'others', 7: 'home', 0: 'not specified'} +dict_vehicle = {1: 'bicyle', 2: 'car_driver', + 3: 'car_codriver', 4: 'public transport', 5: 'walk'} + +# # check if people do the same trip more than once +# trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] +# duplicate_trips = trips.duplicated() +# if (duplicate_trips.any()): +# print('Error: The Person does the "same" trip more than once (or dos 2 things in 5 mins). Number of duplicate trips: ' + str(duplicate_trips[duplicate_trips==True].size)) +# # if (~bd[['tripID']].duplicated().any()): +# # print('There are no duplicate TripIDs. There are multiple TripIDs for the same Trip. \n') +# activities_after_duplicate_trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime', 'ActivityAfter']].loc[trips.duplicated(keep=False)] +# if (~activities_after_duplicate_trips.duplicated(keep=False).all()): +# print('Error: Multiple activities after the same trip. \n') + +# # check if persons have more than one home +# person_homes = bd[['personID', 'loc_id_end', 'ActivityAfter']].loc[bd['ActivityAfter']==7] +# person_homes = person_homes.drop_duplicates().groupby(['personID']).size().reset_index(name='counts') +# person_homes.drop(person_homes.loc[person_homes['counts']<2].index, inplace=True) +# if(person_homes.size > 0): +# print('Error: There are people that have more than one home. \n') + +# # check if the proportion of single-person-households is too high +# households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) + +# # check if the proportion of single-person-households is too high +# if (households.loc[households['counts']==1]['counts'].size)/(households['counts'].size) > 0.5: +# print("Error: The proportion of single-person-households is too high: " + +# str((households.loc[households['counts']==1]['counts'].size)/(households['counts'].size))) + +# # check if there are invalid entries +# # if not bd['idTrafficZone'].ge(30000000).all(): +# # print('Error: There is an entry in "tripID" that is not assignable. \n') +# # # number of entries that are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripID'].ge(30000000)].size) + '. \n') +# if not bd['personID'].ge(100000000).all(): +# print('Error: There is an entry in "personID" that is not assignable. \n') +# # number of entries that are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['personID'].ge(100000000)].size) + '. \n') +# # if not bd['tripChain'].between(1, 100).all(): +# # print('Error: There is an entry in "tripChain" that is not assignable. \n') +# # # number of entries that are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripChain'].between(1, 100)].size) + '. \n') +# # # max assigned value +# # print('Max assigned value: ' + str(bd['tripChain'].max()) + '. \n') +# # if not bd['countyStart'].ge(30000000).all(): +# # print('Error: There is an entry in "countyStart" that is not assignable. \n') +# # # which ones are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyStart'].ge(30000000)].size) + '. \n') +# # if not bd['countyEnd'].ge(30000000).all(): +# # print('Error: There is an entry in "countyEnd" that is not assignable. \n') +# # # which ones are not assignable +# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyEnd'].ge(30000000)].size) + '. \n') +# # if not bd['hhID'].ge(100000000).all(): +# # print('Error: There is an entry in "hhID" that is not assignable. \n') +# # if not bd['tripChainID'].between(-1, -1).all(): +# # print('Error: There is an entry in "tripChainID" that is not assignable. \n') +# if not bd['vehicleChoice'].between(1, 5).all(): +# print('Error: There is an entry in "vehicleChoice" that is not assignable. \n') +# #print number of entries that are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['vehicleChoice'].between(1, 5)].size) + '. \n') +# if not bd['ActivityAfter'].between(0, 7).all(): +# print('Error: There is an entry in "ActivityAfter" that is not assignable. \n') +# #print number of entries that are not assignable +# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['ActivityAfter'].between(0, 7)].size) + '. \n') + +# # check if there are empty cells +# for header in bd.columns: +# if (bd[header].isna().any()): +# print('Error: ' + str(len(bd[bd[header].isna()])) + ' empty entries in column' + str(header) + '. \n') + +# # check age groups with schools +# number_of_people = bd[['personID']].drop_duplicates().size +# print(str(number_of_people) + ' are people. \n') + +# # number_of_trips = bd[['tripID']].drop_duplicates().size +# # print(str(number_of_trips) + ' trips. \n') + + +# students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] +# print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') +# print(str(students.loc[students['age'] > 20].size) + ' trips of ' + str(students.size) + ' trips going to school are in a higher age group than 10. \n') + +# children = bd[['personID','ActivityAfter']].loc[(bd['age']<=16) & (bd['age']>=7)] +# number_of_children = children['personID'].drop_duplicates().size +# number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size +# print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') + + +# workers = bd[['personID','ActivityAfter']].loc[(bd['age']>30)] +# number_of_workers = workers['personID'].drop_duplicates().size +# number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size +# print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' workers do not go to work. \n') + + + +# ############################################### + + +# ####### visual check on values in data frame ####### + +# # def get_trip_chain_activity_after(person_id): +# # bd_persons_trip_chain_activity_after = bd.loc[bd['personID'] == person_id, [ +# # 'tripChain', 'ActivityAfter']] +# # bd_persons_trip_chain_activity_after = bd_persons_trip_chain_activity_after.sort_values( +# # by=['tripChain'], ascending=True, ignore_index=True) +# # bd_persons_trip_chain_activity_after['ActivityAfter'] = bd_persons_trip_chain_activity_after['ActivityAfter'].map( +# # dict_leisure) +# # # and vehicle choice +# # bd_persons_trip_chain_vehicle_choice = bd.loc[bd['personID'] == person_id, [ +# # 'tripChain', 'vehicleChoice']] +# # bd_persons_trip_chain_vehicle_choice = bd_persons_trip_chain_vehicle_choice.sort_values( +# # by=['tripChain'], ascending=True, ignore_index=True) +# # bd_persons_trip_chain_vehicle_choice['vehicleChoice'] = bd_persons_trip_chain_vehicle_choice['vehicleChoice'].map( +# # dict_vehicle) +# # return bd_persons_trip_chain_activity_after, bd_persons_trip_chain_vehicle_choice + + +# # read in the data +# if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'figs_bs_data')): +# os.makedirs(os.path.join(os.path.dirname( +# os.path.abspath(__file__)), 'figs_bs_data')) +# figs_path = os.path.join(os.path.dirname( +# os.path.abspath(__file__)), 'figs_bs_data') + +# # check whether first start location is the last end location +# first_trip = bd[['personID','loc_id_start']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) +# last_trip = bd[['personID', 'loc_id_end']].drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) +# print("Number of persons where first start location is home: " + str(first_trip.loc[first_trip['loc_id_start']==-1]['loc_id_start'].size)+ ".") +# print("Number of persons where last end location is home: " + str(last_trip.loc[last_trip['loc_id_end']==-1]['loc_id_end'].size)+ ".") + +# # check what persons are doing which only do one trip +# # location_types = last_trip.groupby(['ActivityAfter']).size() + +# # location_types.plot(kind='bar') +# # plt.xlabel('Activity') +# # plt.ylabel('Number of persons') +# # plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) + +# # probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located +# # bd_tz_bs = bd.groupby(['idTrafficZone']).size().reset_index( +# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # # Count traffic zones where person is residing and longitude and latuitude of this in "EPSG:3035" format +# # bd_traffic_zones_persons = bd.groupby(['idTrafficZone']).size().reset_index( +# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # for row in bd_traffic_zones_persons.iterrows(): +# # bd_traffic_zones_persons.loc[row[0], ['longitude', 'latitude'] +# # ] = bd.loc[bd_traffic_zones_persons.loc[row[0], 'idTrafficZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +# # print(bd_traffic_zones_persons) + +# #### Counting people #### +# bd_persons = bd.groupby(['personID']).size().reset_index( +# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # Get the frequency of each number in the 'numbers' column +# bd_personss = bd_persons['counts'].value_counts().sort_index() +# # Plot the frequency of each number +# bd_personss.plot(kind='bar') +# plt.xlabel('Number of trips per day') +# plt.ylabel('Number of persons') +# plt.title('Number of trips per person tripcount (Braunschweig)') +# plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) + +# bd_persons_ages = bd[['personID', 'age']].drop_duplicates() +# bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ +# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# bd_persons_ages_cohorts = bd_persons_ages.groupby( +# ['AgeCohort']).size().reset_index(name='counts') +# bd_persons_ages_cohorts.index = bd_persons_ages_cohorts['AgeCohort'].to_list() +# bd_persons_ages_cohorts.plot.bar(figsize=( +# 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) +# plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) + +# # get the id with the persons with the highest number and print them +# # [id_person_max_trips, id_person_max_1_trips] = [ +# # bd_persons['personID'][0], bd_persons['personID'][1]] +# # print(get_trip_chain_activity_after(id_person_max_trips)) + +# # select internal and external trips (from/to Braunschweig) +# # bd_persons_inside_bs = bd.loc[bd['startZone'].isin( +# # bd_tz_bs['idTrafficZone']) & bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] +# # bd_persons_outside_bs = bd.loc[~bd['startZone'].isin( +# # bd_tz_bs['idTrafficZone']) & ~bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] + +# # check how many trips are in the same traffic zone +# bd_taz_start = bd.groupby('startZone').size().reset_index(name='counts') +# #bd_same_taz = bd.loc[bd['startZone'] == bd['destZone']] +# bd_different_taz = bd.loc[bd['startZone'] != bd['destZone']] +# #bd_same_taz = bd_same_taz.groupby(['startZone']).size().reset_index(name='counts') +# bd_different_taz = bd_different_taz.groupby( +# ['startZone']).size().reset_index(name='counts') +# #bd_same_taz['percentage'] = bd_same_taz['counts']/bd_taz_start['counts'] +# bd_different_taz['complement_counts'] = bd_taz_start['counts'] - \ +# bd_different_taz['counts'] +# bd_different_taz['total_counts'] = bd_taz_start['counts'] +# bd_different_taz = (bd_different_taz.sort_values( +# by='total_counts', ascending=False, ignore_index=True)) +# plt.figure() +# plt.plot(bd_different_taz['counts']) +# plt.plot(bd_different_taz['complement_counts']) +# plt.legend(['different TAZ', 'same TAZ']) +# plt.xlabel('Traffic analysis zones') +# plt.ylabel('Amount of trips inside/outside a TAZ') +# plt.savefig(os.path.join(figs_path, 'TAZ_distribution.png'), dpi=300) + +# # which age takes which mode of transport +# bd_persons_age_vehicle_choice = bd.loc[:, ['personID', 'age', 'vehicleChoice']].sort_values( +# by=['age'], ascending=True, ignore_index=True) +# bd_persons_age_vehicle_choice['vehicleChoice'] = bd_persons_age_vehicle_choice['vehicleChoice'].map( +# dict_vehicle) +# # accumulate the number of trips per age and vehicle choice +# bd_persons_age_vehicle_choice = bd_persons_age_vehicle_choice.groupby( +# ['age', 'vehicleChoice']).size().reset_index( +# name='counts').sort_values( +# by=['age'], +# ascending=True, ignore_index=True) +# # assign each age to an age cohort +# bd_persons_age_vehicle_choice['ageCohort'] = pd.cut(bd_persons_age_vehicle_choice['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ +# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# # plot a cake chart for each age cohort +# bd_persons_age_vehicle_choice_cake = bd_persons_age_vehicle_choice.groupby( +# ['ageCohort', 'vehicleChoice']).sum().reset_index() +# bd_persons_age_vehicle_choice_cake_age_veh = bd_persons_age_vehicle_choice_cake.pivot( +# index='ageCohort', columns='vehicleChoice', values='counts') +# bd_persons_age_vehicle_choice_cake_age_veh.plot.pie(subplots=True, layout=(3, 2), figsize=( +# 10, 10), title=bd_persons_age_vehicle_choice_cake_age_veh.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'vehicle_choice_per_age.png'), dpi=300) + +# # switch age cohort and vehicle choice +# bd_persons_age_vehicle_choice_cake_veh_age = bd_persons_age_vehicle_choice_cake.pivot( +# index='vehicleChoice', columns='ageCohort', values='counts') +# bd_persons_age_vehicle_choice_cake_veh_age.plot.pie(subplots=True, layout=(3, 3), figsize=( +# 20, 10), title=bd_persons_age_vehicle_choice_cake_veh_age.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'vehicle_choice_reversed.png'), dpi=300) + +# # Analyse trip purposes per age cohort +# bd_persons_age_purpose = bd.loc[:, ['personID', 'age', 'ActivityAfter']] +# bd_persons_age_purpose['ActivityAfter'] = bd_persons_age_purpose['ActivityAfter'].map( +# dict_leisure) +# bd_persons_age_purpose['ageCohort'] = pd.cut(bd_persons_age_purpose['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ +# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# bd_persons_age_purpose_acc = bd_persons_age_purpose.groupby( +# ['ActivityAfter', 'ageCohort']).size().reset_index(name='counts') +# bd_persons_age_purpose_cake = bd_persons_age_purpose_acc.pivot( +# index='ageCohort', columns='ActivityAfter', values='counts') +# bd_persons_age_purpose_cake.plot.pie(subplots=True, layout=(2, 4), figsize=( +# 15, 5), title=bd_persons_age_purpose_cake.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'trip_purpose.png'), dpi=300) + +# # switch age cohorts and purpose +# bd_persons_age_purpose_cake_reversed = bd_persons_age_purpose_acc.pivot( +# index='ActivityAfter', columns='ageCohort', values='counts') +# bd_persons_age_purpose_cake_reversed.plot.pie(subplots=True, layout=(2, 5), figsize=( +# 15, 5), title=bd_persons_age_purpose_cake_reversed.columns.to_list(), legend=False, ylabel='') +# plt.savefig(os.path.join(figs_path, 'trip_purpose_reversed.png'), dpi=300) + +# # Count traffic zones where people are starting their trips +# bd_traffic_zones_start = bd.groupby(['startZone']).size().reset_index( +# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# for row in bd_traffic_zones_start.iterrows(): +# bd_traffic_zones_start.loc[row[0], ['longitude', 'latitude'] +# ] = bd.loc[bd_traffic_zones_start.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +# print(bd_traffic_zones_start) + +# # plot longitude and latitude of traffic zones +# bd_traffic_zones_start.plot( +# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_start['counts'] / 100, figsize=(10, 15), +# title='Traffic zones where people are starting their trips (Braunschweig)') +# plt.savefig(os.path.join(figs_path, 'traffic_zones_start.png'), dpi=300) + +# # Count traffic zones where people are going and leaving +# bd_traffic_zones_end = bd.groupby(['destZone']).size().reset_index( +# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# for row in bd_traffic_zones_end.iterrows(): +# bd_traffic_zones_end.loc[row[0], ['longitude', 'latitude'] +# ] = bd.loc[bd_traffic_zones_end.loc[row[0], 'destZone'] == bd['destZone'], ['loCs', 'laCs']].values[0] +# print(bd_traffic_zones_end) + +# # plot longitude and latitude of traffic zones +# bd_traffic_zones_end.plot( +# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_end['counts'] / 100, figsize=(10, 10), +# title='Traffic zones where people are ending their trips (Braunschweig)') +# plt.savefig(os.path.join(figs_path, 'traffic_zones_end.png'), dpi=300) + +# # Time analyzing +# # Time of day +# bd_time = bd.groupby(['startTime']).size().reset_index(name='counts') +# print(bd_time) +# bd_time.plot(kind='line', x='startTime', y='counts') +# plt.xlabel('Time of day') +# plt.ylabel('Number of trips') +# plt.title('Time of day (Braunschweig)' + ' (n = ' + str(len(bd)) + ' trips)') +# plt.savefig(os.path.join(figs_path, 'time_of_day.png'), dpi=300) + +# # time of day rolling average +# bd_time['rolling_mean'] = bd_time['counts'].rolling(window=7).mean() +# bd_time.plot(kind='line', x='startTime', y='rolling_mean') +# plt.xlabel('Time of day') +# plt.ylabel('Number of trips') +# plt.title('Time of day (Braunschweig)' + ' (n = ' + +# str(len(bd)) + ' trips), rolling mean with window size 7') +# plt.savefig(os.path.join(figs_path, 'time_of_day_rolling.png'), dpi=300) + +# # Frequency matrix of trips between traffic zones +# matrix_freq = pd.crosstab(bd['startZone'], bd['destZone']) +# nnz_matrix_freq = np.count_nonzero(matrix_freq) +# subset_matrix_freq = matrix_freq.iloc[0:30, 0:30] +# nnz_sub_matrix_freq = np.count_nonzero(subset_matrix_freq) +# sns.heatmap(subset_matrix_freq, cmap="Blues", vmin=0) +# plt.xlabel('Destination traffic zone') +# plt.ylabel('Start traffic zone') +# plt.title('Number of non-zero entries in frequency matrix: ' + str(nnz_sub_matrix_freq) + ' out of ' + str(subset_matrix_freq.size) + ' entries (' + +# str(round(nnz_sub_matrix_freq / subset_matrix_freq.size * 100, 2)) + '%)') +# plt.savefig(os.path.join(figs_path, 'heatmap.png'), dpi=300) + +# # frequency matrix of trips from which leisure activity to which leisure activity + +# # check if all activities of bd activity before are in the dictionary +# if bd['ActivityBefore'].isin(dict_leisure.keys()).all(): +# print('All activities in dictionary') +# # check if there is a activity missing that is in the dictionary +# if not set(dict_leisure.keys()).issubset(set(bd['ActivityBefore'].unique())): +# print('There is an activity missing that is in the dictionary:') +# for key in (set(dict_leisure.keys()).difference(set(bd['ActivityBefore'].unique()))): +# print(key, dict_leisure[key]) + + +# matrix_frqu_leisure = pd.crosstab( +# bd['ActivityBefore'], +# bd['ActivityAfter'], +# normalize='index') +# sns.heatmap(matrix_frqu_leisure, vmin=0, xticklabels=dict_leisure.values(), +# yticklabels=dict_leisure.values()) +# plt.xlabel('Leisure activity after trip') +# plt.ylabel('Leisure activity before trip') +# plt.title('Frequency of trips from which leisure activity to which leisure activity') +# plt.savefig(os.path.join(figs_path, 'heatmap_leisure.png'), dpi=300) + + +# # quick check if a data point in the matrix is correct +# check = bd.loc[(bd['startZone'] == 31010011) & ( +# bd['destZone'] == 31010011), 'startZone'].count() + + +# # plotting the duration of trips +# fig, axs = plt.subplots(2) +# axs[0].hist(bd['travelTime']/60/60, bins=100, +# range=(0, max(bd['travelTime'])*1.2/60/60)) +# axs[0].set_title('Trip duration (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips)') +# axs[0].set_xlabel('Trip duration in hours') +# axs[0].set_ylabel('Number of trips') +# axs[1].hist(bd['travelTime']/60/60, bins=100, +# range=(0, max(bd['travelTime'])*1.2/60/60)) +# axs[1].set_yscale('log') +# axs[1].set_title('Trip duration (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips) log scale') +# axs[1].set_xlabel('Trip duration in hours') +# axs[1].set_ylabel('Number of trips') + +# # same thing with the distance of the trips +# fig2, axs2 = plt.subplots(2) +# axs2[0].hist(bd['tripDistance'], bins=100, +# range=(0, max(bd['tripDistance'])*1.2,)) +# axs2[0].set_title('Trip distance (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips)') +# axs2[0].set_xlabel('Trip distance in Kilometers') +# axs2[0].set_ylabel('Number of trips') +# axs2[1].hist(bd['tripDistance'], bins=100, +# range=(0, max(bd['tripDistance'])*1.2,)) +# axs2[1].set_yscale('log') +# axs2[1].set_title('Trip distance (Braunschweig)' + +# ' (n = ' + str(len(bd)) + ' trips) log scale') +# axs2[1].set_xlabel('Trip distance in Kilometers') +# axs2[1].set_ylabel('Number of trips') + + +# # analyze age distribution with age cohorts +# bd_persons_id_and_age = bd[['personID', 'age']].drop_duplicates() +# bd_age_cohorts = pd.cut( +# bd_persons_id_and_age['age'], +# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95, 106], +# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95', '96-105']).reset_index( +# name='age_cohort').groupby( +# ['age_cohort']).size().reset_index( +# name='counts') +# bd_age_cohorts.plot(kind='bar', x='age_cohort', y='counts') +# plt.xlabel('Age cohort') +# plt.ylabel('Number of persons') +# plt.title('Age distribution of persons in Braunschweig in age cohorts, number ') +# plt.savefig(os.path.join(figs_path, 'age_cohorts.png'), dpi=300) + +# # relation between age and trip duration in minutes and hours +# bd_age_duration = bd.groupby(['age']).mean().reset_index() +# bd_age_duration['travelTime'] = bd_age_duration['travelTime'] / 60 +# bd_age_duration.plot(kind='bar', x='age', y='travelTime') + +# # also do this for trip distance +# bd_age_distance = bd.groupby(['age']).mean().reset_index() +# bd_age_distance.plot(kind='bar', x='age', y='tripDistance') + +# # analyze trip distance in distance cohort +# bd_trip_distance_cohorts = pd.cut( +# bd['tripDistance'], +# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], +# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( +# name='trip_distance_cohort').groupby( +# ['trip_distance_cohort']).size().reset_index( +# name='counts') +# bd_trip_distance_cohorts.plot(kind='bar', x='trip_distance_cohort', y='counts') +# plt.xlabel('Trip distance cohort in km') +# plt.ylabel('Number of trips') +# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + str(len(bd))) +# plt.savefig(os.path.join(figs_path, 'trip_distance_cohorts.png'), dpi=300) + +# # pie diagram of trip distance cohorts for each age cohort +# bd_trip_distance_cohorts_vehicle = pd.cut( +# bd['tripDistance'], +# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], +# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( +# name='trip_distance_cohort') +# bd_age_cohorts = pd.cut(bd['age'], +# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95], +# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95']).reset_index( +# name='age_cohort') +# # attach the age cohort to the dataframe +# bd_trip_distance_cohorts_vehicle = pd.concat( +# [bd_trip_distance_cohorts_vehicle['trip_distance_cohort'], bd_age_cohorts['age_cohort']], axis=1) +# # group by age cohort and distance cohort +# bd_trip_distance_cohorts_vehicle = bd_trip_distance_cohorts_vehicle.groupby( +# ['trip_distance_cohort', 'age_cohort']).size().reset_index(name='counts') +# # plot a pie chart for each age cohort +# for age_cohort in bd_trip_distance_cohorts_vehicle['age_cohort'].unique(): +# bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort].plot( +# kind='pie', y='counts', labels=bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort]['trip_distance_cohort'], autopct='%1.1f%%', startangle=90) +# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + +# str(len(bd)) + ' for age cohort ' + age_cohort) +# plt.savefig(os.path.join( +# figs_path, 'trip_distance_cohorts_' + age_cohort + '.png'), dpi=300) + +# # now the same for trip duration vs vehicle type +# bd_trip_duration_cohorts_vehicle = pd.cut( +# bd['travelTime'], +# bins=[-1, 500, 1000, 5000, 10000, 423789798324], +# labels=['0-500', '500-1000', '1000-5000', '5000-10000', '10000+']).reset_index( +# name='trip_duration_cohort') +# bd_vehicle_type = bd['vehicleChoice'].reset_index(name='vehicleChoice') +# # attach the age cohort to the dataframe +# bd_trip_duration_cohorts_vehicle = pd.concat( +# [bd_trip_duration_cohorts_vehicle['trip_duration_cohort'], bd_vehicle_type['vehicleChoice']], axis=1) +# # group by age cohort and distance cohort +# bd_trip_duration_cohorts_vehicle = bd_trip_duration_cohorts_vehicle.groupby( +# ['trip_duration_cohort', 'vehicleChoice']).size().reset_index(name='counts') +# # plot a pie chart for each age cohort +# for vehicle_type in bd_trip_duration_cohorts_vehicle['vehicleChoice'].unique(): +# bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type].plot( +# kind='pie', y='counts', labels=bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type]['trip_duration_cohort'], autopct='%1.1f%%', startangle=90) +# plt.title('Trip duration distribution in Braunschweig in trip duration cohorts, in minutes. Number of trips: ' + str(len(bd) +# ) + ' for vehicle type ' + str(dict_vehicle[vehicle_type])) +# plt.savefig(os.path.join(figs_path, 'trip_duration_cohorts_' + +# str(dict_vehicle[vehicle_type]) + '.png'), dpi=300) + + +# # also do a scatter plot of trip duration and trip distance with a regression line +# bd_age_distance.plot(kind='scatter', x='age', y='tripDistance') +# plt.plot(np.unique(bd_age_distance['age']), np.poly1d(np.polyfit(bd_age_distance['age'], +# bd_age_distance['tripDistance'], 1))(np.unique(bd_age_distance['age']))) +# bd_age_duration.plot(kind='scatter', x='age', y='travelTime') +# plt.plot(np.unique(bd_age_duration['age']), np.poly1d(np.polyfit( +# bd_age_duration['age'], bd_age_duration['travelTime'], 1))(np.unique(bd_age_duration['age']))) +# plt.show() + +# ### draft to compute number of locations of type 6? +# x = bd[bd.ActivityAfter==6].loc[:, 'loc_id_end'].nunique() +# # downscaling of locations of type 6 to 2000 agents +# x / (bd['personID'].nunique()/2000) + +# x = 42 + + + + +## draft to add collumn to check if the location in Braunschweig +bd['home_in_bs'] = 0 +#list of persons who are in braunschweig +list_person_in_bs = np.array([]) +for index, row in bd.iterrows(): + if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): + list_person_in_bs = np.append(list_person_in_bs, row['personID']) +#drop duplicates +list_person_in_bs = np.unique(list_person_in_bs) +for index, row in bd.iterrows(): + if row['personID'] in list_person_in_bs: + bd.at[index, 'home_in_bs'] = 1 + + +bd.to_csv('modified_braunschweig_result.csv', index=False) + +#count number of trips which are in braunschweig +# bs_trip_count = 0 +# for index, row in bd.iterrows(): +# if ((row['countyStart']==3101) or (row['countyEnd']==3101 )): +# bs_trip_count = bs_trip_count+1 + +# #percentage of trips in braunschweigx +# bs_trip_count/len(bd)*100 + +# count how many persons are in braunschweig +bs_person_count = 0 +# collapse all persons to one trip and check if the trip is in braunschweig +persons_in_bs = bd[['personID', 'home_in_bs']].drop_duplicates().groupby(['personID']).aggregate('sum').reset_index() +# percentage number of persons in braunschweig is persons with not zero home_in_bs / all persons +persons_in_bs.loc[persons_in_bs['home_in_bs']==0].size/persons_in_bs.size*100 + + + +x=1 diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5fd7d4fdb0..214acd4918 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -350,6 +350,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t trip_start = row[index["start_time"]]; uint32_t transport_mode = row[index["travel_mode"]]; uint32_t acticity_end = row[index["activity_end"]]; + bool home_in_bs = (bool)row[index["in_bs"]]; // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; @@ -364,7 +365,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, } auto first_location_id = it_first_location_id->second.first; auto first_location = locations.find(first_location_id)->second; - auto& person = world.add_person(first_location, determine_age_group(age)); + auto& person = world.add_person(first_location, determine_age_group(age), home_in_bs); auto home = locations.find(home_id)->second; person.set_assigned_location(home); person.set_assigned_location(hospital); @@ -825,16 +826,50 @@ void write_txt_file_for_graphical_compartment_output(std::vector run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, +struct LogInfectionStatePerAgeGroup : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the number of Person%s in an #InfectionState. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the number of Person%s in an #InfectionState. + */ + static Type log(const mio::abm::Simulation& sim) + { + + Eigen::VectorXd sum = Eigen::VectorXd::Zero( + Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())); + auto curr_time = sim.get_time(); + PRAGMA_OMP(for) + for (auto&& location : sim.get_world().get_locations()) { + for (uint32_t age_group = 0; age_group < num_age_groups; age_group++) { + for (uint32_t inf_state = 0; inf_state < (uint32_t)mio::abm::InfectionState::Count; inf_state++) { + auto test = location.get_subpopulation_per_age_group(curr_time, mio::abm::InfectionState(inf_state), + age_group); + auto test2 =(((size_t)(mio::abm::InfectionState::Count)) * (age_group)) + inf_state; + sum(test2) += test; + } + } + } + return std::make_pair(curr_time, sum); + } +}; +mio::IOResult run(const std::string& input_file, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation auto ensemble_results = std::vector>>{}; // Vector of collected results ensemble_results.reserve(size_t(num_runs)); + auto ensemble_infection_per_loc_type = + std::vector>>{}; // Vector of infection per location type results + auto ensemble_infection_per_age_group = + std::vector>>{}; // Vector of infection per age group results + auto ensemble_infection_state_per_age_group = + std::vector>>{}; // Vector of infection state per age group results + auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 500; + auto max_num_persons = 23; int tid = -1; #pragma omp parallel private(tid) // Start of parallel region: forks threads @@ -858,28 +893,57 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::History historyTimeSeries{ Eigen::Index(mio::abm::InfectionState::Count)}; mio::History historyPersonInfDelta; + mio::History historyInfectionPerLocationType{ + Eigen::Index(mio::abm::LocationType::Count)}; + mio::History historyInfectionPerAgeGroup{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; + mio::History historyInfectionStatePerAgeGroup{ + Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + // Collect the id of location in world. std::vector loc_ids; for (auto& location : sim.get_world().get_locations()) { loc_ids.push_back(location.get_index()); } // Advance the world to tmax - sim.advance(tmax, historyPersonInf, historyTimeSeries, historyPersonInfDelta); + sim.advance(tmax, historyPersonInf, historyTimeSeries, historyInfectionPerLocationType, + historyInfectionPerAgeGroup, historyPersonInfDelta, historyInfectionStatePerAgeGroup); // TODO: update result of the simulation to be a vector of location result. auto temp_sim_result = std::vector>{std::get<0>(historyTimeSeries.get_log())}; + auto temp_sim_infection_per_loc_tpye = + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_per_age_group = + std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; + auto temp_sim_infection_state_per_age_group = + std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + // Push result of the simulation back to the result vector ensemble_results.push_back(temp_sim_result); + ensemble_infection_per_loc_type.push_back(temp_sim_infection_per_loc_tpye); + ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); + ensemble_params.push_back(std::vector{sim.get_world()}); + ensemble_infection_state_per_age_group.push_back(temp_sim_infection_state_per_age_group); // Option to save the current run result to file - if (save_result_result && save_single_runs) { + /* if (save_result_result && save_single_runs) { auto result_dir_run = result_dir / ("abm_result_run_" + std::to_string(run_idx) + ".h5"); - BOOST_OUTCOME_TRY(save_result(ensemble_results.back(), loc_ids, 1, result_dir_run.string())); - } + BOOST_OUTCOME_TRY(save_result(ensemble_results.back(), {0}, 1, result_dir_run.string())); + } */ write_log_to_file_person_and_location_data(historyPersonInf); write_log_to_file_trip_data(historyPersonInfDelta); std::cout << "Run " << run_idx << " of " << num_runs << " finished." << std::endl; ++run_idx; } + + BOOST_OUTCOME_TRY( + save_results(ensemble_results, ensemble_params, {0}, result_dir / "infection_course/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_results, ensemble_params, {0}, result_dir / "infection_per_location_type/", + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_results, ensemble_params, {0}, result_dir / "infection_per_age_group/", + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, + result_dir / "infection_state_per_age_group/", save_single_runs)); + write_txt_file_for_graphical_compartment_output(ensemble_results); BOOST_OUTCOME_TRY(save_result_result); return mio::success(); @@ -890,7 +954,8 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_dir = "/Users/david/Documents/HZI/memilio/data/"; + std::string input_file = + "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/modified_braunschweig_result.csv"; size_t num_runs; bool save_single_runs = true; @@ -915,7 +980,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); printf("Running with number of runs = 1.\n"); - num_runs = 1; + num_runs = 2; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From c8046831f83613e38215376be15bd8166ee9685c Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 1 Mar 2024 09:21:18 +0100 Subject: [PATCH 041/488] Fix input dir --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 214acd4918..d005e27799 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -853,7 +853,7 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { return std::make_pair(curr_time, sum); } }; -mio::IOResult run(const std::string& input_file, const fs::path& result_dir, size_t num_runs, +mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { auto t0 = mio::abm::TimePoint(0); // Start time per simulation @@ -954,8 +954,8 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_file = - "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/modified_braunschweig_result.csv"; + std::string input_dir = + "/Users/David/Documemts/HZI/memilio/data/"; size_t num_runs; bool save_single_runs = true; From 4d444d7b011015b8514a098c21c864c9d16ae0a1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 1 Mar 2024 09:31:01 +0100 Subject: [PATCH 042/488] Refactor code to improve readability and remove unnecessary variables Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d005e27799..040c43153e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -843,10 +843,9 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { for (auto&& location : sim.get_world().get_locations()) { for (uint32_t age_group = 0; age_group < num_age_groups; age_group++) { for (uint32_t inf_state = 0; inf_state < (uint32_t)mio::abm::InfectionState::Count; inf_state++) { - auto test = location.get_subpopulation_per_age_group(curr_time, mio::abm::InfectionState(inf_state), - age_group); - auto test2 =(((size_t)(mio::abm::InfectionState::Count)) * (age_group)) + inf_state; - sum(test2) += test; + sum((((size_t)(mio::abm::InfectionState::Count)) * (age_group)) + inf_state) += + location.get_subpopulation_per_age_group(curr_time, mio::abm::InfectionState(inf_state), + age_group); } } } @@ -890,8 +889,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::History historyPersonInf; - mio::History historyTimeSeries{ - Eigen::Index(mio::abm::InfectionState::Count)}; mio::History historyPersonInfDelta; mio::History historyInfectionPerLocationType{ Eigen::Index(mio::abm::LocationType::Count)}; @@ -906,10 +903,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s loc_ids.push_back(location.get_index()); } // Advance the world to tmax - sim.advance(tmax, historyPersonInf, historyTimeSeries, historyInfectionPerLocationType, - historyInfectionPerAgeGroup, historyPersonInfDelta, historyInfectionStatePerAgeGroup); + sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, + historyPersonInfDelta, historyInfectionStatePerAgeGroup); // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_result = std::vector>{std::get<0>(historyTimeSeries.get_log())}; auto temp_sim_infection_per_loc_tpye = std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; auto temp_sim_infection_per_age_group = @@ -918,7 +914,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; // Push result of the simulation back to the result vector - ensemble_results.push_back(temp_sim_result); ensemble_infection_per_loc_type.push_back(temp_sim_infection_per_loc_tpye); ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); ensemble_params.push_back(std::vector{sim.get_world()}); @@ -954,8 +949,7 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_dir = - "/Users/David/Documemts/HZI/memilio/data/"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; size_t num_runs; bool save_single_runs = true; From 6820bfa20a54558c6305fc18c805dc008fce64d5 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 1 Mar 2024 09:48:27 +0100 Subject: [PATCH 043/488] Allocate memory for TimeSeries objects --- cpp/simulations/paper_abm_bs_testing.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 040c43153e..7e68c107fb 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -857,14 +857,15 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s { auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation - auto ensemble_results = std::vector>>{}; // Vector of collected results - ensemble_results.reserve(size_t(num_runs)); auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results + ensemble_infection_per_loc_type.reserve(size_t(num_runs)); auto ensemble_infection_per_age_group = std::vector>>{}; // Vector of infection per age group results + ensemble_infection_per_age_group.reserve(size_t(num_runs)); auto ensemble_infection_state_per_age_group = std::vector>>{}; // Vector of infection state per age group results + ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations @@ -930,16 +931,14 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s ++run_idx; } - BOOST_OUTCOME_TRY( - save_results(ensemble_results, ensemble_params, {0}, result_dir / "infection_course/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_results, ensemble_params, {0}, result_dir / "infection_per_location_type/", - save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_results, ensemble_params, {0}, result_dir / "infection_per_age_group/", - save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, + result_dir / "infection_per_location_type/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_age_group, ensemble_params, {0}, + result_dir / "infection_per_age_group/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); - write_txt_file_for_graphical_compartment_output(ensemble_results); + //write_txt_file_for_graphical_compartment_output(ensemble_infection_state_per_age_group); BOOST_OUTCOME_TRY(save_result_result); return mio::success(); } @@ -949,7 +948,7 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::warn); std::string result_dir = "."; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; size_t num_runs; bool save_single_runs = true; From 51b039cfbde3afcffda39d81987411f716b96e4b Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 1 Mar 2024 11:40:04 +0100 Subject: [PATCH 044/488] Prepare creation and copying of one world, fix plots. --- cpp/models/abm/world.h | 6 ++- cpp/simulations/analyze_bs_run.py | 39 ++++++++++---- cpp/simulations/paper_abm_bs_testing.cpp | 66 ++++++++++++++---------- 3 files changed, 74 insertions(+), 37 deletions(-) diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index 70270f273a..c517cf5099 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -75,8 +75,13 @@ class World : parameters(other.parameters) , m_persons() , m_locations() + , m_has_locations(other.m_has_locations) + , m_testing_strategy(other.m_testing_strategy) , m_trip_list(other.m_trip_list) + , m_use_migration_rules(other.m_use_migration_rules) + , m_migration_rules(other.m_migration_rules) , m_cemetery_id(add_location(LocationType::Cemetery)) + , m_rng(other.m_rng) { for (auto& origin_loc : other.get_locations()) { if (origin_loc.get_type() != LocationType::Cemetery) { @@ -93,7 +98,6 @@ class World } } } - use_migration_rules(other.m_use_migration_rules); } //type is move-only for stable references of persons/locations diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index a9d9621655..1c61fcfa77 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -75,26 +75,45 @@ def plot_infection_per_age_group(df): plt.show() def plot_results(path): - # df = pd.read_hdf(os.path.join(path, 'infection_course/p50/Results_sum.h5')) - f = h5py.File("/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/build/bin/infection_state_per_age_group/p50/Results.h5", 'r') + # median / 50-percentile + f = h5py.File( + "/Users/David/Documents/HZI/memilio/data/results/infection_state_per_age_group/p50/Results.h5", 'r') # Get the HDF5 group; key needs to be a group name from above group = f['0'] # This assumes group[some_key_inside_the_group] is a dataset, # and returns a np.array: - # time = group['Time'][()] - total = group['Total'][()] - group1 = group['Group1'][()] - group2 = group['Group2'][()] - - comp_simulated = np.sum(total[:, comp], axis=1) + time = group['Time'][()] + total_50 = group['Total'][()] # After you are done f.close() - return comp_simulated[:] - # print(df.head()) + # 05-percentile + f = h5py.File( + "/Users/David/Documents/HZI/memilio/data/results/infection_state_per_age_group/p05/Results.h5", 'r') + group = f['0'] + total_05 = group['Total'][()] + f.close() + + # 95-percentile + f = h5py.File( + "/Users/David/Documents/HZI/memilio/data/results/infection_state_per_age_group/p95/Results.h5", 'r') + group = f['0'] + total_95 = group['Total'][()] + f.close() + + plot_infection_states(time, total_50, total_05, total_95) + + +def plot_infection_states(x, y50, y05, y95): + plt.plot(x, y50) + plt.legend(['S', 'E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Rec', 'Dead']) + + for i in range(y50.shape[1]): + plt.fill_between(x, y50[:, i], y05[:, i], alpha=0.1) + plt.fill_between(x, y50[:, i], y95[:, i], alpha=0.1) def plot_mean_and_std(Y): diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7e68c107fb..4b5b0cc50f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -54,26 +54,32 @@ const std::map infection_ {mio::osecir::InfectionState::Recovered, mio::abm::InfectionState::Recovered}, {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; +mio::CustomIndexArray initial_infection_distribution{ + {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.}; + /** - * Assign an infection state to each person according to real world data read in through the ODE secir model. - */ -void assign_infection_state(mio::abm::World& world, const fs::path& input_dir, mio::abm::TimePoint t) + * Determine initial distribution of infection states. +*/ +void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(mio::Date(2020, 03, 01), 1, input_dir); + auto initial_graph = get_graph(date, 1, input_dir); size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; - mio::CustomIndexArray initial_values{ - {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.}; - initial_values.array() = braunschweig_node.populations.array().cast(); - //std::cout << initial_values.array() << std::endl; + initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); +} +/** + * Assign an infection state to each person according to real world data read in through the ODE secir model. + */ +void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) +{ // convert initial population to ABM initial infections for (auto& person : world.get_persons()) { auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( - rng, initial_values.slice(person.get_age()).as_array().array())); + rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); //bool detected = false; if (infection_state != mio::osecir::InfectionState::Susceptible) { @@ -693,11 +699,10 @@ void set_local_parameters(mio::abm::World& world) * Create a sampled simulation with start time t0. * @param t0 The start time of the Simulation. */ -mio::abm::Simulation create_sampled_simulation(const fs::path& input_dir, const mio::abm::TimePoint& t0, - int max_num_persons) +void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, + int max_num_persons) { //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world - auto world = mio::abm::World(num_age_groups); set_parameters(world.parameters); set_local_parameters(world); @@ -708,18 +713,15 @@ mio::abm::Simulation create_sampled_simulation(const fs::path& input_dir, const world.use_migration_rules(false); // Assign an infection state to each person. - assign_infection_state(world, input_dir, t0); + assign_infection_state(world, t0); - auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); + //auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); // During the lockdown, 25% of people work from home and schools are closed for 90% of students. // Social events are very rare. - mio::abm::set_home_office(t_lockdown, 0.25, world.parameters); - mio::abm::set_school_closure(t_lockdown, 0.9, world.parameters); - mio::abm::close_social_events(t_lockdown, 0.9, world.parameters); - - auto sim = mio::abm::Simulation(t0, std::move(world)); - return sim; + //mio::abm::set_home_office(t_lockdown, 0.25, world.parameters); + //mio::abm::set_school_closure(t_lockdown, 0.9, world.parameters); + //mio::abm::close_social_events(t_lockdown, 0.9, world.parameters); } template @@ -855,8 +857,9 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { + mio::Date start_date{2020, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(10); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -869,7 +872,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 23; + auto max_num_persons = 10; + + // Determine inital infection state distribution + determine_initial_infection_states_world(input_dir, start_date); int tid = -1; #pragma omp parallel private(tid) // Start of parallel region: forks threads @@ -881,11 +887,19 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } // ** end of the the parallel: joins threads + // Create one world for all simulations that will be copied + //auto world = mio::abm::World(num_age_groups); + //create_sampled_world(world, input_dir, t0, max_num_persons); + // Loop over a number of runs while (run_idx <= num_runs) { // Create the sampled simulation with start time t0. - auto sim = create_sampled_simulation(input_dir, t0, max_num_persons); + auto world = mio::abm::World(num_age_groups); + create_sampled_world(world, input_dir, t0, max_num_persons); + // auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED! + auto sim = mio::abm::Simulation(t0, std::move(world)); + //output object mio::History @@ -947,8 +961,8 @@ int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::warn); - std::string result_dir = "."; - std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; + std::string result_dir = "/Users/David/Documents/HZI/memilio/data/results/"; + std::string input_dir = "/Users/David/Documents/HZI/memilio/data/"; size_t num_runs; bool save_single_runs = true; @@ -973,7 +987,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); printf("Running with number of runs = 1.\n"); - num_runs = 2; + num_runs = 1; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From ca2555a079632b7ed8c983ccd1d75e5d49ae78ea Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:58:51 +0100 Subject: [PATCH 045/488] Update file paths in analyze_bs_run.py and paper_abm_bs_testing.cpp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 13 ++++++++----- cpp/simulations/paper_abm_bs_testing.cpp | 16 ++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 1c61fcfa77..debacf9a90 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -77,7 +77,7 @@ def plot_infection_per_age_group(df): def plot_results(path): # median / 50-percentile f = h5py.File( - "/Users/David/Documents/HZI/memilio/data/results/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/infection_state_per_age_group/p50/Results.h5", 'r') # Get the HDF5 group; key needs to be a group name from above group = f['0'] @@ -92,19 +92,20 @@ def plot_results(path): # 05-percentile f = h5py.File( - "/Users/David/Documents/HZI/memilio/data/results/infection_state_per_age_group/p05/Results.h5", 'r') + path+"/infection_state_per_age_group/p05/Results.h5", 'r') group = f['0'] total_05 = group['Total'][()] f.close() # 95-percentile f = h5py.File( - "/Users/David/Documents/HZI/memilio/data/results/infection_state_per_age_group/p95/Results.h5", 'r') + path + "/infection_state_per_age_group/p95/Results.h5", 'r') group = f['0'] total_95 = group['Total'][()] f.close() plot_infection_states(time, total_50, total_05, total_95) + x=1 def plot_infection_states(x, y50, y05, y95): @@ -137,11 +138,13 @@ def plot_mean_and_std(Y): if __name__ == "__main__": + #path to results + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: - folder_path = "build/bin" + folder_path = path n_runs = len([entry for entry in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, entry))]) #main(n_runs) - plot_results('build/bin/') + plot_results(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4b5b0cc50f..fea1c83270 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -64,8 +64,8 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m { // estimate intial population by ODE compartiments auto initial_graph = get_graph(date, 1, input_dir); - size_t braunschweig_id = 16; // Braunschweig has ID 16 - auto braunschweig_node = initial_graph.value()[braunschweig_id]; + size_t braunschweig_id = 16; // Braunschweig has ID 16 + auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); } @@ -858,8 +858,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s bool save_single_runs = true) { mio::Date start_date{2020, 3, 1}; - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(10); // End time per simulation + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(40); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -872,7 +872,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 10; + auto max_num_persons = 1000; // Determine inital infection state distribution determine_initial_infection_states_world(input_dir, start_date); @@ -961,8 +961,8 @@ int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::warn); - std::string result_dir = "/Users/David/Documents/HZI/memilio/data/results/"; - std::string input_dir = "/Users/David/Documents/HZI/memilio/data/"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -987,7 +987,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); printf("Running with number of runs = 1.\n"); - num_runs = 1; + num_runs = 2; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From 69c389638713277c130c153210c44dc71d9596f5 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Sat, 2 Mar 2024 19:38:43 +0100 Subject: [PATCH 046/488] Test cases --- cpp/simulations/paper_abm_bs_testing.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fea1c83270..f559c81007 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -722,6 +722,12 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con //mio::abm::set_home_office(t_lockdown, 0.25, world.parameters); //mio::abm::set_school_closure(t_lockdown, 0.9, world.parameters); //mio::abm::close_social_events(t_lockdown, 0.9, world.parameters); + + // Verschiedene Fälle: + //1. ohne testing scheme + //2. testing scheme: Test bei Symptomen (unabh. von Location, 1x am Tag, InfectedSymptomatic, 70% der Bevölkerung) ab Tag 0 + //3. testen in schulen und Arbeitsplätzen (unabh. von Alter, 1x am Tag, unabh. von InfectionState) ab Tag 0 + //4. 2.+3. } template @@ -857,9 +863,9 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { - mio::Date start_date{2020, 3, 1}; + mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(40); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -872,7 +878,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 1000; + auto max_num_persons = 300000; // Determine inital infection state distribution determine_initial_infection_states_world(input_dir, start_date); @@ -987,7 +993,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); printf("Running with number of runs = 1.\n"); - num_runs = 2; + num_runs = 100; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From b8cb175bb2a607123580282b025f2a80b0fc9c23 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 5 Mar 2024 16:06:30 +0100 Subject: [PATCH 047/488] Update world initialization and simulation parameters Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.h | 20 +++++++------------- cpp/simulations/paper_abm_bs_testing.cpp | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index c517cf5099..c479bfc57c 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -75,13 +75,8 @@ class World : parameters(other.parameters) , m_persons() , m_locations() - , m_has_locations(other.m_has_locations) - , m_testing_strategy(other.m_testing_strategy) , m_trip_list(other.m_trip_list) - , m_use_migration_rules(other.m_use_migration_rules) - , m_migration_rules(other.m_migration_rules) , m_cemetery_id(add_location(LocationType::Cemetery)) - , m_rng(other.m_rng) { for (auto& origin_loc : other.get_locations()) { if (origin_loc.get_type() != LocationType::Cemetery) { @@ -89,15 +84,14 @@ class World m_locations.emplace_back( std::make_unique(origin_loc.copy_location_without_persons(parameters.get_num_groups()))); } - for (auto& person : other.get_persons()) { - // If a person is in this location, copy this person and add it to this location. - if (person.get_location() == origin_loc) { - LocationId origin_id = {origin_loc.get_index(), origin_loc.get_type()}; - m_persons.push_back( - std::make_unique(person.copy_person(get_individualized_location(origin_id)))); - } - } } + for (auto& person : other.get_persons()) { + // add all persons in order. copy_person also adds them to their respective location + auto& origin_loc = + get_individualized_location({person.get_location().get_index(), person.get_location().get_type()}); + m_persons.push_back(std::make_unique(person.copy_person(origin_loc))); + } + use_migration_rules(other.m_use_migration_rules); } //type is move-only for stable references of persons/locations diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fea1c83270..e45d1cb5f1 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -854,12 +854,13 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { return std::make_pair(curr_time, sum); } }; + mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { - mio::Date start_date{2020, 3, 1}; + mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(40); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(20); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -888,17 +889,17 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } // ** end of the the parallel: joins threads // Create one world for all simulations that will be copied - //auto world = mio::abm::World(num_age_groups); - //create_sampled_world(world, input_dir, t0, max_num_persons); + auto world = mio::abm::World(num_age_groups); + create_sampled_world(world, input_dir, t0, max_num_persons); // Loop over a number of runs while (run_idx <= num_runs) { // Create the sampled simulation with start time t0. - auto world = mio::abm::World(num_age_groups); - create_sampled_world(world, input_dir, t0, max_num_persons); - // auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED! - auto sim = mio::abm::Simulation(t0, std::move(world)); + // auto world = mio::abm::World(num_age_groups); + // create_sampled_world(world, input_dir, t0, max_num_persons); + auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED! + auto sim = mio::abm::Simulation(t0, std::move(world_copy)); //output object mio::History time(s).\n"); printf("\tStore the results in .\n"); printf("Running with number of runs = 1.\n"); - num_runs = 2; + num_runs = 15; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From 7dd4a79e87a1a06f1cb590ca0ac399f576c60068 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 5 Mar 2024 16:13:35 +0100 Subject: [PATCH 048/488] for jureca Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e45d1cb5f1..a39ea75832 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -860,7 +860,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s { mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(20); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -962,7 +962,7 @@ int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::warn); - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project/loki/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 010fe375ddda4d502a8f7b6828929df277b7cc3f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:04:00 +0100 Subject: [PATCH 049/488] fix free pointer bug Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/memilio/epidemiology/damping.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/memilio/epidemiology/damping.h b/cpp/memilio/epidemiology/damping.h index 403b1406e6..05d233d915 100644 --- a/cpp/memilio/epidemiology/damping.h +++ b/cpp/memilio/epidemiology/damping.h @@ -352,7 +352,8 @@ class Dampings */ auto get_matrix_at(SimulationTime t) const { - assert(!m_accumulated_dampings_cached.empty() && "Cache is not current. Did you disable the automatic cache update?"); + assert(!m_accumulated_dampings_cached.empty() && + "Cache is not current. Did you disable the automatic cache update?"); auto ub = std::upper_bound(m_accumulated_dampings_cached.begin(), m_accumulated_dampings_cached.end(), std::make_tuple(t), [](auto&& tup1, auto&& tup2) { @@ -519,7 +520,7 @@ class Dampings static void inclusive_exclusive_sum_rec(Iter b, Iter e, Matrix& sum) { if (b != e) { - sum = sum + std::get(*b) - (sum.array() * std::get(*b).array()).matrix(); + sum = (sum + std::get(*b) - (sum.array() * std::get(*b).array()).matrix()).eval(); inclusive_exclusive_sum_rec(++b, e, sum); } } @@ -604,13 +605,13 @@ void Dampings::update_active_dampings( //replace active of the same type and level auto& active_same_type = *iter_active_same_type; //find active with the same level - auto& sum_same_level = *std::find_if(sum_by_level.begin(), sum_by_level.end(), [&damping](auto& sum) { + auto& sum_same_level = *std::find_if(sum_by_level.begin(), sum_by_level.end(), [&damping](auto& sum) { return get(sum) == get(damping); }); //remove active with the same type and level and add new one get(sum_same_level) += get(damping) - get(active_same_type).get(); //avoid negative values due to rounding error if e.g. a previous damping is lifted - get(sum_same_level) = get(sum_same_level).cwiseMax(0.); + get(sum_same_level) = get(sum_same_level).cwiseMax(0.); get(active_same_type) = get(damping); } else { From c24c93d38e4e35229297211af32fbe2f66754adf Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:04:39 +0100 Subject: [PATCH 050/488] Remove parallel region in paper_abm_bs_testing.cpp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a39ea75832..b790775569 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -878,16 +878,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution determine_initial_infection_states_world(input_dir, start_date); - int tid = -1; -#pragma omp parallel private(tid) // Start of parallel region: forks threads - { - tid = omp_get_thread_num(); // default is number of CPUs on machine - printf("Hello from Thread %d\n", tid); - if (tid == 0) { - printf("Number of threads = %d\n", omp_get_num_threads()); - } - } // ** end of the the parallel: joins threads - // Create one world for all simulations that will be copied auto world = mio::abm::World(num_age_groups); create_sampled_world(world, input_dir, t0, max_num_persons); From 024e5cf6102c913d2e7d6c77e048b29c8c39140b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 5 Mar 2024 17:14:32 +0100 Subject: [PATCH 051/488] prepare for jureca Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b790775569..67a03dfcf3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -873,7 +873,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 1000; + auto max_num_persons = 230000; // Determine inital infection state distribution determine_initial_infection_states_world(input_dir, start_date); @@ -977,8 +977,7 @@ int main(int argc, char** argv) printf("abm_braunschweig \n"); printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - printf("Running with number of runs = 1.\n"); - num_runs = 15; + num_runs = 25; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From cc7e08371621b7a1b1bac74ddaaaef729b39b300 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 6 Mar 2024 10:17:23 +0100 Subject: [PATCH 052/488] Improve plotting, including testing schemese --- cpp/simulations/analyze_bs_run.py | 102 ++++++++++++++--------- cpp/simulations/paper_abm_bs_testing.cpp | 86 +++++++++++++++++-- 2 files changed, 142 insertions(+), 46 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index debacf9a90..3f60ee0ce8 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -19,48 +19,48 @@ import matplotlib.lines as mlines import h5py -def main(n_runs): - # read in folder and convert txt files to numpy arrays - # folder path - folder_path = "memilio/epidata/folder_run_bs" +def main(path, n_runs): # get first_file in folder - first_file = os.listdir(folder_path)[0] - file_path = os.path.join(folder_path, first_file) + # first_file = os.listdir(path)[0] + # file_path = os.path.join(path, first_file) # read in txt file - df = pd.read_csv(file_path, delim_whitespace=True) + # df = pd.read_csv(file_path, delim_whitespace=True) # convert to numpy array - df_np = df.to_numpy() + # df_np = df.to_numpy() # get the number of rows and columns - num_rows = df_np.shape[0] - num_cols = df_np.shape[1] + # num_rows = df_np.shape[0] + # num_cols = df_np.shape[1] # get the number of compartments - num_compartments = num_cols - 1 + # num_compartments = num_cols - 1 # get the number of time steps - num_time_steps = num_rows-1 + # num_time_steps = num_rows-1 # get the compartment names - compartment_names = df.columns[1:] + # compartment_names = df.columns[1:] # get the time steps - time_steps = df_np[:, 0] + # time_steps = df_np[:, 0] # get number of files in folder - num_files = len([entry for entry in os.listdir(folder_path)]) + # num_files = len([entry for entry in os.listdir(path)]) # read in each txt file and convert to numpy array - df_np_3d = np.empty((num_rows, num_cols, n_runs)) - for (file, i) in zip(os.listdir(folder_path), range(n_runs)): - file_path = os.path.join(folder_path, file) + # df_np_3d = np.empty((num_rows, num_cols, n_runs)) + print(os.listdir(path)) + for file in os.listdir(path): + file_path = os.path.join(path, file) # read in txt file - df = pd.read_csv(file_path, delim_whitespace=True) - if file.startswith("infection_per_location_type"): + + if file.startswith("infection_per_location_type.txt"): + df = pd.read_csv(file_path, delim_whitespace=True) plot_infection_per_location_type(df) - if file.startswith("infection_per_age_group"): - plot_infection_per_age_group(df) - if file.startswith("run_"): + if file.startswith("infection_per_age_group.txt"): + df = pd.read_csv(file_path, delim_whitespace=True) + #plot_infection_per_age_group(df) + # if file.startswith("run_"): # convert to numpy array - df_np = df.to_numpy() + # df_np = df.to_numpy() # attach to array - df_np_3d[:, :, i] = df_np - plot_mean_and_std(df_np_3d) + # df_np_3d[:, :, i] = df_np + # plot_mean_and_std(df_np_3d) def plot_infection_per_location_type(df): @@ -92,29 +92,52 @@ def plot_results(path): # 05-percentile f = h5py.File( - path+"/infection_state_per_age_group/p05/Results.h5", 'r') + path+"/infection_state_per_age_group/p25/Results.h5", 'r') group = f['0'] - total_05 = group['Total'][()] + total_25 = group['Total'][()] f.close() # 95-percentile f = h5py.File( - path + "/infection_state_per_age_group/p95/Results.h5", 'r') + path + "/infection_state_per_age_group/p75/Results.h5", 'r') group = f['0'] - total_95 = group['Total'][()] + total_75 = group['Total'][()] f.close() - plot_infection_states(time, total_50, total_05, total_95) - x=1 + plot_infection_states(time, total_50, total_25, total_75) -def plot_infection_states(x, y50, y05, y95): +def plot_infection_states(x, y50, y25, y75): + plt.figure('Infection_states') plt.plot(x, y50) plt.legend(['S', 'E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Rec', 'Dead']) for i in range(y50.shape[1]): - plt.fill_between(x, y50[:, i], y05[:, i], alpha=0.1) - plt.fill_between(x, y50[:, i], y95[:, i], alpha=0.1) + plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.1) + plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.1) + + +def plot_infections_per_age_group(path): + f = h5py.File( + path+"/infection_per_age_group/p50/Results.h5", 'r') + + # Get the HDF5 group; key needs to be a group name from above + group = f['0'] + + # This assumes group[some_key_inside_the_group] is a dataset, + # and returns a np.array: + time = group['Time'][()] + + plt.figure('Age_Group') + for g in ['Group' + str(n) for n in range(1, 7)]: + gr = group[g][()] + plt.plot(time, gr) + + plt.legend(['0-4', '5-14', '15-34', '35-59', '60-79', '80+']) + + # After you are done + f.close() + def plot_mean_and_std(Y): @@ -139,12 +162,11 @@ def plot_mean_and_std(Y): if __name__ == "__main__": #path to results - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" + path = "/Users/David/Documents/HZI/memilio/data/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: - folder_path = path - n_runs = len([entry for entry in os.listdir(folder_path) - if os.path.isfile(os.path.join(folder_path, entry))]) - #main(n_runs) + n_runs = len([entry for entry in os.listdir(path) + if os.path.isfile(os.path.join(path, entry))]) plot_results(path) + main(path, n_runs) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f559c81007..4a5dddaeac 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -55,7 +55,7 @@ const std::map infection_ {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; mio::CustomIndexArray initial_infection_distribution{ - {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.}; + {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.02}; /** * Determine initial distribution of infection states. @@ -695,6 +695,44 @@ void set_local_parameters(mio::abm::World& world) } } +/** + * @brief Add testing strategies to the world. +*/ +void add_testing_strategies(mio::abm::World& world, bool school, bool work, bool symptomatic) +{ + // Tests in schools + auto testing_criteria_school = mio::abm::TestingCriteria(); + + auto testing_min_time = mio::abm::days(7); + auto start_date = mio::abm::TimePoint(0); + auto end_date = mio::abm::TimePoint(0) + mio::abm::days(60); + auto test_type = mio::abm::AntigenTest(); + auto probability = mio::UncertainValue(); + assign_uniform_distribution(probability, 0.5, 0.5); + + auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date, + end_date, test_type, probability.draw_sample()); + if (school) + world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); + + // Tests in work places + auto testing_criteria_work = mio::abm::TestingCriteria(); + + assign_uniform_distribution(probability, 0.5, 0.5); + auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, + test_type, probability.draw_sample()); + if (work) + world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); + + // Test when symptomatic + auto testing_criteria_symptomatic = mio::abm::TestingCriteria({}, {mio::abm::InfectionState::InfectedSymptoms}); + auto testing_scheme_symptomatic = + mio::abm::TestingScheme(testing_criteria_symptomatic, testing_min_time, start_date, end_date, test_type, 0.7); + + if (symptomatic) + world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_symptomatic); +} + /** * Create a sampled simulation with start time t0. * @param t0 The start time of the Simulation. @@ -728,6 +766,8 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con //2. testing scheme: Test bei Symptomen (unabh. von Location, 1x am Tag, InfectedSymptomatic, 70% der Bevölkerung) ab Tag 0 //3. testen in schulen und Arbeitsplätzen (unabh. von Alter, 1x am Tag, unabh. von InfectionState) ab Tag 0 //4. 2.+3. + + add_testing_strategies(world, false, false, false); } template @@ -834,6 +874,25 @@ void write_txt_file_for_graphical_compartment_output(std::vector +void write_log_to_file_infection_per_location_type(const T& history, const fs::path& result_dir) +{ + std::ofstream myfile4((result_dir / "infection_per_location_type.txt").string()); + const std::vector& labels = { + "Home", "Work", "School", "SocialEvent", "BasicsShop", + "Hospital", "ICU", "Car", "PublicTransport", "TransportWithoutContact", + "Cemetery"}; + std::get<0>(history.get_log()).print_table(labels, 12, 4, myfile4); +} + +template +void write_log_to_file_infection_per_age_group(const T& history, const fs::path& result_dir) +{ + std::ofstream myfile5((result_dir / "infection_per_age_group.txt").string()); + const std::vector& labels = {"0_to_4", "5_to_14", "15_to_34", "35_to_59", "60_to_79", "80_plus"}; + std::get<0>(history.get_log()).print_table(labels, 7, 4, myfile5); +} + struct LogInfectionStatePerAgeGroup : mio::LogAlways { using Type = std::pair; /** @@ -865,7 +924,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s { mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(30); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -878,10 +937,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 300000; + auto max_num_persons = 1000; // Determine inital infection state distribution - determine_initial_infection_states_world(input_dir, start_date); + printf("Compute initial infection distribution for real world data... "); + //determine_initial_infection_states_world(input_dir, start_date); + printf("done.\n"); int tid = -1; #pragma omp parallel private(tid) // Start of parallel region: forks threads @@ -902,7 +963,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groups); + create_sampled_world(world, input_dir, t0, max_num_persons); + // auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED! auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -943,14 +1006,24 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s /* if (save_result_result && save_single_runs) { auto result_dir_run = result_dir / ("abm_result_run_" + std::to_string(run_idx) + ".h5"); BOOST_OUTCOME_TRY(save_result(ensemble_results.back(), {0}, 1, result_dir_run.string())); + result_dir_run = result_dir / ("abm_result_infections_per_loc_run_" + std::to_string(run_idx) + ".h5"); + BOOST_OUTCOME_TRY( + save_result(ensemble_results_infections_per_loc.back(), loc_type_ids, 1, result_dir_run.string())); + result_dir_run = result_dir / ("abm_result_infections_per_age_run_" + std::to_string(run_idx) + ".h5"); + BOOST_OUTCOME_TRY( + save_result(ensemble_results_infections_per_age.back(), age_group_ids, 1, result_dir_run.string())); } */ write_log_to_file_person_and_location_data(historyPersonInf); write_log_to_file_trip_data(historyPersonInfDelta); + write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup, result_dir); + write_log_to_file_infection_per_location_type(historyInfectionPerLocationType, result_dir); std::cout << "Run " << run_idx << " of " << num_runs << " finished." << std::endl; ++run_idx; } + printf("Saving results ... "); + BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, result_dir / "infection_per_location_type/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_age_group, ensemble_params, {0}, @@ -958,6 +1031,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); + printf("done.\n"); //write_txt_file_for_graphical_compartment_output(ensemble_infection_state_per_age_group); BOOST_OUTCOME_TRY(save_result_result); return mio::success(); @@ -967,7 +1041,7 @@ int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::warn); - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -993,7 +1067,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); printf("Running with number of runs = 1.\n"); - num_runs = 100; + num_runs = 10; } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From 750373ac379867373633d99a3db6eefa08e6ca9b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 6 Mar 2024 10:45:53 +0100 Subject: [PATCH 053/488] timer Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 41 +++++++++++++----------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1b7fbfc191..37ab9a1ae8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "abm/abm.h" #include "memilio/io/result_io.h" #include "memilio/utils/uncertain_value.h" @@ -923,7 +924,6 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { - mio::Date start_date{2021, 3, 1}; mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation @@ -939,34 +939,28 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 230000; + auto max_num_persons = 10000; // Determine inital infection state distribution printf("Compute initial infection distribution for real world data... "); - //determine_initial_infection_states_world(input_dir, start_date); + determine_initial_infection_states_world(input_dir, start_date); printf("done.\n"); - int tid = -1; -#pragma omp parallel private(tid) // Start of parallel region: forks threads - { - tid = omp_get_thread_num(); // default is number of CPUs on machine - printf("Hello from Thread %d\n", tid); - if (tid == 0) { - printf("Number of threads = %d\n", omp_get_num_threads()); - } - } // ** end of the the parallel: joins threads - // Create one world for all simulations that will be copied - auto world = mio::abm::World(num_age_groups); - create_sampled_world(world, input_dir, t0, max_num_persons); + // auto world = mio::abm::World(num_age_groups); + // create_sampled_world(world, input_dir, t0, max_num_persons); // Loop over a number of runs while (run_idx <= num_runs) { - + // Start the clock before create_sampled_world + auto start1 = std::chrono::high_resolution_clock::now(); // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groups); - create_sampled_world(world, input_dir, t0, max_num_persons); + // Stop the clock after create_sampled_world and calculate the duration + auto stop1 = std::chrono::high_resolution_clock::now(); + auto duration1 = std::chrono::duration(stop1 - start1); + std::cout << "Time taken by create_sampled_world: " << duration1.count() << " seconds" << std::endl; // auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED! auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -988,9 +982,17 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : sim.get_world().get_locations()) { loc_ids.push_back(location.get_index()); } + + // Start the clock before sim.advance + auto start2 = std::chrono::high_resolution_clock::now(); // Advance the world to tmax sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, historyPersonInfDelta, historyInfectionStatePerAgeGroup); + // Stop the clock after sim.advance and calculate the duration + auto stop2 = std::chrono::high_resolution_clock::now(); + auto duration2 = std::chrono::duration(stop2 - start2); + std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; + // TODO: update result of the simulation to be a vector of location result. auto temp_sim_infection_per_loc_tpye = std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; @@ -1043,7 +1045,7 @@ int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::warn); - std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -1068,8 +1070,9 @@ int main(int argc, char** argv) printf("abm_braunschweig \n"); printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - printf("Running with number of runs = 1.\n"); + num_runs = 10; + printf("Running with number of runs = %d.\n", (int)num_runs); } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging From b2bb2df83c7508013ae055113cc67a87736cd231 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:06:30 +0100 Subject: [PATCH 054/488] Enable OpenMP for Multithreading Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index a3ed0331df..247cb20e34 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -16,7 +16,7 @@ option(MEMILIO_SANITIZE_UNDEFINED "Enable undefined behavior sanitizer." OFF) option(MEMILIO_BUILD_SHARED_LIBS "Build memilio as a shared library." ON) option(MEMILIO_BUILD_STATIC_LIBS "Build memilio as a static library." ON) option(MEMILIO_ENABLE_MPI "Build memilio with MPI." OFF) -option(MEMILIO_ENABLE_OPENMP "Enable Multithreading with OpenMP." OFF) +option(MEMILIO_ENABLE_OPENMP "Enable Multithreading with OpenMP." ON) mark_as_advanced(MEMILIO_USE_BUNDLED_SPDLOG MEMILIO_SANITIZE_ADDRESS MEMILIO_SANITIZE_UNDEFINED) From b602cac24f9548e30c386dfe520295a503d14282 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:13:07 +0100 Subject: [PATCH 055/488] Add parallel region to print number of threads Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 37ab9a1ae8..15d7be1ebd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -941,6 +941,14 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations auto max_num_persons = 10000; + int tid = -1; +#pragma omp parallel private(tid) // Start of parallel region: forks threads + { + if (tid == 0) { + printf("Number of threads = %d\n", omp_get_num_threads()); + } + } // ** end of the the parallel: joins threads + // Determine inital infection state distribution printf("Compute initial infection distribution for real world data... "); determine_initial_infection_states_world(input_dir, start_date); From 0eaab5da9034cf337d90132f0f328df2db5a9bb1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:23:52 +0100 Subject: [PATCH 056/488] Add thread information to parallel region Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 15d7be1ebd..d087c69ba1 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -944,6 +944,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s int tid = -1; #pragma omp parallel private(tid) // Start of parallel region: forks threads { + tid = omp_get_thread_num(); // default is number of CPUs on machine + printf("Hello from Thread %d\n", tid); if (tid == 0) { printf("Number of threads = %d\n", omp_get_num_threads()); } From 788eb6ae3616ff6561d8ac6c660bfbb757d5de5a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:27:16 +0100 Subject: [PATCH 057/488] Remove print statement in parallel region Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d087c69ba1..6aa0abbe83 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -945,7 +945,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s #pragma omp parallel private(tid) // Start of parallel region: forks threads { tid = omp_get_thread_num(); // default is number of CPUs on machine - printf("Hello from Thread %d\n", tid); if (tid == 0) { printf("Number of threads = %d\n", omp_get_num_threads()); } From 2af0b24ac894bf104280b476e2463de22373b025 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 7 Mar 2024 13:18:19 +0100 Subject: [PATCH 058/488] Add high viral load protection factor interpolation to bench --- cpp/benchmarks/abm.cpp | 7 +++++++ cpp/models/abm/infection.cpp | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index e5d7c75216..77881aeaae 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -1,4 +1,5 @@ #include "abm/simulation.h" +#include "memilio/math/interpolation.h" #include "memilio/utils/stl_util.h" #include "benchmark/benchmark.h" @@ -108,6 +109,12 @@ mio::abm::Simulation make_simulation(size_t num_persons, std::initializer_list() = [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); + }; + return mio::abm::Simulation(mio::abm::TimePoint(0), std::move(world)); } diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 8804aa0c94..8adf2e870e 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -38,8 +38,8 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age auto vl_params = params.get()[{virus, age}]; ScalarType high_viral_load_factor = 1; if (latest_exposure.first != ExposureType::NoProtection) { - auto test = init_date.days() - latest_exposure.second.days(); - high_viral_load_factor -= params.get()(test); + high_viral_load_factor -= + params.get()(init_date.days() - latest_exposure.second.days()); } m_viral_load.peak = vl_params.viral_load_peak.get_distribution_instance()(rng, vl_params.viral_load_peak.params) * high_viral_load_factor; From f4c8e986123a10c4ec16943d023348abe2f7d238 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 7 Mar 2024 13:37:18 +0100 Subject: [PATCH 059/488] Add OpenMP parallelization to abm_benchmark function Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index 77881aeaae..9649ae8d62 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -125,6 +125,14 @@ mio::abm::Simulation make_simulation(size_t num_persons, std::initializer_list seeds) { + int tid = -1; +#pragma omp parallel private(tid) // Start of parallel region: forks threads + { + tid = omp_get_thread_num(); // default is number of CPUs on machine + if (tid == 0) { + printf("Number of threads = %d\n", omp_get_num_threads()); + } + } // ** end of the the parallel: joins threads mio::set_log_level(mio::LogLevel::warn); for (auto&& _ : state) { From 76a929ea75ded1e7272bbe152c027df04ba87008 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:23:17 +0100 Subject: [PATCH 060/488] Attempt to fix logger. Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/models/abm/simulation.h | 5 ++++ cpp/simulations/paper_abm_bs_testing.cpp | 30 +++++++++++------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index 2e25e1d39d..071373a0e8 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -69,7 +69,12 @@ class Simulation (history.log(*this), ...); while (m_t < tmax) { evolve_world(tmax); + double start; + double end; + start = omp_get_wtime(); (history.log(*this), ...); + end = omp_get_wtime(); + printf("Logging took %f seconds\n", end - start); } } diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6aa0abbe83..3b925b8040 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -907,15 +907,13 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero( Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())); auto curr_time = sim.get_time(); - PRAGMA_OMP(for) - for (auto&& location : sim.get_world().get_locations()) { - for (uint32_t age_group = 0; age_group < num_age_groups; age_group++) { - for (uint32_t inf_state = 0; inf_state < (uint32_t)mio::abm::InfectionState::Count; inf_state++) { - sum((((size_t)(mio::abm::InfectionState::Count)) * (age_group)) + inf_state) += - location.get_subpopulation_per_age_group(curr_time, mio::abm::InfectionState(inf_state), - age_group); - } - } + const auto persons = sim.get_world().get_persons(); + + PRAGMA_OMP(parallel for) + for (auto i = size_t(0); i < persons.size(); ++i) { + auto& p = persons[i]; + sum[(((size_t)(mio::abm::InfectionState::Count)) * ((uint32_t)p.get_age().get())) + + ((uint32_t)p.get_infection_state(curr_time))] += 1; } return std::make_pair(curr_time, sum); } @@ -926,7 +924,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s { mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -939,7 +937,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds auto run_idx = size_t(1); // The run index auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 10000; + auto max_num_persons = 100; int tid = -1; #pragma omp parallel private(tid) // Start of parallel region: forks threads @@ -952,7 +950,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution printf("Compute initial infection distribution for real world data... "); - determine_initial_infection_states_world(input_dir, start_date); + //determine_initial_infection_states_world(input_dir, start_date); printf("done.\n"); // Create one world for all simulations that will be copied @@ -995,8 +993,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Start the clock before sim.advance auto start2 = std::chrono::high_resolution_clock::now(); // Advance the world to tmax - sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, - historyPersonInfDelta, historyInfectionStatePerAgeGroup); + sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyPersonInfDelta, + historyInfectionPerAgeGroup, historyInfectionStatePerAgeGroup); // Stop the clock after sim.advance and calculate the duration auto stop2 = std::chrono::high_resolution_clock::now(); auto duration2 = std::chrono::duration(stop2 - start2); @@ -1054,7 +1052,7 @@ int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::warn); - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -1080,7 +1078,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 10; + num_runs = 2; printf("Running with number of runs = %d.\n", (int)num_runs); } From 310d3356bf98051dfe28dd51d5189b85875ca3f5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 8 Mar 2024 16:41:39 +0100 Subject: [PATCH 061/488] paralelize using mpi Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/CMakeLists.txt | 4 +- cpp/models/abm/simulation.h | 7 +- cpp/simulations/paper_abm_bs_testing.cpp | 222 ++++++++++++++++------- 3 files changed, 166 insertions(+), 67 deletions(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 247cb20e34..7c380d141b 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -6,7 +6,7 @@ option(MEMILIO_BUILD_TESTS "Build memilio unit tests." ON) option(MEMILIO_BUILD_EXAMPLES "Build memilio examples." ON) option(MEMILIO_BUILD_MODELS "Build memilio models." ON) option(MEMILIO_BUILD_SIMULATIONS "Build memilio simulations that were used for scientific articles." ON) -option(MEMILIO_BUILD_BENCHMARKS "Build memilio benchmarks with google benchmark." OFF) +option(MEMILIO_BUILD_BENCHMARKS "Build memilio benchmarks with google benchmark." ON) option(MEMILIO_USE_BUNDLED_SPDLOG "Use spdlog bundled with epi" ON) option(MEMILIO_USE_BUNDLED_EIGEN "Use eigen bundled with epi" ON) option(MEMILIO_USE_BUNDLED_BOOST "Use boost bundled with epi (only for epi-io)" ON) @@ -15,7 +15,7 @@ option(MEMILIO_SANITIZE_ADDRESS "Enable address sanitizer." OFF) option(MEMILIO_SANITIZE_UNDEFINED "Enable undefined behavior sanitizer." OFF) option(MEMILIO_BUILD_SHARED_LIBS "Build memilio as a shared library." ON) option(MEMILIO_BUILD_STATIC_LIBS "Build memilio as a static library." ON) -option(MEMILIO_ENABLE_MPI "Build memilio with MPI." OFF) +option(MEMILIO_ENABLE_MPI "Build memilio with MPI." ON) option(MEMILIO_ENABLE_OPENMP "Enable Multithreading with OpenMP." ON) mark_as_advanced(MEMILIO_USE_BUNDLED_SPDLOG MEMILIO_SANITIZE_ADDRESS MEMILIO_SANITIZE_UNDEFINED) diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index 071373a0e8..6349cb2a61 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -67,15 +67,16 @@ class Simulation { //log initial system state (history.log(*this), ...); + double sum = 0; while (m_t < tmax) { evolve_world(tmax); - double start; - double end; + double start, end; start = omp_get_wtime(); (history.log(*this), ...); end = omp_get_wtime(); - printf("Logging took %f seconds\n", end - start); + sum = sum + (end - start); } + std::cout << "Time spent on logging: " << sum << std::endl; } /** diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3b925b8040..da76a0f432 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -31,6 +31,8 @@ #include "abm/vaccine.h" #include "abm/common_abm_loggers.h" #include "generate_graph_from_data.cpp" +#include "memilio/utils/miompi.h" +#include "memilio/io/binary_serializer.h" namespace fs = boost::filesystem; @@ -906,59 +908,127 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero( Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())); - auto curr_time = sim.get_time(); + auto curr_time = sim.get_time(); const auto persons = sim.get_world().get_persons(); PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < persons.size(); ++i) { - auto& p = persons[i]; - sum[(((size_t)(mio::abm::InfectionState::Count)) * ((uint32_t)p.get_age().get())) + - ((uint32_t)p.get_infection_state(curr_time))] += 1; + auto& p = persons[i]; + auto index = (((size_t)(mio::abm::InfectionState::Count)) * ((uint32_t)p.get_age().get())) + + ((uint32_t)p.get_infection_state(curr_time)); + // PRAGMA_OMP(atomic) + sum[index] += 1; } return std::make_pair(curr_time, sum); } }; +template +T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) +{ + auto gathered_ensemble_vec = T{}; + + if (rank == 0) { + gathered_ensemble_vec.reserve(num_runs); + std::copy(ensemble_vec.begin(), ensemble_vec.end(), std::back_inserter(gathered_ensemble_vec)); + for (int src_rank = 1; src_rank < num_procs; ++src_rank) { + int bytes_size; + MPI_Recv(&bytes_size, 1, MPI_INT, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); + mio::ByteStream bytes(bytes_size); + MPI_Recv(bytes.data(), bytes.data_size(), MPI_BYTE, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); + + auto src_ensemble_results = mio::deserialize_binary(bytes, mio::Tag{}); + if (!src_ensemble_results) { + mio::log_error("Error receiving ensemble results from rank {}.", src_rank); + } + std::copy(src_ensemble_results.value().begin(), src_ensemble_results.value().end(), + std::back_inserter(gathered_ensemble_vec)); + } + } + else { + auto bytes = mio::serialize_binary(ensemble_vec); + auto bytes_size = int(bytes.data_size()); + MPI_Send(&bytes_size, 1, MPI_INT, 0, 0, mio::mpi::get_world()); + MPI_Send(bytes.data(), bytes.data_size(), MPI_BYTE, 0, 0, mio::mpi::get_world()); + } + return gathered_ensemble_vec; +} + +std::vector distribute_runs(size_t num_runs, int num_procs) +{ + //evenly distribute runs + //lower processes do one more run if runs are not evenly distributable + auto num_runs_local = num_runs / num_procs; //integer division! + auto remainder = num_runs % num_procs; + + std::vector run_distribution(num_procs); + std::fill(run_distribution.begin(), run_distribution.begin() + remainder, num_runs_local + 1); + std::fill(run_distribution.begin() + remainder, run_distribution.end(), num_runs_local); + + return run_distribution; +} + mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { + int num_procs, rank; +#ifdef MEMILIO_ENABLE_MPI + MPI_Comm_size(mio::mpi::get_world(), &num_procs); + MPI_Comm_rank(mio::mpi::get_world(), &rank); +#else + num_procs = 1; + rank = 0; +#endif + + auto run_distribution = distribute_runs(num_runs, num_procs); + auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); + auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; + mio::Date start_date{2021, 3, 1}; - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(1); // End time per simulation - auto ensemble_infection_per_loc_type = - std::vector>>{}; // Vector of infection per location type results - ensemble_infection_per_loc_type.reserve(size_t(num_runs)); - auto ensemble_infection_per_age_group = - std::vector>>{}; // Vector of infection per age group results - ensemble_infection_per_age_group.reserve(size_t(num_runs)); + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(40); // End time per simulation + auto max_num_persons = 30000; + // auto ensemble_infection_per_loc_type = + // std::vector>>{}; // Vector of infection per location type results + // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); + // auto ensemble_infection_per_age_group = + // std::vector>>{}; // Vector of infection per age group results + // ensemble_infection_per_age_group.reserve(size_t(num_runs)); + auto ensemble_infection_state_per_age_group = std::vector>>{}; // Vector of infection state per age group results ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); - auto ensemble_params = std::vector>{}; // Vector of all worlds - auto run_idx = size_t(1); // The run index - auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - auto max_num_persons = 100; + auto ensemble_params = std::vector>{}; // Vector of all worlds + ensemble_params.reserve(size_t(num_runs)); + // auto run_idx = size_t(1); // The run index + // auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations int tid = -1; #pragma omp parallel private(tid) // Start of parallel region: forks threads { tid = omp_get_thread_num(); // default is number of CPUs on machine + printf("Hello World from thread = %d and rank = %d\n", tid, rank); if (tid == 0) { printf("Number of threads = %d\n", omp_get_num_threads()); } } // ** end of the the parallel: joins threads // Determine inital infection state distribution - printf("Compute initial infection distribution for real world data... "); - //determine_initial_infection_states_world(input_dir, start_date); - printf("done.\n"); + //Time this + auto start0 = std::chrono::high_resolution_clock::now(); + determine_initial_infection_states_world(input_dir, start_date); + auto stop0 = std::chrono::high_resolution_clock::now(); + auto duration0 = std::chrono::duration(stop0 - start0); + std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" + << std::endl; // Create one world for all simulations that will be copied // auto world = mio::abm::World(num_age_groups); // create_sampled_world(world, input_dir, t0, max_num_persons); // Loop over a number of runs - while (run_idx <= num_runs) { + for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { + // Start the clock before create_sampled_world auto start1 = std::chrono::high_resolution_clock::now(); // Create the sampled simulation with start time t0. @@ -973,46 +1043,47 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto sim = mio::abm::Simulation(t0, std::move(world)); //output object - mio::History - historyPersonInf; - mio::History historyPersonInfDelta; - mio::History historyInfectionPerLocationType{ - Eigen::Index(mio::abm::LocationType::Count)}; - mio::History historyInfectionPerAgeGroup{ - Eigen::Index(sim.get_world().parameters.get_num_groups())}; + // mio::History + // historyPersonInf; + // mio::History historyPersonInfDelta; + // mio::History historyInfectionPerLocationType{ + // Eigen::Index(mio::abm::LocationType::Count)}; + // mio::History historyInfectionPerAgeGroup{ + // Eigen::Index(sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; // Collect the id of location in world. - std::vector loc_ids; - for (auto& location : sim.get_world().get_locations()) { - loc_ids.push_back(location.get_index()); - } + // std::vector loc_ids; + // for (auto& location : sim.get_world().get_locations()) { + // loc_ids.push_back(location.get_index()); + // } // Start the clock before sim.advance auto start2 = std::chrono::high_resolution_clock::now(); // Advance the world to tmax - sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyPersonInfDelta, - historyInfectionPerAgeGroup, historyInfectionStatePerAgeGroup); + // sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, + // historyPersonInfDelta, historyInfectionStatePerAgeGroup); + sim.advance(tmax, historyInfectionStatePerAgeGroup); // Stop the clock after sim.advance and calculate the duration auto stop2 = std::chrono::high_resolution_clock::now(); auto duration2 = std::chrono::duration(stop2 - start2); std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_infection_per_loc_tpye = - std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; - auto temp_sim_infection_per_age_group = - std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; + // auto temp_sim_infection_per_loc_tpye = + // std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + // auto temp_sim_infection_per_age_group = + // std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; // Push result of the simulation back to the result vector - ensemble_infection_per_loc_type.push_back(temp_sim_infection_per_loc_tpye); - ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); - ensemble_params.push_back(std::vector{sim.get_world()}); - ensemble_infection_state_per_age_group.push_back(temp_sim_infection_state_per_age_group); + // ensemble_infection_per_loc_type.push_back(temp_sim_infection_per_loc_tpye); + // ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); + // ensemble_params.push_back(std::vector{sim.get_world()}); + ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); // Option to save the current run result to file /* if (save_result_result && save_single_runs) { auto result_dir_run = result_dir / ("abm_result_run_" + std::to_string(run_idx) + ".h5"); @@ -1024,35 +1095,59 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s BOOST_OUTCOME_TRY( save_result(ensemble_results_infections_per_age.back(), age_group_ids, 1, result_dir_run.string())); } */ - write_log_to_file_person_and_location_data(historyPersonInf); - write_log_to_file_trip_data(historyPersonInfDelta); - write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup, result_dir); - write_log_to_file_infection_per_location_type(historyInfectionPerLocationType, result_dir); - - std::cout << "Run " << run_idx << " of " << num_runs << " finished." << std::endl; - ++run_idx; + // write_log_to_file_person_and_location_data(historyPersonInf); + // write_log_to_file_trip_data(historyPersonInfDelta); + // write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup, result_dir); + // write_log_to_file_infection_per_location_type(historyInfectionPerLocationType, result_dir); + + std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; + + //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); + //for now this doesnt work, but we can still save the results of the last world since the + //parameters are the same for each run + if (rank == 0 && run_idx == end_run_idx - 1) { + for (size_t i = 0; i < num_runs; i++) { + ensemble_params.emplace_back(std::vector{sim.get_world()}); + } + } } printf("Saving results ... "); - BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, - result_dir / "infection_per_location_type/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_age_group, ensemble_params, {0}, - result_dir / "infection_per_age_group/", save_single_runs)); +#ifdef MEMILIO_ENABLE_MPI + //gather results + auto final_ensemble_infection_state_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); + if (rank == 0) { + BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, + result_dir / "infection_state_per_age_group/", save_single_runs)); + } +#else + BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); +#endif + + // BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, + // result_dir / "infection_per_location_type/", save_single_runs)); + // BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_age_group, ensemble_params, {0}, + // result_dir / "infection_per_age_group/", save_single_runs)); + printf("done.\n"); //write_txt_file_for_graphical_compartment_output(ensemble_infection_state_per_age_group); - BOOST_OUTCOME_TRY(save_result_result); + // BOOST_OUTCOME_TRY(save_result_result); return mio::success(); } int main(int argc, char** argv) { - mio::set_log_level(mio::LogLevel::warn); + mio::set_log_level(mio::LogLevel::err); +#ifdef MEMILIO_ENABLE_MPI + mio::mpi::init(); +#endif - std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -1078,21 +1173,24 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 2; + num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); } // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging - //printf("Seeds: "); - //for (auto s : mio::thread_local_rng().get_seeds()) { - // printf("%u, ", s); - //} - //printf("\n"); + // printf("Seeds: "); + // for (auto s : mio::thread_local_rng().get_seeds()) { + // printf("%u, ", s); + // } + // printf("\n"); auto result = run(input_dir, result_dir, num_runs, save_single_runs); if (!result) { printf("%s\n", result.error().formatted_message().c_str()); + mio::mpi::finalize(); return -1; } + + mio::mpi::finalize(); return 0; } From 6e4285aa881509f30f707ee622cccfac5785ce51 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:42:16 +0100 Subject: [PATCH 062/488] Update max_num_persons value in paper_abm_bs_testing.cpp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index da76a0f432..3433036523 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -911,7 +911,7 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { auto curr_time = sim.get_time(); const auto persons = sim.get_world().get_persons(); - PRAGMA_OMP(parallel for) + // PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < persons.size(); ++i) { auto& p = persons[i]; auto index = (((size_t)(mio::abm::InfectionState::Count)) * ((uint32_t)p.get_age().get())) + @@ -987,7 +987,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(40); // End time per simulation - auto max_num_persons = 30000; + auto max_num_persons = 100000; // auto ensemble_infection_per_loc_type = // std::vector>>{}; // Vector of infection per location type results // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -1173,7 +1173,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 1; + num_runs = 124; printf("Running with number of runs = %d.\n", (int)num_runs); } From f1e80096bade784c31a75a828b316467d85a57a3 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Sun, 10 Mar 2024 10:43:16 +0100 Subject: [PATCH 063/488] Fix multihread memory allocation for vectors in logging --- cpp/models/abm/common_abm_loggers.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index dbe6a7d602..3525f43609 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -89,6 +89,7 @@ struct LogLocationInformation : mio::LogOnce { static Type log(const mio::abm::Simulation& sim) { Type location_information{}; + location_information.reserve(sim.get_world().get_locations().size()); for (auto&& location : sim.get_world().get_locations()) { auto n_cells = location.get_cells().size(); int loc_capacity = 0; @@ -119,6 +120,7 @@ struct LogPersonInformation : mio::LogOnce { static Type log(const mio::abm::Simulation& sim) { Type person_information{}; + person_information.reserve(sim.get_world().get_persons().size()); for (auto&& person : sim.get_world().get_persons()) { person_information.push_back(std::make_tuple( person.get_person_id(), sim.get_world().find_location(mio::abm::LocationType::Home, person).get_index(), @@ -148,7 +150,9 @@ struct LogDataForMovement : mio::LogAlways { static Type log(const mio::abm::Simulation& sim) { Type movement_data{}; - for (Person p : sim.get_world().get_persons()) { + movement_data.reserve(sim.get_world().get_persons().size()); + PRAGMA_OMP(parallel for) + for (auto&& p : sim.get_world().get_persons()) { movement_data.push_back(std::make_tuple( p.get_person_id(), p.get_location().get_index(), sim.get_time(), p.get_last_transport_mode(), guess_activity_type(p.get_location().get_type()), p.get_infection_state(sim.get_time()))); @@ -172,7 +176,7 @@ struct LogInfectionState : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::InfectionState::Count)); auto curr_time = sim.get_time(); - PRAGMA_OMP(for) + PRAGMA_OMP(parallel for) for (auto&& location : sim.get_world().get_locations()) { for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); @@ -197,7 +201,7 @@ struct LogInfectionPerLocationType : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::LocationType::Count)); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - PRAGMA_OMP(for) + PRAGMA_OMP(parallel for) for (auto&& person : sim.get_world().get_persons()) { if (person.is_home_in_bs() && (person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && @@ -224,7 +228,7 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - PRAGMA_OMP(for) + PRAGMA_OMP(parallel for) for (auto&& person : sim.get_world().get_persons()) { if (person.is_home_in_bs() && (person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && From 93370610865678f58c85ec0ad16a773fddb075d8 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Mon, 11 Mar 2024 10:52:34 +0100 Subject: [PATCH 064/488] Change Logger to consider Braunschweig's agent ids from Parameters --- cpp/models/abm/common_abm_loggers.h | 71 +++++++++++++++++++----- cpp/models/abm/location.cpp | 6 +- cpp/models/abm/parameters.h | 19 ++++++- cpp/models/abm/person.cpp | 4 +- cpp/models/abm/person.h | 12 +--- cpp/models/abm/world.cpp | 4 +- cpp/models/abm/world.h | 3 +- cpp/simulations/abm_braunschweig.cpp | 32 ++++------- cpp/simulations/paper_abm_bs_testing.cpp | 9 ++- 9 files changed, 99 insertions(+), 61 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index 3525f43609..a7ec250ded 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -166,6 +166,8 @@ struct LogDataForMovement : mio::LogAlways { */ struct LogInfectionState : mio::LogAlways { using Type = std::pair; + std::unordered_set ids_in_bs; + /** * @brief Log the TimeSeries of the number of Person%s in an #InfectionState. * @param[in] sim The simulation of the abm. @@ -173,13 +175,27 @@ struct LogInfectionState : mio::LogAlways { */ static Type log(const mio::abm::Simulation& sim) { - Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::InfectionState::Count)); auto curr_time = sim.get_time(); + auto ids_in_bs = sim.get_world().parameters.get(); PRAGMA_OMP(parallel for) - for (auto&& location : sim.get_world().get_locations()) { - for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { - sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); + // If there is no interresting person ids to logged, log all persons. + if (ids_in_bs.size() == 0) { + for (auto&& location : sim.get_world().get_locations()) { + for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { + sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); + } + } + } + // Otherwise log accordingly + else { + for (auto&& person : sim.get_world().get_persons()) { + for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { + if (person.get_infection_state(curr_time) == mio::abm::InfectionState(inf_state) && + ids_in_bs.find(person.get_person_id()) != ids_in_bs.end()) { + sum[inf_state] += 1; + } + } } } return std::make_pair(curr_time, sum); @@ -201,12 +217,25 @@ struct LogInfectionPerLocationType : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::LocationType::Count)); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); + auto ids_in_bs = sim.get_world().parameters.get(); PRAGMA_OMP(parallel for) - for (auto&& person : sim.get_world().get_persons()) { - if (person.is_home_in_bs() && - (person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { - sum[(int)(person.get_location().get_type())] += 1; + // If there is no interresting person ids to logged, log all persons. + if (ids_in_bs.size() == 0) { + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + sum[(int)(person.get_location().get_type())] += 1; + } + } + } + // Otherwise log accordingly + else { + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && + (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { + sum[(int)(person.get_location().get_type())] += 1; + } } } return std::make_pair(curr_time, sum); @@ -228,14 +257,28 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); + auto ids_in_bs = sim.get_world().parameters.get(); PRAGMA_OMP(parallel for) - for (auto&& person : sim.get_world().get_persons()) { - if (person.is_home_in_bs() && - (person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { - sum[(size_t)(person.get_age())] += 1; + // If there is no interresting person ids to logged, log all persons. + if (ids_in_bs.size() == 0) { + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + sum[(size_t)(person.get_age())] += 1; + } } } + // Otherwise log accordingly + else { + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && + (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { + sum[(size_t)(person.get_age())] += 1; + } + } + } + return std::make_pair(curr_time, sum); } }; diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index e806e1c138..5c5c20a0ae 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -206,14 +206,14 @@ ScalarType Cell::compute_space_per_person_relative() size_t Cell::get_subpopulation(TimePoint t, InfectionState state) const { return count_if(m_persons.begin(), m_persons.end(), [&](observer_ptr p) { - return p->get_infection_state(t) == state && p->is_home_in_bs(); + return p->get_infection_state(t) == state; }); } size_t Location::get_subpopulation(TimePoint t, InfectionState state) const { return count_if(m_persons.begin(), m_persons.end(), [&](observer_ptr p) { - return p->get_infection_state(t) == state && p->is_home_in_bs(); + return p->get_infection_state(t) == state; }); } @@ -221,7 +221,7 @@ size_t Location::get_subpopulation_per_age_group(TimePoint t, InfectionState sta { mio::unused(age_group); return count_if(m_persons.begin(), m_persons.end(), [&](observer_ptr p) { - return p->get_infection_state(t) == state && p->is_home_in_bs() && p->get_age() == age_group; + return p->get_infection_state(t) == state && p->get_age() == age_group; }); } diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index d10cdc1cfc..fd88a316bf 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -32,7 +32,7 @@ #include "memilio/epidemiology/damping.h" #include "memilio/epidemiology/contact_matrix.h" #include -#include +#include namespace mio { @@ -636,6 +636,21 @@ struct AgeGroupGotoWork { } }; +/** + * @brief The set of Agent Ids to be logged. + */ +struct LogAgentIds { + using Type = std::unordered_set; + static Type get_default(AgeGroup /*num_agegroups*/) + { + return {}; + } + static std::string name() + { + return "LogAgentIds"; + } +}; + using ParametersBase = ParameterSet; + InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, LogAgentIds>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index 5119de98de..fa06b3a6d7 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -32,8 +32,7 @@ namespace mio namespace abm { -Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t person_id, - bool is_home_in_bs) +Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t person_id) : m_location(&location) , m_assigned_locations((uint32_t)LocationType::Count, INVALID_LOCATION_INDEX) , m_quarantine_start(TimePoint(-(std::numeric_limits::max() / 2))) @@ -46,7 +45,6 @@ Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age , m_person_id(person_id) , m_cells{0} , m_last_transport_mode(TransportMode::Unknown) - , m_is_home_in_bs(is_home_in_bs) { m_random_workgroup = UniformDistribution::get_instance()(rng); m_random_schoolgroup = UniformDistribution::get_instance()(rng); diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index 0128ba403a..d52267ee5f 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -130,7 +130,7 @@ class Person * @param[in] is_home_in_bs Whether the Person has a home in Braunschweig. */ explicit Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, - uint32_t person_id = INVALID_PERSON_ID, bool is_home_in_bs = true); + uint32_t person_id = INVALID_PERSON_ID); /** * @brief Create a copy of this #Person object with a new Location. @@ -506,15 +506,6 @@ class Person loc, age, id); } - /** - * @brief Whether the Person has a home in Braunschweig. - * @return Whether the Person has a home in Braunschweig. - */ - bool is_home_in_bs() - { - return m_is_home_in_bs; - } - private: observer_ptr m_location; ///< Current Location of the Person. std::vector m_assigned_locations; /**! Vector with the indices of the assigned Locations so that the @@ -536,7 +527,6 @@ class Person std::vector m_cells; ///< Vector with all Cell%s the Person visits at its current Location. mio::abm::TransportMode m_last_transport_mode; ///< TransportMode the Person used to get to its current Location. Counter m_rng_counter{0}; ///< counter for RandomNumberGenerator. - bool m_is_home_in_bs; ///< Whether the Person has a home in Braunschweig. }; } // namespace abm diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index dc02e47e4b..0cb0d8c9b1 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -43,12 +43,12 @@ LocationId World::add_location(LocationType type, uint32_t num_cells) return id; } -Person& World::add_person(const LocationId id, AgeGroup age, bool is_home_in_bs) +Person& World::add_person(const LocationId id, AgeGroup age) { assert(age.get() < parameters.get_num_groups()); uint32_t person_id = static_cast(m_persons.size()); m_persons.push_back( - std::make_unique(m_rng, get_individualized_location(id), age, person_id, is_home_in_bs)); + std::make_unique(m_rng, get_individualized_location(id), age, person_id)); auto& person = *m_persons.back(); person.set_assigned_location(m_cemetery_id); get_individualized_location(id).add_person(person); diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index c479bfc57c..2adf59f329 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -172,10 +172,9 @@ class World * @brief Add a Person to the World. * @param[in] id Index and type of the initial Location of the Person. * @param[in] age AgeGroup of the person. - * @param[in] is_home_in_bs Whether the Person has a home in Braunschweig. * @return Reference to the newly created Person. */ - Person& add_person(const LocationId id, AgeGroup age, bool is_home_in_bs = false); + Person& add_person(const LocationId id, AgeGroup age); /** * @brief Get a range of all Location%s in the World. diff --git a/cpp/simulations/abm_braunschweig.cpp b/cpp/simulations/abm_braunschweig.cpp index 60b04d21ee..bfdef50324 100644 --- a/cpp/simulations/abm_braunschweig.cpp +++ b/cpp/simulations/abm_braunschweig.cpp @@ -41,6 +41,8 @@ const auto age_group_35_to_59 = mio::AgeGroup(3); const auto age_group_60_to_79 = mio::AgeGroup(4); const auto age_group_80_plus = mio::AgeGroup(5); +std::unordered_set ids_in_bs; + /** * Set a value and distribution of an UncertainValue. * Assigns average of min and max as a value and UNIFORM(min, max) as a distribution. @@ -333,12 +335,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, fin.seekg(0); std::getline(fin, line); // Skip header row - // Check if the input file has a column 'home_in_bs' - bool has_column_home_in_bs = false; - if (index.find("home_in_bs") != index.end()) { - has_column_home_in_bs = true; - } - // Add the persons and trips while (std::getline(fin, line)) { row.clear(); @@ -373,23 +369,14 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, auto first_location_id = it_first_location_id->second.first; auto first_location = locations.find(first_location_id)->second; auto home = locations.find(home_id)->second; - // If the a column 'home_in_bs' in the input, assign Person accordingly - if (has_column_home_in_bs) { - uint32_t home_in_bs = row[index["home_in_bs"]]; - auto& person = world.add_person(first_location, determine_age_group(age), home_in_bs == 1); - person.set_assigned_location(home); - person.set_assigned_location(hospital); - person.set_assigned_location(icu); - persons.insert({person_id, person}); - } - // Treat all the Person as they have a home in Braunschweig (default) - else { - auto& person = world.add_person(first_location, determine_age_group(age)); - person.set_assigned_location(home); - person.set_assigned_location(hospital); - person.set_assigned_location(icu); - persons.insert({person_id, person}); + if (row[index["home_in_bs"]] == 1) { + ids_in_bs.insert(person_id); } + auto& person = world.add_person(first_location, determine_age_group(age)); + person.set_assigned_location(home); + person.set_assigned_location(hospital); + person.set_assigned_location(icu); + persons.insert({person_id, person}); it_person = persons.find(person_id); } @@ -405,6 +392,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); } world.get_trip_list().use_weekday_trips_on_weekend(); + world.parameters.get() = ids_in_bs; } void set_parameters(mio::abm::Parameters params) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3433036523..ea62a89cbf 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -339,6 +339,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, fin.clear(); fin.seekg(0); std::getline(fin, line); // Skip header row + std::unordered_set ids_in_bs; // Add the persons and trips while (std::getline(fin, line)) { @@ -374,8 +375,11 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, } auto first_location_id = it_first_location_id->second.first; auto first_location = locations.find(first_location_id)->second; - auto& person = world.add_person(first_location, determine_age_group(age), home_in_bs); - auto home = locations.find(home_id)->second; + auto& person = world.add_person(first_location, determine_age_group(age)); + if (home_in_bs) { + ids_in_bs.insert(person_id); + } + auto home = locations.find(home_id)->second; person.set_assigned_location(home); person.set_assigned_location(hospital); person.set_assigned_location(icu); @@ -395,6 +399,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); } world.get_trip_list().use_weekday_trips_on_weekend(); + world.parameters.get() = ids_in_bs; } std::pair get_my_and_sigma(std::pair mean_and_std) From 5140b71c5615015a24a66cf3d0f087e7ab586743 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 15 Mar 2024 09:16:57 +0100 Subject: [PATCH 065/488] omp fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/common_abm_loggers.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index a7ec250ded..c40b62e567 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -178,9 +178,10 @@ struct LogInfectionState : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::InfectionState::Count)); auto curr_time = sim.get_time(); auto ids_in_bs = sim.get_world().parameters.get(); - PRAGMA_OMP(parallel for) + // If there is no interresting person ids to logged, log all persons. if (ids_in_bs.size() == 0) { + PRAGMA_OMP(parallel for) for (auto&& location : sim.get_world().get_locations()) { for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); @@ -218,9 +219,9 @@ struct LogInfectionPerLocationType : mio::LogAlways { auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); auto ids_in_bs = sim.get_world().parameters.get(); - PRAGMA_OMP(parallel for) // If there is no interresting person ids to logged, log all persons. if (ids_in_bs.size() == 0) { + PRAGMA_OMP(parallel for) for (auto&& person : sim.get_world().get_persons()) { if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { @@ -258,9 +259,10 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); auto ids_in_bs = sim.get_world().parameters.get(); - PRAGMA_OMP(parallel for) + // If there is no interresting person ids to logged, log all persons. if (ids_in_bs.size() == 0) { + PRAGMA_OMP(parallel for) for (auto&& person : sim.get_world().get_persons()) { if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { From 36a523285a6632beb9a7a9feb5a62ca25938d50f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 15 Mar 2024 14:11:58 +0100 Subject: [PATCH 066/488] Fix interaction logic and update plot function Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/person.cpp | 7 ++++-- cpp/simulations/analyze_bs_run.py | 13 ++++++++-- cpp/simulations/paper_abm_bs_testing.cpp | 30 ++++++++++++++---------- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index fa06b3a6d7..abd315b27b 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -62,8 +62,11 @@ Person Person::copy_person(Location& location) void Person::interact(RandomNumberGenerator& rng, TimePoint t, TimeSpan dt, const Parameters& params) { - if (get_infection_state(t) == InfectionState::Susceptible || - get_infection_state(t) == InfectionState::Recovered) { // Susceptible or Recovered people can be (re)infected + // if (get_infection_state(t) == InfectionState::Susceptible || + // get_infection_state(t) == InfectionState::Recovered) { // Susceptible or Recovered people can be (re)infected + // m_location->interact(rng, *this, t, dt, params); + // } + if (get_infection_state(t) == InfectionState::Susceptible) { // Susceptible or Recovered people can be (re)infected m_location->interact(rng, *this, t, dt, params); } m_time_at_location += dt; diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 3f60ee0ce8..be7d2ad345 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -104,7 +104,7 @@ def plot_results(path): total_75 = group['Total'][()] f.close() - plot_infection_states(time, total_50, total_25, total_75) + plot_infection_states_dead(time, total_50, total_25, total_75) def plot_infection_states(x, y50, y25, y75): @@ -116,6 +116,15 @@ def plot_infection_states(x, y50, y25, y75): plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.1) plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.1) +def plot_infection_states_dead(x, y50, y25, y75): + plt.figure('Infection_states_dead') + plt.plot(x, y50[:,[5,7]]) + plt.legend(['I_Crit', 'Dead']) + + # for i in [5,7]: + # plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.1) + # plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.1) + def plot_infections_per_age_group(path): f = h5py.File( @@ -162,7 +171,7 @@ def plot_mean_and_std(Y): if __name__ == "__main__": #path to results - path = "/Users/David/Documents/HZI/memilio/data/results" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ea62a89cbf..439fd9565e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -991,10 +991,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(40); // End time per simulation - auto max_num_persons = 100000; - // auto ensemble_infection_per_loc_type = - // std::vector>>{}; // Vector of infection per location type results + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(120); // End time per simulation + auto max_num_persons = 30000; + auto ensemble_infection_per_loc_type = + std::vector>>{}; // Vector of infection per location type results // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); // auto ensemble_infection_per_age_group = // std::vector>>{}; // Vector of infection per age group results @@ -1052,8 +1052,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // mio::abm::LogDataForMovement> // historyPersonInf; // mio::History historyPersonInfDelta; - // mio::History historyInfectionPerLocationType{ - // Eigen::Index(mio::abm::LocationType::Count)}; + mio::History historyInfectionPerLocationType{ + Eigen::Index(mio::abm::LocationType::Count)}; // mio::History historyInfectionPerAgeGroup{ // Eigen::Index(sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ @@ -1070,22 +1070,22 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Advance the world to tmax // sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, // historyPersonInfDelta, historyInfectionStatePerAgeGroup); - sim.advance(tmax, historyInfectionStatePerAgeGroup); + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); // Stop the clock after sim.advance and calculate the duration auto stop2 = std::chrono::high_resolution_clock::now(); auto duration2 = std::chrono::duration(stop2 - start2); std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; // TODO: update result of the simulation to be a vector of location result. - // auto temp_sim_infection_per_loc_tpye = - // std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_per_loc_tpye = + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; // auto temp_sim_infection_per_age_group = // std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; // Push result of the simulation back to the result vector - // ensemble_infection_per_loc_type.push_back(temp_sim_infection_per_loc_tpye); + ensemble_infection_per_loc_type.push_back(temp_sim_infection_per_loc_tpye); // ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); // ensemble_params.push_back(std::vector{sim.get_world()}); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); @@ -1103,7 +1103,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // write_log_to_file_person_and_location_data(historyPersonInf); // write_log_to_file_trip_data(historyPersonInfDelta); // write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup, result_dir); - // write_log_to_file_infection_per_location_type(historyInfectionPerLocationType, result_dir); + write_log_to_file_infection_per_location_type(historyInfectionPerLocationType, result_dir); std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; @@ -1123,14 +1123,20 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s //gather results auto final_ensemble_infection_state_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); + auto final_ensemble_infection_per_loc_type = + gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type); if (rank == 0) { BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type, ensemble_params, {0}, + result_dir / "infection_per_location_type/", save_single_runs)); } #else BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, + result_dir / "infection_per_location_type/", save_single_runs)); #endif @@ -1178,7 +1184,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 124; + num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); } From c3b78bcc9b2c3315e1e9dfccf7699f40e6402ec0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 20 Mar 2024 22:57:24 +0100 Subject: [PATCH 067/488] Fix logging bug in common_abm_loggers.h --- cpp/models/abm/common_abm_loggers.h | 4 +- cpp/simulations/paper_abm_bs_testing.cpp | 99 ++++++++++++++++++++---- 2 files changed, 85 insertions(+), 18 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index c40b62e567..b75a159a62 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -220,8 +220,8 @@ struct LogInfectionPerLocationType : mio::LogAlways { auto curr_time = sim.get_time(); auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. - if (ids_in_bs.size() == 0) { - PRAGMA_OMP(parallel for) + if (0 == 0) { + // PRAGMA_OMP(parallel for) for (auto&& person : sim.get_world().get_persons()) { if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 439fd9565e..09d6d6027d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -226,10 +226,14 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::map locations = {}; std::map persons = {}; - std::map person_ids = {}; + std::vector> schools = + {}; //schools need to save the id, the zone it is in and the amount of persons who will be assigned to it, we need it double when we actually assign persons + std::map person_ids = {}; std::map> locations_before; std::map> locations_after; + uint32_t max_number_of_persons_in_school = 600; + // For the world we need: Hospitals, ICUs (for both we just create one for now), Homes for each unique householdID, One Person for each person_id with respective age and home_id. // We assume that no person goes to an hospital, altough e.g. "Sonstiges" could be a hospital @@ -296,6 +300,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::getline(fin, line); // Skip header row // Add all locations to the world + int school_id_counter = -100; + uint32_t last_person_id = 0; while (std::getline(fin, line)) { row.clear(); @@ -308,7 +314,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, break; uint32_t home_id = row[index["huid"]]; - uint32_t target_location_id = std::abs(row[index["loc_id_end"]]); + int target_location_id = row[index["loc_id_end"]]; + uint32_t end_zone = row[index["end_zone"]]; uint32_t activity_end = row[index["activity_end"]]; mio::abm::GeographicalLocation location_long_lat = {(double)row[index["lon_end"]] / 1e+5, (double)row[index["lat_end"]] / 1e+5}; @@ -317,15 +324,39 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (it_home == locations.end()) { home = world.add_location(mio::abm::LocationType::Home, 1); locations.insert({home_id, home}); - mio::abm::GeographicalLocation location_long_lat_home = {(double)row[index["lon_start"]] / 1e+5, - (double)row[index["lat_start"]] / 1e+5}; - world.get_individualized_location(home).set_geographical_location(location_long_lat_home); } else { home = it_home->second; } mio::abm::LocationId location; + + switch (target_location_id) { + case -1: //home has to be anonymized + target_location_id = home_id; + case -2: //schools have to be anonymized we place them into a general school and every 600 persons into a new school + { + if (last_person_id != person_id) { + bool found_school = false; + for (auto& school : schools) { + if (std::get<1>(school) == end_zone && std::get<2>(school) < max_number_of_persons_in_school) { + target_location_id = std::get<0>(school); + std::get<2>(school)++; + last_person_id = person_id; + found_school = true; + break; + } + } + if (!found_school) { + target_location_id = school_id_counter--; + schools.push_back(std::make_tuple(target_location_id, end_zone, 1, 0)); + } + } + } + default: + break; + } + auto it_location = locations.find( target_location_id); // Check if location already exists also for home which have the same id (home_id = target_location_id) if (it_location == locations.end()) { @@ -342,6 +373,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::unordered_set ids_in_bs; // Add the persons and trips + last_person_id = 0; while (std::getline(fin, line)) { row.clear(); @@ -353,14 +385,33 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (person_ids.find(person_id) == person_ids.end()) break; - uint32_t age = row[index["age"]]; - uint32_t home_id = row[index["huid"]]; - uint32_t target_location_id = std::abs(row[index["loc_id_end"]]); - uint32_t start_location_id = std::abs(row[index["loc_id_start"]]); - uint32_t trip_start = row[index["start_time"]]; - uint32_t transport_mode = row[index["travel_mode"]]; - uint32_t acticity_end = row[index["activity_end"]]; - bool home_in_bs = (bool)row[index["in_bs"]]; + uint32_t age = row[index["age"]]; + uint32_t home_id = row[index["huid"]]; + int target_location_id = row[index["loc_id_end"]]; + int start_location_id = row[index["loc_id_start"]]; + uint32_t end_zone = row[index["end_zone"]]; + uint32_t trip_start = row[index["start_time"]]; + uint32_t transport_mode = row[index["travel_mode"]]; + uint32_t acticity_end = row[index["activity_end"]]; + bool home_in_bs = true; + + switch (target_location_id) { + case -1: //home has to be anonymized + target_location_id = home_id; + case -2: //schools have to be anonymized we place them into a general school and every 600 persons into a new school + for (auto& school : schools) { + if (std::get<1>(school) == end_zone && std::get<3>(school) < max_number_of_persons_in_school) { + if (last_person_id != person_id) { + last_person_id = person_id; + std::get<3>(school)++; + } + target_location_id = std::get<0>(school); + break; + } + } + default: + break; + } // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; @@ -400,6 +451,22 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, } world.get_trip_list().use_weekday_trips_on_weekend(); world.parameters.get() = ids_in_bs; + + // //Some Data about the world: + // //write how many persons are in each home + // std::map persons_in_home; + // for (auto& person : world.get_persons()) { + // auto home = person.get_assigned_location_index(mio::abm::LocationType::Home); + // if (persons_in_home.find(home) == persons_in_home.end()) { + // persons_in_home.insert({home, 1}); + // } + // else { + // persons_in_home[home]++; + // } + // } + // for (auto& home : persons_in_home) { + // mio::log_info("Home ", home.first, " has ", home.second, " persons."); + // } } std::pair get_my_and_sigma(std::pair mean_and_std) @@ -992,7 +1059,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(120); // End time per simulation - auto max_num_persons = 30000; + auto max_num_persons = 50000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -1021,7 +1088,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution //Time this auto start0 = std::chrono::high_resolution_clock::now(); - determine_initial_infection_states_world(input_dir, start_date); + // determine_initial_infection_states_world(input_dir, start_date); auto stop0 = std::chrono::high_resolution_clock::now(); auto duration0 = std::chrono::duration(stop0 - start0); std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" @@ -1085,7 +1152,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; // Push result of the simulation back to the result vector - ensemble_infection_per_loc_type.push_back(temp_sim_infection_per_loc_tpye); + ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); // ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); // ensemble_params.push_back(std::vector{sim.get_world()}); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); From d267e08b9cdb252ccb12537af035dd37f9cadfe1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:23:25 +0100 Subject: [PATCH 068/488] Add functions to modify school and home IDs --- cpp/simulations/cleanup_data.py | 93 +++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 cpp/simulations/cleanup_data.py diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py new file mode 100644 index 0000000000..dd283e959d --- /dev/null +++ b/cpp/simulations/cleanup_data.py @@ -0,0 +1,93 @@ +import pandas as pd +import numpy as np +import os +import sys + + +def add_school_ids(pd): + # Schools are anonymized with loc_id_start and loc_id_end = -2 + # for every row where loc_id_start or loc_id_end is -2 we assume a school in the county and change the id to something unique (somewhere betwenn-100 to -10000) + pd_data = pd['person_id', 'loc_id_start', 'loc_id_end', 'countyStart', 'countyEnd', 'activity_start' , 'activity_end'] + #list of schools + schools = np.array([]) + # we go through every row and check if the loc_id_start or loc_id_end is -2 and the activity_start or activity_end is 2 + # if so we change the loc_id_start or loc_id_end to a unique id which represents a school in that county + # if in one unique school are more than 600 persons we change the id to a new unique id which represents a new school in that county + # one thing to consider is that a usually goes to and leaves the same school so we have to check if the school is already in the list and the person already is assigned to that school + + # array to save how many schools in each country and how many persons in each school + schools_in_county = np.array([]) + persons_in_schools = np.array([]) + + + + + + + + + + +def add_home_ids(pd): + # when there is a -1 in loc_id_start or loc_id_end, the person is at home (due to anonymization we dont know exactly if the person goes to their home or another we assume their own home) + pd_data = pd['loc_id_start', 'loc_id_end', 'huid', 'activity_start', 'activity_end'] + #every row where loc_id_start or loc_id_end is -1 and activity_start or activity_end is 7 is a person who goes /comes from home + # there we change the loc_id_start and loc_id_end to huid + for index, row in pd.iterrows(): + if(row['loc_id_start'] == -1 and row['activity_start'] == 7): + pd.at[index, 'loc_id_start'] = row['huid'] + if(row['loc_id_end'] == -1 and row['activity_end'] == 7): + pd.at[index, 'loc_id_end'] = row['huid'] + return pd + + + + +def add_home_is_in_bs_column(pd): + # check if csv file has column home_in_bs + if 'home_in_bs' in pd.columns: + print("Column 'home_in_bs' is present in DataFrame.") + # nothing tbd + else: + print("Column 'home_in_bs' is not present in DataFrame.") + # add column home_in_bs + pd['home_in_bs'] = 0 + #list of persons who are in braunschweig + list_person_in_bs = np.array([]) + for index, row in pd.iterrows(): + if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): + list_person_in_bs = np.append(list_person_in_bs, row['personID']) + #drop duplicates + list_person_in_bs = np.unique(list_person_in_bs) + for index, row in pd.iterrows(): + if row['personID'] in list_person_in_bs: + pd.at[index, 'home_in_bs'] = 1 + return pd + + +bd = pd.read_csv(r'C:\\Users\\korf_sa\\Documents\\rep\\data\\mobility\\braunschweig_januar.csv', header=None, skiprows=1) + +# read in column headers from first line of csv file +with open(r'C:\\Users\\korf_sa\\Documents\\rep\\data\\mobility\\braunschweig_januar.csv', 'r') as file: + first_line = file.readline() + column_headers = first_line.split(',') + column_headers = [header.strip() for header in column_headers] + +#check if anythiong changed since writing this script +if(column_headers[0:19] == ['puid', 'start_zone', 'end_zone', 'loc_id_start', 'loc_id_end', 'start_county', 'end_county', 'huid', 'trip_distance', 'start_time', 'travel_time_sec', 'lon_start', 'lat_start', 'lon_end', 'lat_end', 'travel_mode', 'activity_start', 'activity_end', 'age']): + print("Column headers are correct") +else: + print("Column headers are not correct") + + +# add column headers to DataFrame +pd_new = add_home_is_in_bs_column(bd) +pd_new = add_home_ids(pd_new) + + + + + + + + From 364bf3e86bf37cab80928174d517c3413d569e57 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 22 Mar 2024 16:38:04 +0100 Subject: [PATCH 069/488] Added implementation to change -1/-2/-3 location values --- cpp/simulations/cleanup_data.py | 204 +++++++++++++++++++++++++------- 1 file changed, 164 insertions(+), 40 deletions(-) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index dd283e959d..ebbf31a0c4 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -1,37 +1,162 @@ -import pandas as pd -import numpy as np import os import sys +import numpy as np +import pandas as pd + + +def add_external_ids(pd): + # Schools are anonymized with loc_id_start and loc_id_end = -2 + # for every row where loc_id_start or loc_id_end is -2 we assume a school in the zone and change the id to something unique (somewhere betwenn-100 to -10000) + + # list of external locations + work_places_dict = {} # map zone to work place id and size + person_to_work_place_dict = {} # maps persons to work places to track persons + # start of work place ids, decrement by 1 for each new work place + work_place_ids = -10100 + max_persons_per_work_place = 40 + + shops_dict = {} + person_to_shop_dict = {} + shop_ids = -20100 + max_persons_per_shop = 200 + + social_event_dict = {} + person_to_social_event_dict = {} + social_event_ids = -30100 + max_persons_per_social_event = 100 + + # we go through every row and check if the loc_id_start or loc_id_end is -3 + # if so we change the loc_id_start or loc_id_end to a unique id which represents an activity in that zone + # if in one unique location are more than X (see above) persons we change the id to a new unique id which represents a new location in that zone + + start_or_end_loc = '' + start_or_end_zone = '' + for index, row in pd.iterrows(): + if ((row['loc_id_start'] == -3) | (row['loc_id_end'] == -3)): + if row['loc_id_start'] == -3: + start_or_end_loc = 'loc_id_start' + start_or_end_zone = 'start_zone' + start_or_end_activity = 'activity_start' + else: + start_or_end_loc = 'loc_id_end' + start_or_end_zone = 'end_zone' + start_or_end_activity = 'activity_end' + + found = False + if (row[start_or_end_activity] == 1): # work places + if (not row['puid'] in person_to_work_place_dict.keys()): + # check if a work place is already available and not full + if (row[start_or_end_zone] in work_places_dict.keys()): + if (work_places_dict[row[start_or_end_zone]][1] < max_persons_per_work_place): + # add persons to existing work place + person_to_work_place_dict[row['puid'] + ] = work_places_dict[row[start_or_end_zone]][0] + work_places_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new work place + work_places_dict[row[start_or_end_zone]] = [ + work_place_ids, 1] + work_place_ids -= 1 + person_to_work_place_dict[row['puid'] + ] = work_places_dict[row[start_or_end_zone]][0] + # overwrite "-3" in location_id + pd.at[index, start_or_end_loc] = person_to_work_place_dict[row['puid']] + + # shops and private matters + elif (row[start_or_end_activity] == 3 | row[start_or_end_activity] == 5): + if (not row['puid'] in person_to_shop_dict.keys()): + # check if a shop is already available and not full + if (row[start_or_end_zone] in shops_dict.keys()): + if (shops_dict[row[start_or_end_zone]][1] < max_persons_per_shop): + # add persons to existing shop + person_to_shop_dict[row['puid'] + ] = shops_dict[row[start_or_end_zone]][0] + shops_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new shop + shops_dict[row[start_or_end_zone]] = [ + shop_ids, 1] + shop_ids -= 1 + person_to_shop_dict[row['puid'] + ] = shops_dict[row[start_or_end_zone]][0] + # overwrite "-3" in location_id + pd.at[index, start_or_end_loc] = person_to_shop_dict[row['puid']] + + # social events and 'other' + elif (row[start_or_end_activity] == 4 | row[start_or_end_activity] == 6): + if (not row['puid'] in person_to_social_event_dict.keys()): + # check if a social event is already available and not full + if (row[start_or_end_zone] in social_event_dict.keys()): + if (social_event_dict[row[start_or_end_zone]][1] < max_persons_per_social_event): + # add persons to existing social event + person_to_social_event_dict[row['puid'] + ] = social_event_dict[row[start_or_end_zone]][0] + social_event_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new social event + social_event_dict[row[start_or_end_zone]] = [ + social_event_ids, 1] + social_event_ids -= 1 + person_to_social_event_dict[row['puid'] + ] = social_event_dict[row[start_or_end_zone]][0] + # overwrite "-3" in location_id + pd.at[index, start_or_end_loc] = person_to_social_event_dict[row['puid']] + + return pd def add_school_ids(pd): # Schools are anonymized with loc_id_start and loc_id_end = -2 - # for every row where loc_id_start or loc_id_end is -2 we assume a school in the county and change the id to something unique (somewhere betwenn-100 to -10000) - pd_data = pd['person_id', 'loc_id_start', 'loc_id_end', 'countyStart', 'countyEnd', 'activity_start' , 'activity_end'] - #list of schools - schools = np.array([]) - # we go through every row and check if the loc_id_start or loc_id_end is -2 and the activity_start or activity_end is 2 - # if so we change the loc_id_start or loc_id_end to a unique id which represents a school in that county - # if in one unique school are more than 600 persons we change the id to a new unique id which represents a new school in that county - # one thing to consider is that a usually goes to and leaves the same school so we have to check if the school is already in the list and the person already is assigned to that school - - # array to save how many schools in each country and how many persons in each school - schools_in_county = np.array([]) - persons_in_schools = np.array([]) + # for every row where loc_id_start or loc_id_end is -2 we assume a school in the zone and change the id to something unique (somewhere betwenn-100 to -10000) - - - - + # list of schools + schools_dict = {} # map zone to school id and size + person_to_school_dict = {} # maps persons to schools to track persons + school_ids = -100 # start of school ids, decrement by 1 for each new school + max_persons_per_school = 600 + # we go through every row and check if the loc_id_start or loc_id_end is -2 + # if so we change the loc_id_start or loc_id_end to a unique id which represents a school in that zone + # if in one unique school are more than 600 persons we change the id to a new unique id which represents a new school in that zone + start_or_end_loc = '' + start_or_end_zone = '' + for index, row in pd.iterrows(): + if (((row['loc_id_start'] == -2) | (row['loc_id_end'] == -2)) & (not row['puid'] in person_to_school_dict.keys())): + if row['loc_id_start'] == -2: + start_or_end_loc = 'loc_id_start' + start_or_end_zone = 'start_zone' + else: + start_or_end_loc = 'loc_id_end' + start_or_end_zone = 'end_zone' + + found = False + # check if a school is already available and not full + if (row[start_or_end_zone] in schools_dict.keys()): + if (schools_dict[row[start_or_end_zone]][1] < max_persons_per_school): + # add persons to existing school + person_to_school_dict[row['puid'] + ] = schools_dict[row[start_or_end_zone]][0] + schools_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new school + schools_dict[row[start_or_end_zone]] = [school_ids, 1] + school_ids -= 1 + person_to_school_dict[row['puid'] + ] = schools_dict[row[start_or_end_zone]][0] + # overwrite "-2" in location_id + pd.at[index, start_or_end_loc] = person_to_school_dict[row['puid']] + return pd def add_home_ids(pd): # when there is a -1 in loc_id_start or loc_id_end, the person is at home (due to anonymization we dont know exactly if the person goes to their home or another we assume their own home) - pd_data = pd['loc_id_start', 'loc_id_end', 'huid', 'activity_start', 'activity_end'] - #every row where loc_id_start or loc_id_end is -1 and activity_start or activity_end is 7 is a person who goes /comes from home + # every row where loc_id_start or loc_id_end is -1 and activity_start or activity_end is 7 is a person who goes /comes from home # there we change the loc_id_start and loc_id_end to huid for index, row in pd.iterrows(): if(row['loc_id_start'] == -1 and row['activity_start'] == 7): @@ -41,8 +166,6 @@ def add_home_ids(pd): return pd - - def add_home_is_in_bs_column(pd): # check if csv file has column home_in_bs if 'home_in_bs' in pd.columns: @@ -55,39 +178,40 @@ def add_home_is_in_bs_column(pd): #list of persons who are in braunschweig list_person_in_bs = np.array([]) for index, row in pd.iterrows(): - if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): - list_person_in_bs = np.append(list_person_in_bs, row['personID']) + if ((row['start_county'] == 3101 and row['activity_start'] == 7) or (row['end_county'] == 3101 and row['activity_end'] == 7)): + list_person_in_bs = np.append(list_person_in_bs, row['puid']) #drop duplicates list_person_in_bs = np.unique(list_person_in_bs) for index, row in pd.iterrows(): - if row['personID'] in list_person_in_bs: + if row['puid'] in list_person_in_bs: pd.at[index, 'home_in_bs'] = 1 return pd -bd = pd.read_csv(r'C:\\Users\\korf_sa\\Documents\\rep\\data\\mobility\\braunschweig_januar.csv', header=None, skiprows=1) +PATH = "/Users/david/Documents/HZI/memilio/data/mobility/braunschweig_result.csv" + +bd = pd.read_csv(PATH) # read in column headers from first line of csv file -with open(r'C:\\Users\\korf_sa\\Documents\\rep\\data\\mobility\\braunschweig_januar.csv', 'r') as file: +with open(PATH, 'r') as file: first_line = file.readline() column_headers = first_line.split(',') column_headers = [header.strip() for header in column_headers] -#check if anythiong changed since writing this script +# check if anythiong changed since writing this script if(column_headers[0:19] == ['puid', 'start_zone', 'end_zone', 'loc_id_start', 'loc_id_end', 'start_county', 'end_county', 'huid', 'trip_distance', 'start_time', 'travel_time_sec', 'lon_start', 'lat_start', 'lon_end', 'lat_end', 'travel_mode', 'activity_start', 'activity_end', 'age']): print("Column headers are correct") else: print("Column headers are not correct") - -# add column headers to DataFrame -pd_new = add_home_is_in_bs_column(bd) -pd_new = add_home_ids(pd_new) - - - - - - - - +bd_new = add_home_is_in_bs_column(bd) +print('Added flag for persons who live in Braunschweig.') +bd_new = add_home_ids(bd_new) +print('Home IDs set.') +bd_new = add_school_ids(bd_new) +print('School IDs set.') +bd_new = add_external_ids(bd_new) +print('External location IDs set.') + +# Write data back to disk +bd_new.to_csv('modified_braunschweig_result.csv', index=False) From 930ea06be538b375a3d2a44fdadb48957b9adbaa Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 22 Mar 2024 16:54:38 +0100 Subject: [PATCH 070/488] Fix key error --- cpp/simulations/cleanup_data.py | 47 +++++++++++++++++---------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index ebbf31a0c4..79334f0445 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -125,31 +125,32 @@ def add_school_ids(pd): start_or_end_loc = '' start_or_end_zone = '' for index, row in pd.iterrows(): - if (((row['loc_id_start'] == -2) | (row['loc_id_end'] == -2)) & (not row['puid'] in person_to_school_dict.keys())): - if row['loc_id_start'] == -2: - start_or_end_loc = 'loc_id_start' - start_or_end_zone = 'start_zone' - else: - start_or_end_loc = 'loc_id_end' - start_or_end_zone = 'end_zone' - - found = False - # check if a school is already available and not full - if (row[start_or_end_zone] in schools_dict.keys()): - if (schools_dict[row[start_or_end_zone]][1] < max_persons_per_school): - # add persons to existing school + if ((row['loc_id_start'] == -2) | (row['loc_id_end'] == -2)): + if (not row['puid'] in person_to_school_dict.keys()): + if row['loc_id_start'] == -2: + start_or_end_loc = 'loc_id_start' + start_or_end_zone = 'start_zone' + else: + start_or_end_loc = 'loc_id_end' + start_or_end_zone = 'end_zone' + + found = False + # check if a school is already available and not full + if (row[start_or_end_zone] in schools_dict.keys()): + if (schools_dict[row[start_or_end_zone]][1] < max_persons_per_school): + # add persons to existing school + person_to_school_dict[row['puid'] + ] = schools_dict[row[start_or_end_zone]][0] + schools_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new school + schools_dict[row[start_or_end_zone]] = [school_ids, 1] + school_ids -= 1 person_to_school_dict[row['puid'] ] = schools_dict[row[start_or_end_zone]][0] - schools_dict[row[start_or_end_zone]][1] += 1 - found = True - if (not found): - # make new school - schools_dict[row[start_or_end_zone]] = [school_ids, 1] - school_ids -= 1 - person_to_school_dict[row['puid'] - ] = schools_dict[row[start_or_end_zone]][0] - # overwrite "-2" in location_id - pd.at[index, start_or_end_loc] = person_to_school_dict[row['puid']] + # overwrite "-2" in location_id + pd.at[index, start_or_end_loc] = person_to_school_dict[row['puid']] return pd From 89331fc0684269f547a4bc10a1a3a5cf560d1f26 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 26 Mar 2024 17:27:15 +0100 Subject: [PATCH 071/488] Refactor code to remove unused variables and optimize location assignment Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/cleanup_data.py | 122 ++++++++++++++++++----- cpp/simulations/paper_abm_bs_testing.cpp | 71 ++----------- 2 files changed, 109 insertions(+), 84 deletions(-) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 79334f0445..5aa71486ee 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -32,16 +32,77 @@ def add_external_ids(pd): start_or_end_loc = '' start_or_end_zone = '' for index, row in pd.iterrows(): - if ((row['loc_id_start'] == -3) | (row['loc_id_end'] == -3)): - if row['loc_id_start'] == -3: - start_or_end_loc = 'loc_id_start' - start_or_end_zone = 'start_zone' - start_or_end_activity = 'activity_start' - else: - start_or_end_loc = 'loc_id_end' - start_or_end_zone = 'end_zone' - start_or_end_activity = 'activity_end' + if ((row['loc_id_start'] == -3)): + start_or_end_loc = 'loc_id_start' + start_or_end_zone = 'start_zone' + start_or_end_activity = 'activity_start' + found = False + if (row[start_or_end_activity] == 1): # work places + if (not row['puid'] in person_to_work_place_dict.keys()): + # check if a work place is already available and not full + if (row[start_or_end_zone] in work_places_dict.keys()): + if (work_places_dict[row[start_or_end_zone]][1] < max_persons_per_work_place): + # add persons to existing work place + person_to_work_place_dict[row['puid'] + ] = work_places_dict[row[start_or_end_zone]][0] + work_places_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new work place + work_places_dict[row[start_or_end_zone]] = [ + work_place_ids, 1] + work_place_ids -= 1 + person_to_work_place_dict[row['puid'] + ] = work_places_dict[row[start_or_end_zone]][0] + # overwrite "-3" in location_id + pd.at[index, start_or_end_loc] = person_to_work_place_dict[row['puid']] + + # shops and private matters + elif (row[start_or_end_activity] == 3 or row[start_or_end_activity] == 5): + if (not row['puid'] in person_to_shop_dict.keys()): + # check if a shop is already available and not full + if (row[start_or_end_zone] in shops_dict.keys()): + if (shops_dict[row[start_or_end_zone]][1] < max_persons_per_shop): + # add persons to existing shop + person_to_shop_dict[row['puid'] + ] = shops_dict[row[start_or_end_zone]][0] + shops_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new shop + shops_dict[row[start_or_end_zone]] = [ + shop_ids, 1] + shop_ids -= 1 + person_to_shop_dict[row['puid'] + ] = shops_dict[row[start_or_end_zone]][0] + # overwrite "-3" in location_id + pd.at[index, start_or_end_loc] = person_to_shop_dict[row['puid']] + # social events and 'other' + elif (row[start_or_end_activity] == 4 or row[start_or_end_activity] == 6): + if (not row['puid'] in person_to_social_event_dict.keys()): + # check if a social event is already available and not full + if (row[start_or_end_zone] in social_event_dict.keys()): + if (social_event_dict[row[start_or_end_zone]][1] < max_persons_per_social_event): + # add persons to existing social event + person_to_social_event_dict[row['puid'] + ] = social_event_dict[row[start_or_end_zone]][0] + social_event_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new social event + social_event_dict[row[start_or_end_zone]] = [ + social_event_ids, 1] + social_event_ids -= 1 + person_to_social_event_dict[row['puid'] + ] = social_event_dict[row[start_or_end_zone]][0] + # overwrite "-3" in location_id + pd.at[index, start_or_end_loc] = person_to_social_event_dict[row['puid']] + + if ((row['loc_id_end'] == -3)): + start_or_end_loc = 'loc_id_end' + start_or_end_zone = 'end_zone' + start_or_end_activity = 'activity_end' found = False if (row[start_or_end_activity] == 1): # work places if (not row['puid'] in person_to_work_place_dict.keys()): @@ -64,7 +125,7 @@ def add_external_ids(pd): pd.at[index, start_or_end_loc] = person_to_work_place_dict[row['puid']] # shops and private matters - elif (row[start_or_end_activity] == 3 | row[start_or_end_activity] == 5): + elif (row[start_or_end_activity] == 3 or row[start_or_end_activity] == 5): if (not row['puid'] in person_to_shop_dict.keys()): # check if a shop is already available and not full if (row[start_or_end_zone] in shops_dict.keys()): @@ -85,7 +146,7 @@ def add_external_ids(pd): pd.at[index, start_or_end_loc] = person_to_shop_dict[row['puid']] # social events and 'other' - elif (row[start_or_end_activity] == 4 | row[start_or_end_activity] == 6): + elif (row[start_or_end_activity] == 4 or row[start_or_end_activity] == 6): if (not row['puid'] in person_to_social_event_dict.keys()): # check if a social event is already available and not full if (row[start_or_end_zone] in social_event_dict.keys()): @@ -104,7 +165,6 @@ def add_external_ids(pd): ] = social_event_dict[row[start_or_end_zone]][0] # overwrite "-3" in location_id pd.at[index, start_or_end_loc] = person_to_social_event_dict[row['puid']] - return pd @@ -125,15 +185,31 @@ def add_school_ids(pd): start_or_end_loc = '' start_or_end_zone = '' for index, row in pd.iterrows(): - if ((row['loc_id_start'] == -2) | (row['loc_id_end'] == -2)): + if ((row['loc_id_start'] == -2)): + start_or_end_loc = 'loc_id_start' + start_or_end_zone = 'start_zone' + if (not row['puid'] in person_to_school_dict.keys()): + found = False + # check if a school is already available and not full + if (row[start_or_end_zone] in schools_dict.keys()): + if (schools_dict[row[start_or_end_zone]][1] < max_persons_per_school): + # add persons to existing school + person_to_school_dict[row['puid'] + ] = schools_dict[row[start_or_end_zone]][0] + schools_dict[row[start_or_end_zone]][1] += 1 + found = True + if (not found): + # make new school + schools_dict[row[start_or_end_zone]] = [school_ids, 1] + school_ids -= 1 + person_to_school_dict[row['puid'] + ] = schools_dict[row[start_or_end_zone]][0] + # overwrite "-2" in location_id + pd.at[index, start_or_end_loc] = person_to_school_dict[row['puid']] + if ((row['loc_id_end'] == -2)): + start_or_end_loc = 'loc_id_end' + start_or_end_zone = 'end_zone' if (not row['puid'] in person_to_school_dict.keys()): - if row['loc_id_start'] == -2: - start_or_end_loc = 'loc_id_start' - start_or_end_zone = 'start_zone' - else: - start_or_end_loc = 'loc_id_end' - start_or_end_zone = 'end_zone' - found = False # check if a school is already available and not full if (row[start_or_end_zone] in schools_dict.keys()): @@ -179,7 +255,7 @@ def add_home_is_in_bs_column(pd): #list of persons who are in braunschweig list_person_in_bs = np.array([]) for index, row in pd.iterrows(): - if ((row['start_county'] == 3101 and row['activity_start'] == 7) or (row['end_county'] == 3101 and row['activity_end'] == 7)): + if ((row['start_county'] == 3101 and row['activity_start'] == 7) or (row['end_county'] == 3101 and row['activity_end'] == 7)): # this assumes he goes to his home, but could be another persons home list_person_in_bs = np.append(list_person_in_bs, row['puid']) #drop duplicates list_person_in_bs = np.unique(list_person_in_bs) @@ -189,7 +265,7 @@ def add_home_is_in_bs_column(pd): return pd -PATH = "/Users/david/Documents/HZI/memilio/data/mobility/braunschweig_result.csv" +PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result.csv" bd = pd.read_csv(PATH) @@ -211,7 +287,7 @@ def add_home_is_in_bs_column(pd): print('Home IDs set.') bd_new = add_school_ids(bd_new) print('School IDs set.') -bd_new = add_external_ids(bd_new) +bd_new = add_external_ids(bd) print('External location IDs set.') # Write data back to disk diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 09d6d6027d..7f66a7228d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -226,14 +226,11 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::map locations = {}; std::map persons = {}; - std::vector> schools = - {}; //schools need to save the id, the zone it is in and the amount of persons who will be assigned to it, we need it double when we actually assign persons + std::map person_ids = {}; std::map> locations_before; std::map> locations_after; - uint32_t max_number_of_persons_in_school = 600; - // For the world we need: Hospitals, ICUs (for both we just create one for now), Homes for each unique householdID, One Person for each person_id with respective age and home_id. // We assume that no person goes to an hospital, altough e.g. "Sonstiges" could be a hospital @@ -267,7 +264,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, // The starting location of a person is the end location of the last trip he made, either on the same day or on // the day before - uint32_t target_location_id = std::abs(row[index["loc_id_end"]]); + uint32_t target_location_id = row[index["loc_id_end"]]; int trip_start = row[index["start_time"]]; if (trip_start < t0.hour_of_day()) { auto it_person = locations_before.find(person_id); @@ -300,8 +297,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::getline(fin, line); // Skip header row // Add all locations to the world - int school_id_counter = -100; - uint32_t last_person_id = 0; while (std::getline(fin, line)) { row.clear(); @@ -315,7 +310,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t home_id = row[index["huid"]]; int target_location_id = row[index["loc_id_end"]]; - uint32_t end_zone = row[index["end_zone"]]; uint32_t activity_end = row[index["activity_end"]]; mio::abm::GeographicalLocation location_long_lat = {(double)row[index["lon_end"]] / 1e+5, (double)row[index["lat_end"]] / 1e+5}; @@ -331,32 +325,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, mio::abm::LocationId location; - switch (target_location_id) { - case -1: //home has to be anonymized - target_location_id = home_id; - case -2: //schools have to be anonymized we place them into a general school and every 600 persons into a new school - { - if (last_person_id != person_id) { - bool found_school = false; - for (auto& school : schools) { - if (std::get<1>(school) == end_zone && std::get<2>(school) < max_number_of_persons_in_school) { - target_location_id = std::get<0>(school); - std::get<2>(school)++; - last_person_id = person_id; - found_school = true; - break; - } - } - if (!found_school) { - target_location_id = school_id_counter--; - schools.push_back(std::make_tuple(target_location_id, end_zone, 1, 0)); - } - } - } - default: - break; - } - auto it_location = locations.find( target_location_id); // Check if location already exists also for home which have the same id (home_id = target_location_id) if (it_location == locations.end()) { @@ -373,7 +341,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::unordered_set ids_in_bs; // Add the persons and trips - last_person_id = 0; while (std::getline(fin, line)) { row.clear(); @@ -385,34 +352,16 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (person_ids.find(person_id) == person_ids.end()) break; - uint32_t age = row[index["age"]]; - uint32_t home_id = row[index["huid"]]; - int target_location_id = row[index["loc_id_end"]]; - int start_location_id = row[index["loc_id_start"]]; - uint32_t end_zone = row[index["end_zone"]]; + uint32_t age = row[index["age"]]; + uint32_t home_id = row[index["huid"]]; + int target_location_id = row[index["loc_id_end"]]; + int start_location_id = row[index["loc_id_start"]]; + uint32_t trip_start = row[index["start_time"]]; uint32_t transport_mode = row[index["travel_mode"]]; uint32_t acticity_end = row[index["activity_end"]]; bool home_in_bs = true; - switch (target_location_id) { - case -1: //home has to be anonymized - target_location_id = home_id; - case -2: //schools have to be anonymized we place them into a general school and every 600 persons into a new school - for (auto& school : schools) { - if (std::get<1>(school) == end_zone && std::get<3>(school) < max_number_of_persons_in_school) { - if (last_person_id != person_id) { - last_person_id = person_id; - std::get<3>(school)++; - } - target_location_id = std::get<0>(school); - break; - } - } - default: - break; - } - // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; auto start_location = locations.find(start_location_id)->second; @@ -821,7 +770,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con set_local_parameters(world); // Create the world object from statistical data. - create_world_from_data(world, (input_dir / "mobility/braunschweig_result.csv").generic_string(), t0, + create_world_from_data(world, (input_dir / "mobility/modified_braunschweig_result.csv").generic_string(), t0, max_num_persons); world.use_migration_rules(false); @@ -1058,8 +1007,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(120); // End time per simulation - auto max_num_persons = 50000; + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(50); // End time per simulation + auto max_num_persons = 23000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); From 82b7e863241d02e675804a9e141e0decd142f7d4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:57:21 +0100 Subject: [PATCH 072/488] Add plot_infection_states function call to plot_results Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index be7d2ad345..f8d192f28c 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -105,6 +105,8 @@ def plot_results(path): f.close() plot_infection_states_dead(time, total_50, total_25, total_75) + plot_infection_states(time, total_50, total_25, total_75) + def plot_infection_states(x, y50, y25, y75): From 8352e0f77ac1ac35de4b09fce583c9b707745747 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 5 Apr 2024 12:28:21 +0200 Subject: [PATCH 073/488] Introduce InfectionRateFromViralShed parameter --- cpp/memilio/utils/random_number_generator.h | 7 ++++ cpp/models/abm/analyze_result.h | 4 +- cpp/models/abm/infection.cpp | 2 +- cpp/models/abm/infection.h | 11 +++-- cpp/models/abm/location.cpp | 8 ++-- cpp/models/abm/location.h | 3 +- cpp/models/abm/parameters.h | 46 +++++++++++++++++---- cpp/models/abm/time.h | 2 +- cpp/models/abm/world.cpp | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 9 ++-- cpp/tests/test_abm_infection.cpp | 14 +++---- cpp/tests/test_abm_location.cpp | 6 +-- cpp/tests/test_abm_masks.cpp | 2 +- 13 files changed, 82 insertions(+), 34 deletions(-) diff --git a/cpp/memilio/utils/random_number_generator.h b/cpp/memilio/utils/random_number_generator.h index 74e28ed53d..79f48601d4 100644 --- a/cpp/memilio/utils/random_number_generator.h +++ b/cpp/memilio/utils/random_number_generator.h @@ -683,6 +683,13 @@ using PoissonDistribution = DistributionAdapter>; template using LogNormalDistribution = DistributionAdapter>; +/** + * adapted gamma_distribution. + * @see DistributionAdapter + */ +template +using GammaDistribution = DistributionAdapter>; + } // namespace mio #endif diff --git a/cpp/models/abm/analyze_result.h b/cpp/models/abm/analyze_result.h index 745f52379e..5362d2fee2 100644 --- a/cpp/models/abm/analyze_result.h +++ b/cpp/models/abm/analyze_result.h @@ -249,12 +249,12 @@ std::vector ensemble_params_percentile(const std::vector auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}].params.a(); + model.parameters.template get()[{virus_variant, age_group}].params.alpha(); return result; }); param_percentil(node, [age_group, virus_variant](auto&& model) -> auto& { static auto result = - model.parameters.template get()[{virus_variant, age_group}].params.b(); + model.parameters.template get()[{virus_variant, age_group}].params.beta(); return result; }); param_percentil(node, [virus_variant](auto&& model) -> auto& { diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 8adf2e870e..8d974e0748 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -76,7 +76,7 @@ ScalarType Infection::get_viral_load(TimePoint t) const } } -ScalarType Infection::get_infectivity(TimePoint t) const +ScalarType Infection::get_viral_shed(TimePoint t) const { if (m_viral_load.start_date >= t || get_infection_state(t) == InfectionState::Exposed) return 0; diff --git a/cpp/models/abm/infection.h b/cpp/models/abm/infection.h index 6133da13a3..82875be38d 100644 --- a/cpp/models/abm/infection.h +++ b/cpp/models/abm/infection.h @@ -74,17 +74,20 @@ class Infection ScalarType get_viral_load(TimePoint t) const; /** - * @brief Get infectivity at a given time. + * @brief Get viral shed at a specific time. * Computed depending on current ViralLoad and individual invlogit function of each Person * corresponding to https://www.science.org/doi/full/10.1126/science.abi5273 * The mapping corresponds to Fig. 2 C. * Formula of invlogit function can be found here: * https://github.com/VirologyCharite/SARS-CoV-2-VL-paper/tree/main * in ExtendedMethods.html, Section 3.1.2.1. + * Also in accordance to Fig. 3d of another publication: + * https://www.nature.com/articles/s41564-022-01105-z/figures/3 + * The result is in arbitrary units and has to be scaled to the rate "infections per day". * @param[in] t TimePoint of the querry. - * @return Infectivity at given TimePoint. + * @return Viral shed at given TimePoint. */ - ScalarType get_infectivity(TimePoint t) const; + ScalarType get_viral_shed(TimePoint t) const; /** * @brief: Get VirusVariant. @@ -159,7 +162,7 @@ class Infection ViralLoad m_viral_load; ///< ViralLoad of the Infection. ScalarType m_log_norm_alpha, m_log_norm_beta; ///< Parameters for the infectivity mapping, which is modelled through an invlogit function. - ScalarType m_individual_virus_shed_factor; ///< Individual virus shed factor. + ScalarType m_individual_virus_shed_factor; ///< Individual virus shed per day. bool m_detected; ///< Whether an Infection is detected or not. }; diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 5c5c20a0ae..0479343b9a 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -128,7 +128,7 @@ void Location::adjust_contact_rates(size_t num_agegroups) } } -void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegroups) +void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegroups, const Parameters& params) { //cache for next step so it stays constant during the step while subpopulations change //otherwise we would have to cache all state changes during a step which uses more memory @@ -143,8 +143,10 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou /* average infectivity over the time step * to second order accuracy using midpoint rule */ - cell.m_cached_exposure_rate_contacts[{virus, age}] += inf.get_infectivity(t + dt / 2); - cell.m_cached_exposure_rate_air[{virus}] += inf.get_infectivity(t + dt / 2); + cell.m_cached_exposure_rate_contacts[{virus, age}] += + params.get()[{virus}] * inf.get_viral_shed(t + dt / 2); + cell.m_cached_exposure_rate_air[{virus}] += + inf.get_viral_shed(t + dt / 2); // TODO: Change to non-contact function! } } diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index df633218fc..8873168a11 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -224,8 +224,9 @@ class Location * @param[in] t Current TimePoint of the Simulation. * @param[in] dt The duration of the Simulation step. * @param[in] num_agegroups The number of age groups in the model. + * @param[in] params Parameters of the Model. */ - void cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegroups); + void cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegroups, const Parameters& params); /** * @brief Get the Location specific Infection parameters. diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index fd88a316bf..9b65402948 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -287,12 +287,13 @@ struct InfectivityDistributions { /** * @brief Individual virus shed factor to account for variability in infectious viral load spread. + * Default values taken from https://www.nature.com/articles/s41564-022-01105-z/ */ struct VirusShedFactor { - using Type = CustomIndexArray::ParamType, VirusVariant, AgeGroup>; + using Type = CustomIndexArray::ParamType, VirusVariant, AgeGroup>; static Type get_default(AgeGroup size) { - Type default_val({VirusVariant::Count, size}, UniformDistribution::ParamType{0., 0.28}); + Type default_val({VirusVariant::Count, size}, GammaDistribution::ParamType{1.6, 1. / 22}); return default_val; } static std::string name() @@ -331,6 +332,21 @@ struct MaskProtection { } }; +/** + * @brief Determines the infection rate by viral shed. Used as a linear factor. +*/ +struct InfectionRateFromViralShed { + using Type = CustomIndexArray; + static Type get_default(AgeGroup /*size*/) + { + return Type({VirusVariant::Count}, 1.0); + } + static std::string name() + { + return "InfectionRateFromViralShed"; + } +}; + /** * @brief Aerosol transmission rates. */ @@ -657,10 +673,11 @@ using ParametersBase = TimeInfectedSevereToRecovered, TimeInfectedCriticalToDead, TimeInfectedCriticalToRecovered, SymptomsPerInfectedNoSymptoms, SeverePerInfectedSymptoms, CriticalPerInfectedSevere, DeathsPerInfectedCritical, ViralLoadDistributions, InfectivityDistributions, VirusShedFactor, - DetectInfection, MaskProtection, AerosolTransmissionRates, LockdownDate, QuarantineDuration, - SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, GotoWorkTimeMaximum, - GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, AgeGroupGotoWork, - InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, LogAgentIds>; + DetectInfection, MaskProtection, InfectionRateFromViralShed, AerosolTransmissionRates, LockdownDate, + QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, + GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, + AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, + LogAgentIds>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. @@ -693,10 +710,25 @@ struct ContactRates { } }; +/** + * @brief Average contact duration in days. +*/ +struct ContactDuration { + using Type = ScalarType; + static Type get_default(AgeGroup /*size*/) + { + return Type(5. / 24 / 60); // 5 minutes + } + static std::string name() + { + return "ContactDuration"; + } +}; + /** * @brief Parameters of the Infection that depend on the Location. */ -using LocalInfectionParameters = ParameterSet; +using LocalInfectionParameters = ParameterSet; /** * @brief Parameters of the simulation that are the same everywhere within the World. diff --git a/cpp/models/abm/time.h b/cpp/models/abm/time.h index 7b5f0b8e1b..040bf85eb5 100644 --- a/cpp/models/abm/time.h +++ b/cpp/models/abm/time.h @@ -317,7 +317,7 @@ inline TimeSpan hours(int hours) /** * @brief Create a TimeSpan with a specified number of days. - * @param[in] seconds Number of days in the TimeSpan. + * @param[in] days Number of days in the TimeSpan. */ inline TimeSpan days(int days) { diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 0cb0d8c9b1..008a8c0c75 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -154,7 +154,7 @@ void World::begin_step(TimePoint t, TimeSpan dt) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->adjust_contact_rates(parameters.get_num_groups()); - location->cache_exposure_rates(t, dt, parameters.get_num_groups()); + location->cache_exposure_rates(t, dt, parameters.get_num_groups(), parameters); } } diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 09d6d6027d..408446bb3d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -58,7 +58,7 @@ const std::map infection_ {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; mio::CustomIndexArray initial_infection_distribution{ - {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.02}; + {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.005}; /** * Determine initial distribution of infection states. @@ -526,6 +526,8 @@ void set_parameters(mio::abm::Parameters& params) params.get() = 0.002; // Set infection parameters + params.get() = 1.; + // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { return mio::linear_interpolation_of_data_set( @@ -1088,7 +1090,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution //Time this auto start0 = std::chrono::high_resolution_clock::now(); - // determine_initial_infection_states_world(input_dir, start_date); + //determine_initial_infection_states_world(input_dir, start_date); auto stop0 = std::chrono::high_resolution_clock::now(); auto duration0 = std::chrono::duration(stop0 - start0); std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" @@ -1106,6 +1108,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groups); create_sampled_world(world, input_dir, t0, max_num_persons); + world.parameters.get() = pow(10, run_idx - 5); // Stop the clock after create_sampled_world and calculate the duration auto stop1 = std::chrono::high_resolution_clock::now(); auto duration1 = std::chrono::duration(stop1 - start1); @@ -1251,7 +1254,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 1; + num_runs = 10; printf("Running with number of runs = %d.\n", (int)num_runs); } diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index 2f1b78aabb..9fcde7b7c9 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -58,7 +58,7 @@ TEST(TestInfection, init) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] - .params.a())) // Virus Shed Factor + .params.alpha())) // Virus Shed Factor // 2nd infection .WillOnce(testing::Return(1.0)) // TimeInfectedNoSymptomsToSymptoms .WillOnce(testing::Return(1.0)) // IncubationTime @@ -75,7 +75,7 @@ TEST(TestInfection, init) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] - .params.a())) // Virus Shed Factor + .params.alpha())) // Virus Shed Factor .WillRepeatedly(testing::Return(1.0)); auto infection = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, @@ -88,7 +88,7 @@ TEST(TestInfection, init) mio::abm::InfectionState::Exposed); EXPECT_EQ(infection.get_infection_state(mio::abm::TimePoint(0) + mio::abm::days(1)), mio::abm::InfectionState::InfectedNoSymptoms); - EXPECT_NEAR(infection.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), 0.02689414213699951, 1e-14); + EXPECT_NEAR(infection.get_viral_shed(mio::abm::TimePoint(0) + mio::abm::days(3)), 0.02689414213699951, 1e-14); params.get()[{mio::abm::ExposureType::GenericVaccine, age_group_test, virus_variant_test}] = [](ScalarType days) -> ScalarType { @@ -106,7 +106,7 @@ TEST(TestInfection, init) mio::abm::InfectionState::InfectedSymptoms); EXPECT_EQ(infection_w_previous_exp.get_infection_state(mio::abm::TimePoint(0) + mio::abm::days(1)), mio::abm::InfectionState::Recovered); - EXPECT_NEAR(infection_w_previous_exp.get_infectivity(mio::abm::TimePoint(0) + mio::abm::days(3)), + EXPECT_NEAR(infection_w_previous_exp.get_viral_shed(mio::abm::TimePoint(0) + mio::abm::days(3)), 9.1105119440064545e-05, 1e-14); } @@ -152,7 +152,7 @@ TEST(TestInfection, drawInfectionCourseBackward) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] - .params.a())) // Virus Shed Factor + .params.alpha())) // Virus Shed Factor // 2nd infection .WillOnce(testing::Return(0.4)) // Transition to InfectedSymptoms .WillOnce(testing::Return(1.0)) // TimeInfectedSymptomsToRecovered @@ -169,7 +169,7 @@ TEST(TestInfection, drawInfectionCourseBackward) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] - .params.a())) // Virus Shed Factor + .params.alpha())) // Virus Shed Factor // 3rd infection .WillOnce(testing::Return(0.2)) // Transition to InfectedSevere .WillOnce(testing::Return(1.0)) // TimeInfectedSevereToRecovered @@ -187,7 +187,7 @@ TEST(TestInfection, drawInfectionCourseBackward) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] .infectivity_beta.params.a())) .WillOnce(testing::Return(params.get()[{virus_variant_test, age_group_test}] - .params.a())) // Virus Shed Factor + .params.alpha())) // Virus Shed Factor // 4th infection .WillOnce(testing::Return(0.0)) // Transition to InfectedCritical .WillOnce(testing::Return(1.0)) //TimeInfectedCriticalToRecovered diff --git a/cpp/tests/test_abm_location.cpp b/cpp/tests/test_abm_location.cpp index d9166250f9..37e7205896 100644 --- a/cpp/tests/test_abm_location.cpp +++ b/cpp/tests/test_abm_location.cpp @@ -128,7 +128,7 @@ TEST(TestLocation, CacheExposureRate) infected2.migrate_to(location, {0, 1}); //cache precomputed results - location.cache_exposure_rates(t, dt, num_age_groups); + location.cache_exposure_rates(t, dt, num_age_groups, params); EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_contacts[{variant, age}]), 0.0015015859523894731, 1e-14); @@ -144,7 +144,7 @@ TEST(TestLocation, CacheExposureRate) location.set_capacity(2, 22, 0); // Capacity for Cell 1 location.set_capacity(2, 22, 1); // Capacity for Cell 2 location.set_capacity(2, 22, 2); // Capacity for Cell 3 - location.cache_exposure_rates(t, dt, num_age_groups); + location.cache_exposure_rates(t, dt, num_age_groups, params); EXPECT_NEAR((location.get_cells()[0].m_cached_exposure_rate_air[{variant}]), 0.0045047578571684191, 1e-14); EXPECT_NEAR((location.get_cells()[1].m_cached_exposure_rate_air[{variant}]), 0.0022523789285842095, 1e-14); @@ -261,7 +261,7 @@ TEST(TestLocation, interact) location.add_person(infected3, {0}); //cache precomputed results - location.cache_exposure_rates(t, dt, num_age_groups); + location.cache_exposure_rates(t, dt, num_age_groups, params); ScopedMockDistribution>>> mock_exponential_dist; diff --git a/cpp/tests/test_abm_masks.cpp b/cpp/tests/test_abm_masks.cpp index dd0fa484af..1d02b72b47 100644 --- a/cpp/tests/test_abm_masks.cpp +++ b/cpp/tests/test_abm_masks.cpp @@ -74,7 +74,7 @@ TEST(TestMasks, maskProtection) //cache precomputed results auto dt = mio::abm::days(1); - infection_location.cache_exposure_rates(t, dt, num_age_groups); + infection_location.cache_exposure_rates(t, dt, num_age_groups, params); // susc_person1 wears a mask, default protection is 1 susc_person1.set_wear_mask(true); // susc_person2 does not wear a mask From 2dbb1fa5509d027f60fd846defa234407f83c956 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Tue, 9 Apr 2024 10:29:08 +0200 Subject: [PATCH 074/488] Start extrapolation of real world data to fit parameter --- cpp/simulations/analyze_bs_run.py | 9 ++++++ cpp/simulations/generate_graph_from_data.cpp | 24 ++++++++++++++++ cpp/simulations/paper_abm_bs_testing.cpp | 29 ++++++++++++++++---- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index f8d192f28c..c1f11f4c5a 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -104,6 +104,15 @@ def plot_results(path): total_75 = group['Total'][()] f.close() + # real world + # TODO + f = h5py.File( + path + "PFADEINFUEGEN/Results.h5", 'r') + group = f['3101'] + total_50 = group['Total'][()] + f.close() + + plot_infection_states_dead(time, total_50, total_25, total_75) plot_infection_states(time, total_50, total_25, total_75) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 3987e5bb62..e2659d3182 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -235,6 +235,30 @@ mio::IOResult> get_graph(mio::Date start_date, c return mio::success(nodes); } +/** + * Calls the function to generate the extrapolated data based on the reported data. The generated data is saved in the + * data directory. + * @param start_date start date of the simulation. + * @param num_days number of days to extrapolate the data. + * @param data_dir data directory. + * @returns created graph or any io errors that happen during reading of the files. + */ +mio::IOResult generate_extrapolated_data(std::vector nodes, std::vector node_ids, + mio::Date start_date, const int num_days, const fs::path& data_dir) +{ + + auto scaling_factor_infected = std::vector(size_t(nodes[0].parameters.get_num_groups()), 1.0); + auto scaling_factor_icu = 1.0; + + BOOST_OUTCOME_TRY(export_input_data_county_timeseries( + nodes, data_dir.string(), node_ids, start_date, scaling_factor_infected, scaling_factor_icu, num_days, + mio::path_join(data_dir.string(), "pydata/Germany", "county_divi_ma7.json"), + mio::path_join(data_dir.string(), "pydata/Germany", "cases_all_county_age_ma7.json"), + mio::path_join(data_dir.string(), "pydata/Germany", "county_current_population.json"))); + + return mio::success(); +} + /* int main(int argc, char** argv) { diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 251084b662..c20318a9b3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -69,9 +69,19 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m auto initial_graph = get_graph(date, 1, input_dir); size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; + extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 30); // 30 days initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); } +/** + * Create extrapolation of real world data to compare with. +*/ +void extrapolate_real_world_data(mio::osecir::Model& model, const std::string& input_dir, const mio::Date date, + int num_days) +{ + generate_extrapolated_data({model}, {3101}, date, num_days, input_dir); +} + /** * Assign an infection state to each person according to real world data read in through the ODE secir model. */ @@ -662,7 +672,6 @@ void set_local_parameters(mio::abm::World& world) 0.0204 0.1444 0.5738 1.2127 0.3433 0.0178 0.0371 0.0393 0.4171 0.9666 0.7495 0.0257 0.0791 0.0800 0.3480 0.5588 0.2769 0.0180 - */ mio::CustomIndexArray contacts_other( {mio::AgeGroup(n_age_groups), mio::AgeGroup(n_age_groups)}, 0.); @@ -707,15 +716,23 @@ void set_local_parameters(mio::abm::World& world) switch (loc.get_type()) { case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; + loc.get_infection_parameters().get().array() *= + 1.8; // scaling due to beeing at school 1/1.8 * 100% of the time break; case mio::abm::LocationType::School: - loc.get_infection_parameters().get() = contacts_work; + loc.get_infection_parameters().get() = contacts_school; + loc.get_infection_parameters().get().array() *= + 4.8; // scaling due to beeing at school 1/4.8 * 100% of the time break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; + loc.get_infection_parameters().get().array() *= + 3.5; // scaling due to beeing at school 1/3.5 * 100% of the time break; default: loc.get_infection_parameters().get() = contacts_other; + loc.get_infection_parameters().get().array() *= + 5.2675; // scaling due to beeing at school 1/5.2675 * 100% of the time break; } } @@ -1009,8 +1026,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(50); // End time per simulation - auto max_num_persons = 23000; + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(20); // End time per simulation + auto max_num_persons = 1000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -1039,7 +1056,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution //Time this auto start0 = std::chrono::high_resolution_clock::now(); - //determine_initial_infection_states_world(input_dir, start_date); + determine_initial_infection_states_world(input_dir, start_date); auto stop0 = std::chrono::high_resolution_clock::now(); auto duration0 = std::chrono::duration(stop0 - start0); std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" @@ -1057,7 +1074,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groups); create_sampled_world(world, input_dir, t0, max_num_persons); - world.parameters.get() = pow(10, run_idx - 5); + world.parameters.get() = pow(10, (int)run_idx - 5); // Stop the clock after create_sampled_world and calculate the duration auto stop1 = std::chrono::high_resolution_clock::now(); auto duration1 = std::chrono::duration(stop1 - start1); From cc197a9be004c3ab93ef6582e15658efaaf6c325 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 9 Apr 2024 18:53:48 +0200 Subject: [PATCH 075/488] Refactor plot_infection_states function to include real world data in analyze_bs_run.py Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 41 ++++++++++----- cpp/simulations/paper_abm_bs_testing.cpp | 63 ++++++++++++++++-------- 2 files changed, 72 insertions(+), 32 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index c1f11f4c5a..15b2c52f6a 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -77,7 +77,7 @@ def plot_infection_per_age_group(df): def plot_results(path): # median / 50-percentile f = h5py.File( - path+"/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/infection_state_per_age_group/results_run0_sum.h5", 'r') # Get the HDF5 group; key needs to be a group name from above group = f['0'] @@ -94,31 +94,31 @@ def plot_results(path): f = h5py.File( path+"/infection_state_per_age_group/p25/Results.h5", 'r') group = f['0'] - total_25 = group['Total'][()] + total_25 =total_50 f.close() # 95-percentile f = h5py.File( path + "/infection_state_per_age_group/p75/Results.h5", 'r') group = f['0'] - total_75 = group['Total'][()] + total_75 = total_50 f.close() # real world # TODO f = h5py.File( - path + "PFADEINFUEGEN/Results.h5", 'r') + path + "/Results_rki.h5", 'r') group = f['3101'] - total_50 = group['Total'][()] + total_real = group['Total'][()] f.close() - plot_infection_states_dead(time, total_50, total_25, total_75) - plot_infection_states(time, total_50, total_25, total_75) + plot_infection_states_dead(time, total_50, total_25, total_75,total_real) + plot_infection_states(time, total_50, total_25, total_75,total_real) -def plot_infection_states(x, y50, y25, y75): +def plot_infection_states(x, y50, y25, y75,y_real): plt.figure('Infection_states') plt.plot(x, y50) plt.legend(['S', 'E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Rec', 'Dead']) @@ -127,15 +127,32 @@ def plot_infection_states(x, y50, y25, y75): plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.1) plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.1) -def plot_infection_states_dead(x, y50, y25, y75): - plt.figure('Infection_states_dead') - plt.plot(x, y50[:,[5,7]]) - plt.legend(['I_Crit', 'Dead']) +def plot_infection_states_dead(x, y50, y25, y75,y_real): + # plt.figure('Infection_states_dead') + # # plt.plot(x, y50[:,[5,7]]) + x_real = np.linspace(0, y_real.shape[0]-1,y_real.shape[0]) + # plt.plot(x_real, y_real[:,[2]]) + # plt.legend(['I_Crit', 'Dead']) # for i in [5,7]: # plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.1) # plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.1) + fig, ax1 = plt.subplots() + + color = 'tab:red' + ax1.set_xlabel('time (s)') + ax1.set_ylabel('y50', color=color) + ax1.plot(x, y50[:,[5]], color=color) + ax1.tick_params(axis='y', labelcolor=color) + ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis + color = 'tab:blue' + ax2.set_ylabel('y_real', color=color) # we already handled the x-label with ax1 + ax2.plot(x_real, y_real[:,[2]], color=color) + ax2.tick_params(axis='y', labelcolor=color) + fig.tight_layout() # otherwise the right y-label is slightly clipped + plt.show() + def plot_infections_per_age_group(path): f = h5py.File( diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c20318a9b3..53871339b8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -61,25 +61,25 @@ mio::CustomIndexArray initia {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.005}; /** - * Determine initial distribution of infection states. + * Create extrapolation of real world data to compare with. */ -void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date) +void extrapolate_real_world_data(mio::osecir::Model& model, const std::string& input_dir, const mio::Date date, + int num_days) { - // estimate intial population by ODE compartiments - auto initial_graph = get_graph(date, 1, input_dir); - size_t braunschweig_id = 16; // Braunschweig has ID 16 - auto braunschweig_node = initial_graph.value()[braunschweig_id]; - extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 30); // 30 days - initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); + auto test = generate_extrapolated_data({model}, {3101}, date, num_days, input_dir); } /** - * Create extrapolation of real world data to compare with. + * Determine initial distribution of infection states. */ -void extrapolate_real_world_data(mio::osecir::Model& model, const std::string& input_dir, const mio::Date date, - int num_days) +void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date) { - generate_extrapolated_data({model}, {3101}, date, num_days, input_dir); + // estimate intial population by ODE compartiments + auto initial_graph = get_graph(date, 1, input_dir); + size_t braunschweig_id = 16; // Braunschweig has ID 16 + auto braunschweig_node = initial_graph.value()[braunschweig_id]; + extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 30); // 30 days + initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); } /** @@ -479,13 +479,36 @@ void set_parameters(mio::abm::Parameters& params) TimeInfectedCriticalToRecovered_my_sigma.second}; // Set percentage parameters - params.get() = 0.5; - params.get() = 0.1; - params.get() = 0.05; - params.get() = 0.002; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.75; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.75; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.8; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.8; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.8; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.0075; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.0075; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.019; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.0615; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.165; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.225; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.075; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.075; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.075; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.15; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.3; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.4; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.14; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.14; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.4; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.6; // Set infection parameters - params.get() = 1.; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 1.0; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -1026,8 +1049,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(20); // End time per simulation - auto max_num_persons = 1000; + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(50); // End time per simulation + auto max_num_persons = 10000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); @@ -1074,7 +1097,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groups); create_sampled_world(world, input_dir, t0, max_num_persons); - world.parameters.get() = pow(10, (int)run_idx - 5); + world.parameters.get() = pow(10, ((int)run_idx) - 5); // Stop the clock after create_sampled_world and calculate the duration auto stop1 = std::chrono::high_resolution_clock::now(); auto duration1 = std::chrono::duration(stop1 - start1); From 7f66ca4f2da7bb2c364ad5ac77c2d510265fca88 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:18:00 +0200 Subject: [PATCH 076/488] Change TestType to enum class and create TestData struct to extract TestParameter for each type --- cpp/examples/abm_history_object.cpp | 7 ++-- cpp/examples/abm_minimal.cpp | 11 +++--- cpp/models/abm/parameters.h | 51 +++++++++---------------- cpp/models/abm/testing_strategy.cpp | 11 +++--- cpp/models/abm/testing_strategy.h | 6 +-- cpp/simulations/abm.cpp | 8 ++-- cpp/tests/test_abm_person.cpp | 27 +++++++------ cpp/tests/test_abm_testing_strategy.cpp | 20 +++++++--- cpp/tests/test_abm_world.cpp | 4 +- 9 files changed, 71 insertions(+), 74 deletions(-) diff --git a/cpp/examples/abm_history_object.cpp b/cpp/examples/abm_history_object.cpp index dd3b1224ad..8bb30859b4 100644 --- a/cpp/examples/abm_history_object.cpp +++ b/cpp/examples/abm_history_object.cpp @@ -125,10 +125,11 @@ int main() auto probability = 0.5; auto start_date = mio::abm::TimePoint(0); auto end_date = mio::abm::TimePoint(0) + mio::abm::days(30); - auto test_type = mio::abm::AntigenTest(); + auto test_type = mio::abm::TestType::Antigen; + auto test_parameters = world.parameters.get()[test_type]; auto testing_criteria_work = mio::abm::TestingCriteria(); - auto testing_scheme_work = - mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, test_type, probability); + auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, + test_parameters, probability); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); // Assign infection state to each person. diff --git a/cpp/examples/abm_minimal.cpp b/cpp/examples/abm_minimal.cpp index e42b48b651..4d906b051b 100644 --- a/cpp/examples/abm_minimal.cpp +++ b/cpp/examples/abm_minimal.cpp @@ -41,10 +41,10 @@ int main() world.parameters.get() = 4.; // Set the age group the can go to school is AgeGroup(1) (i.e. 5-14) - world.parameters.get() = false; + world.parameters.get() = false; world.parameters.get()[age_group_5_to_14] = true; // Set the age group the can go to work is AgeGroup(2) and AgeGroup(3) (i.e. 15-34 and 35-59) - world.parameters.get() = false; + world.parameters.get() = false; world.parameters.get()[age_group_15_to_34] = true; world.parameters.get()[age_group_35_to_59] = true; @@ -110,10 +110,11 @@ int main() auto probability = 0.5; auto start_date = mio::abm::TimePoint(0); auto end_date = mio::abm::TimePoint(0) + mio::abm::days(10); - auto test_type = mio::abm::AntigenTest(); + auto test_type = mio::abm::TestType::Antigen; + auto test_parameters = world.parameters.get()[test_type]; auto testing_criteria_work = mio::abm::TestingCriteria(); - auto testing_scheme_work = - mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, test_type, probability); + auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, + test_parameters, probability); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); // Assign infection state to each person. diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 6460777b30..92c9e68050 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -316,45 +316,31 @@ struct TestParameters { UncertainValue specificity; }; -struct GenericTest { - using Type = TestParameters; - static Type get_default() - { - return Type{0.9, 0.99}; - } - static std::string name() - { - return "GenericTest"; - } -}; - /** - * @brief Reliability of an AntigenTest. + * @brief Type of a Test. */ -struct AntigenTest : public GenericTest { - using Type = TestParameters; - static Type get_default() - { - return Type{0.8, 0.88}; - } - static std::string name() - { - return "AntigenTest"; - } +enum class TestType : std::uint32_t +{ + Generic = 0, + Antigen, + PCR, + + Count }; -/** - * @brief Reliability of a PCRTest. - */ -struct PCRTest : public GenericTest { - using Type = TestParameters; - static Type get_default() +struct TestData { + using Type = CustomIndexArray; + static auto get_default(AgeGroup /*size*/) { - return Type{0.9, 0.99}; + Type default_val = Type({TestType::Count}); + default_val[{TestType::Generic}] = TestParameters{0.9, 0.99}; + default_val[{TestType::Antigen}] = TestParameters{0.8, 0.88}; + default_val[{TestType::PCR}] = TestParameters{0.9, 0.99}; + return default_val; } static std::string name() { - return "PCRTest"; + return "TestData"; } }; @@ -550,7 +536,8 @@ using ParametersBase = InfectivityDistributions, DetectInfection, MaskProtection, AerosolTransmissionRates, LockdownDate, QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, - AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor>; + AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, + TestData>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 9e9dff039d..f2e0354264 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -69,12 +69,13 @@ bool TestingCriteria::evaluate(const Person& p, TimePoint t) const } TestingScheme::TestingScheme(const TestingCriteria& testing_criteria, TimeSpan minimal_time_since_last_test, - TimePoint start_date, TimePoint end_date, const GenericTest& test_type, double probability) + TimePoint start_date, TimePoint end_date, const TestParameters& test_parameters, + double probability) : m_testing_criteria(testing_criteria) , m_minimal_time_since_last_test(minimal_time_since_last_test) , m_start_date(start_date) , m_end_date(end_date) - , m_test_type(test_type) + , m_test_parameters(test_parameters) , m_probability(probability) { } @@ -84,8 +85,8 @@ bool TestingScheme::operator==(const TestingScheme& other) const return this->m_testing_criteria == other.m_testing_criteria && this->m_minimal_time_since_last_test == other.m_minimal_time_since_last_test && this->m_start_date == other.m_start_date && this->m_end_date == other.m_end_date && - this->m_test_type.get_default().sensitivity == other.m_test_type.get_default().sensitivity && - this->m_test_type.get_default().specificity == other.m_test_type.get_default().specificity && + this->m_test_parameters.sensitivity == other.m_test_parameters.sensitivity && + this->m_test_parameters.specificity == other.m_test_parameters.specificity && this->m_probability == other.m_probability; //To be adjusted and also TestType should be static. } @@ -106,7 +107,7 @@ bool TestingScheme::run_scheme(Person::RandomNumberGenerator& rng, Person& perso if (m_testing_criteria.evaluate(person, t)) { double random = UniformDistribution::get_instance()(rng); if (random < m_probability) { - return !person.get_tested(rng, t, m_test_type.get_default()); + return !person.get_tested(rng, t, m_test_parameters); } } } diff --git a/cpp/models/abm/testing_strategy.h b/cpp/models/abm/testing_strategy.h index e947ec30c7..db07663dae 100644 --- a/cpp/models/abm/testing_strategy.h +++ b/cpp/models/abm/testing_strategy.h @@ -111,11 +111,11 @@ class TestingScheme * performed after a Person's last test. * @param start_date Starting date of the scheme. * @param end_date Ending date of the scheme. - * @param test_type The type of test to be performed. + * @param test_parameters The parameters of test to be performed. * @param probability Probability of the test to be performed if a testing rule applies. */ TestingScheme(const TestingCriteria& testing_criteria, TimeSpan minimal_time_since_last_test, TimePoint start_date, - TimePoint end_date, const GenericTest& test_type, ScalarType probability); + TimePoint end_date, const TestParameters& test_parameters, ScalarType probability); /** * @brief Compares two TestingScheme%s for functional equality. @@ -148,7 +148,7 @@ class TestingScheme TimeSpan m_minimal_time_since_last_test; ///< Shortest period of time between two tests. TimePoint m_start_date; ///< Starting date of the scheme. TimePoint m_end_date; ///< Ending date of the scheme. - GenericTest m_test_type; ///< Type of the test. + TestParameters m_test_parameters; ///< Parameters of the test. ScalarType m_probability; ///< Probability of performing the test. bool m_is_active = false; ///< Whether the scheme is currently active. }; diff --git a/cpp/simulations/abm.cpp b/cpp/simulations/abm.cpp index 20a3240904..b218d8f31f 100644 --- a/cpp/simulations/abm.cpp +++ b/cpp/simulations/abm.cpp @@ -330,8 +330,8 @@ void create_assign_locations(mio::abm::World& world) auto probability = mio::UncertainValue(); assign_uniform_distribution(probability, 0.5, 1.0); - auto test_type = mio::abm::AntigenTest(); - auto testing_scheme = mio::abm::TestingScheme(testing_criteria, testing_min_time, start_date, end_date, test_type, + auto test_params = world.parameters.get()[mio::abm::TestType::Antigen]; + auto testing_scheme = mio::abm::TestingScheme(testing_criteria, testing_min_time, start_date, end_date, test_params, probability.draw_sample()); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme); @@ -427,7 +427,7 @@ void create_assign_locations(mio::abm::World& world) testing_min_time = mio::abm::days(7); auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date, - end_date, test_type, probability.draw_sample()); + end_date, test_params, probability.draw_sample()); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); auto test_at_work = std::vector{mio::abm::LocationType::Work}; @@ -436,7 +436,7 @@ void create_assign_locations(mio::abm::World& world) assign_uniform_distribution(probability, 0.1, 0.5); testing_min_time = mio::abm::days(1); auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, - test_type, probability.draw_sample()); + test_params, probability.draw_sample()); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); } diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index ef2f8b6427..e081959234 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -102,8 +102,8 @@ TEST(TestPerson, setGetAssignedLocation) TEST(TestPerson, quarantine) { using testing::Return; - auto rng = mio::RandomNumberGenerator(); - auto test_params = mio::abm::TestParameters{1.01,1.01}; //100% safe test + auto rng = mio::RandomNumberGenerator(); + auto test_params = mio::abm::TestParameters{1.01, 1.01}; //100% safe test auto infection_parameters = mio::abm::Parameters(num_age_groups); mio::abm::Location home(mio::abm::LocationType::Home, 0, num_age_groups); @@ -128,7 +128,7 @@ TEST(TestPerson, quarantine) auto person = make_test_person(home, age_group_35_to_59, mio::abm::InfectionState::InfectedSymptoms, t_morning, infection_parameters); auto rng_person = mio::abm::Person::RandomNumberGenerator(rng, person); - + person.get_tested(rng_person, t_morning, test_params); ASSERT_EQ(person.get_infection_state(t_morning), mio::abm::InfectionState::InfectedSymptoms); @@ -153,9 +153,8 @@ TEST(TestPerson, get_tested) auto susceptible = mio::abm::Person(rng, loc, age_group_15_to_34); auto rng_suscetible = mio::abm::Person::RandomNumberGenerator(rng, susceptible); - auto pcr_test = mio::abm::PCRTest(); - auto antigen_test = mio::abm::AntigenTest(); - + auto pcr_parameters = params.get()[mio::abm::TestType::PCR]; + auto antigen_parameters = params.get()[mio::abm::TestType::Antigen]; // Test pcr test ScopedMockDistribution>>> mock_uniform_dist_pcr; @@ -165,14 +164,14 @@ TEST(TestPerson, get_tested) .WillOnce(Return(0.95)) .WillOnce(Return(0.6)) .WillOnce(Return(0.999)); - ASSERT_EQ(infected.get_tested(rng_infected, t, pcr_test.get_default()), true); + ASSERT_EQ(infected.get_tested(rng_infected, t, pcr_parameters), true); ASSERT_EQ(infected.is_in_quarantine(t, params), true); infected.remove_quarantine(); - ASSERT_EQ(infected.get_tested(rng_infected, t, pcr_test.get_default()), false); + ASSERT_EQ(infected.get_tested(rng_infected, t, pcr_parameters), false); ASSERT_EQ(infected.is_in_quarantine(t, params), false); - ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_test.get_default()), false); + ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_parameters), false); ASSERT_EQ(susceptible.is_in_quarantine(t, params), false); - ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_test.get_default()), true); + ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, pcr_parameters), true); ASSERT_EQ(susceptible.is_in_quarantine(t, params), true); ASSERT_EQ(susceptible.get_time_of_last_test(), mio::abm::TimePoint(0)); @@ -185,10 +184,10 @@ TEST(TestPerson, get_tested) .WillOnce(Return(0.95)) .WillOnce(Return(0.6)) .WillOnce(Return(0.999)); - ASSERT_EQ(infected.get_tested(rng_infected, t, antigen_test.get_default()), true); - ASSERT_EQ(infected.get_tested(rng_infected, t, antigen_test.get_default()), false); - ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_test.get_default()), false); - ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_test.get_default()), true); + ASSERT_EQ(infected.get_tested(rng_infected, t, antigen_parameters), true); + ASSERT_EQ(infected.get_tested(rng_infected, t, antigen_parameters), false); + ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_parameters), false); + ASSERT_EQ(susceptible.get_tested(rng_suscetible, t, antigen_parameters), true); ASSERT_EQ(susceptible.get_time_of_last_test(), mio::abm::TimePoint(0)); } diff --git a/cpp/tests/test_abm_testing_strategy.cpp b/cpp/tests/test_abm_testing_strategy.cpp index 7442701625..4c22d7ceb0 100644 --- a/cpp/tests/test_abm_testing_strategy.cpp +++ b/cpp/tests/test_abm_testing_strategy.cpp @@ -68,13 +68,13 @@ TEST(TestTestingScheme, runScheme) const auto start_date = mio::abm::TimePoint(0); const auto end_date = mio::abm::TimePoint(60 * 60 * 24 * 3); const auto probability = 0.8; - const auto test_type = mio::abm::PCRTest(); + const auto test_params = mio::abm::TestData().get_default(0)[mio::abm::TestType::PCR]; std::vector test_infection_states = {mio::abm::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedNoSymptoms}; auto testing_scheme1 = - mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, test_type, probability); + mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, test_params, probability); ASSERT_EQ(testing_scheme1.is_active(), false); testing_scheme1.update_activity_status(mio::abm::TimePoint(10)); @@ -86,7 +86,7 @@ TEST(TestTestingScheme, runScheme) std::vector test_infection_states2 = {mio::abm::InfectionState::Recovered}; auto testing_criteria2 = mio::abm::TestingCriteria({}, test_infection_states2); auto testing_scheme2 = - mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, test_type, probability); + mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, test_params, probability); mio::abm::Location loc_home(mio::abm::LocationType::Home, 0, num_age_groups); mio::abm::Location loc_work(mio::abm::LocationType::Work, 0, num_age_groups); @@ -115,18 +115,18 @@ TEST(TestTestingScheme, initAndRunTestingStrategy) const auto start_date = mio::abm::TimePoint(0); const auto end_date = mio::abm::TimePoint(60 * 60 * 24 * 3); const auto probability = 0.8; - const auto test_type = mio::abm::PCRTest(); + const auto test_params = mio::abm::TestData().get_default(0)[mio::abm::TestType::PCR]; std::vector test_infection_states = {mio::abm::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedNoSymptoms}; auto testing_criteria1 = mio::abm::TestingCriteria({}, test_infection_states); auto testing_scheme1 = - mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, test_type, probability); + mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, test_params, probability); testing_scheme1.update_activity_status(mio::abm::TimePoint(0)); std::vector test_infection_states2 = {mio::abm::InfectionState::Recovered}; auto testing_criteria2 = mio::abm::TestingCriteria({}, test_infection_states2); auto testing_scheme2 = - mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, test_type, probability); + mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, test_params, probability); mio::abm::Location loc_work(mio::abm::LocationType::Work, 0); auto person1 = make_test_person(loc_work, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); @@ -150,3 +150,11 @@ TEST(TestTestingScheme, initAndRunTestingStrategy) true); // Person tests and tests negative ASSERT_EQ(test_strategy.run_strategy(rng_person1, person1, loc_work, start_date), true); // Person doesn't test } + +TEST(TestTestingCriteria, getDefaultTestParameters) +{ + // Create the world with 4 age groups. + auto world = mio::abm::World(num_age_groups); + auto test_type = mio::abm::TestType::Antigen; + auto test_parameters = world.parameters.get()[test_type]; +} diff --git a/cpp/tests/test_abm_world.cpp b/cpp/tests/test_abm_world.cpp index 4275202b86..83bce5256d 100644 --- a/cpp/tests/test_abm_world.cpp +++ b/cpp/tests/test_abm_world.cpp @@ -432,10 +432,10 @@ TEST(TestWorldTestingCriteria, testAddingAndUpdatingAndRunningTestingSchemes) const auto start_date = mio::abm::TimePoint(20); const auto end_date = mio::abm::TimePoint(60 * 60 * 24 * 3); const auto probability = 1.0; - const auto test_type = mio::abm::PCRTest(); + const auto test_params = world.parameters.get()[mio::abm::TestType::PCR]; auto testing_scheme = - mio::abm::TestingScheme(testing_criteria, testing_frequency, start_date, end_date, test_type, probability); + mio::abm::TestingScheme(testing_criteria, testing_frequency, start_date, end_date, test_params, probability); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme); ASSERT_EQ(world.get_testing_strategy().run_strategy(rng_person, person, work, current_time), From c35e436cf2fb0d1df60693efd250725e4db3e349 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:42:31 +0200 Subject: [PATCH 077/488] Add test to get default TestParameters --- cpp/tests/test_abm_testing_strategy.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/cpp/tests/test_abm_testing_strategy.cpp b/cpp/tests/test_abm_testing_strategy.cpp index 4c22d7ceb0..e2161ea2b2 100644 --- a/cpp/tests/test_abm_testing_strategy.cpp +++ b/cpp/tests/test_abm_testing_strategy.cpp @@ -153,8 +153,19 @@ TEST(TestTestingScheme, initAndRunTestingStrategy) TEST(TestTestingCriteria, getDefaultTestParameters) { - // Create the world with 4 age groups. auto world = mio::abm::World(num_age_groups); - auto test_type = mio::abm::TestType::Antigen; - auto test_parameters = world.parameters.get()[test_type]; + auto test_parameters = world.parameters.get()[mio::abm::TestType::Generic]; + ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); + ASSERT_NEAR(test_parameters.specificity, 0.99, 1e-7); + test_parameters = world.parameters.get()[mio::abm::TestType::Antigen]; + ASSERT_NEAR(test_parameters.sensitivity, 0.8, 1e-7); + ASSERT_NEAR(test_parameters.specificity, 0.88, 1e-7); + test_parameters = world.parameters.get()[mio::abm::TestType::PCR]; + ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); + ASSERT_NEAR(test_parameters.specificity, 0.99, 1e-7); + + world.parameters.get()[mio::abm::TestType::PCR].sensitivity = 0.8; + world.parameters.get()[mio::abm::TestType::PCR].specificity = 0.88; + ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); + ASSERT_NEAR(test_parameters.specificity, 0.99, 1e-7); } From 107749f341a0dcf26a1e18982621b5bf04436f46 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:05:48 +0200 Subject: [PATCH 078/488] Fix some things, improve runs, improve plots --- cpp/models/abm/infection.cpp | 2 +- cpp/models/abm/location.cpp | 2 +- cpp/simulations/analyze_bs_run.py | 86 +++++++++++++++++------- cpp/simulations/check_bs_data.py | 69 ++++++++++--------- cpp/simulations/paper_abm_bs_testing.cpp | 60 +++++++++-------- 5 files changed, 131 insertions(+), 88 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 8d974e0748..728509a86d 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -164,7 +164,7 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng case InfectionState::InfectedSymptoms: { // roll out next infection step - ScalarType severity_protection_factor = 1.; + ScalarType severity_protection_factor = 0.; p = uniform_dist(rng); if (latest_exposure.first != ExposureType::NoProtection) { severity_protection_factor = diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 0479343b9a..7467ea26f0 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -146,7 +146,7 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou cell.m_cached_exposure_rate_contacts[{virus, age}] += params.get()[{virus}] * inf.get_viral_shed(t + dt / 2); cell.m_cached_exposure_rate_air[{virus}] += - inf.get_viral_shed(t + dt / 2); // TODO: Change to non-contact function! + inf.get_viral_shed(t + dt / 2); // TODO: Adapt function/factor for air transmission. } } diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 15b2c52f6a..18c457b539 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -44,7 +44,7 @@ def main(path, n_runs): # num_files = len([entry for entry in os.listdir(path)]) # read in each txt file and convert to numpy array # df_np_3d = np.empty((num_rows, num_cols, n_runs)) - print(os.listdir(path)) + # print(os.listdir(path)) for file in os.listdir(path): file_path = os.path.join(path, file) # read in txt file @@ -77,7 +77,7 @@ def plot_infection_per_age_group(df): def plot_results(path): # median / 50-percentile f = h5py.File( - path+"/infection_state_per_age_group/results_run0_sum.h5", 'r') + path+"/infection_state_per_age_group/p50/Results.h5", 'r') # Get the HDF5 group; key needs to be a group name from above group = f['0'] @@ -94,14 +94,14 @@ def plot_results(path): f = h5py.File( path+"/infection_state_per_age_group/p25/Results.h5", 'r') group = f['0'] - total_25 =total_50 + total_25 = group['Total'][()] f.close() # 95-percentile f = h5py.File( path + "/infection_state_per_age_group/p75/Results.h5", 'r') group = f['0'] - total_75 = total_50 + total_75 = group['Total'][()] f.close() # real world @@ -112,46 +112,82 @@ def plot_results(path): total_real = group['Total'][()] f.close() - - plot_infection_states_dead(time, total_50, total_25, total_75,total_real) - plot_infection_states(time, total_50, total_25, total_75,total_real) - + plot_infection_states_individual( + time, total_50, total_25, total_75, total_real) + plot_infection_states(time, total_50, total_25, total_75) -def plot_infection_states(x, y50, y25, y75,y_real): +def plot_infection_states(x, y50, y25, y75): plt.figure('Infection_states') - plt.plot(x, y50) + plt.title('Infection states') + color_plot = cmx.get_cmap('Set1').colors + print(color_plot) + + for i in range(y50.shape[1]): + plt.plot(x, y50[:, i], color=color_plot[i]) + plt.legend(['S', 'E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Rec', 'Dead']) for i in range(y50.shape[1]): - plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.1) - plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.1) + plt.fill_between(x, y50[:, i], y25[:, i], + alpha=0.5, color=color_plot[i]) + plt.fill_between(x, y50[:, i], y75[:, i], + alpha=0.5, color=color_plot[i]) + -def plot_infection_states_dead(x, y50, y25, y75,y_real): +def plot_infection_states_individual(x, y50, y25, y75, y_real): # plt.figure('Infection_states_dead') # # plt.plot(x, y50[:,[5,7]]) x_real = np.linspace(0, y_real.shape[0]-1,y_real.shape[0]) # plt.plot(x_real, y_real[:,[2]]) # plt.legend(['I_Crit', 'Dead']) - # for i in [5,7]: - # plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.1) - # plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.1) + fig, ax = plt.subplots(3, 1) + + # Severe + color = 'tab:red' + ax[0].set_xlabel('time (s)') + ax[0].set_ylabel('y50', color=color) + ax[0].plot(x, y50[:, [4]], color=color) + ax[0].tick_params(axis='y', labelcolor=color) + # instantiate a second axes that shares the same x-axis + ax2 = ax[0].twinx() + color = 'tab:blue' + # we already handled the x-label with ax1 + ax2.set_ylabel('y_real', color=color) + ax2.plot(x_real, y_real[:, [6]], '*', color=color) + ax2.tick_params(axis='y', labelcolor=color) + fig.tight_layout() # otherwise the right y-label is slightly clipped - fig, ax1 = plt.subplots() + # Critical + color = 'tab:red' + ax[1].set_xlabel('time (s)') + ax[1].set_ylabel('y50', color=color) + ax[1].plot(x, y50[:, [5]], color=color) + ax[1].tick_params(axis='y', labelcolor=color) + # instantiate a second axes that shares the same x-axis + ax2 = ax[1].twinx() + color = 'tab:blue' + # we already handled the x-label with ax1 + ax2.set_ylabel('y_real', color=color) + ax2.plot(x_real, y_real[:, [7]], '*', color=color) + ax2.tick_params(axis='y', labelcolor=color) + fig.tight_layout() # otherwise the right y-label is slightly clipped + # Dead color = 'tab:red' - ax1.set_xlabel('time (s)') - ax1.set_ylabel('y50', color=color) - ax1.plot(x, y50[:,[5]], color=color) - ax1.tick_params(axis='y', labelcolor=color) - ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis + ax[2].set_xlabel('time (s)') + ax[2].set_ylabel('y50', color=color) + ax[2].plot(x, y50[:, [7]], color=color) + ax[2].tick_params(axis='y', labelcolor=color) + # instantiate a second axes that shares the same x-axis + ax2 = ax[2].twinx() color = 'tab:blue' ax2.set_ylabel('y_real', color=color) # we already handled the x-label with ax1 - ax2.plot(x_real, y_real[:,[2]], color=color) + ax2.plot(x_real, y_real[:, [9]], '*', color=color) ax2.tick_params(axis='y', labelcolor=color) fig.tight_layout() # otherwise the right y-label is slightly clipped - plt.show() + plt.show() def plot_infections_per_age_group(path): @@ -199,7 +235,7 @@ def plot_mean_and_std(Y): if __name__ == "__main__": #path to results - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" + path = "/Users/David/Documents/HZI/memilio/data/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: diff --git a/cpp/simulations/check_bs_data.py b/cpp/simulations/check_bs_data.py index 8dbcf183b5..56c34e33ae 100644 --- a/cpp/simulations/check_bs_data.py +++ b/cpp/simulations/check_bs_data.py @@ -14,7 +14,8 @@ ####### minimal sanity check on data ####### -bd = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/pycode/memilio-epidata/memilio/epidata/bs_und_umgebung.csv', header=None, skiprows=1) +bd = pd.read_csv( + r'/Users/David/Documents/HZI/memilio/data/mobility/modified_braunschweig_result.csv', header=None, skiprows=1) # setup dictionary for the leisure activities, and vehicle choice and column names # bd.rename( @@ -147,12 +148,12 @@ # # return bd_persons_trip_chain_activity_after, bd_persons_trip_chain_vehicle_choice -# # read in the data -# if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'figs_bs_data')): -# os.makedirs(os.path.join(os.path.dirname( -# os.path.abspath(__file__)), 'figs_bs_data')) -# figs_path = os.path.join(os.path.dirname( -# os.path.abspath(__file__)), 'figs_bs_data') +# define figure path +if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'figs_bs_data')): + os.makedirs(os.path.join(os.path.dirname( + os.path.abspath(__file__)), 'figs_bs_data')) +figs_path = os.path.join(os.path.dirname( + os.path.abspath(__file__)), 'figs_bs_data') # # check whether first start location is the last end location # first_trip = bd[['personID','loc_id_start']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) @@ -191,15 +192,18 @@ # plt.title('Number of trips per person tripcount (Braunschweig)') # plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) -# bd_persons_ages = bd[['personID', 'age']].drop_duplicates() +bd_persons_ages = bd[['personID', 'age']].drop_duplicates() # bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ # '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -# bd_persons_ages_cohorts = bd_persons_ages.groupby( -# ['AgeCohort']).size().reset_index(name='counts') -# bd_persons_ages_cohorts.index = bd_persons_ages_cohorts['AgeCohort'].to_list() -# bd_persons_ages_cohorts.plot.bar(figsize=( -# 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) -# plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) +# ages according to RKI data +bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 2, 5, 14, 17, 24, 29, 39, 49, 64, 74, 105], labels=[ + '0-2', '3-5', '6-14', '15-17', '18-24', '25-29', '30-39', '40-49', '50-64', '65-74', '75+']) +bd_persons_ages_cohorts = bd_persons_ages.groupby( + ['AgeCohort']).size().reset_index(name='counts') +bd_persons_ages_cohorts.index = bd_persons_ages_cohorts['AgeCohort'].to_list() +bd_persons_ages_cohorts.plot.bar(figsize=( + 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) +plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) # # get the id with the persons with the highest number and print them # # [id_person_max_trips, id_person_max_1_trips] = [ @@ -511,20 +515,19 @@ ## draft to add collumn to check if the location in Braunschweig -bd['home_in_bs'] = 0 -#list of persons who are in braunschweig -list_person_in_bs = np.array([]) -for index, row in bd.iterrows(): - if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): - list_person_in_bs = np.append(list_person_in_bs, row['personID']) -#drop duplicates -list_person_in_bs = np.unique(list_person_in_bs) -for index, row in bd.iterrows(): - if row['personID'] in list_person_in_bs: - bd.at[index, 'home_in_bs'] = 1 - - -bd.to_csv('modified_braunschweig_result.csv', index=False) +# bd['home_in_bs'] = 0 +# #list of persons who are in braunschweig +# list_person_in_bs = np.array([]) +# for index, row in bd.iterrows(): +# if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): +# list_person_in_bs = np.append(list_person_in_bs, row['personID']) +# #drop duplicates +# list_person_in_bs = np.unique(list_person_in_bs) +# for index, row in bd.iterrows(): +# if row['personID'] in list_person_in_bs: +# bd.at[index, 'home_in_bs'] = 1 +# +# bd.to_csv('modified_braunschweig_result.csv', index=False) #count number of trips which are in braunschweig # bs_trip_count = 0 @@ -536,11 +539,11 @@ # bs_trip_count/len(bd)*100 # count how many persons are in braunschweig -bs_person_count = 0 -# collapse all persons to one trip and check if the trip is in braunschweig -persons_in_bs = bd[['personID', 'home_in_bs']].drop_duplicates().groupby(['personID']).aggregate('sum').reset_index() -# percentage number of persons in braunschweig is persons with not zero home_in_bs / all persons -persons_in_bs.loc[persons_in_bs['home_in_bs']==0].size/persons_in_bs.size*100 +# bs_person_count = 0 +# # collapse all persons to one trip and check if the trip is in braunschweig +# persons_in_bs = bd[['personID', 'home_in_bs']].drop_duplicates().groupby(['personID']).aggregate('sum').reset_index() +# # percentage number of persons in braunschweig is persons with not zero home_in_bs / all persons +# persons_in_bs.loc[persons_in_bs['home_in_bs']==0].size/persons_in_bs.size*100 diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 53871339b8..5a575d81fd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -58,7 +58,7 @@ const std::map infection_ {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; mio::CustomIndexArray initial_infection_distribution{ - {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 0.005}; + {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 1.}; /** * Create extrapolation of real world data to compare with. @@ -76,10 +76,12 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m { // estimate intial population by ODE compartiments auto initial_graph = get_graph(date, 1, input_dir); - size_t braunschweig_id = 16; // Braunschweig has ID 16 - auto braunschweig_node = initial_graph.value()[braunschweig_id]; - extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 30); // 30 days + const size_t braunschweig_id = 16; // Braunschweig has ID 16 + auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); + + //std::cout << initial_infection_distribution.array() << std::endl; + extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 60); // 60 days } /** @@ -1049,20 +1051,21 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(50); // End time per simulation - auto max_num_persons = 10000; - auto ensemble_infection_per_loc_type = - std::vector>>{}; // Vector of infection per location type results - // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); - // auto ensemble_infection_per_age_group = - // std::vector>>{}; // Vector of infection per age group results - // ensemble_infection_per_age_group.reserve(size_t(num_runs)); + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation + auto max_num_persons = 12550; + // auto ensemble_infection_per_loc_type = + // std::vector>>{}; // Vector of infection per location type results + // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); + auto ensemble_infection_per_age_group = + std::vector>>{}; // Vector of infection per age group results + ensemble_infection_per_age_group.reserve(size_t(num_runs)); auto ensemble_infection_state_per_age_group = std::vector>>{}; // Vector of infection state per age group results ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); + // auto run_idx = size_t(1); // The run index // auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations @@ -1097,7 +1100,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groups); create_sampled_world(world, input_dir, t0, max_num_persons); - world.parameters.get() = pow(10, ((int)run_idx) - 5); + world.parameters.get() = pow(10, ((int)run_idx) * 0 + 1.5); // Stop the clock after create_sampled_world and calculate the duration auto stop1 = std::chrono::high_resolution_clock::now(); auto duration1 = std::chrono::duration(stop1 - start1); @@ -1113,8 +1116,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // mio::History historyPersonInfDelta; mio::History historyInfectionPerLocationType{ Eigen::Index(mio::abm::LocationType::Count)}; - // mio::History historyInfectionPerAgeGroup{ - // Eigen::Index(sim.get_world().parameters.get_num_groups())}; + mio::History historyInfectionPerAgeGroup{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; @@ -1129,23 +1132,24 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Advance the world to tmax // sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, // historyPersonInfDelta, historyInfectionStatePerAgeGroup); - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + historyInfectionPerAgeGroup); // Stop the clock after sim.advance and calculate the duration auto stop2 = std::chrono::high_resolution_clock::now(); auto duration2 = std::chrono::duration(stop2 - start2); std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_infection_per_loc_tpye = - std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; - // auto temp_sim_infection_per_age_group = - // std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; + // auto temp_sim_infection_per_loc_tpye = + // std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_per_age_group = + std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; // Push result of the simulation back to the result vector - ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); - // ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); + // ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); + ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); // ensemble_params.push_back(std::vector{sim.get_world()}); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); // Option to save the current run result to file @@ -1182,13 +1186,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s //gather results auto final_ensemble_infection_state_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); - auto final_ensemble_infection_per_loc_type = - gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type); + //auto final_ensemble_infection_per_loc_type = + // gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type); if (rank == 0) { BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type, ensemble_params, {0}, - result_dir / "infection_per_location_type/", save_single_runs)); + // BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type, ensemble_params, {0}, + // result_dir / "infection_per_location_type/", save_single_runs)); } #else @@ -1217,7 +1221,7 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -1243,7 +1247,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 10; + num_runs = 20; printf("Running with number of runs = %d.\n", (int)num_runs); } From fbad78f822b754f861a715a5b54cdf28d99021b3 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:12:51 +0200 Subject: [PATCH 079/488] Modify TestingScheme in Pycode to include TestParameters instead of TestType --- pycode/memilio-simulation/memilio/simulation/abm.cpp | 11 ++++++----- .../memilio/simulation_test/test_abm.py | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/abm.cpp b/pycode/memilio-simulation/memilio/simulation/abm.cpp index b8c9e86ab2..677a197ce9 100644 --- a/pycode/memilio-simulation/memilio/simulation/abm.cpp +++ b/pycode/memilio-simulation/memilio/simulation/abm.cpp @@ -140,15 +140,16 @@ PYBIND11_MODULE(_simulation_abm, m) .def(py::init&, const std::vector&>(), py::arg("age_groups"), py::arg("infection_states")); - py::class_(m, "GenericTest").def(py::init<>()); - py::class_(m, "AntigenTest").def(py::init<>()); - py::class_(m, "PCRTest").def(py::init<>()); + pymio::iterable_enum(m, "TestType") + .value("Generic", mio::abm::TestType::Generic) + .value("Antigen", mio::abm::TestType::Antigen) + .value("PCR", mio::abm::TestType::PCR); py::class_(m, "TestingScheme") .def(py::init(), + const mio::abm::TestParameters&, double>(), py::arg("testing_criteria"), py::arg("testing_min_time_since_last_test"), py::arg("start_date"), - py::arg("end_date"), py::arg("test_type"), py::arg("probability")) + py::arg("end_date"), py::arg("test_parameters"), py::arg("probability")) .def_property_readonly("active", &mio::abm::TestingScheme::is_active); py::class_(m, "Vaccination") diff --git a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py index a77d1c31d4..85d26be043 100644 --- a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py +++ b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py @@ -58,7 +58,7 @@ def test_locations(self): testing_crit = abm.TestingCriteria( testing_ages, testing_inf_states) testing_scheme = abm.TestingScheme(testing_crit, abm.days( - 1), t0, t0 + abm.days(1), abm.AntigenTest(), 1.0) + 1), t0, t0 + abm.days(1), abm.TestParameters(1.0,1.0), 1.0) # initially false, will only active once simulation starts self.assertEqual(testing_scheme.active, False) From f467d9ee0f0b54a6ffa5725163dd8bc6d27a42f6 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Tue, 23 Apr 2024 16:15:19 +0200 Subject: [PATCH 080/488] Modify TestingScheme in Pycode to include TestParameters instead of TestType --- pycode/memilio-simulation/memilio/simulation_test/test_abm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py index 85d26be043..6d2ef5405d 100644 --- a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py +++ b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py @@ -58,7 +58,7 @@ def test_locations(self): testing_crit = abm.TestingCriteria( testing_ages, testing_inf_states) testing_scheme = abm.TestingScheme(testing_crit, abm.days( - 1), t0, t0 + abm.days(1), abm.TestParameters(1.0,1.0), 1.0) + 1), t0, t0 + abm.days(1), abm.TestParameters(1.0, 1.0), 1.0) # initially false, will only active once simulation starts self.assertEqual(testing_scheme.active, False) From 46b12b6708794b3100ac1c28d45511514c9b049d Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:56:56 +0200 Subject: [PATCH 081/488] Put TestType to another file and small improvement for the tests --- cpp/models/abm/parameters.h | 13 +------ cpp/models/abm/test_type.h | 46 +++++++++++++++++++++++++ cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/testing_strategy.h | 2 +- cpp/tests/test_abm_testing_strategy.cpp | 29 +++++++++------- cpp/tests/test_abm_world.cpp | 4 +-- 6 files changed, 67 insertions(+), 29 deletions(-) create mode 100644 cpp/models/abm/test_type.h diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 92c9e68050..dcccb84320 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -24,6 +24,7 @@ #include "abm/time.h" #include "abm/virus_variant.h" #include "abm/vaccine.h" +#include "abm/test_type.h" #include "memilio/utils/custom_index_array.h" #include "memilio/utils/uncertain_value.h" #include "memilio/math/eigen.h" @@ -316,18 +317,6 @@ struct TestParameters { UncertainValue specificity; }; -/** - * @brief Type of a Test. - */ -enum class TestType : std::uint32_t -{ - Generic = 0, - Antigen, - PCR, - - Count -}; - struct TestData { using Type = CustomIndexArray; static auto get_default(AgeGroup /*size*/) diff --git a/cpp/models/abm/test_type.h b/cpp/models/abm/test_type.h new file mode 100644 index 0000000000..0d1b8756a9 --- /dev/null +++ b/cpp/models/abm/test_type.h @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2020-2024 MEmilio +* +* Authors: Khoa Nguyen +* +* Contact: Martin J. Kuehn +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef EPI_ABM_TEST_TYPE_H +#define EPI_ABM_TEST_TYPE_H + +#include + +namespace mio +{ +namespace abm +{ + +/** + * @brief Type of a Test. + */ +enum class TestType : std::uint32_t +{ + Generic = 0, + Antigen, + PCR, + + Count +}; + +} // namespace abm +} // namespace mio + +#endif diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index f2e0354264..91fe8fc7d9 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -69,7 +69,7 @@ bool TestingCriteria::evaluate(const Person& p, TimePoint t) const } TestingScheme::TestingScheme(const TestingCriteria& testing_criteria, TimeSpan minimal_time_since_last_test, - TimePoint start_date, TimePoint end_date, const TestParameters& test_parameters, + TimePoint start_date, TimePoint end_date, TestParameters test_parameters, double probability) : m_testing_criteria(testing_criteria) , m_minimal_time_since_last_test(minimal_time_since_last_test) diff --git a/cpp/models/abm/testing_strategy.h b/cpp/models/abm/testing_strategy.h index db07663dae..ffb678fb53 100644 --- a/cpp/models/abm/testing_strategy.h +++ b/cpp/models/abm/testing_strategy.h @@ -115,7 +115,7 @@ class TestingScheme * @param probability Probability of the test to be performed if a testing rule applies. */ TestingScheme(const TestingCriteria& testing_criteria, TimeSpan minimal_time_since_last_test, TimePoint start_date, - TimePoint end_date, const TestParameters& test_parameters, ScalarType probability); + TimePoint end_date, TestParameters test_parameters, ScalarType probability); /** * @brief Compares two TestingScheme%s for functional equality. diff --git a/cpp/tests/test_abm_testing_strategy.cpp b/cpp/tests/test_abm_testing_strategy.cpp index e2161ea2b2..325bb2a713 100644 --- a/cpp/tests/test_abm_testing_strategy.cpp +++ b/cpp/tests/test_abm_testing_strategy.cpp @@ -68,13 +68,13 @@ TEST(TestTestingScheme, runScheme) const auto start_date = mio::abm::TimePoint(0); const auto end_date = mio::abm::TimePoint(60 * 60 * 24 * 3); const auto probability = 0.8; - const auto test_params = mio::abm::TestData().get_default(0)[mio::abm::TestType::PCR]; + const auto test_params_pcr = mio::abm::TestParameters{0.9, 0.99}; std::vector test_infection_states = {mio::abm::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedNoSymptoms}; - auto testing_scheme1 = - mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, test_params, probability); + auto testing_scheme1 = mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, + test_params_pcr, probability); ASSERT_EQ(testing_scheme1.is_active(), false); testing_scheme1.update_activity_status(mio::abm::TimePoint(10)); @@ -85,8 +85,8 @@ TEST(TestTestingScheme, runScheme) std::vector test_infection_states2 = {mio::abm::InfectionState::Recovered}; auto testing_criteria2 = mio::abm::TestingCriteria({}, test_infection_states2); - auto testing_scheme2 = - mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, test_params, probability); + auto testing_scheme2 = mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, + test_params_pcr, probability); mio::abm::Location loc_home(mio::abm::LocationType::Home, 0, num_age_groups); mio::abm::Location loc_work(mio::abm::LocationType::Work, 0, num_age_groups); @@ -115,18 +115,18 @@ TEST(TestTestingScheme, initAndRunTestingStrategy) const auto start_date = mio::abm::TimePoint(0); const auto end_date = mio::abm::TimePoint(60 * 60 * 24 * 3); const auto probability = 0.8; - const auto test_params = mio::abm::TestData().get_default(0)[mio::abm::TestType::PCR]; + const auto test_params_pcr = mio::abm::TestParameters{0.9, 0.99}; std::vector test_infection_states = {mio::abm::InfectionState::InfectedSymptoms, mio::abm::InfectionState::InfectedNoSymptoms}; auto testing_criteria1 = mio::abm::TestingCriteria({}, test_infection_states); - auto testing_scheme1 = - mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, test_params, probability); + auto testing_scheme1 = mio::abm::TestingScheme(testing_criteria1, testing_min_time, start_date, end_date, + test_params_pcr, probability); testing_scheme1.update_activity_status(mio::abm::TimePoint(0)); std::vector test_infection_states2 = {mio::abm::InfectionState::Recovered}; auto testing_criteria2 = mio::abm::TestingCriteria({}, test_infection_states2); - auto testing_scheme2 = - mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, test_params, probability); + auto testing_scheme2 = mio::abm::TestingScheme(testing_criteria2, testing_min_time, start_date, end_date, + test_params_pcr, probability); mio::abm::Location loc_work(mio::abm::LocationType::Work, 0); auto person1 = make_test_person(loc_work, age_group_15_to_34, mio::abm::InfectionState::InfectedNoSymptoms); @@ -151,8 +151,9 @@ TEST(TestTestingScheme, initAndRunTestingStrategy) ASSERT_EQ(test_strategy.run_strategy(rng_person1, person1, loc_work, start_date), true); // Person doesn't test } -TEST(TestTestingCriteria, getDefaultTestParameters) +TEST(TestTestingCriteria, getParametersFromTestData) { + // Test whether the TestParameters from the default TestData is set correctly. auto world = mio::abm::World(num_age_groups); auto test_parameters = world.parameters.get()[mio::abm::TestType::Generic]; ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); @@ -164,8 +165,10 @@ TEST(TestTestingCriteria, getDefaultTestParameters) ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); ASSERT_NEAR(test_parameters.specificity, 0.99, 1e-7); + // Test whether the TestParameters of TestData can be modified. world.parameters.get()[mio::abm::TestType::PCR].sensitivity = 0.8; world.parameters.get()[mio::abm::TestType::PCR].specificity = 0.88; - ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); - ASSERT_NEAR(test_parameters.specificity, 0.99, 1e-7); + test_parameters = world.parameters.get()[mio::abm::TestType::PCR]; + ASSERT_NEAR(test_parameters.sensitivity, 0.8, 1e-7); + ASSERT_NEAR(test_parameters.specificity, 0.88, 1e-7); } diff --git a/cpp/tests/test_abm_world.cpp b/cpp/tests/test_abm_world.cpp index 83bce5256d..0fff071387 100644 --- a/cpp/tests/test_abm_world.cpp +++ b/cpp/tests/test_abm_world.cpp @@ -432,10 +432,10 @@ TEST(TestWorldTestingCriteria, testAddingAndUpdatingAndRunningTestingSchemes) const auto start_date = mio::abm::TimePoint(20); const auto end_date = mio::abm::TimePoint(60 * 60 * 24 * 3); const auto probability = 1.0; - const auto test_params = world.parameters.get()[mio::abm::TestType::PCR]; + const auto test_params_pcr = mio::abm::TestParameters{0.9, 0.99}; auto testing_scheme = - mio::abm::TestingScheme(testing_criteria, testing_frequency, start_date, end_date, test_params, probability); + mio::abm::TestingScheme(testing_criteria, testing_frequency, start_date, end_date, test_params_pcr, probability); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme); ASSERT_EQ(world.get_testing_strategy().run_strategy(rng_person, person, work, current_time), From fbeb1ee46076f915d5f9c4857f203eddc76c059d Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:47:14 +0200 Subject: [PATCH 082/488] Change Pycode test_abm to call world.parameters instead of abm.parameters --- pycode/memilio-simulation/memilio/simulation_test/test_abm.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py index 6d2ef5405d..1eae8d2954 100644 --- a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py +++ b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py @@ -53,12 +53,11 @@ def test_locations(self): home.infection_parameters.MaximumContacts = 10 self.assertEqual(home.infection_parameters.MaximumContacts, 10) - testing_inf_states = [] testing_crit = abm.TestingCriteria( testing_ages, testing_inf_states) testing_scheme = abm.TestingScheme(testing_crit, abm.days( - 1), t0, t0 + abm.days(1), abm.TestParameters(1.0, 1.0), 1.0) + 1), t0, t0 + abm.days(1), world.parameters.TestData[abm.TestType.PCR], 1.0) # initially false, will only active once simulation starts self.assertEqual(testing_scheme.active, False) From f42d4d2459f957d2083cf7d5755e128d4109f800 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:04:44 +0200 Subject: [PATCH 083/488] Refactor check_bs_data.py for improved analysis and visualization --- cpp/simulations/check_bs_data.py | 28 +++++++- cpp/simulations/paper_abm_bs_testing.cpp | 91 +++++++++++++----------- 2 files changed, 75 insertions(+), 44 deletions(-) diff --git a/cpp/simulations/check_bs_data.py b/cpp/simulations/check_bs_data.py index 56c34e33ae..e00897ad2d 100644 --- a/cpp/simulations/check_bs_data.py +++ b/cpp/simulations/check_bs_data.py @@ -15,7 +15,7 @@ ####### minimal sanity check on data ####### bd = pd.read_csv( - r'/Users/David/Documents/HZI/memilio/data/mobility/modified_braunschweig_result.csv', header=None, skiprows=1) + r'C:\Users\korf_sa\Documents\rep\data\mobility\modified_braunschweig_result.csv', header=None, skiprows=1) # setup dictionary for the leisure activities, and vehicle choice and column names # bd.rename( @@ -34,6 +34,32 @@ dict_vehicle = {1: 'bicyle', 2: 'car_driver', 3: 'car_codriver', 4: 'public transport', 5: 'walk'} +#check if there are same locations where people end their trips with different activity_after +bd_same_loc = bd[['loc_id_end', 'ActivityAfter']].drop_duplicates() +#count how many different activities are after the same location +bd_same_loc = bd_same_loc.groupby(['loc_id_end']).size().reset_index(name='counts') + +#check how many persons in which age group have the activity_after 2 +bd_age_activity = bd[['personID','age', 'ActivityAfter']].loc[bd['ActivityAfter']==1] +#drop pid duplicates +bd_age_activity = bd_age_activity.drop_duplicates() +bd_age_activity = bd_age_activity.groupby(['age']).size().reset_index(name='counts') +bd_age_activity.plot(kind='bar', x='age', y='counts') +plt.xlabel('Age') +plt.ylabel('Number of persons') +plt.title('Number of persons going to work in Braunschweig') +plt.show() +#also put the age into bins +bd_age_activity['ageCohort'] = pd.cut(bd_age_activity['age'], bins=[-1, 2, 5, 14, 17, 24, 29, 39, 49, 64, 74, 105], labels=[ + '0-2', '3-5', '6-14', '15-17', '18-24', '25-29', '30-39', '40-49', '50-64', '65-74', '75+']) +bd_age_activity_cohorts = bd_age_activity.groupby( + ['ageCohort']).size().reset_index(name='counts') +bd_age_activity_cohorts.index = bd_age_activity_cohorts['ageCohort'].to_list() +bd_age_activity_cohorts.plot.bar(figsize=( + 10, 7), title='Age distribution of people going to school', xlabel='Age cohorts', ylabel='Number of persons', legend=None) +plt.show() + +x=1 # # check if people do the same trip more than once # trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] # duplicate_trips = trips.duplicated() diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5a575d81fd..f70ee4e1e0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -37,7 +37,7 @@ namespace fs = boost::filesystem; // Assign the name to general age group. -size_t num_age_groups = 6; +size_t num_age_groupss = 6; const auto age_group_0_to_4 = mio::AgeGroup(0); const auto age_group_5_to_14 = mio::AgeGroup(1); const auto age_group_15_to_34 = mio::AgeGroup(2); @@ -58,7 +58,7 @@ const std::map infection_ {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; mio::CustomIndexArray initial_infection_distribution{ - {mio::AgeGroup(num_age_groups), mio::osecir::InfectionState::Count}, 1.}; + {mio::AgeGroup(num_age_groupss), mio::osecir::InfectionState::Count}, 0.005}; /** * Create extrapolation of real world data to compare with. @@ -81,7 +81,7 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); //std::cout << initial_infection_distribution.array() << std::endl; - extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 60); // 60 days + // extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 60); // 60 days } /** @@ -95,6 +95,7 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); + // std::cout << "INfection dist" << initial_infection_distribution.slice(person.get_age()).as_array().array() << std::endl; //bool detected = false; if (infection_state != mio::osecir::InfectionState::Susceptible) { @@ -201,9 +202,12 @@ mio::AgeGroup determine_age_group(uint32_t age) else if (age <= 79) { return age_group_60_to_79; } - else { + else if (age > 79){ return age_group_80_plus; } + else { + return age_group_0_to_4; + } } void create_world_from_data(mio::abm::World& world, const std::string& filename, const mio::abm::TimePoint t0, @@ -367,7 +371,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t age = row[index["age"]]; uint32_t home_id = row[index["huid"]]; int target_location_id = row[index["loc_id_end"]]; - int start_location_id = row[index["loc_id_start"]]; + // int start_location_id = row[index["loc_id_start"]]; uint32_t trip_start = row[index["start_time"]]; uint32_t transport_mode = row[index["travel_mode"]]; @@ -376,7 +380,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; - auto start_location = locations.find(start_location_id)->second; + auto it_person = persons.find(person_id); @@ -401,11 +405,12 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, it_person->second.set_assigned_location( target_location); //This assumes that we only have in each tripchain only one location type for each person - if (locations.find(start_location_id) == locations.end()) { - // For trips where the start location is not known use Home instead - start_location = {it_person->second.get_assigned_location_index(mio::abm::LocationType::Home), + // if (locations.find(start_location_id) == locations.end()) { + // // For trips where the start location is not known use Home instead + + // } + mio::abm::LocationId start_location = {it_person->second.get_assigned_location_index(mio::abm::LocationType::Home), mio::abm::LocationType::Home}; - } world.get_trip_list().add_trip(mio::abm::Trip( it_person->second.get_person_id(), mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location, start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); @@ -545,7 +550,7 @@ void set_parameters(mio::abm::Parameters& params) // set location specific parameters void set_local_parameters(mio::abm::World& world) { - const int n_age_groups = world.parameters.get_num_groups(); + const int n_age_groups = (int)world.parameters.get_num_groups(); // setting this up in matrix-form would be much nicer, // but we somehow can't construct Eigen object with initializer lists @@ -1051,12 +1056,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(60); // End time per simulation - auto max_num_persons = 12550; + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation + auto max_num_persons = 235000; - // auto ensemble_infection_per_loc_type = - // std::vector>>{}; // Vector of infection per location type results - // ensemble_infection_per_loc_type.reserve(size_t(num_runs)); + auto ensemble_infection_per_loc_type = + std::vector>>{}; // Vector of infection per location type results + ensemble_infection_per_loc_type.reserve(size_t(num_runs)); auto ensemble_infection_per_age_group = std::vector>>{}; // Vector of infection per age group results ensemble_infection_per_age_group.reserve(size_t(num_runs)); @@ -1069,42 +1074,42 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // auto run_idx = size_t(1); // The run index // auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - int tid = -1; -#pragma omp parallel private(tid) // Start of parallel region: forks threads - { - tid = omp_get_thread_num(); // default is number of CPUs on machine - printf("Hello World from thread = %d and rank = %d\n", tid, rank); - if (tid == 0) { - printf("Number of threads = %d\n", omp_get_num_threads()); - } - } // ** end of the the parallel: joins threads +// int tid = -1; +// #pragma omp parallel private(tid) // Start of parallel region: forks threads +// { +// tid = omp_get_thread_num(); // default is number of CPUs on machine +// printf("Hello World from thread = %d and rank = %d\n", tid, rank); +// if (tid == 0) { +// printf("Number of threads = %d\n", omp_get_num_threads()); +// } +// } // ** end of the the parallel: joins threads // Determine inital infection state distribution //Time this - auto start0 = std::chrono::high_resolution_clock::now(); + // auto start0 = std::chrono::high_resolution_clock::now(); determine_initial_infection_states_world(input_dir, start_date); - auto stop0 = std::chrono::high_resolution_clock::now(); - auto duration0 = std::chrono::duration(stop0 - start0); - std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" - << std::endl; + // auto stop0 = std::chrono::high_resolution_clock::now(); + // auto duration0 = std::chrono::duration(stop0 - start0); + // std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" + // << std::endl; // Create one world for all simulations that will be copied - // auto world = mio::abm::World(num_age_groups); + // auto world = mio::abm::World(num_age_groupss); // create_sampled_world(world, input_dir, t0, max_num_persons); // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { // Start the clock before create_sampled_world - auto start1 = std::chrono::high_resolution_clock::now(); + // auto start1 = std::chrono::high_resolution_clock::now(); // Create the sampled simulation with start time t0. - auto world = mio::abm::World(num_age_groups); + auto world = mio::abm::World(num_age_groupss); create_sampled_world(world, input_dir, t0, max_num_persons); - world.parameters.get() = pow(10, ((int)run_idx) * 0 + 1.5); + world.parameters.get() = 7; // Stop the clock after create_sampled_world and calculate the duration - auto stop1 = std::chrono::high_resolution_clock::now(); - auto duration1 = std::chrono::duration(stop1 - start1); - std::cout << "Time taken by create_sampled_world: " << duration1.count() << " seconds" << std::endl; + // auto stop1 = std::chrono::high_resolution_clock::now(); + // auto duration1 = std::chrono::duration(stop1 - start1); + // std::cout << "Time taken by create_sampled_world: " << duration1.count() << " seconds" << std::endl; // auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED! auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -1135,9 +1140,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); // Stop the clock after sim.advance and calculate the duration - auto stop2 = std::chrono::high_resolution_clock::now(); - auto duration2 = std::chrono::duration(stop2 - start2); - std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; + // auto stop2 = std::chrono::high_resolution_clock::now(); + // auto duration2 = std::chrono::duration(stop2 - start2); + // std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; // TODO: update result of the simulation to be a vector of location result. // auto temp_sim_infection_per_loc_tpye = @@ -1221,8 +1226,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/Users/David/Documents/HZI/memilio/data"; - std::string result_dir = input_dir + "/results"; + std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; + std::string result_dir = input_dir + "\\results"; size_t num_runs; bool save_single_runs = true; @@ -1247,7 +1252,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 20; + num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); } From e40251af1b3c654bc01608d78dc3189c81dd37d2 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:14:30 +0200 Subject: [PATCH 084/488] Small modifications according to Rene's comments --- cpp/models/abm/parameters.h | 3 +++ cpp/models/abm/test_type.h | 4 ++-- cpp/tests/test_abm_testing_strategy.cpp | 22 ------------------- .../memilio/simulation/abm.cpp | 1 + .../memilio/simulation_test/test_abm.py | 2 +- 5 files changed, 7 insertions(+), 25 deletions(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index dcccb84320..edb6b31a8f 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -317,6 +317,9 @@ struct TestParameters { UncertainValue specificity; }; +/** + * @brief Store a map from the TestTypes to their TestParameters. + */ struct TestData { using Type = CustomIndexArray; static auto get_default(AgeGroup /*size*/) diff --git a/cpp/models/abm/test_type.h b/cpp/models/abm/test_type.h index 0d1b8756a9..253e31e4b5 100644 --- a/cpp/models/abm/test_type.h +++ b/cpp/models/abm/test_type.h @@ -18,8 +18,8 @@ * limitations under the License. */ -#ifndef EPI_ABM_TEST_TYPE_H -#define EPI_ABM_TEST_TYPE_H +#ifndef MIO_ABM_TEST_TYPE_H +#define MIO_ABM_TEST_TYPE_H #include diff --git a/cpp/tests/test_abm_testing_strategy.cpp b/cpp/tests/test_abm_testing_strategy.cpp index 325bb2a713..1f72a98a7b 100644 --- a/cpp/tests/test_abm_testing_strategy.cpp +++ b/cpp/tests/test_abm_testing_strategy.cpp @@ -150,25 +150,3 @@ TEST(TestTestingScheme, initAndRunTestingStrategy) true); // Person tests and tests negative ASSERT_EQ(test_strategy.run_strategy(rng_person1, person1, loc_work, start_date), true); // Person doesn't test } - -TEST(TestTestingCriteria, getParametersFromTestData) -{ - // Test whether the TestParameters from the default TestData is set correctly. - auto world = mio::abm::World(num_age_groups); - auto test_parameters = world.parameters.get()[mio::abm::TestType::Generic]; - ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); - ASSERT_NEAR(test_parameters.specificity, 0.99, 1e-7); - test_parameters = world.parameters.get()[mio::abm::TestType::Antigen]; - ASSERT_NEAR(test_parameters.sensitivity, 0.8, 1e-7); - ASSERT_NEAR(test_parameters.specificity, 0.88, 1e-7); - test_parameters = world.parameters.get()[mio::abm::TestType::PCR]; - ASSERT_NEAR(test_parameters.sensitivity, 0.9, 1e-7); - ASSERT_NEAR(test_parameters.specificity, 0.99, 1e-7); - - // Test whether the TestParameters of TestData can be modified. - world.parameters.get()[mio::abm::TestType::PCR].sensitivity = 0.8; - world.parameters.get()[mio::abm::TestType::PCR].specificity = 0.88; - test_parameters = world.parameters.get()[mio::abm::TestType::PCR]; - ASSERT_NEAR(test_parameters.sensitivity, 0.8, 1e-7); - ASSERT_NEAR(test_parameters.specificity, 0.88, 1e-7); -} diff --git a/pycode/memilio-simulation/memilio/simulation/abm.cpp b/pycode/memilio-simulation/memilio/simulation/abm.cpp index 677a197ce9..45b10fd372 100644 --- a/pycode/memilio-simulation/memilio/simulation/abm.cpp +++ b/pycode/memilio-simulation/memilio/simulation/abm.cpp @@ -68,6 +68,7 @@ PYBIND11_MODULE(_simulation_abm, m) .def_readwrite("specificity", &mio::abm::TestParameters::specificity); pymio::bind_CustomIndexArray(m, "_AgeParameterArray"); + pymio::bind_CustomIndexArray(m, "_TestData"); pymio::bind_Index(m, "ExposureTypeIndex"); pymio::bind_ParameterSet(m, "ParametersBase"); py::class_(m, "Parameters") diff --git a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py index 1eae8d2954..bd56dc9adb 100644 --- a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py +++ b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py @@ -57,7 +57,7 @@ def test_locations(self): testing_crit = abm.TestingCriteria( testing_ages, testing_inf_states) testing_scheme = abm.TestingScheme(testing_crit, abm.days( - 1), t0, t0 + abm.days(1), world.parameters.TestData[abm.TestType.PCR], 1.0) + 1), t0, t0 + abm.days(1), world.parameters.TestData[abm.TestType.Antigen], 1.0) # initially false, will only active once simulation starts self.assertEqual(testing_scheme.active, False) From 10fbe994bc5427b959f631cd757cb0fe5760f312 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 25 Apr 2024 13:25:23 +0200 Subject: [PATCH 085/488] Refactor simulation.h to comment out unused code blocks and remove debug output --- cpp/models/abm/simulation.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index 6349cb2a61..c2a896a964 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -70,13 +70,13 @@ class Simulation double sum = 0; while (m_t < tmax) { evolve_world(tmax); - double start, end; - start = omp_get_wtime(); + // double start, end; + // start = omp_get_wtime(); (history.log(*this), ...); - end = omp_get_wtime(); - sum = sum + (end - start); + // end = omp_get_wtime(); + // sum = sum + (end - start); } - std::cout << "Time spent on logging: " << sum << std::endl; + // std::cout << "Time spent on logging: " << sum << std::endl; } /** From 09de0aa3edb1da3f42091c6cd9931d0fdf409461 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 25 Apr 2024 14:46:06 +0200 Subject: [PATCH 086/488] Change from using world.parameters to use abm.TestParameters in test_abm.py --- pycode/memilio-simulation/memilio/simulation/abm.cpp | 1 - pycode/memilio-simulation/memilio/simulation_test/test_abm.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/abm.cpp b/pycode/memilio-simulation/memilio/simulation/abm.cpp index 45b10fd372..677a197ce9 100644 --- a/pycode/memilio-simulation/memilio/simulation/abm.cpp +++ b/pycode/memilio-simulation/memilio/simulation/abm.cpp @@ -68,7 +68,6 @@ PYBIND11_MODULE(_simulation_abm, m) .def_readwrite("specificity", &mio::abm::TestParameters::specificity); pymio::bind_CustomIndexArray(m, "_AgeParameterArray"); - pymio::bind_CustomIndexArray(m, "_TestData"); pymio::bind_Index(m, "ExposureTypeIndex"); pymio::bind_ParameterSet(m, "ParametersBase"); py::class_(m, "Parameters") diff --git a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py index bd56dc9adb..fdead3cd2d 100644 --- a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py +++ b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py @@ -57,7 +57,7 @@ def test_locations(self): testing_crit = abm.TestingCriteria( testing_ages, testing_inf_states) testing_scheme = abm.TestingScheme(testing_crit, abm.days( - 1), t0, t0 + abm.days(1), world.parameters.TestData[abm.TestType.Antigen], 1.0) + 1), t0, t0 + abm.days(1), abm.TestParameters(0.9,0.99), 1.0) # initially false, will only active once simulation starts self.assertEqual(testing_scheme.active, False) From a8dd034f04a933bc2550f19aa08db386c716ee8e Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 25 Apr 2024 14:48:56 +0200 Subject: [PATCH 087/488] Change from using world.parameters to use abm.TestParameters in test_abm.py --- pycode/memilio-simulation/memilio/simulation_test/test_abm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py index fdead3cd2d..b22201a4fd 100644 --- a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py +++ b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py @@ -57,7 +57,7 @@ def test_locations(self): testing_crit = abm.TestingCriteria( testing_ages, testing_inf_states) testing_scheme = abm.TestingScheme(testing_crit, abm.days( - 1), t0, t0 + abm.days(1), abm.TestParameters(0.9,0.99), 1.0) + 1), t0, t0 + abm.days(1), abm.TestParameters(0.9, 0.99), 1.0) # initially false, will only active once simulation starts self.assertEqual(testing_scheme.active, False) From ef6342780596b749112e2a35de80e5c79c60a31b Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:38:47 +0200 Subject: [PATCH 088/488] Some change to blind TestParameters to world.parameters --- cpp/models/abm/parameters.h | 12 ++++++++++++ pycode/memilio-simulation/memilio/simulation/abm.cpp | 1 + .../memilio/simulation/utils/custom_index_array.h | 4 ++-- .../memilio/simulation_test/test_abm.py | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index edb6b31a8f..d4c515415d 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -315,6 +315,18 @@ struct HighViralLoadProtectionFactor { struct TestParameters { UncertainValue sensitivity; UncertainValue specificity; + + TestParameters() = default; + + TestParameters(UncertainValue input_sensitivity, UncertainValue input_specificity) { + sensitivity = input_sensitivity; + specificity = input_specificity; + } + + TestParameters(UncertainValue value) { + sensitivity = value; + sensitivity = value; + } }; /** diff --git a/pycode/memilio-simulation/memilio/simulation/abm.cpp b/pycode/memilio-simulation/memilio/simulation/abm.cpp index 677a197ce9..45b10fd372 100644 --- a/pycode/memilio-simulation/memilio/simulation/abm.cpp +++ b/pycode/memilio-simulation/memilio/simulation/abm.cpp @@ -68,6 +68,7 @@ PYBIND11_MODULE(_simulation_abm, m) .def_readwrite("specificity", &mio::abm::TestParameters::specificity); pymio::bind_CustomIndexArray(m, "_AgeParameterArray"); + pymio::bind_CustomIndexArray(m, "_TestData"); pymio::bind_Index(m, "ExposureTypeIndex"); pymio::bind_ParameterSet(m, "ParametersBase"); py::class_(m, "Parameters") diff --git a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h index 08fc2dda5a..f109696be8 100755 --- a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h +++ b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h @@ -201,11 +201,11 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) }, pybind11::return_value_policy::reference_internal) .def("__setitem__", - [](C& self, Index const& idx, double value) { + [](C& self, Index const& idx, C::value_type value) { self[idx] = value; }) .def("__setitem__", - [](C& self, std::tuple...> idx, double value) { + [](C& self, std::tuple...> idx, C::value_type value) { self[{std::get>(idx)...}] = value; }) .def( diff --git a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py index b22201a4fd..bd56dc9adb 100644 --- a/pycode/memilio-simulation/memilio/simulation_test/test_abm.py +++ b/pycode/memilio-simulation/memilio/simulation_test/test_abm.py @@ -57,7 +57,7 @@ def test_locations(self): testing_crit = abm.TestingCriteria( testing_ages, testing_inf_states) testing_scheme = abm.TestingScheme(testing_crit, abm.days( - 1), t0, t0 + abm.days(1), abm.TestParameters(0.9, 0.99), 1.0) + 1), t0, t0 + abm.days(1), world.parameters.TestData[abm.TestType.Antigen], 1.0) # initially false, will only active once simulation starts self.assertEqual(testing_scheme.active, False) From a0d7e58d28427fea158cc1966b6a232c14a8a98d Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 26 Apr 2024 11:34:11 +0200 Subject: [PATCH 089/488] Add way to apply the exact number of infections to agents, improve plots --- cpp/models/abm/world.cpp | 5 +++ cpp/models/abm/world.h | 7 ++++ cpp/simulations/analyze_bs_run.py | 10 +++-- cpp/simulations/paper_abm_bs_testing.cpp | 49 +++++++++++++++++++++++- 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 008a8c0c75..a40ac07427 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -178,6 +178,11 @@ Location& World::get_individualized_location(LocationId id) return *m_locations[id.index]; } +Person& World::get_person(uint32_t id) const +{ + return *m_persons[id]; +} + const Location& World::find_location(LocationType type, const Person& person) const { auto index = person.get_assigned_location_index(type); diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index 2adf59f329..70a7858964 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -197,6 +197,13 @@ class World Location& get_individualized_location(LocationId id); + /** + * @brief Get a Person. + * @param[in] id PersonId of the Person. + * @return Reference to the Person. + */ + Person& get_person(uint32_t id) const; + /** * @brief Find an assigned Location of a Person. * @param[in] type The #LocationType that specifies the assigned Location. diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 18c457b539..c1733640d1 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -121,7 +121,6 @@ def plot_infection_states(x, y50, y25, y75): plt.figure('Infection_states') plt.title('Infection states') color_plot = cmx.get_cmap('Set1').colors - print(color_plot) for i in range(y50.shape[1]): plt.plot(x, y50[:, i], color=color_plot[i]) @@ -155,8 +154,9 @@ def plot_infection_states_individual(x, y50, y25, y75, y_real): color = 'tab:blue' # we already handled the x-label with ax1 ax2.set_ylabel('y_real', color=color) - ax2.plot(x_real, y_real[:, [6]], '*', color=color) + ax2.plot(x_real, y_real[:, [6]], color=color) ax2.tick_params(axis='y', labelcolor=color) + plt.title('Severe') fig.tight_layout() # otherwise the right y-label is slightly clipped # Critical @@ -170,8 +170,9 @@ def plot_infection_states_individual(x, y50, y25, y75, y_real): color = 'tab:blue' # we already handled the x-label with ax1 ax2.set_ylabel('y_real', color=color) - ax2.plot(x_real, y_real[:, [7]], '*', color=color) + ax2.plot(x_real, y_real[:, [7]], color=color) ax2.tick_params(axis='y', labelcolor=color) + plt.title('Critical') fig.tight_layout() # otherwise the right y-label is slightly clipped # Dead @@ -184,8 +185,9 @@ def plot_infection_states_individual(x, y50, y25, y75, y_real): ax2 = ax[2].twinx() color = 'tab:blue' ax2.set_ylabel('y_real', color=color) # we already handled the x-label with ax1 - ax2.plot(x_real, y_real[:, [9]], '*', color=color) + ax2.plot(x_real, y_real[:, [9]], color=color) ax2.tick_params(axis='y', labelcolor=color) + plt.title('Dead') fig.tight_layout() # otherwise the right y-label is slightly clipped plt.show() diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f70ee4e1e0..02087d754e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -81,13 +81,14 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); //std::cout << initial_infection_distribution.array() << std::endl; - // extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 60); // 60 days + //extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days } /** * Assign an infection state to each person according to real world data read in through the ODE secir model. + * Infections are set with probabilities computed by the values in the rows in initial_infection_distribution. */ -void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) +void assign_infection_state_prob(mio::abm::World& world, mio::abm::TimePoint t) { // convert initial population to ABM initial infections for (auto& person : world.get_persons()) { @@ -109,6 +110,50 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) } } +/** + * Assign an infection state to each person according to real world data read in through the ODE secir model. + * Infections are set with the rounded values in the rows in initial_infection_distribution. + * Only works if enough persons in the all age groups exist. + * The number of agents in the model should fit to the sum of the rows in initial_infection_distribution, + * otherwise many agents will be susceptible. + */ +void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) +{ + // save all persons with age groups + std::vector> persons_by_age(num_age_groupss); + + for (auto& person : world.get_persons()) { + persons_by_age[person.get_age().get()].push_back(person.get_person_id()); + } + + for (size_t age = 0; age < num_age_groupss; ++age) { + auto age_slice = initial_infection_distribution.slice(mio::AgeGroup(age)).as_array().array(); + auto age_grp = mio::AgeGroup(age).get(); + // Check that the world has enough persons in each age group to initialize infections. + // (All persons minus the susceptibles.) + // For lower population sizes use the same method with _prob at the end. + assert(age_slice.sum() - age_slice[0] <= persons_by_age[age_grp].size() && + "Not enough persons to initialize with given amount of infections."); + + // Iterate over all InfectionStates except the susceptibles. + for (auto i = 1; i < age_slice.size(); ++i) { + for (auto j = 0; j < std::floor(age_slice[i]); ++j) { + // select random person and assign Infection + uint32_t id_rnd = persons_by_age[age_grp][mio::UniformIntDistribution::get_instance()( + world.get_rng(), 0U, persons_by_age[age_grp].size() - 1)]; + mio::abm::Person& person = world.get_person(id_rnd); + auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); + person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), + world.parameters, t, + infection_state_map.at(mio::osecir::InfectionState(i)))); + persons_by_age[age_grp].erase( + std::remove(persons_by_age[age_grp].begin(), persons_by_age[age_grp].end(), id_rnd), + persons_by_age[age_grp].end()); + } + } + } +} + int stringToMinutes(const std::string& input) { size_t colonPos = input.find(":"); From 45e3cf60e9af24ea7203f4f3245e506207b367a3 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 26 Apr 2024 16:57:36 +0200 Subject: [PATCH 090/488] Fix output bugs --- cpp/models/abm/person.cpp | 2 +- cpp/models/abm/simulation.h | 10 +++++----- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index abd315b27b..9b77ee2f63 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -21,7 +21,7 @@ #include "abm/location_type.h" #include "abm/mask_type.h" #include "abm/parameters.h" -#include "abm/world.h" +#include "abm/infection.h" #include "abm/location.h" #include "memilio/utils/random_number_generator.h" #include "abm/time.h" diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index c2a896a964..6349cb2a61 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -70,13 +70,13 @@ class Simulation double sum = 0; while (m_t < tmax) { evolve_world(tmax); - // double start, end; - // start = omp_get_wtime(); + double start, end; + start = omp_get_wtime(); (history.log(*this), ...); - // end = omp_get_wtime(); - // sum = sum + (end - start); + end = omp_get_wtime(); + sum = sum + (end - start); } - // std::cout << "Time spent on logging: " << sum << std::endl; + std::cout << "Time spent on logging: " << sum << std::endl; } /** diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 02087d754e..c23cbc93c2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1178,7 +1178,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // } // Start the clock before sim.advance - auto start2 = std::chrono::high_resolution_clock::now(); + // auto start2 = std::chrono::high_resolution_clock::now(); // Advance the world to tmax // sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, // historyPersonInfDelta, historyInfectionStatePerAgeGroup); From bb9eafd6593928d771188c357c652330b027c7f1 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:14:42 +0200 Subject: [PATCH 091/488] small plot improvements Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index c1733640d1..b7bf7a7cbe 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -122,12 +122,15 @@ def plot_infection_states(x, y50, y25, y75): plt.title('Infection states') color_plot = cmx.get_cmap('Set1').colors - for i in range(y50.shape[1]): + states_plot = [1, 2, 3, 4, 5, 7] + legend_plot = ['E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Dead'] + + for i in states_plot: plt.plot(x, y50[:, i], color=color_plot[i]) - plt.legend(['S', 'E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Rec', 'Dead']) + plt.legend(legend_plot) - for i in range(y50.shape[1]): + for i in states_plot: plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.5, color=color_plot[i]) plt.fill_between(x, y50[:, i], y75[:, i], From 2bf21c7d2c27b92e711867f4f9bf5130bb84ef4f Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:31:05 +0200 Subject: [PATCH 092/488] Try to fix pybinds of custom_index_array for non-double types. Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- .../simulation/utils/custom_index_array.h | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h index f109696be8..afaacd66d2 100755 --- a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h +++ b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h @@ -191,7 +191,10 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) })) .def("numel", &C::numel) .def( - "__getitem__", [](const C& self, Index const& idx) -> auto& { return self[idx]; }, + "__getitem__", + [](const C& self, Index const& idx) -> auto& { + return self[idx]; + }, pybind11::return_value_policy::reference_internal) .def( "__getitem__", @@ -201,11 +204,11 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) }, pybind11::return_value_policy::reference_internal) .def("__setitem__", - [](C& self, Index const& idx, C::value_type value) { + [](C& self, Index const& idx, typename C::value_type value) { self[idx] = value; }) .def("__setitem__", - [](C& self, std::tuple...> idx, C::value_type value) { + [](C& self, std::tuple...> idx, typename C::value_type value) { self[{std::get>(idx)...}] = value; }) .def( @@ -216,10 +219,12 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) pybind11::keep_alive<0, 1>()) .def("get_flat_index", &C::get_flat_index) //scalar assignment - .def("__setitem__", &assign_scalar) - //scalar assignment with conversion from double - //TODO: may need SFINAE in the future, only compiles if value type is convertible from double, e.g. UncertainValue - .def("__setitem__", &assign_scalar); + .def("__setitem__", &assign_scalar); + + //scalar assignment with conversion from double + if (std::is_convertible::value) { + c.def("__setitem__", &assign_scalar); + } //TODO: __setitem__ with list or numpy array, e.g. array[AgeGroup(0):AgeGroup(3)] = [1, 2, 3] //TODO: __getitem__. Is it ever necessary to store a reference to a slice? From e21de5bc23c95f0de76e9769827ec752e0fde4bf Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:31:05 +0200 Subject: [PATCH 093/488] Add a test for draw_infection_course_forward() to pass the coverage test --- cpp/tests/test_abm_infection.cpp | 16 +++++++++++++--- .../simulation/utils/custom_index_array.h | 19 ++++++++++++------- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index bb6df0c064..b5a9d7cb28 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -103,10 +103,20 @@ TEST(TestInfection, getInfectionState) auto rng = mio::abm::Person::RandomNumberGenerator(mio::Key{0}, 0, counter); auto params = mio::abm::Parameters(num_age_groups); auto t = mio::abm::TimePoint(0); - auto infection = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, + auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, mio::abm::InfectionState::Exposed, {}, true); - EXPECT_EQ(infection.get_infection_state(t), mio::abm::InfectionState::Exposed); - EXPECT_EQ(infection.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible); + EXPECT_EQ(infection1.get_infection_state(t), mio::abm::InfectionState::Exposed); + EXPECT_EQ(infection1.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible); + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 1; + ScopedMockDistribution>>> mock_uniform_dist; + EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Return(0.8)); // Recovered + auto infection2 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, + mio::abm::InfectionState::InfectedCritical, {}, true); + EXPECT_EQ(infection2.get_infection_state(t), mio::abm::InfectionState::InfectedCritical); + EXPECT_EQ(infection2.get_infection_state(t + mio::abm::days(1)), mio::abm::InfectionState::Recovered); } TEST(TestInfection, drawInfectionCourseBackward) diff --git a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h index f109696be8..afaacd66d2 100755 --- a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h +++ b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h @@ -191,7 +191,10 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) })) .def("numel", &C::numel) .def( - "__getitem__", [](const C& self, Index const& idx) -> auto& { return self[idx]; }, + "__getitem__", + [](const C& self, Index const& idx) -> auto& { + return self[idx]; + }, pybind11::return_value_policy::reference_internal) .def( "__getitem__", @@ -201,11 +204,11 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) }, pybind11::return_value_policy::reference_internal) .def("__setitem__", - [](C& self, Index const& idx, C::value_type value) { + [](C& self, Index const& idx, typename C::value_type value) { self[idx] = value; }) .def("__setitem__", - [](C& self, std::tuple...> idx, C::value_type value) { + [](C& self, std::tuple...> idx, typename C::value_type value) { self[{std::get>(idx)...}] = value; }) .def( @@ -216,10 +219,12 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) pybind11::keep_alive<0, 1>()) .def("get_flat_index", &C::get_flat_index) //scalar assignment - .def("__setitem__", &assign_scalar) - //scalar assignment with conversion from double - //TODO: may need SFINAE in the future, only compiles if value type is convertible from double, e.g. UncertainValue - .def("__setitem__", &assign_scalar); + .def("__setitem__", &assign_scalar); + + //scalar assignment with conversion from double + if (std::is_convertible::value) { + c.def("__setitem__", &assign_scalar); + } //TODO: __setitem__ with list or numpy array, e.g. array[AgeGroup(0):AgeGroup(3)] = [1, 2, 3] //TODO: __getitem__. Is it ever necessary to store a reference to a slice? From 684e55b37f72fa500d69401c2db1d7213cbd7958 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:05:43 +0200 Subject: [PATCH 094/488] Try fix #2 Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- .../memilio/simulation/utils/custom_index_array.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h index afaacd66d2..ea51c950cf 100755 --- a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h +++ b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h @@ -204,11 +204,11 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) }, pybind11::return_value_policy::reference_internal) .def("__setitem__", - [](C& self, Index const& idx, typename C::value_type value) { + [](C& self, Index const& idx, Type value) { self[idx] = value; }) .def("__setitem__", - [](C& self, std::tuple...> idx, typename C::value_type value) { + [](C& self, std::tuple...> idx, Type value) { self[{std::get>(idx)...}] = value; }) .def( @@ -219,10 +219,10 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) pybind11::keep_alive<0, 1>()) .def("get_flat_index", &C::get_flat_index) //scalar assignment - .def("__setitem__", &assign_scalar); + .def("__setitem__", &assign_scalar); //scalar assignment with conversion from double - if (std::is_convertible::value) { + if (std::is_convertible::value) { c.def("__setitem__", &assign_scalar); } //TODO: __setitem__ with list or numpy array, e.g. array[AgeGroup(0):AgeGroup(3)] = [1, 2, 3] From 115e89776497eb39cba2c1d359dd176231467a83 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:05:43 +0200 Subject: [PATCH 095/488] Try seconds fix for pybinds Signed-off-by: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> --- .../memilio/simulation/utils/custom_index_array.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h index afaacd66d2..ea51c950cf 100755 --- a/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h +++ b/pycode/memilio-simulation/memilio/simulation/utils/custom_index_array.h @@ -204,11 +204,11 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) }, pybind11::return_value_policy::reference_internal) .def("__setitem__", - [](C& self, Index const& idx, typename C::value_type value) { + [](C& self, Index const& idx, Type value) { self[idx] = value; }) .def("__setitem__", - [](C& self, std::tuple...> idx, typename C::value_type value) { + [](C& self, std::tuple...> idx, Type value) { self[{std::get>(idx)...}] = value; }) .def( @@ -219,10 +219,10 @@ void bind_CustomIndexArray(pybind11::module_& m, std::string const& name) pybind11::keep_alive<0, 1>()) .def("get_flat_index", &C::get_flat_index) //scalar assignment - .def("__setitem__", &assign_scalar); + .def("__setitem__", &assign_scalar); //scalar assignment with conversion from double - if (std::is_convertible::value) { + if (std::is_convertible::value) { c.def("__setitem__", &assign_scalar); } //TODO: __setitem__ with list or numpy array, e.g. array[AgeGroup(0):AgeGroup(3)] = [1, 2, 3] From 60db2ad2e61d3b44ace4358073a87b455c9ad943 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 29 Apr 2024 11:31:05 +0200 Subject: [PATCH 096/488] Add a test for draw_infection_course_forward() to pass the coverage test --- cpp/tests/test_abm_infection.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index bb6df0c064..b5a9d7cb28 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -103,10 +103,20 @@ TEST(TestInfection, getInfectionState) auto rng = mio::abm::Person::RandomNumberGenerator(mio::Key{0}, 0, counter); auto params = mio::abm::Parameters(num_age_groups); auto t = mio::abm::TimePoint(0); - auto infection = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, + auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, mio::abm::InfectionState::Exposed, {}, true); - EXPECT_EQ(infection.get_infection_state(t), mio::abm::InfectionState::Exposed); - EXPECT_EQ(infection.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible); + EXPECT_EQ(infection1.get_infection_state(t), mio::abm::InfectionState::Exposed); + EXPECT_EQ(infection1.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible); + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 1; + ScopedMockDistribution>>> mock_uniform_dist; + EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) + .Times(testing::AtLeast(1)) + .WillOnce(testing::Return(0.8)); // Recovered + auto infection2 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, + mio::abm::InfectionState::InfectedCritical, {}, true); + EXPECT_EQ(infection2.get_infection_state(t), mio::abm::InfectionState::InfectedCritical); + EXPECT_EQ(infection2.get_infection_state(t + mio::abm::days(1)), mio::abm::InfectionState::Recovered); } TEST(TestInfection, drawInfectionCourseBackward) From 7c5c0ea877cecae564314d817005cac6790d7072 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:00:09 +0200 Subject: [PATCH 097/488] Fix error in added test --- cpp/tests/test_abm_infection.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index b5a9d7cb28..53d47c1a9f 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -99,12 +99,12 @@ TEST(TestInfection, init) TEST(TestInfection, getInfectionState) { - auto counter = mio::Counter(0); - auto rng = mio::abm::Person::RandomNumberGenerator(mio::Key{0}, 0, counter); - auto params = mio::abm::Parameters(num_age_groups); - auto t = mio::abm::TimePoint(0); + auto counter = mio::Counter(0); + auto rng = mio::abm::Person::RandomNumberGenerator(mio::Key{0}, 0, counter); + auto params = mio::abm::Parameters(num_age_groups); + auto t = mio::abm::TimePoint(0); auto infection1 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, - mio::abm::InfectionState::Exposed, {}, true); + mio::abm::InfectionState::Exposed, {}, true); EXPECT_EQ(infection1.get_infection_state(t), mio::abm::InfectionState::Exposed); EXPECT_EQ(infection1.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible); @@ -112,9 +112,9 @@ TEST(TestInfection, getInfectionState) ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(1)) - .WillOnce(testing::Return(0.8)); // Recovered + .WillRepeatedly(testing::Return(0.8)); // Recovered auto infection2 = mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, age_group_15_to_34, params, t, - mio::abm::InfectionState::InfectedCritical, {}, true); + mio::abm::InfectionState::InfectedCritical, {}, true); EXPECT_EQ(infection2.get_infection_state(t), mio::abm::InfectionState::InfectedCritical); EXPECT_EQ(infection2.get_infection_state(t + mio::abm::days(1)), mio::abm::InfectionState::Recovered); } From 031c2d0f3ca69ee8c5ae841c94327720ce2ec2ce Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 2 May 2024 09:50:40 +0200 Subject: [PATCH 098/488] Add analyze_npi.py script for analyzing NPI data in Germany counties --- cpp/simulations/analyze_npi.py | 51 ++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 cpp/simulations/analyze_npi.py diff --git a/cpp/simulations/analyze_npi.py b/cpp/simulations/analyze_npi.py new file mode 100644 index 0000000000..186eae94ee --- /dev/null +++ b/cpp/simulations/analyze_npi.py @@ -0,0 +1,51 @@ +import pandas as pd +import matplotlib +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import os + + +# from the first file 'datensatzbeschreibung_massnahmen' we want to extract the following information: +# on the site DSB BL we have the following information: +#first column is the short name of the measure +# third column is the explanation of the measure +#we want a map from the short name to the explanation + +# get the data from the first file +csv_file = pd.read_csv( + r'C:\Users\korf_sa\Documents\rep\cpp\simulations\datensatzbeschreibung_massnahmen.csv', header=None, skiprows=1) + + + + +csv_file = pd.read_csv( + r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_maincat.csv', header=None, skiprows=1) +# csv_file = pd.read_csv( +# r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_subcat.csv', header=None, skiprows=1) + +zip_code_brunswick = 3101 +start_date = '2021-03-01' +end_date = '2021-05-31' + +#mapping from column entry to column name: +dict_leisure = {1: 'ContactPriv', 2: 'Schools', 3: 'Kita', 4: 'IndoorEvents', + 5: 'OutdoorEvents', 6: 'Culture', 7: 'Retail', 8: 'Gastronomy'} + +#delete all files with different zip code +csv_file = csv_file[csv_file[2] == zip_code_brunswick] +# also delete all files with different date +csv_file = csv_file[(csv_file[1] >= start_date) & (csv_file[1] <= end_date)] +#delete all the columns that are zero +# csv_file = csv_file.loc[:, (csv_file != 0).any(axis=0)] +#delete all the columns that are not zero but keep header number 0 + +#plot a heatmap of the resulting 0/1 matrix within the dataframe + +sns.heatmap(csv_file.iloc[:, 3:], cmap='coolwarm', cbar=False) +plt.show() + +# we want + +x=1 \ No newline at end of file From 35a402f157ff970652108698ca42d396db51fe8b Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 2 May 2024 14:25:11 +0200 Subject: [PATCH 099/488] Change plot_infection_states_individual() to show single y-axis + change plot_infection_per_location_type() to show multiple subplots --- cpp/simulations/analyze_bs_run.py | 97 ++++++++++++++----------------- 1 file changed, 45 insertions(+), 52 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index b7bf7a7cbe..4f565007bb 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -54,7 +54,7 @@ def main(path, n_runs): plot_infection_per_location_type(df) if file.startswith("infection_per_age_group.txt"): df = pd.read_csv(file_path, delim_whitespace=True) - #plot_infection_per_age_group(df) + # plot_infection_per_age_group(df) # if file.startswith("run_"): # convert to numpy array # df_np = df.to_numpy() @@ -64,16 +64,29 @@ def main(path, n_runs): def plot_infection_per_location_type(df): - df.plot(x='Time', y=['Home', 'Work', 'School', 'SocialEvent', 'BasicsShop', 'Hospital', - 'ICU', 'Car', 'PublicTransport', 'TransportWithoutContact', 'Cemetery'], figsize=(10, 6)) + # df.plot.area(x='Time', y=['Home', 'Work', 'School', 'SocialEvent', 'BasicsShop'], stacked=True, figsize=(10, 6)) + + fig, axs = plt.subplots(5, 2, constrained_layout=True) + df.plot(x='Time', y='Home', color='tab:blue', ax=axs[0, 0]) + df.plot(x='Time', y='Work', color='tab:green', ax=axs[0, 1]) + df.plot(x='Time', y='School', color='tab:red', ax=axs[1, 0]) + df.plot(x='Time', y='SocialEvent', color='tab:orange', ax=axs[1, 1]) + df.plot(x='Time', y='BasicsShop', color='tab:purple', ax=axs[2, 0]) + df.plot(x='Time', y='Hospital', color='tab:brown', ax=axs[2, 1]) + df.plot(x='Time', y='ICU', color='tab:pink', ax=axs[3, 0]) + df.plot(x='Time', y='Car', color='tab:gray', ax=axs[3, 1]) + df.plot(x='Time', y='PublicTransport', color='tab:olive', ax=axs[4, 0]) + df.plot(x='Time', y='Cemetery', color='tab:cyan', ax=axs[4, 1]) plt.show() def plot_infection_per_age_group(df): df.plot(x='Time', y=['0_to_4', '5_to_14', '15_to_34', '35_to_59', '60_to_79', '80_plus'], figsize=(10, 6)) + plt.show() + def plot_results(path): # median / 50-percentile f = h5py.File( @@ -131,67 +144,47 @@ def plot_infection_states(x, y50, y25, y75): plt.legend(legend_plot) for i in states_plot: - plt.fill_between(x, y50[:, i], y25[:, i], - alpha=0.5, color=color_plot[i]) - plt.fill_between(x, y50[:, i], y75[:, i], - alpha=0.5, color=color_plot[i]) + plt.fill_between(x, y50[:, i], y25[:, i], + alpha=0.5, color=color_plot[i]) + plt.fill_between(x, y50[:, i], y75[:, i], + alpha=0.5, color=color_plot[i]) def plot_infection_states_individual(x, y50, y25, y75, y_real): # plt.figure('Infection_states_dead') # # plt.plot(x, y50[:,[5,7]]) - x_real = np.linspace(0, y_real.shape[0]-1,y_real.shape[0]) + x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) # plt.plot(x_real, y_real[:,[2]]) # plt.legend(['I_Crit', 'Dead']) fig, ax = plt.subplots(3, 1) # Severe - color = 'tab:red' ax[0].set_xlabel('time (s)') - ax[0].set_ylabel('y50', color=color) - ax[0].plot(x, y50[:, [4]], color=color) - ax[0].tick_params(axis='y', labelcolor=color) - # instantiate a second axes that shares the same x-axis - ax2 = ax[0].twinx() - color = 'tab:blue' - # we already handled the x-label with ax1 - ax2.set_ylabel('y_real', color=color) - ax2.plot(x_real, y_real[:, [6]], color=color) - ax2.tick_params(axis='y', labelcolor=color) - plt.title('Severe') + ax[0].plot(x, y50[:, [4]], color='tab:red', label='y50') + ax[0].plot(x_real, y_real[:, [6]], color='tab:blue', label='y_real') + ax[0].tick_params(axis='y') + ax[0].title.set_text('Severe') + ax[0].legend() fig.tight_layout() # otherwise the right y-label is slightly clipped # Critical - color = 'tab:red' ax[1].set_xlabel('time (s)') - ax[1].set_ylabel('y50', color=color) - ax[1].plot(x, y50[:, [5]], color=color) - ax[1].tick_params(axis='y', labelcolor=color) - # instantiate a second axes that shares the same x-axis - ax2 = ax[1].twinx() - color = 'tab:blue' - # we already handled the x-label with ax1 - ax2.set_ylabel('y_real', color=color) - ax2.plot(x_real, y_real[:, [7]], color=color) - ax2.tick_params(axis='y', labelcolor=color) - plt.title('Critical') + ax[1].plot(x, y50[:, [5]], color='tab:red', label='y50') + ax[1].plot(x_real, y_real[:, [7]], color='tab:blue', label='y_real') + ax[1].tick_params(axis='y') + ax[1].title.set_text('Critical') + ax[1].legend() fig.tight_layout() # otherwise the right y-label is slightly clipped # Dead - color = 'tab:red' ax[2].set_xlabel('time (s)') - ax[2].set_ylabel('y50', color=color) - ax[2].plot(x, y50[:, [7]], color=color) - ax[2].tick_params(axis='y', labelcolor=color) - # instantiate a second axes that shares the same x-axis - ax2 = ax[2].twinx() - color = 'tab:blue' - ax2.set_ylabel('y_real', color=color) # we already handled the x-label with ax1 - ax2.plot(x_real, y_real[:, [9]], color=color) - ax2.tick_params(axis='y', labelcolor=color) - plt.title('Dead') + ax[2].plot(x, y50[:, [7]], color='tab:red', label='y50') + ax[2].plot(x_real, y_real[:, [9]], color='tab:blue', label='y_real') + ax[2].tick_params(axis='y') + ax[2].title.set_text('Dead') fig.tight_layout() # otherwise the right y-label is slightly clipped + ax[2].legend() plt.show() @@ -220,15 +213,15 @@ def plot_infections_per_age_group(path): def plot_mean_and_std(Y): x_plot = Y[:, 0, 0] - compartments = Y[:,1:,1:] + compartments = Y[:, 1:, 1:] # average value - compartments_avg = np.mean(compartments,axis=2) - #plot average + compartments_avg = np.mean(compartments, axis=2) + # plot average for i in range(compartments_avg.shape[1]): - plt.plot(x_plot,compartments_avg[:,i]) - - #plt.plot(x_plot,compartments_avg) - #legend + plt.plot(x_plot, compartments_avg[:, i]) + + # plt.plot(x_plot,compartments_avg) + # legend plt.legend(['S', 'E', 'I_NS', 'I_Sy', 'I_Sev', 'I_Crit', 'R', 'D']) plt.show() # standard deviation @@ -239,8 +232,8 @@ def plot_mean_and_std(Y): if __name__ == "__main__": - #path to results - path = "/Users/David/Documents/HZI/memilio/data/results" + # path to results + path = "./results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: From 427e2e4ef9bcb41102895b4601cb3d260182f9a4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 3 May 2024 09:38:22 +0200 Subject: [PATCH 100/488] Shorten matrix to zip code of Brunswick and time period of interest Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_npi.py | 97 +++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 25 deletions(-) diff --git a/cpp/simulations/analyze_npi.py b/cpp/simulations/analyze_npi.py index 186eae94ee..b524f1bb26 100644 --- a/cpp/simulations/analyze_npi.py +++ b/cpp/simulations/analyze_npi.py @@ -5,47 +5,94 @@ import seaborn as sns import numpy as np import os +import openpyxl +# # from the first file 'datensatzbeschreibung_massnahmen' we want to extract the following information: +# # on the site DSB BL we have the following information: +# #first column is the short name of the measure +# # third column is the explanation of the measure +# #we want a map from the short name to the explanation -# from the first file 'datensatzbeschreibung_massnahmen' we want to extract the following information: -# on the site DSB BL we have the following information: -#first column is the short name of the measure -# third column is the explanation of the measure -#we want a map from the short name to the explanation - -# get the data from the first file -csv_file = pd.read_csv( - r'C:\Users\korf_sa\Documents\rep\cpp\simulations\datensatzbeschreibung_massnahmen.csv', header=None, skiprows=1) +# # get the data from the first file +# csv_file = pd.read_csv( +# r'C:\Users\korf_sa\Documents\rep\cpp\simulations\datensatzbeschreibung_massnahmen.csv', header=None, skiprows=1) -csv_file = pd.read_csv( - r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_maincat.csv', header=None, skiprows=1) # csv_file = pd.read_csv( -# r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_subcat.csv', header=None, skiprows=1) +# r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_maincat.csv', header=None, skiprows=1) +# # csv_file = pd.read_csv( +# # r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_subcat.csv', header=None, skiprows=1) + + + +# #mapping from column entry to column name: +# dict_leisure = {1: 'ContactPriv', 2: 'Schools', 3: 'Kita', 4: 'IndoorEvents', +# 5: 'OutdoorEvents', 6: 'Culture', 7: 'Retail', 8: 'Gastronomy'} + +# #delete all files with different zip code +# csv_file = csv_file[csv_file[2] == zip_code_brunswick] +# # also delete all files with different date +# csv_file = csv_file[(csv_file[1] >= start_date) & (csv_file[1] <= end_date)] +# #delete all the columns that are zero +# # csv_file = csv_file.loc[:, (csv_file != 0).any(axis=0)] +# #delete all the columns that are not zero but keep header number 0 + +# #plot a heatmap of the resulting 0/1 matrix within the dataframe + +# sns.heatmap(csv_file.iloc[:, 3:], cmap='coolwarm', cbar=False) +# plt.show() + +# # we want + +# x=1 + + + +#import the first excel file with the measures and ther abbreviations +df_abb = pd.read_excel('/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/datensatzbeschreibung_massnahmen.xlsx', sheet_name='DSB BL') + +#read in the matrix which tells us which measure is active on which day +df_measure_matrix = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/germany_counties_npi_subcat.csv', header=None, skiprows=1) zip_code_brunswick = 3101 start_date = '2021-03-01' end_date = '2021-05-31' -#mapping from column entry to column name: -dict_leisure = {1: 'ContactPriv', 2: 'Schools', 3: 'Kita', 4: 'IndoorEvents', - 5: 'OutdoorEvents', 6: 'Culture', 7: 'Retail', 8: 'Gastronomy'} - +#now we want to shorten the matrix to the zip code of Brunswick and the time period of interest #delete all files with different zip code -csv_file = csv_file[csv_file[2] == zip_code_brunswick] +df_measure_matrix = df_measure_matrix[df_measure_matrix[2] == zip_code_brunswick] # also delete all files with different date -csv_file = csv_file[(csv_file[1] >= start_date) & (csv_file[1] <= end_date)] +df_measure_matrix = df_measure_matrix[(df_measure_matrix[1] >= start_date) & (df_measure_matrix[1] <= end_date)] + +# now we want to do the following: +# 1. for every measure we want to count how many days it was active +# 2. We want to sort the measures by the number of days they were active +# 3. We want to plot the measures in a bar plot with the number of days they were active +# 4. We want a txt file which has for each measure the full explanation and the days it was active + +# begin with 1. +# get the number of days a measure was active +measure_by_days = df_measure_matrix.iloc[:, 3:] +# count the number of days a measure was active +measure_by_days = measure_by_days.sum() +# sort the measures by the number of days they were active +measure_by_days = measure_by_days.sort_values(ascending=False) #delete all the columns that are zero -# csv_file = csv_file.loc[:, (csv_file != 0).any(axis=0)] -#delete all the columns that are not zero but keep header number 0 +measure_by_days = measure_by_days[measure_by_days != 0] -#plot a heatmap of the resulting 0/1 matrix within the dataframe +# now we need create a txt file with the measures and the number of days they were active and the full explanation +# create a txt file +f = open('measures_active_days.txt', 'w') +#get first row of df_abb -sns.heatmap(csv_file.iloc[:, 3:], cmap='coolwarm', cbar=False) -plt.show() -# we want +# for every measure +for measure in measure_by_days.axes[0]: + # get the full explanation + full_explanation = df_abb['Beschreibung'][measure-3] + # write the full explanation and the number of days the measure was active to the txt file + f.write(full_explanation + ' ' + str(measure_by_days[measure]) + '\n') -x=1 \ No newline at end of file +x=1 From c071018666ccefa9da505a70de06e663fe3a233a Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Fri, 3 May 2024 11:10:42 +0200 Subject: [PATCH 101/488] Add moving average plot to the function plot_infection_per_location_type() --- cpp/simulations/analyze_bs_run.py | 42 +++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 4f565007bb..7b29496069 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -64,19 +64,35 @@ def main(path, n_runs): def plot_infection_per_location_type(df): - # df.plot.area(x='Time', y=['Home', 'Work', 'School', 'SocialEvent', 'BasicsShop'], stacked=True, figsize=(10, 6)) - - fig, axs = plt.subplots(5, 2, constrained_layout=True) - df.plot(x='Time', y='Home', color='tab:blue', ax=axs[0, 0]) - df.plot(x='Time', y='Work', color='tab:green', ax=axs[0, 1]) - df.plot(x='Time', y='School', color='tab:red', ax=axs[1, 0]) - df.plot(x='Time', y='SocialEvent', color='tab:orange', ax=axs[1, 1]) - df.plot(x='Time', y='BasicsShop', color='tab:purple', ax=axs[2, 0]) - df.plot(x='Time', y='Hospital', color='tab:brown', ax=axs[2, 1]) - df.plot(x='Time', y='ICU', color='tab:pink', ax=axs[3, 0]) - df.plot(x='Time', y='Car', color='tab:gray', ax=axs[3, 1]) - df.plot(x='Time', y='PublicTransport', color='tab:olive', ax=axs[4, 0]) - df.plot(x='Time', y='Cemetery', color='tab:cyan', ax=axs[4, 1]) + # Calculate moving average for all location types + df['MA_Home'] = df.Home.rolling(10, min_periods=1).mean() + df['MA_Work'] = df.Work.rolling(10, min_periods=1).mean() + df['MA_School'] = df.School.rolling(10, min_periods=1).mean() + df['MA_SocialEvent'] = df.SocialEvent.rolling(10, min_periods=1).mean() + df['MA_BasicsShop'] = df.BasicsShop.rolling(10, min_periods=1).mean() + df['MA_Hospital'] = df.Hospital.rolling(10, min_periods=1).mean() + df['MA_ICU'] = df.ICU.rolling(10, min_periods=1).mean() + df['MA_Car'] = df.Car.rolling(10, min_periods=1).mean() + df['MA_PublicTransport'] = df.PublicTransport.rolling( + 10, min_periods=1).mean() + df['MA_Cemetery'] = df.Cemetery.rolling(10, min_periods=1).mean() + + df.plot(x='Time', y=['MA_Home', 'MA_Work', 'MA_School', 'MA_SocialEvent', 'MA_BasicsShop', + 'MA_Hospital', 'MA_ICU', 'MA_Car', 'MA_PublicTransport', 'MA_Cemetery'], figsize=(10, 6)) + + # Subplots of individual location types + # fig, axs = plt.subplots(5, 2, constrained_layout=True) + # df.plot(x='Time', y='MA_Home', color='tab:blue', ax=axs[0, 0]) + # df.plot(x='Time', y='MA_Work', color='tab:green', ax=axs[0, 1]) + # df.plot(x='Time', y='MA_School', color='tab:red', ax=axs[1, 0]) + # df.plot(x='Time', y='MA_SocialEvent', color='tab:orange', ax=axs[1, 1]) + # df.plot(x='Time', y='MA_BasicsShop', color='tab:purple', ax=axs[2, 0]) + # df.plot(x='Time', y='MA_Hospital', color='tab:brown', ax=axs[2, 1]) + # df.plot(x='Time', y='MA_ICU', color='tab:pink', ax=axs[3, 0]) + # df.plot(x='Time', y='MA_Car', color='tab:gray', ax=axs[3, 1]) + # df.plot(x='Time', y='MA_PublicTransport', color='tab:olive', ax=axs[4, 0]) + # df.plot(x='Time', y='MA_Cemetery', color='tab:cyan', ax=axs[4, 1]) + plt.show() From 9780f95c31341a1d859d9c522ba2c5677680da6f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 3 May 2024 13:57:38 +0200 Subject: [PATCH 102/488] Refactor TransportMode enum values for clarity and consistency Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/movement_data.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/models/abm/movement_data.h b/cpp/models/abm/movement_data.h index 10ba131909..f95f5778cf 100644 --- a/cpp/models/abm/movement_data.h +++ b/cpp/models/abm/movement_data.h @@ -28,21 +28,20 @@ namespace mio namespace abm { - /** * @brief Mode of Transport. */ enum class TransportMode : uint32_t { - Bike = 0, + Unknown = 0, + Bike, CarDriver, CarPassenger, PublicTransport, Walking, - Other, - Unknown -}; + Other +}; /** * @brief Type of the activity. From 0c560f55b8651d40de94f8b3589677027943070d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 7 May 2024 16:54:12 +0200 Subject: [PATCH 103/488] enhance analyze_npi Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_npi.py | 118 +++++++++++++++------------------ 1 file changed, 52 insertions(+), 66 deletions(-) diff --git a/cpp/simulations/analyze_npi.py b/cpp/simulations/analyze_npi.py index b524f1bb26..723e32ffdb 100644 --- a/cpp/simulations/analyze_npi.py +++ b/cpp/simulations/analyze_npi.py @@ -7,46 +7,34 @@ import os import openpyxl -# # from the first file 'datensatzbeschreibung_massnahmen' we want to extract the following information: -# # on the site DSB BL we have the following information: -# #first column is the short name of the measure -# # third column is the explanation of the measure -# #we want a map from the short name to the explanation -# # get the data from the first file -# csv_file = pd.read_csv( -# r'C:\Users\korf_sa\Documents\rep\cpp\simulations\datensatzbeschreibung_massnahmen.csv', header=None, skiprows=1) - - - - -# csv_file = pd.read_csv( -# r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_maincat.csv', header=None, skiprows=1) -# # csv_file = pd.read_csv( -# # r'C:\Users\korf_sa\Documents\rep\cpp\simulations\germany_counties_npi_subcat.csv', header=None, skiprows=1) - - - -# #mapping from column entry to column name: -# dict_leisure = {1: 'ContactPriv', 2: 'Schools', 3: 'Kita', 4: 'IndoorEvents', -# 5: 'OutdoorEvents', 6: 'Culture', 7: 'Retail', 8: 'Gastronomy'} - -# #delete all files with different zip code -# csv_file = csv_file[csv_file[2] == zip_code_brunswick] -# # also delete all files with different date -# csv_file = csv_file[(csv_file[1] >= start_date) & (csv_file[1] <= end_date)] -# #delete all the columns that are zero -# # csv_file = csv_file.loc[:, (csv_file != 0).any(axis=0)] -# #delete all the columns that are not zero but keep header number 0 - -# #plot a heatmap of the resulting 0/1 matrix within the dataframe - -# sns.heatmap(csv_file.iloc[:, 3:], cmap='coolwarm', cbar=False) -# plt.show() - -# # we want - -# x=1 +#define a function which takes in a list of dates in the form yyyy-mm-dd and summarizes them in a range of dates where the dates are consecutive, e.g. [2021-01-01, 2021-01-02, 2021-01-03, 2021-01-05] -> [2021-01-01 to 2021-01-03, 2021-01-05] +def summarize_dates(dates): + #sort the list of dates + dates.sort() + #initialize the list of ranges + ranges = [] + #initialize the start of the range + start = dates[0] + #initialize the end of the range + end = dates[0] + #iterate through the list of dates + for i in range(1, len(dates)): + #if the date is the next day of the previous date + if pd.to_datetime(dates[i]) == pd.to_datetime(dates[i-1]) + pd.DateOffset(days=1): + #set the end of the range to the current date + end = dates[i] + #if the date is not the next day of the previous date + else: + #append the range to the list of ranges + ranges.append(str(start) + ' to ' + str(end)) + #set the start of the range to the current date + start = dates[i] + #set the end of the range to the current date + end = dates[i] + #append the last range to the list of ranges + ranges.append(str(start) + ' to ' + str(end)) + return ranges @@ -54,45 +42,43 @@ df_abb = pd.read_excel('/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/datensatzbeschreibung_massnahmen.xlsx', sheet_name='DSB BL') #read in the matrix which tells us which measure is active on which day -df_measure_matrix = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/germany_counties_npi_subcat.csv', header=None, skiprows=1) +df_measure_matrix = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/germany_counties_npi_subcat.csv') zip_code_brunswick = 3101 start_date = '2021-03-01' end_date = '2021-05-31' + +one_day_after = pd.to_datetime(start_date) + pd.DateOffset(days=1) #now we want to shorten the matrix to the zip code of Brunswick and the time period of interest #delete all files with different zip code -df_measure_matrix = df_measure_matrix[df_measure_matrix[2] == zip_code_brunswick] -# also delete all files with different date -df_measure_matrix = df_measure_matrix[(df_measure_matrix[1] >= start_date) & (df_measure_matrix[1] <= end_date)] +df_measure_matrix = df_measure_matrix[df_measure_matrix['ID_County'] == zip_code_brunswick] +#also delete all files with different date +df_measure_matrix = df_measure_matrix[(df_measure_matrix['Date'] >= start_date) & (df_measure_matrix['Date'] <= end_date)] +#delete all the columns that just contain zeros +df_measure_matrix = df_measure_matrix.loc[:, (df_measure_matrix != 0).any(axis=0)] + -# now we want to do the following: -# 1. for every measure we want to count how many days it was active -# 2. We want to sort the measures by the number of days they were active -# 3. We want to plot the measures in a bar plot with the number of days they were active -# 4. We want a txt file which has for each measure the full explanation and the days it was active +#rename the first column from the abbreviation to the full explanation +# create a map from the short name to the explanation +dict_measure = {} +for i in range(len(df_abb)): + dict_measure[df_abb['Variablenname'][i]] = df_abb['Beschreibung'][i] +df_measure_matrix = df_measure_matrix.rename(columns=dict_measure) -# begin with 1. -# get the number of days a measure was active -measure_by_days = df_measure_matrix.iloc[:, 3:] -# count the number of days a measure was active -measure_by_days = measure_by_days.sum() -# sort the measures by the number of days they were active -measure_by_days = measure_by_days.sort_values(ascending=False) -#delete all the columns that are zero -measure_by_days = measure_by_days[measure_by_days != 0] # now we need create a txt file with the measures and the number of days they were active and the full explanation -# create a txt file f = open('measures_active_days.txt', 'w') -#get first row of df_abb - - # for every measure -for measure in measure_by_days.axes[0]: - # get the full explanation - full_explanation = df_abb['Beschreibung'][measure-3] - # write the full explanation and the number of days the measure was active to the txt file - f.write(full_explanation + ' ' + str(measure_by_days[measure]) + '\n') +for measure in df_measure_matrix.axes[1][3:]: + # count the days it was active + days = df_measure_matrix[measure].sum() + # get the dates it was active on in one list + dates = df_measure_matrix[df_measure_matrix[measure] == 1]['Date'].to_list() + # summarize the dates in ranges + date_ranges = summarize_dates(dates) + # write the measure and the number of days it was active in the txt file also write down each date the measure was active + f.write(measure + ': ' + str(days) + ' days ' + 'Dates: ' + str(date_ranges) + '\n\n') + x=1 From 2f99549b014d2cf09ec02e59dbef6873786a2797 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 8 May 2024 11:14:57 +0200 Subject: [PATCH 104/488] Refactor ContactDuration struct to remove unused code Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/parameters.h | 17 +------------ cpp/simulations/paper_abm_bs_testing.cpp | 31 ++++++++++++------------ 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 9b65402948..df17a069f7 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -710,25 +710,10 @@ struct ContactRates { } }; -/** - * @brief Average contact duration in days. -*/ -struct ContactDuration { - using Type = ScalarType; - static Type get_default(AgeGroup /*size*/) - { - return Type(5. / 24 / 60); // 5 minutes - } - static std::string name() - { - return "ContactDuration"; - } -}; - /** * @brief Parameters of the Infection that depend on the Location. */ -using LocalInfectionParameters = ParameterSet; +using LocalInfectionParameters = ParameterSet; /** * @brief Parameters of the simulation that are the same everywhere within the World. diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c23cbc93c2..ef88da0073 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -37,7 +37,7 @@ namespace fs = boost::filesystem; // Assign the name to general age group. -size_t num_age_groupss = 6; +size_t num_age_groupss = 6; const auto age_group_0_to_4 = mio::AgeGroup(0); const auto age_group_5_to_14 = mio::AgeGroup(1); const auto age_group_15_to_34 = mio::AgeGroup(2); @@ -75,7 +75,7 @@ void extrapolate_real_world_data(mio::osecir::Model& model, const std::string& i void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(date, 1, input_dir); + auto initial_graph = get_graph(date, 1, input_dir); const size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); @@ -247,7 +247,7 @@ mio::AgeGroup determine_age_group(uint32_t age) else if (age <= 79) { return age_group_60_to_79; } - else if (age > 79){ + else if (age > 79) { return age_group_80_plus; } else { @@ -425,7 +425,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; - auto it_person = persons.find(person_id); @@ -452,10 +451,10 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, target_location); //This assumes that we only have in each tripchain only one location type for each person // if (locations.find(start_location_id) == locations.end()) { // // For trips where the start location is not known use Home instead - + // } - mio::abm::LocationId start_location = {it_person->second.get_assigned_location_index(mio::abm::LocationType::Home), - mio::abm::LocationType::Home}; + mio::abm::LocationId start_location = { + it_person->second.get_assigned_location_index(mio::abm::LocationType::Home), mio::abm::LocationType::Home}; world.get_trip_list().add_trip(mio::abm::Trip( it_person->second.get_person_id(), mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location, start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); @@ -1119,15 +1118,15 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // auto run_idx = size_t(1); // The run index // auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations -// int tid = -1; -// #pragma omp parallel private(tid) // Start of parallel region: forks threads -// { -// tid = omp_get_thread_num(); // default is number of CPUs on machine -// printf("Hello World from thread = %d and rank = %d\n", tid, rank); -// if (tid == 0) { -// printf("Number of threads = %d\n", omp_get_num_threads()); -// } -// } // ** end of the the parallel: joins threads + // int tid = -1; + // #pragma omp parallel private(tid) // Start of parallel region: forks threads + // { + // tid = omp_get_thread_num(); // default is number of CPUs on machine + // printf("Hello World from thread = %d and rank = %d\n", tid, rank); + // if (tid == 0) { + // printf("Number of threads = %d\n", omp_get_num_threads()); + // } + // } // ** end of the the parallel: joins threads // Determine inital infection state distribution //Time this From 4e6dece504491a94cd7c768f28df7c6a88dcc606 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 8 May 2024 13:56:25 +0200 Subject: [PATCH 105/488] several fixes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/common_abm_loggers.h | 71 +++++++++--------- cpp/models/abm/person.h | 1 - cpp/simulations/generate_graph_from_data.cpp | 11 +-- cpp/simulations/paper_abm_bs_testing.cpp | 78 ++++++++++---------- 4 files changed, 79 insertions(+), 82 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index b75a159a62..d7e4a130d6 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -166,7 +166,7 @@ struct LogDataForMovement : mio::LogAlways { */ struct LogInfectionState : mio::LogAlways { using Type = std::pair; - std::unordered_set ids_in_bs; + // std::unordered_set ids_in_bs; /** * @brief Log the TimeSeries of the number of Person%s in an #InfectionState. @@ -177,28 +177,27 @@ struct LogInfectionState : mio::LogAlways { { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::InfectionState::Count)); auto curr_time = sim.get_time(); - auto ids_in_bs = sim.get_world().parameters.get(); + // auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. - if (ids_in_bs.size() == 0) { - PRAGMA_OMP(parallel for) - for (auto&& location : sim.get_world().get_locations()) { - for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { - sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); - } - } - } + // if (ids_in_bs.size() == 0) { + // PRAGMA_OMP(parallel for) + // for (auto&& location : sim.get_world().get_locations()) { + // for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { + // sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); + // } + // } + // } // Otherwise log accordingly - else { - for (auto&& person : sim.get_world().get_persons()) { - for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { - if (person.get_infection_state(curr_time) == mio::abm::InfectionState(inf_state) && - ids_in_bs.find(person.get_person_id()) != ids_in_bs.end()) { - sum[inf_state] += 1; - } + + for (auto&& person : sim.get_world().get_persons()) { + for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { + if (person.get_infection_state(curr_time) == mio::abm::InfectionState(inf_state)) { + sum[inf_state] += 1; } } } + return std::make_pair(curr_time, sum); } }; @@ -218,7 +217,7 @@ struct LogInfectionPerLocationType : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::LocationType::Count)); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - auto ids_in_bs = sim.get_world().parameters.get(); + // auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. if (0 == 0) { // PRAGMA_OMP(parallel for) @@ -233,8 +232,7 @@ struct LogInfectionPerLocationType : mio::LogAlways { else { for (auto&& person : sim.get_world().get_persons()) { if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && - (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { sum[(int)(person.get_location().get_type())] += 1; } } @@ -258,28 +256,27 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - auto ids_in_bs = sim.get_world().parameters.get(); + // auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. - if (ids_in_bs.size() == 0) { - PRAGMA_OMP(parallel for) - for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { - sum[(size_t)(person.get_age())] += 1; - } - } - } + // if (ids_in_bs.size() == 0) { + // PRAGMA_OMP(parallel for) + // for (auto&& person : sim.get_world().get_persons()) { + // if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + // (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + // sum[(size_t)(person.get_age())] += 1; + // } + // } + // } // Otherwise log accordingly - else { - for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && - (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { - sum[(size_t)(person.get_age())] += 1; - } + // else { + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + sum[(size_t)(person.get_age())] += 1; } } + // } return std::make_pair(curr_time, sum); } diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index d52267ee5f..22b170bca9 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -127,7 +127,6 @@ class Person * @param[in, out] location Initial Location of the Person. * @param[in] age The AgeGroup of the Person. * @param[in] person_id Index of the Person. - * @param[in] is_home_in_bs Whether the Person has a home in Braunschweig. */ explicit Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t person_id = INVALID_PERSON_ID); diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index e2659d3182..a8b7052fbe 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -113,8 +113,9 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double timeInfectedCriticalMin[] = {4.95, 4.95, 4.86, 14.14, 14.4, 10.}; const double timeInfectedCriticalMax[] = {8.95, 8.95, 8.86, 20.58, 19.8, 13.2}; - array_assign_uniform_distribution(params.get(), incubationTime, incubationTime); - array_assign_uniform_distribution(params.get(), serialIntervalMin, serialIntervalMax); + array_assign_uniform_distribution(params.get(), incubationTime, incubationTime); + array_assign_uniform_distribution(params.get(), serialIntervalMin, + serialIntervalMax); array_assign_uniform_distribution(params.get(), timeInfectedSymptomsMin, timeInfectedSymptomsMax); array_assign_uniform_distribution(params.get(), timeInfectedSevereMin, @@ -185,10 +186,10 @@ mio::IOResult set_contact_matrices(const fs::path& data_dir, mio::osecir:: //TODO: io error handling auto contact_matrices = mio::ContactMatrixGroup(contact_locations.size(), size_t(params.get_num_groups())); for (auto&& contact_location : contact_locations) { - BOOST_OUTCOME_TRY(baseline, + BOOST_OUTCOME_TRY(auto&& baseline, mio::read_mobility_plain( (data_dir / "contacts" / ("baseline_" + contact_location.second + ".txt")).string())); - BOOST_OUTCOME_TRY(minimum, + BOOST_OUTCOME_TRY(auto&& minimum, mio::read_mobility_plain( (data_dir / "contacts" / ("minimum_" + contact_location.second + ".txt")).string())); contact_matrices[size_t(contact_location.first)].get_baseline() = baseline; @@ -221,7 +222,7 @@ mio::IOResult> get_graph(mio::Date start_date, c auto population_data_path = mio::path_join((data_dir / "pydata" / "Germany").string(), "county_current_population.json"); - BOOST_OUTCOME_TRY(node_ids, mio::get_node_ids(population_data_path, true)); + BOOST_OUTCOME_TRY(auto&& node_ids, mio::get_node_ids(population_data_path, true)); std::vector nodes(node_ids.size(), mio::osecir::Model(num_groups)); for (auto& node : nodes) { node.parameters = params; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ef88da0073..21c687398a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -460,7 +460,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); } world.get_trip_list().use_weekday_trips_on_weekend(); - world.parameters.get() = ids_in_bs; + // world.parameters.get() = ids_in_bs; // //Some Data about the world: // //write how many persons are in each home @@ -815,40 +815,40 @@ void set_local_parameters(mio::abm::World& world) /** * @brief Add testing strategies to the world. */ -void add_testing_strategies(mio::abm::World& world, bool school, bool work, bool symptomatic) -{ - // Tests in schools - auto testing_criteria_school = mio::abm::TestingCriteria(); - - auto testing_min_time = mio::abm::days(7); - auto start_date = mio::abm::TimePoint(0); - auto end_date = mio::abm::TimePoint(0) + mio::abm::days(60); - auto test_type = mio::abm::AntigenTest(); - auto probability = mio::UncertainValue(); - assign_uniform_distribution(probability, 0.5, 0.5); - - auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date, - end_date, test_type, probability.draw_sample()); - if (school) - world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); - - // Tests in work places - auto testing_criteria_work = mio::abm::TestingCriteria(); - - assign_uniform_distribution(probability, 0.5, 0.5); - auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, - test_type, probability.draw_sample()); - if (work) - world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); - - // Test when symptomatic - auto testing_criteria_symptomatic = mio::abm::TestingCriteria({}, {mio::abm::InfectionState::InfectedSymptoms}); - auto testing_scheme_symptomatic = - mio::abm::TestingScheme(testing_criteria_symptomatic, testing_min_time, start_date, end_date, test_type, 0.7); - - if (symptomatic) - world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_symptomatic); -} +// void add_testing_strategies(mio::abm::World& world, bool school, bool work, bool symptomatic) +// { +// // Tests in schools +// auto testing_criteria_school = mio::abm::TestingCriteria(); + +// auto testing_min_time = mio::abm::days(7); +// auto start_date = mio::abm::TimePoint(0); +// auto end_date = mio::abm::TimePoint(0) + mio::abm::days(60); +// // auto test_type = mio::abm::AntigenTest(); +// auto probability = mio::UncertainValue(); +// assign_uniform_distribution(probability, 0.5, 0.5); + +// // auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date, +// // end_date, probability.draw_sample()); +// // if (school) +// // world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); + +// // Tests in work places +// auto testing_criteria_work = mio::abm::TestingCriteria(); + +// assign_uniform_distribution(probability, 0.5, 0.5); +// // auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, +// // test_type, probability.draw_sample()); +// // if (work) +// // world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); + +// // Test when symptomatic +// // auto testing_criteria_symptomatic = mio::abm::TestingCriteria({}, {mio::abm::InfectionState::InfectedSymptoms}); +// // auto testing_scheme_symptomatic = +// // mio::abm::TestingScheme(testing_criteria_symptomatic, testing_min_time, start_date, end_date, test_type, 0.7); + +// // if (symptomatic) +// // world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_symptomatic); +// } /** * Create a sampled simulation with start time t0. @@ -884,7 +884,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con //3. testen in schulen und Arbeitsplätzen (unabh. von Alter, 1x am Tag, unabh. von InfectionState) ab Tag 0 //4. 2.+3. - add_testing_strategies(world, false, false, false); + // add_testing_strategies(world, false, false, false); } template @@ -1101,7 +1101,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 235000; + auto max_num_persons = 23000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1270,8 +1270,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; - std::string result_dir = input_dir + "\\results"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 95634ec08583583321315531979e1e341d93fed2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 9 May 2024 15:35:01 +0200 Subject: [PATCH 106/488] feat: Refactor migration logic for improved performance and readability Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index a40ac07427..e8c71613f4 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -47,8 +47,7 @@ Person& World::add_person(const LocationId id, AgeGroup age) { assert(age.get() < parameters.get_num_groups()); uint32_t person_id = static_cast(m_persons.size()); - m_persons.push_back( - std::make_unique(m_rng, get_individualized_location(id), age, person_id)); + m_persons.push_back(std::make_unique(m_rng, get_individualized_location(id), age, person_id)); auto& person = *m_persons.back(); person.set_assigned_location(m_cemetery_id); get_individualized_location(id).add_person(person); @@ -129,14 +128,18 @@ void World::migration(TimePoint t, TimeSpan dt) if (num_trips != 0) { while (m_trip_list.get_current_index() < num_trips && m_trip_list.get_next_trip_time(weekend).seconds() < (t + dt).time_since_midnight().seconds()) { - auto& trip = m_trip_list.get_next_trip(weekend); - auto& person = m_persons[trip.person_id]; - auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); + auto& trip = m_trip_list.get_next_trip(weekend); + auto& person = m_persons[trip.person_id]; + auto& current_location = person->get_location(); + auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); if (!person->is_in_quarantine(t, parameters) && person->get_infection_state(t) != InfectionState::Dead) { auto& target_location = get_individualized_location(trip.migration_destination); if (m_testing_strategy.run_strategy(personal_rng, *person, target_location, t)) { - person->apply_mask_intervention(personal_rng, target_location); - person->migrate_to(target_location, trip.trip_mode); + if (target_location != current_location && + target_location.get_number_persons() < target_location.get_capacity().persons) { + person->apply_mask_intervention(personal_rng, target_location); + person->migrate_to(target_location); + } } } m_trip_list.increase_index(); From f034897ddbe5fc8a924e4e4dbb5d976c84ac618c Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 10 May 2024 11:09:08 +0200 Subject: [PATCH 107/488] Add syntax for getting last protection at individual time --- cpp/models/abm/location.cpp | 2 +- cpp/models/abm/person.cpp | 8 +++++--- cpp/models/abm/person.h | 2 +- cpp/simulations/abm.cpp | 2 +- cpp/tests/test_abm_infection.cpp | 2 +- cpp/tests/test_abm_person.cpp | 4 ++-- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 7467ea26f0..21e06a106a 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -100,7 +100,7 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time local_indiv_expected_trans); // use VirusVariant::Count for no virus submission if (virus != VirusVariant::Count) { person.add_new_infection(Infection(rng, virus, age_receiver, global_params, t + dt / 2, - mio::abm::InfectionState::Exposed, person.get_latest_protection(), + mio::abm::InfectionState::Exposed, person.get_latest_protection(t), false)); // Starting time in first approximation } } diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index 9b77ee2f63..c5e0f58742 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -270,10 +270,12 @@ bool Person::apply_mask_intervention(RandomNumberGenerator& rng, const Location& return true; } -std::pair Person::get_latest_protection() const +std::pair Person::get_latest_protection(TimePoint t) const { ExposureType latest_exposure_type = ExposureType::NoProtection; - TimePoint infection_time = TimePoint(0); + TimePoint infection_time = TimePoint(std::numeric_limits::min()); + + // TODO: Check for latest infection or vaccination relative to TimePoint t if (!m_infections.empty()) { latest_exposure_type = ExposureType::NaturalInfection; infection_time = m_infections.back().get_start_date(); @@ -287,7 +289,7 @@ std::pair Person::get_latest_protection() const ScalarType Person::get_protection_factor(TimePoint t, VirusVariant virus, const Parameters& params) const { - auto latest_protection = get_latest_protection(); + auto latest_protection = get_latest_protection(t); // If there is no previous protection or vaccination, return 0. if (latest_protection.first == ExposureType::NoProtection) { return 0; diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index 22b170bca9..ce1ba171ed 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -471,7 +471,7 @@ class Person /** * @brief Get the latest #Infection or #Vaccination and its initial TimePoint of the Person. */ - std::pair get_latest_protection() const; + std::pair get_latest_protection(TimePoint t) const; /** * serialize this. diff --git a/cpp/simulations/abm.cpp b/cpp/simulations/abm.cpp index 47fc342444..2876aa2b7f 100644 --- a/cpp/simulations/abm.cpp +++ b/cpp/simulations/abm.cpp @@ -454,7 +454,7 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t, doubl if (infection_state != mio::abm::InfectionState::Susceptible) { person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), world.parameters, t, infection_state, - person.get_latest_protection(), false)); + person.get_latest_protection(t), false)); } } } diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index 04ff59b438..654203c152 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -229,7 +229,7 @@ TEST(TestInfection, getPersonalProtectiveFactor) auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); auto person = mio::abm::Person(rng, location, age_group_15_to_34); person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, mio::abm::TimePoint(0)); - auto latest_protection = person.get_latest_protection(); + auto latest_protection = person.get_latest_protection(mio::abm::TimePoint(0)); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); // Test default parameter functions diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index f66aa1bcc6..74369e63ca 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -300,14 +300,14 @@ TEST(TestPerson, getLatestProtection) auto t = mio::abm::TimePoint(0); person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t); - auto latest_protection = person.get_latest_protection(); + auto latest_protection = person.get_latest_protection(t); ASSERT_EQ(latest_protection.first, mio::abm::ExposureType::GenericVaccine); ASSERT_EQ(latest_protection.second.days(), t.days()); t = mio::abm::TimePoint(40 * 24 * 60 * 60); person.add_new_infection(mio::abm::Infection(prng, static_cast(0), age_group_15_to_34, params, t, mio::abm::InfectionState::Exposed)); - latest_protection = person.get_latest_protection(); + latest_protection = person.get_latest_protection(t); ASSERT_EQ(latest_protection.first, mio::abm::ExposureType::NaturalInfection); ASSERT_EQ(latest_protection.second.days(), t.days()); } From 2b032a257afce753ffb7ff5561c7822ae24e37fb Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 10 May 2024 14:20:01 +0200 Subject: [PATCH 108/488] add unused bc else doesnt compile in get_latest_protection Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/person.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index c5e0f58742..7a168f37e2 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -275,7 +275,8 @@ std::pair Person::get_latest_protection(TimePoint t) co ExposureType latest_exposure_type = ExposureType::NoProtection; TimePoint infection_time = TimePoint(std::numeric_limits::min()); - // TODO: Check for latest infection or vaccination relative to TimePoint t + // TODO: Check for latest infection or vaccination relative to TimePoint t and delete unused + mio::unused(t); if (!m_infections.empty()) { latest_exposure_type = ExposureType::NaturalInfection; infection_time = m_infections.back().get_start_date(); From 0779ec27d67694862eb3104ef1d32cbd39f76f2a Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Mon, 13 May 2024 19:53:18 +0200 Subject: [PATCH 109/488] Check for latest infection/vaccination in get_latest_protection() relative to TimePoint t and delete unused --- cpp/models/abm/person.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index 7a168f37e2..e47c699759 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -273,18 +273,29 @@ bool Person::apply_mask_intervention(RandomNumberGenerator& rng, const Location& std::pair Person::get_latest_protection(TimePoint t) const { ExposureType latest_exposure_type = ExposureType::NoProtection; - TimePoint infection_time = TimePoint(std::numeric_limits::min()); + TimePoint infection_time = TimePoint(std::numeric_limits::min()); - // TODO: Check for latest infection or vaccination relative to TimePoint t and delete unused - mio::unused(t); - if (!m_infections.empty()) { - latest_exposure_type = ExposureType::NaturalInfection; - infection_time = m_infections.back().get_start_date(); + // Look for any Infection that happens before time t + for(const Infection& infection : m_infections) { + if (infection.get_start_date() <= t) { + latest_exposure_type = ExposureType::NaturalInfection; + infection_time = infection.get_start_date(); + } else { + break; + } } - if (!m_vaccinations.empty() && infection_time.days() <= m_vaccinations.back().time.days()) { - latest_exposure_type = m_vaccinations.back().exposure_type; - infection_time = m_vaccinations.back().time; + + // Look for any Vaccination that happens between the lastest Infection and time t + for(const Vaccination& vaccination : m_vaccinations) { + if (vaccination.time <= t && vaccination.time > infection_time) { + latest_exposure_type = vaccination.exposure_type; + infection_time = vaccination.time; + } + if (vaccination.time > t) { + break; + } } + return std::make_pair(latest_exposure_type, infection_time); } From e0ef9102cba64270067741cc51f75f7a6a4c4300 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 14 May 2024 22:36:42 +0200 Subject: [PATCH 110/488] Refactor path to results in analyze_bs_run.py and update default values for TestType::Antigen in parameters.h Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 24 + cpp/models/abm/location.h | 11 + cpp/models/abm/parameters.h | 2 +- cpp/simulations/analyze_bs_run.py | 2 +- cpp/simulations/check_bs_data.py | 892 ++++++++++------------- cpp/simulations/paper_abm_bs_testing.cpp | 82 ++- 6 files changed, 516 insertions(+), 497 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 21e06a106a..4fc9cc5fc0 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -42,6 +42,30 @@ Location::Location(LocationId loc_id, size_t num_agegroups, uint32_t num_cells) assert(num_cells > 0 && "Number of cells has to be larger than 0."); } +void Location::add_damping(TimePoint t_begin, double p) +{ + temp_npi_damping.emplace_back(t_begin, p); +} + +bool Location::entry_allowed(const mio::abm::TimePoint t) const +{ + if (temp_npi_damping.empty()) { + return true; + } + else { + // We want to go through the npi vector and get the last entry that is smaller than t + auto it = std::upper_bound(temp_npi_damping.begin(), temp_npi_damping.end(), t, + [](TimePoint t, const std::pair& p) { + return t < p.first; + }); + //then we want to access the second element of it, draw a random number between 0 and 1 and check if it is smaller than the damping factor + //get a random number between 0 and 1 without m_rng + // double random_number = mio::UniformDistribution::get_instance()(); + // return random_number > it->second; + return true; + } +} + Location Location::copy_location_without_persons(size_t num_agegroups) { Location copy_loc = Location(*this); diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index 8873168a11..e07af276d1 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -31,6 +31,7 @@ #include "memilio/utils/custom_index_array.h" #include "memilio/utils/time_series.h" #include "memilio/utils/memory.h" +#include "abm/time.h" #include #include #include @@ -260,6 +261,14 @@ class Location return m_required_mask; } + /** + * @brief add a damping (chance to enter the location) to the location + * @return The LocationId of the Location. + */ + void add_damping(TimePoint t, double p); + + bool entry_allowed(const mio::abm::TimePoint t) const; + /** * @brief Set the required type of mask for entering this Location. * @param[in] type The Least secure MaskType that is demanded when entering this Location. @@ -422,6 +431,8 @@ class Location MaskType m_required_mask; ///< Least secure type of Mask that is needed to enter the Location. bool m_npi_active; ///< If true requires e.g. Mask%s to enter the Location. GeographicalLocation m_geographical_location; ///< Geographical location (longitude and latitude) of the Location. + std::vector> + temp_npi_damping; ///< Temporary storage for NPI dampings. //TODO: delete these and implement better }; } // namespace abm diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index e42479fe1c..5c2776d554 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -449,7 +449,7 @@ struct TestData { { Type default_val = Type({TestType::Count}); default_val[{TestType::Generic}] = TestParameters{0.9, 0.99}; - default_val[{TestType::Antigen}] = TestParameters{0.8, 0.88}; + default_val[{TestType::Antigen}] = TestParameters{0.65, 0.99}; default_val[{TestType::PCR}] = TestParameters{0.9, 0.99}; return default_val; } diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 7b29496069..de1b4aae27 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -249,7 +249,7 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - path = "./results" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: diff --git a/cpp/simulations/check_bs_data.py b/cpp/simulations/check_bs_data.py index e00897ad2d..843ca8a03c 100644 --- a/cpp/simulations/check_bs_data.py +++ b/cpp/simulations/check_bs_data.py @@ -15,7 +15,7 @@ ####### minimal sanity check on data ####### bd = pd.read_csv( - r'C:\Users\korf_sa\Documents\rep\data\mobility\modified_braunschweig_result.csv', header=None, skiprows=1) + '/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/modified_braunschweig_result_ffa7.csv', header=None, skiprows=1) # setup dictionary for the leisure activities, and vehicle choice and column names # bd.rename( @@ -26,7 +26,7 @@ bd.rename( columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', 10: 'travelTime' , 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', 16: - 'ActivityBefore', 17: 'ActivityAfter', 18: 'age'}, + 'ActivityBefore', 17: 'ActivityAfter', 18: 'age', 19:'home_in_bs'}, inplace=True) dict_leisure = {1: 'work', 2: 'education', 3: 'Shopping', 4: 'free time', @@ -37,7 +37,88 @@ #check if there are same locations where people end their trips with different activity_after bd_same_loc = bd[['loc_id_end', 'ActivityAfter']].drop_duplicates() #count how many different activities are after the same location -bd_same_loc = bd_same_loc.groupby(['loc_id_end']).size().reset_index(name='counts') +bd_same_loc = bd_same_loc.groupby(['loc_id_end']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) + + +# check if people do the same trip more than once +trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] +duplicate_trips = trips.duplicated() +if (duplicate_trips.any()): + print('Error: The Person does the "same" trip more than once (or dos 2 things in 5 mins). Number of duplicate trips: ' + str(duplicate_trips[duplicate_trips==True].size)) + if (~bd[['tripID']].duplicated().any()): + print('There are no duplicate TripIDs. There are multiple TripIDs for the same Trip. \n') +activities_after_duplicate_trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime', 'ActivityAfter']].loc[trips.duplicated(keep=False)] +if (~activities_after_duplicate_trips.duplicated(keep=False).all()): + print('Error: Multiple activities after the same trip. \n') + +# check if persons have more than one home +person_homes = bd[['personID', 'loc_id_end', 'ActivityAfter']].loc[bd['ActivityAfter']==7] +person_homes = person_homes.drop_duplicates().groupby(['personID']).size().reset_index(name='counts') +person_homes.drop(person_homes.loc[person_homes['counts']<2].index, inplace=True) +if(person_homes.size > 0): + print('Error: There are people that have more than one home. \n') + +# check if the proportion of single-person-households is too high +households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +if (households.loc[households['counts']==1]['counts'].size)/(households['counts'].size) > 0.5: + print("Error: The proportion of single-person-households is too high (bigger than 50%): " + + str((households.loc[households['counts']==1]['counts'].size)/(households['counts'].size))) + +# check if there are invalid entries +if not bd['personID'].ge(100000000).all(): + print('Error: There is an entry in "personID" that is not assignable. \n') + # number of entries that are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['personID'].ge(100000000)].size) + '. \n') +if not bd['countyStart'].ge(30000000).all(): + print('Error: There is an entry in "countyStart" that is not assignable. \n') + # which ones are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyStart'].ge(30000000)].size) + '. \n') +if not bd['countyEnd'].ge(30000000).all(): + print('Error: There is an entry in "countyEnd" that is not assignable. \n') + # which ones are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyEnd'].ge(30000000)].size) + '. \n') +if not bd['hhID'].ge(100000000).all(): + print('Error: There is an entry in "hhID" that is not assignable. \n') +if not bd['vehicleChoice'].between(1, 5).all(): + print('Error: There is an entry in "vehicleChoice" that is not assignable. \n') + #print number of entries that are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['vehicleChoice'].between(1, 5)].size) + '. \n') +if not bd['ActivityAfter'].between(0, 7).all(): + print('Error: There is an entry in "ActivityAfter" that is not assignable. \n') + #print number of entries that are not assignable + print('Number of entries that are not assignable: ' + str(bd.loc[~bd['ActivityAfter'].between(0, 7)].size) + '. \n') + +# check if there are empty cells +for header in bd.columns: + if (bd[header].isna().any()): + print('Error: ' + str(len(bd[bd[header].isna()])) + ' empty entries in column' + str(header) + '. \n') + +# check how many persons and trips are in the data +number_of_people = bd[['personID']].drop_duplicates().size +print(str(number_of_people) + ' are people. \n') +number_of_trips = len(bd) +print(str(number_of_trips) + ' trips. \n') + +# check age groups with schools +students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] +#drop where age is 999 +students=students[students['age']!=999] +print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') +print(str(students.loc[students['age'] > 10].size) + ' trips of ' + str(students.size) + ' trips going to school are in a higher age group than 10. \n') + +children = bd[['personID','ActivityAfter']].loc[(bd['age']<=16) & (bd['age']>=7)] +number_of_children = children['personID'].drop_duplicates().size +number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size +print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') + + +workers = bd[['personID','ActivityAfter']].loc[(bd['age']<70)] +number_of_workers = len(workers['personID'].drop_duplicates()) +number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size +print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' workers do not go to work. \n') + + +# ####### visual check on values in data frame ####### #check how many persons in which age group have the activity_after 2 bd_age_activity = bd[['personID','age', 'ActivityAfter']].loc[bd['ActivityAfter']==1] @@ -49,129 +130,6 @@ plt.ylabel('Number of persons') plt.title('Number of persons going to work in Braunschweig') plt.show() -#also put the age into bins -bd_age_activity['ageCohort'] = pd.cut(bd_age_activity['age'], bins=[-1, 2, 5, 14, 17, 24, 29, 39, 49, 64, 74, 105], labels=[ - '0-2', '3-5', '6-14', '15-17', '18-24', '25-29', '30-39', '40-49', '50-64', '65-74', '75+']) -bd_age_activity_cohorts = bd_age_activity.groupby( - ['ageCohort']).size().reset_index(name='counts') -bd_age_activity_cohorts.index = bd_age_activity_cohorts['ageCohort'].to_list() -bd_age_activity_cohorts.plot.bar(figsize=( - 10, 7), title='Age distribution of people going to school', xlabel='Age cohorts', ylabel='Number of persons', legend=None) -plt.show() - -x=1 -# # check if people do the same trip more than once -# trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] -# duplicate_trips = trips.duplicated() -# if (duplicate_trips.any()): -# print('Error: The Person does the "same" trip more than once (or dos 2 things in 5 mins). Number of duplicate trips: ' + str(duplicate_trips[duplicate_trips==True].size)) -# # if (~bd[['tripID']].duplicated().any()): -# # print('There are no duplicate TripIDs. There are multiple TripIDs for the same Trip. \n') -# activities_after_duplicate_trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime', 'ActivityAfter']].loc[trips.duplicated(keep=False)] -# if (~activities_after_duplicate_trips.duplicated(keep=False).all()): -# print('Error: Multiple activities after the same trip. \n') - -# # check if persons have more than one home -# person_homes = bd[['personID', 'loc_id_end', 'ActivityAfter']].loc[bd['ActivityAfter']==7] -# person_homes = person_homes.drop_duplicates().groupby(['personID']).size().reset_index(name='counts') -# person_homes.drop(person_homes.loc[person_homes['counts']<2].index, inplace=True) -# if(person_homes.size > 0): -# print('Error: There are people that have more than one home. \n') - -# # check if the proportion of single-person-households is too high -# households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) - -# # check if the proportion of single-person-households is too high -# if (households.loc[households['counts']==1]['counts'].size)/(households['counts'].size) > 0.5: -# print("Error: The proportion of single-person-households is too high: " + -# str((households.loc[households['counts']==1]['counts'].size)/(households['counts'].size))) - -# # check if there are invalid entries -# # if not bd['idTrafficZone'].ge(30000000).all(): -# # print('Error: There is an entry in "tripID" that is not assignable. \n') -# # # number of entries that are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripID'].ge(30000000)].size) + '. \n') -# if not bd['personID'].ge(100000000).all(): -# print('Error: There is an entry in "personID" that is not assignable. \n') -# # number of entries that are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['personID'].ge(100000000)].size) + '. \n') -# # if not bd['tripChain'].between(1, 100).all(): -# # print('Error: There is an entry in "tripChain" that is not assignable. \n') -# # # number of entries that are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripChain'].between(1, 100)].size) + '. \n') -# # # max assigned value -# # print('Max assigned value: ' + str(bd['tripChain'].max()) + '. \n') -# # if not bd['countyStart'].ge(30000000).all(): -# # print('Error: There is an entry in "countyStart" that is not assignable. \n') -# # # which ones are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyStart'].ge(30000000)].size) + '. \n') -# # if not bd['countyEnd'].ge(30000000).all(): -# # print('Error: There is an entry in "countyEnd" that is not assignable. \n') -# # # which ones are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyEnd'].ge(30000000)].size) + '. \n') -# # if not bd['hhID'].ge(100000000).all(): -# # print('Error: There is an entry in "hhID" that is not assignable. \n') -# # if not bd['tripChainID'].between(-1, -1).all(): -# # print('Error: There is an entry in "tripChainID" that is not assignable. \n') -# if not bd['vehicleChoice'].between(1, 5).all(): -# print('Error: There is an entry in "vehicleChoice" that is not assignable. \n') -# #print number of entries that are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['vehicleChoice'].between(1, 5)].size) + '. \n') -# if not bd['ActivityAfter'].between(0, 7).all(): -# print('Error: There is an entry in "ActivityAfter" that is not assignable. \n') -# #print number of entries that are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['ActivityAfter'].between(0, 7)].size) + '. \n') - -# # check if there are empty cells -# for header in bd.columns: -# if (bd[header].isna().any()): -# print('Error: ' + str(len(bd[bd[header].isna()])) + ' empty entries in column' + str(header) + '. \n') - -# # check age groups with schools -# number_of_people = bd[['personID']].drop_duplicates().size -# print(str(number_of_people) + ' are people. \n') - -# # number_of_trips = bd[['tripID']].drop_duplicates().size -# # print(str(number_of_trips) + ' trips. \n') - - -# students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] -# print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') -# print(str(students.loc[students['age'] > 20].size) + ' trips of ' + str(students.size) + ' trips going to school are in a higher age group than 10. \n') - -# children = bd[['personID','ActivityAfter']].loc[(bd['age']<=16) & (bd['age']>=7)] -# number_of_children = children['personID'].drop_duplicates().size -# number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size -# print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') - - -# workers = bd[['personID','ActivityAfter']].loc[(bd['age']>30)] -# number_of_workers = workers['personID'].drop_duplicates().size -# number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size -# print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' workers do not go to work. \n') - - - -# ############################################### - - -# ####### visual check on values in data frame ####### - -# # def get_trip_chain_activity_after(person_id): -# # bd_persons_trip_chain_activity_after = bd.loc[bd['personID'] == person_id, [ -# # 'tripChain', 'ActivityAfter']] -# # bd_persons_trip_chain_activity_after = bd_persons_trip_chain_activity_after.sort_values( -# # by=['tripChain'], ascending=True, ignore_index=True) -# # bd_persons_trip_chain_activity_after['ActivityAfter'] = bd_persons_trip_chain_activity_after['ActivityAfter'].map( -# # dict_leisure) -# # # and vehicle choice -# # bd_persons_trip_chain_vehicle_choice = bd.loc[bd['personID'] == person_id, [ -# # 'tripChain', 'vehicleChoice']] -# # bd_persons_trip_chain_vehicle_choice = bd_persons_trip_chain_vehicle_choice.sort_values( -# # by=['tripChain'], ascending=True, ignore_index=True) -# # bd_persons_trip_chain_vehicle_choice['vehicleChoice'] = bd_persons_trip_chain_vehicle_choice['vehicleChoice'].map( -# # dict_vehicle) -# # return bd_persons_trip_chain_activity_after, bd_persons_trip_chain_vehicle_choice # define figure path @@ -181,42 +139,41 @@ figs_path = os.path.join(os.path.dirname( os.path.abspath(__file__)), 'figs_bs_data') -# # check whether first start location is the last end location -# first_trip = bd[['personID','loc_id_start']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) -# last_trip = bd[['personID', 'loc_id_end']].drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) -# print("Number of persons where first start location is home: " + str(first_trip.loc[first_trip['loc_id_start']==-1]['loc_id_start'].size)+ ".") -# print("Number of persons where last end location is home: " + str(last_trip.loc[last_trip['loc_id_end']==-1]['loc_id_end'].size)+ ".") - -# # check what persons are doing which only do one trip -# # location_types = last_trip.groupby(['ActivityAfter']).size() - -# # location_types.plot(kind='bar') -# # plt.xlabel('Activity') -# # plt.ylabel('Number of persons') -# # plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) - -# # probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located -# # bd_tz_bs = bd.groupby(['idTrafficZone']).size().reset_index( -# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# # # Count traffic zones where person is residing and longitude and latuitude of this in "EPSG:3035" format -# # bd_traffic_zones_persons = bd.groupby(['idTrafficZone']).size().reset_index( -# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# # for row in bd_traffic_zones_persons.iterrows(): -# # bd_traffic_zones_persons.loc[row[0], ['longitude', 'latitude'] -# # ] = bd.loc[bd_traffic_zones_persons.loc[row[0], 'idTrafficZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] -# # print(bd_traffic_zones_persons) - -# #### Counting people #### -# bd_persons = bd.groupby(['personID']).size().reset_index( -# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# # Get the frequency of each number in the 'numbers' column -# bd_personss = bd_persons['counts'].value_counts().sort_index() -# # Plot the frequency of each number -# bd_personss.plot(kind='bar') -# plt.xlabel('Number of trips per day') -# plt.ylabel('Number of persons') -# plt.title('Number of trips per person tripcount (Braunschweig)') -# plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) +# check whether first start location is the last end location +first_trip = bd[['personID','loc_id_start','hhID']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) +last_trip = bd[['personID', 'loc_id_end','hhID','ActivityAfter']].drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) +print("Number of persons where first start location is home: " + str(first_trip.loc[first_trip['loc_id_start']==first_trip['hhID']]['loc_id_start'].size)+ ".") +print("Number of persons where last end location is home: " + str(last_trip.loc[last_trip['loc_id_end']==first_trip['hhID']]['loc_id_end'].size)+ ".") + +# check what persons are doing after their last trip +location_types = last_trip.groupby(['ActivityAfter']).size() +location_types.plot(kind='bar') +plt.xlabel('Activity') +plt.ylabel('Number of persons') +plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) + +# probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located +bd_tz_bs = bd.groupby(['startZone']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# Count traffic zones where person is residing and longitude and latuitude of this in "EPSG:3035" format +bd_traffic_zones_persons = bd.groupby(['startZone']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +for row in bd_traffic_zones_persons.iterrows(): + bd_traffic_zones_persons.loc[row[0], ['longitude', 'latitude'] + ] = bd.loc[bd_traffic_zones_persons.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +print(bd_traffic_zones_persons) + +#### Counting people #### +bd_persons = bd.groupby(['personID']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# Get the frequency of each number in the 'numbers' column +bd_personss = bd_persons['counts'].value_counts().sort_index() +# Plot the frequency of each number +bd_personss.plot(kind='bar') +plt.xlabel('Number of trips per day') +plt.ylabel('Number of persons') +plt.title('Number of trips per person tripcount (Braunschweig)') +plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) bd_persons_ages = bd[['personID', 'age']].drop_duplicates() # bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ @@ -231,224 +188,222 @@ 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) -# # get the id with the persons with the highest number and print them -# # [id_person_max_trips, id_person_max_1_trips] = [ -# # bd_persons['personID'][0], bd_persons['personID'][1]] -# # print(get_trip_chain_activity_after(id_person_max_trips)) - -# # select internal and external trips (from/to Braunschweig) -# # bd_persons_inside_bs = bd.loc[bd['startZone'].isin( -# # bd_tz_bs['idTrafficZone']) & bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] -# # bd_persons_outside_bs = bd.loc[~bd['startZone'].isin( -# # bd_tz_bs['idTrafficZone']) & ~bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] - -# # check how many trips are in the same traffic zone -# bd_taz_start = bd.groupby('startZone').size().reset_index(name='counts') -# #bd_same_taz = bd.loc[bd['startZone'] == bd['destZone']] -# bd_different_taz = bd.loc[bd['startZone'] != bd['destZone']] -# #bd_same_taz = bd_same_taz.groupby(['startZone']).size().reset_index(name='counts') -# bd_different_taz = bd_different_taz.groupby( -# ['startZone']).size().reset_index(name='counts') -# #bd_same_taz['percentage'] = bd_same_taz['counts']/bd_taz_start['counts'] -# bd_different_taz['complement_counts'] = bd_taz_start['counts'] - \ -# bd_different_taz['counts'] -# bd_different_taz['total_counts'] = bd_taz_start['counts'] -# bd_different_taz = (bd_different_taz.sort_values( -# by='total_counts', ascending=False, ignore_index=True)) -# plt.figure() -# plt.plot(bd_different_taz['counts']) -# plt.plot(bd_different_taz['complement_counts']) -# plt.legend(['different TAZ', 'same TAZ']) -# plt.xlabel('Traffic analysis zones') -# plt.ylabel('Amount of trips inside/outside a TAZ') -# plt.savefig(os.path.join(figs_path, 'TAZ_distribution.png'), dpi=300) - -# # which age takes which mode of transport -# bd_persons_age_vehicle_choice = bd.loc[:, ['personID', 'age', 'vehicleChoice']].sort_values( -# by=['age'], ascending=True, ignore_index=True) -# bd_persons_age_vehicle_choice['vehicleChoice'] = bd_persons_age_vehicle_choice['vehicleChoice'].map( -# dict_vehicle) -# # accumulate the number of trips per age and vehicle choice -# bd_persons_age_vehicle_choice = bd_persons_age_vehicle_choice.groupby( -# ['age', 'vehicleChoice']).size().reset_index( -# name='counts').sort_values( -# by=['age'], -# ascending=True, ignore_index=True) -# # assign each age to an age cohort -# bd_persons_age_vehicle_choice['ageCohort'] = pd.cut(bd_persons_age_vehicle_choice['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ -# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -# # plot a cake chart for each age cohort -# bd_persons_age_vehicle_choice_cake = bd_persons_age_vehicle_choice.groupby( -# ['ageCohort', 'vehicleChoice']).sum().reset_index() -# bd_persons_age_vehicle_choice_cake_age_veh = bd_persons_age_vehicle_choice_cake.pivot( -# index='ageCohort', columns='vehicleChoice', values='counts') -# bd_persons_age_vehicle_choice_cake_age_veh.plot.pie(subplots=True, layout=(3, 2), figsize=( -# 10, 10), title=bd_persons_age_vehicle_choice_cake_age_veh.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'vehicle_choice_per_age.png'), dpi=300) - -# # switch age cohort and vehicle choice -# bd_persons_age_vehicle_choice_cake_veh_age = bd_persons_age_vehicle_choice_cake.pivot( -# index='vehicleChoice', columns='ageCohort', values='counts') -# bd_persons_age_vehicle_choice_cake_veh_age.plot.pie(subplots=True, layout=(3, 3), figsize=( -# 20, 10), title=bd_persons_age_vehicle_choice_cake_veh_age.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'vehicle_choice_reversed.png'), dpi=300) - -# # Analyse trip purposes per age cohort -# bd_persons_age_purpose = bd.loc[:, ['personID', 'age', 'ActivityAfter']] -# bd_persons_age_purpose['ActivityAfter'] = bd_persons_age_purpose['ActivityAfter'].map( -# dict_leisure) -# bd_persons_age_purpose['ageCohort'] = pd.cut(bd_persons_age_purpose['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ -# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -# bd_persons_age_purpose_acc = bd_persons_age_purpose.groupby( -# ['ActivityAfter', 'ageCohort']).size().reset_index(name='counts') -# bd_persons_age_purpose_cake = bd_persons_age_purpose_acc.pivot( -# index='ageCohort', columns='ActivityAfter', values='counts') -# bd_persons_age_purpose_cake.plot.pie(subplots=True, layout=(2, 4), figsize=( -# 15, 5), title=bd_persons_age_purpose_cake.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'trip_purpose.png'), dpi=300) - -# # switch age cohorts and purpose -# bd_persons_age_purpose_cake_reversed = bd_persons_age_purpose_acc.pivot( -# index='ActivityAfter', columns='ageCohort', values='counts') -# bd_persons_age_purpose_cake_reversed.plot.pie(subplots=True, layout=(2, 5), figsize=( -# 15, 5), title=bd_persons_age_purpose_cake_reversed.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'trip_purpose_reversed.png'), dpi=300) - -# # Count traffic zones where people are starting their trips -# bd_traffic_zones_start = bd.groupby(['startZone']).size().reset_index( -# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# for row in bd_traffic_zones_start.iterrows(): -# bd_traffic_zones_start.loc[row[0], ['longitude', 'latitude'] -# ] = bd.loc[bd_traffic_zones_start.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] -# print(bd_traffic_zones_start) - -# # plot longitude and latitude of traffic zones -# bd_traffic_zones_start.plot( -# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_start['counts'] / 100, figsize=(10, 15), -# title='Traffic zones where people are starting their trips (Braunschweig)') -# plt.savefig(os.path.join(figs_path, 'traffic_zones_start.png'), dpi=300) - -# # Count traffic zones where people are going and leaving -# bd_traffic_zones_end = bd.groupby(['destZone']).size().reset_index( -# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# for row in bd_traffic_zones_end.iterrows(): -# bd_traffic_zones_end.loc[row[0], ['longitude', 'latitude'] -# ] = bd.loc[bd_traffic_zones_end.loc[row[0], 'destZone'] == bd['destZone'], ['loCs', 'laCs']].values[0] -# print(bd_traffic_zones_end) - -# # plot longitude and latitude of traffic zones -# bd_traffic_zones_end.plot( -# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_end['counts'] / 100, figsize=(10, 10), -# title='Traffic zones where people are ending their trips (Braunschweig)') -# plt.savefig(os.path.join(figs_path, 'traffic_zones_end.png'), dpi=300) - -# # Time analyzing -# # Time of day -# bd_time = bd.groupby(['startTime']).size().reset_index(name='counts') -# print(bd_time) -# bd_time.plot(kind='line', x='startTime', y='counts') -# plt.xlabel('Time of day') -# plt.ylabel('Number of trips') -# plt.title('Time of day (Braunschweig)' + ' (n = ' + str(len(bd)) + ' trips)') -# plt.savefig(os.path.join(figs_path, 'time_of_day.png'), dpi=300) - -# # time of day rolling average -# bd_time['rolling_mean'] = bd_time['counts'].rolling(window=7).mean() -# bd_time.plot(kind='line', x='startTime', y='rolling_mean') -# plt.xlabel('Time of day') -# plt.ylabel('Number of trips') -# plt.title('Time of day (Braunschweig)' + ' (n = ' + -# str(len(bd)) + ' trips), rolling mean with window size 7') -# plt.savefig(os.path.join(figs_path, 'time_of_day_rolling.png'), dpi=300) - -# # Frequency matrix of trips between traffic zones -# matrix_freq = pd.crosstab(bd['startZone'], bd['destZone']) -# nnz_matrix_freq = np.count_nonzero(matrix_freq) -# subset_matrix_freq = matrix_freq.iloc[0:30, 0:30] -# nnz_sub_matrix_freq = np.count_nonzero(subset_matrix_freq) -# sns.heatmap(subset_matrix_freq, cmap="Blues", vmin=0) -# plt.xlabel('Destination traffic zone') -# plt.ylabel('Start traffic zone') -# plt.title('Number of non-zero entries in frequency matrix: ' + str(nnz_sub_matrix_freq) + ' out of ' + str(subset_matrix_freq.size) + ' entries (' + -# str(round(nnz_sub_matrix_freq / subset_matrix_freq.size * 100, 2)) + '%)') -# plt.savefig(os.path.join(figs_path, 'heatmap.png'), dpi=300) - -# # frequency matrix of trips from which leisure activity to which leisure activity - -# # check if all activities of bd activity before are in the dictionary -# if bd['ActivityBefore'].isin(dict_leisure.keys()).all(): -# print('All activities in dictionary') -# # check if there is a activity missing that is in the dictionary -# if not set(dict_leisure.keys()).issubset(set(bd['ActivityBefore'].unique())): -# print('There is an activity missing that is in the dictionary:') -# for key in (set(dict_leisure.keys()).difference(set(bd['ActivityBefore'].unique()))): -# print(key, dict_leisure[key]) - - -# matrix_frqu_leisure = pd.crosstab( -# bd['ActivityBefore'], -# bd['ActivityAfter'], -# normalize='index') -# sns.heatmap(matrix_frqu_leisure, vmin=0, xticklabels=dict_leisure.values(), -# yticklabels=dict_leisure.values()) -# plt.xlabel('Leisure activity after trip') -# plt.ylabel('Leisure activity before trip') -# plt.title('Frequency of trips from which leisure activity to which leisure activity') -# plt.savefig(os.path.join(figs_path, 'heatmap_leisure.png'), dpi=300) - - -# # quick check if a data point in the matrix is correct -# check = bd.loc[(bd['startZone'] == 31010011) & ( -# bd['destZone'] == 31010011), 'startZone'].count() - - -# # plotting the duration of trips -# fig, axs = plt.subplots(2) -# axs[0].hist(bd['travelTime']/60/60, bins=100, -# range=(0, max(bd['travelTime'])*1.2/60/60)) -# axs[0].set_title('Trip duration (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips)') -# axs[0].set_xlabel('Trip duration in hours') -# axs[0].set_ylabel('Number of trips') -# axs[1].hist(bd['travelTime']/60/60, bins=100, -# range=(0, max(bd['travelTime'])*1.2/60/60)) -# axs[1].set_yscale('log') -# axs[1].set_title('Trip duration (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips) log scale') -# axs[1].set_xlabel('Trip duration in hours') -# axs[1].set_ylabel('Number of trips') - -# # same thing with the distance of the trips -# fig2, axs2 = plt.subplots(2) -# axs2[0].hist(bd['tripDistance'], bins=100, -# range=(0, max(bd['tripDistance'])*1.2,)) -# axs2[0].set_title('Trip distance (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips)') -# axs2[0].set_xlabel('Trip distance in Kilometers') -# axs2[0].set_ylabel('Number of trips') -# axs2[1].hist(bd['tripDistance'], bins=100, -# range=(0, max(bd['tripDistance'])*1.2,)) -# axs2[1].set_yscale('log') -# axs2[1].set_title('Trip distance (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips) log scale') -# axs2[1].set_xlabel('Trip distance in Kilometers') -# axs2[1].set_ylabel('Number of trips') - - -# # analyze age distribution with age cohorts -# bd_persons_id_and_age = bd[['personID', 'age']].drop_duplicates() -# bd_age_cohorts = pd.cut( -# bd_persons_id_and_age['age'], -# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95, 106], -# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95', '96-105']).reset_index( -# name='age_cohort').groupby( -# ['age_cohort']).size().reset_index( -# name='counts') -# bd_age_cohorts.plot(kind='bar', x='age_cohort', y='counts') -# plt.xlabel('Age cohort') -# plt.ylabel('Number of persons') -# plt.title('Age distribution of persons in Braunschweig in age cohorts, number ') -# plt.savefig(os.path.join(figs_path, 'age_cohorts.png'), dpi=300) +# get the id with the persons with the highest number and print them +[id_person_max_trips, id_person_max_1_trips] = [ + bd_persons['personID'][0], bd_persons['personID'][1]] +print('Person with the highest number of trips: ' + str(id_person_max_trips) + '. Number of trips: ' + + str(bd_persons['counts'][0]) + '. \n') + +# select internal and external trips (from/to Braunschweig) +bd_persons_inside_bs = bd[(bd['startZone']>=31010001) & (bd['startZone']<=31019999) & (bd['destZone']>=31010001) & (bd['destZone']<=31019999)] +bd_persons_outside_bs = bd[((~bd['startZone']>=31010001) | (~bd['startZone']<=31019999)) & ((~bd['destZone']>=31010001) | (~bd['destZone']<=31019999))] + +# check how many trips are in the same traffic zone +bd_taz_start = bd.groupby('startZone').size().reset_index(name='counts') +#bd_same_taz = bd.loc[bd['startZone'] == bd['destZone']] +bd_different_taz = bd.loc[bd['startZone'] != bd['destZone']] +#bd_same_taz = bd_same_taz.groupby(['startZone']).size().reset_index(name='counts') +bd_different_taz = bd_different_taz.groupby( + ['startZone']).size().reset_index(name='counts') +#bd_same_taz['percentage'] = bd_same_taz['counts']/bd_taz_start['counts'] +bd_different_taz['complement_counts'] = bd_taz_start['counts'] - \ + bd_different_taz['counts'] +bd_different_taz['total_counts'] = bd_taz_start['counts'] +bd_different_taz = (bd_different_taz.sort_values( + by='total_counts', ascending=False, ignore_index=True)) +plt.figure() +plt.plot(bd_different_taz['counts']) +plt.plot(bd_different_taz['complement_counts']) +plt.legend(['different TAZ', 'same TAZ']) +plt.xlabel('Traffic analysis zones') +plt.ylabel('Amount of trips inside/outside a TAZ') +plt.savefig(os.path.join(figs_path, 'TAZ_distribution.png'), dpi=300) + +# which age takes which mode of transport +bd_persons_age_vehicle_choice = bd.loc[:, ['personID', 'age', 'vehicleChoice']].sort_values( + by=['age'], ascending=True, ignore_index=True) +bd_persons_age_vehicle_choice['vehicleChoice'] = bd_persons_age_vehicle_choice['vehicleChoice'].map( + dict_vehicle) +# accumulate the number of trips per age and vehicle choice +bd_persons_age_vehicle_choice = bd_persons_age_vehicle_choice.groupby( + ['age', 'vehicleChoice']).size().reset_index( + name='counts').sort_values( + by=['age'], + ascending=True, ignore_index=True) +# assign each age to an age cohort +bd_persons_age_vehicle_choice['ageCohort'] = pd.cut(bd_persons_age_vehicle_choice['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ + '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +# plot a cake chart for each age cohort +bd_persons_age_vehicle_choice_cake = bd_persons_age_vehicle_choice.groupby( + ['ageCohort', 'vehicleChoice']).sum().reset_index() +bd_persons_age_vehicle_choice_cake_age_veh = bd_persons_age_vehicle_choice_cake.pivot( + index='ageCohort', columns='vehicleChoice', values='counts') +bd_persons_age_vehicle_choice_cake_age_veh.plot.pie(subplots=True, layout=(3, 2), figsize=( + 10, 10), title=bd_persons_age_vehicle_choice_cake_age_veh.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'vehicle_choice_per_age.png'), dpi=300) + +# switch age cohort and vehicle choice +bd_persons_age_vehicle_choice_cake_veh_age = bd_persons_age_vehicle_choice_cake.pivot( + index='vehicleChoice', columns='ageCohort', values='counts') +bd_persons_age_vehicle_choice_cake_veh_age.plot.pie(subplots=True, layout=(3, 3), figsize=( + 20, 10), title=bd_persons_age_vehicle_choice_cake_veh_age.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'vehicle_choice_reversed.png'), dpi=300) + +# Analyse trip purposes per age cohort +bd_persons_age_purpose = bd.loc[:, ['personID', 'age', 'ActivityAfter']] +bd_persons_age_purpose['ActivityAfter'] = bd_persons_age_purpose['ActivityAfter'].map( + dict_leisure) +bd_persons_age_purpose['ageCohort'] = pd.cut(bd_persons_age_purpose['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ + '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) +bd_persons_age_purpose_acc = bd_persons_age_purpose.groupby( + ['ActivityAfter', 'ageCohort']).size().reset_index(name='counts') +bd_persons_age_purpose_cake = bd_persons_age_purpose_acc.pivot( + index='ageCohort', columns='ActivityAfter', values='counts') +bd_persons_age_purpose_cake.plot.pie(subplots=True, layout=(2, 4), figsize=( + 15, 5), title=bd_persons_age_purpose_cake.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'trip_purpose.png'), dpi=300) + +# switch age cohorts and purpose +bd_persons_age_purpose_cake_reversed = bd_persons_age_purpose_acc.pivot( + index='ActivityAfter', columns='ageCohort', values='counts') +bd_persons_age_purpose_cake_reversed.plot.pie(subplots=True, layout=(2, 5), figsize=( + 15, 5), title=bd_persons_age_purpose_cake_reversed.columns.to_list(), legend=False, ylabel='') +plt.savefig(os.path.join(figs_path, 'trip_purpose_reversed.png'), dpi=300) + +# Count traffic zones where people are starting their trips +bd_traffic_zones_start = bd.groupby(['startZone']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +for row in bd_traffic_zones_start.iterrows(): + bd_traffic_zones_start.loc[row[0], ['longitude', 'latitude'] + ] = bd.loc[bd_traffic_zones_start.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] +print(bd_traffic_zones_start) + +#take out the traffic zones that have long and lat 0 +bd_traffic_zones_start = bd_traffic_zones_start.loc[bd_traffic_zones_start['longitude'] > 100000] +bd_traffic_zones_start = bd_traffic_zones_start.loc[bd_traffic_zones_start['latitude'] >100000] + +# plot longitude and latitude of traffic zones +bd_traffic_zones_start.plot( + kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_start['counts'] / 100, figsize=(10, 15), + title='Traffic zones where people are starting their trips (Braunschweig)') +plt.savefig(os.path.join(figs_path, 'traffic_zones_start.png'), dpi=300) + +# Count traffic zones where people are going and leaving +bd_traffic_zones_end = bd.groupby(['destZone']).size().reset_index( + name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +for row in bd_traffic_zones_end.iterrows(): + bd_traffic_zones_end.loc[row[0], ['longitude', 'latitude'] + ] = bd.loc[bd_traffic_zones_end.loc[row[0], 'destZone'] == bd['destZone'], ['loCs', 'laCs']].values[0] +print(bd_traffic_zones_end) + +# plot longitude and latitude of traffic zones +bd_traffic_zones_end.plot( + kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_end['counts'] / 100, figsize=(10, 10), + title='Traffic zones where people are ending their trips (Braunschweig)') +plt.savefig(os.path.join(figs_path, 'traffic_zones_end.png'), dpi=300) + +# Time analyzing +# Time of day +bd_time = bd.groupby(['startTime']).size().reset_index(name='counts') +print(bd_time) +bd_time.plot(kind='line', x='startTime', y='counts') +plt.xlabel('Time of day') +plt.ylabel('Number of trips') +plt.title('Time of day (Braunschweig)' + ' (n = ' + str(len(bd)) + ' trips)') +plt.savefig(os.path.join(figs_path, 'time_of_day.png'), dpi=300) + +# time of day rolling average +bd_time['rolling_mean'] = bd_time['counts'].rolling(window=7).mean() +bd_time.plot(kind='line', x='startTime', y='rolling_mean') +plt.xlabel('Time of day') +plt.ylabel('Number of trips') +plt.title('Time of day (Braunschweig)' + ' (n = ' + + str(len(bd)) + ' trips), rolling mean with window size 7') +plt.savefig(os.path.join(figs_path, 'time_of_day_rolling.png'), dpi=300) + +# Frequency matrix of trips between traffic zones +matrix_freq = pd.crosstab(bd['startZone'], bd['destZone']) +nnz_matrix_freq = np.count_nonzero(matrix_freq) +subset_matrix_freq = matrix_freq.iloc[0:30, 0:30] +nnz_sub_matrix_freq = np.count_nonzero(subset_matrix_freq) +sns.heatmap(subset_matrix_freq, cmap="Blues", vmin=0) +plt.xlabel('Destination traffic zone') +plt.ylabel('Start traffic zone') +plt.title('Number of non-zero entries in frequency matrix: ' + str(nnz_sub_matrix_freq) + ' out of ' + str(subset_matrix_freq.size) + ' entries (' + + str(round(nnz_sub_matrix_freq / subset_matrix_freq.size * 100, 2)) + '%)') +plt.savefig(os.path.join(figs_path, 'heatmap.png'), dpi=300) + +# frequency matrix of trips from which leisure activity to which leisure activity + +# check if all activities of bd activity before are in the dictionary +if bd['ActivityBefore'].isin(dict_leisure.keys()).all(): + print('All activities in dictionary') +# check if there is a activity missing that is in the dictionary +if not set(dict_leisure.keys()).issubset(set(bd['ActivityBefore'].unique())): + print('There is an activity missing that is in the dictionary:') + for key in (set(dict_leisure.keys()).difference(set(bd['ActivityBefore'].unique()))): + print(key, dict_leisure[key]) + + +matrix_frqu_leisure = pd.crosstab( + bd['ActivityBefore'], + bd['ActivityAfter'], + normalize='index') +sns.heatmap(matrix_frqu_leisure, vmin=0, xticklabels=dict_leisure.values(), + yticklabels=dict_leisure.values()) +plt.xlabel('Leisure activity after trip') +plt.ylabel('Leisure activity before trip') +plt.title('Frequency of trips from which leisure activity to which leisure activity') +plt.savefig(os.path.join(figs_path, 'heatmap_leisure.png'), dpi=300) + + +# plotting the duration of trips +fig, axs = plt.subplots(2) +axs[0].hist(bd['travelTime']/60/60, bins=100, + range=(0, max(bd['travelTime'])*1.2/60/60)) +axs[0].set_title('Trip duration (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips)') +axs[0].set_xlabel('Trip duration in hours') +axs[0].set_ylabel('Number of trips') +axs[1].hist(bd['travelTime']/60/60, bins=100, + range=(0, max(bd['travelTime'])*1.2/60/60)) +axs[1].set_yscale('log') +axs[1].set_title('Trip duration (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips) log scale') +axs[1].set_xlabel('Trip duration in hours') +axs[1].set_ylabel('Number of trips') + +# same thing with the distance of the trips +fig2, axs2 = plt.subplots(2) +axs2[0].hist(bd['tripDistance'], bins=100, + range=(0, max(bd['tripDistance'])*1.2,)) +axs2[0].set_title('Trip distance (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips)') +axs2[0].set_xlabel('Trip distance in Kilometers') +axs2[0].set_ylabel('Number of trips') +axs2[1].hist(bd['tripDistance'], bins=100, + range=(0, max(bd['tripDistance'])*1.2,)) +axs2[1].set_yscale('log') +axs2[1].set_title('Trip distance (Braunschweig)' + + ' (n = ' + str(len(bd)) + ' trips) log scale') +axs2[1].set_xlabel('Trip distance in Kilometers') +axs2[1].set_ylabel('Number of trips') + + +# analyze age distribution with age cohorts +bd_persons_id_and_age = bd[['personID', 'age']].drop_duplicates() +bd_age_cohorts = pd.cut( + bd_persons_id_and_age['age'], + bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95, 106], + labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95', '96-105']).reset_index( + name='age_cohort').groupby( + ['age_cohort']).size().reset_index( + name='counts') +bd_age_cohorts.plot(kind='bar', x='age_cohort', y='counts') +plt.xlabel('Age cohort') +plt.ylabel('Number of persons') +plt.title('Age distribution of persons in Braunschweig in age cohorts, number ') +plt.savefig(os.path.join(figs_path, 'age_cohorts.png'), dpi=300) # # relation between age and trip duration in minutes and hours # bd_age_duration = bd.groupby(['age']).mean().reset_index() @@ -459,118 +414,71 @@ # bd_age_distance = bd.groupby(['age']).mean().reset_index() # bd_age_distance.plot(kind='bar', x='age', y='tripDistance') -# # analyze trip distance in distance cohort -# bd_trip_distance_cohorts = pd.cut( -# bd['tripDistance'], -# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], -# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( -# name='trip_distance_cohort').groupby( -# ['trip_distance_cohort']).size().reset_index( -# name='counts') -# bd_trip_distance_cohorts.plot(kind='bar', x='trip_distance_cohort', y='counts') -# plt.xlabel('Trip distance cohort in km') -# plt.ylabel('Number of trips') -# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + str(len(bd))) -# plt.savefig(os.path.join(figs_path, 'trip_distance_cohorts.png'), dpi=300) - -# # pie diagram of trip distance cohorts for each age cohort -# bd_trip_distance_cohorts_vehicle = pd.cut( -# bd['tripDistance'], -# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], -# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( -# name='trip_distance_cohort') -# bd_age_cohorts = pd.cut(bd['age'], -# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95], -# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95']).reset_index( -# name='age_cohort') -# # attach the age cohort to the dataframe -# bd_trip_distance_cohorts_vehicle = pd.concat( -# [bd_trip_distance_cohorts_vehicle['trip_distance_cohort'], bd_age_cohorts['age_cohort']], axis=1) -# # group by age cohort and distance cohort -# bd_trip_distance_cohorts_vehicle = bd_trip_distance_cohorts_vehicle.groupby( -# ['trip_distance_cohort', 'age_cohort']).size().reset_index(name='counts') -# # plot a pie chart for each age cohort -# for age_cohort in bd_trip_distance_cohorts_vehicle['age_cohort'].unique(): -# bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort].plot( -# kind='pie', y='counts', labels=bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort]['trip_distance_cohort'], autopct='%1.1f%%', startangle=90) -# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + -# str(len(bd)) + ' for age cohort ' + age_cohort) -# plt.savefig(os.path.join( -# figs_path, 'trip_distance_cohorts_' + age_cohort + '.png'), dpi=300) - -# # now the same for trip duration vs vehicle type -# bd_trip_duration_cohorts_vehicle = pd.cut( -# bd['travelTime'], -# bins=[-1, 500, 1000, 5000, 10000, 423789798324], -# labels=['0-500', '500-1000', '1000-5000', '5000-10000', '10000+']).reset_index( -# name='trip_duration_cohort') -# bd_vehicle_type = bd['vehicleChoice'].reset_index(name='vehicleChoice') -# # attach the age cohort to the dataframe -# bd_trip_duration_cohorts_vehicle = pd.concat( -# [bd_trip_duration_cohorts_vehicle['trip_duration_cohort'], bd_vehicle_type['vehicleChoice']], axis=1) -# # group by age cohort and distance cohort -# bd_trip_duration_cohorts_vehicle = bd_trip_duration_cohorts_vehicle.groupby( -# ['trip_duration_cohort', 'vehicleChoice']).size().reset_index(name='counts') -# # plot a pie chart for each age cohort -# for vehicle_type in bd_trip_duration_cohorts_vehicle['vehicleChoice'].unique(): -# bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type].plot( -# kind='pie', y='counts', labels=bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type]['trip_duration_cohort'], autopct='%1.1f%%', startangle=90) -# plt.title('Trip duration distribution in Braunschweig in trip duration cohorts, in minutes. Number of trips: ' + str(len(bd) -# ) + ' for vehicle type ' + str(dict_vehicle[vehicle_type])) -# plt.savefig(os.path.join(figs_path, 'trip_duration_cohorts_' + -# str(dict_vehicle[vehicle_type]) + '.png'), dpi=300) - - -# # also do a scatter plot of trip duration and trip distance with a regression line -# bd_age_distance.plot(kind='scatter', x='age', y='tripDistance') -# plt.plot(np.unique(bd_age_distance['age']), np.poly1d(np.polyfit(bd_age_distance['age'], -# bd_age_distance['tripDistance'], 1))(np.unique(bd_age_distance['age']))) -# bd_age_duration.plot(kind='scatter', x='age', y='travelTime') -# plt.plot(np.unique(bd_age_duration['age']), np.poly1d(np.polyfit( -# bd_age_duration['age'], bd_age_duration['travelTime'], 1))(np.unique(bd_age_duration['age']))) -# plt.show() - -# ### draft to compute number of locations of type 6? -# x = bd[bd.ActivityAfter==6].loc[:, 'loc_id_end'].nunique() -# # downscaling of locations of type 6 to 2000 agents -# x / (bd['personID'].nunique()/2000) - -# x = 42 - - - - -## draft to add collumn to check if the location in Braunschweig -# bd['home_in_bs'] = 0 -# #list of persons who are in braunschweig -# list_person_in_bs = np.array([]) -# for index, row in bd.iterrows(): -# if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): -# list_person_in_bs = np.append(list_person_in_bs, row['personID']) -# #drop duplicates -# list_person_in_bs = np.unique(list_person_in_bs) -# for index, row in bd.iterrows(): -# if row['personID'] in list_person_in_bs: -# bd.at[index, 'home_in_bs'] = 1 -# -# bd.to_csv('modified_braunschweig_result.csv', index=False) - -#count number of trips which are in braunschweig -# bs_trip_count = 0 -# for index, row in bd.iterrows(): -# if ((row['countyStart']==3101) or (row['countyEnd']==3101 )): -# bs_trip_count = bs_trip_count+1 - -# #percentage of trips in braunschweigx -# bs_trip_count/len(bd)*100 - -# count how many persons are in braunschweig -# bs_person_count = 0 -# # collapse all persons to one trip and check if the trip is in braunschweig -# persons_in_bs = bd[['personID', 'home_in_bs']].drop_duplicates().groupby(['personID']).aggregate('sum').reset_index() -# # percentage number of persons in braunschweig is persons with not zero home_in_bs / all persons -# persons_in_bs.loc[persons_in_bs['home_in_bs']==0].size/persons_in_bs.size*100 - +# analyze trip distance in distance cohort +bd_trip_distance_cohorts = pd.cut( + bd['tripDistance'], + bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], + labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( + name='trip_distance_cohort').groupby( + ['trip_distance_cohort']).size().reset_index( + name='counts') +bd_trip_distance_cohorts.plot(kind='bar', x='trip_distance_cohort', y='counts') +plt.xlabel('Trip distance cohort in km') +plt.ylabel('Number of trips') +plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + str(len(bd))) +plt.savefig(os.path.join(figs_path, 'trip_distance_cohorts.png'), dpi=300) + +# pie diagram of trip distance cohorts for each age cohort +bd_trip_distance_cohorts_vehicle = pd.cut( + bd['tripDistance'], + bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], + labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( + name='trip_distance_cohort') +bd_age_cohorts = pd.cut(bd['age'], + bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95], + labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95']).reset_index( + name='age_cohort') +# attach the age cohort to the dataframe +bd_trip_distance_cohorts_vehicle = pd.concat( + [bd_trip_distance_cohorts_vehicle['trip_distance_cohort'], bd_age_cohorts['age_cohort']], axis=1) +# group by age cohort and distance cohort +bd_trip_distance_cohorts_vehicle = bd_trip_distance_cohorts_vehicle.groupby( + ['trip_distance_cohort', 'age_cohort']).size().reset_index(name='counts') +# plot a pie chart for each age cohort +for age_cohort in bd_trip_distance_cohorts_vehicle['age_cohort'].unique(): + bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort].plot( + kind='pie', y='counts', labels=bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort]['trip_distance_cohort'], autopct='%1.1f%%', startangle=90) + plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + + str(len(bd)) + ' for age cohort ' + age_cohort) + plt.savefig(os.path.join( + figs_path, 'trip_distance_cohorts_' + age_cohort + '.png'), dpi=300) + +# now the same for trip duration vs vehicle type +bd_trip_duration_cohorts_vehicle = pd.cut( + bd['travelTime'], + bins=[-1, 500, 1000, 5000, 10000, 423789798324], + labels=['0-500', '500-1000', '1000-5000', '5000-10000', '10000+']).reset_index( + name='trip_duration_cohort') +bd_vehicle_type = bd['vehicleChoice'].reset_index(name='vehicleChoice') +# attach the age cohort to the dataframe +bd_trip_duration_cohorts_vehicle = pd.concat( + [bd_trip_duration_cohorts_vehicle['trip_duration_cohort'], bd_vehicle_type['vehicleChoice']], axis=1) +# group by age cohort and distance cohort +bd_trip_duration_cohorts_vehicle = bd_trip_duration_cohorts_vehicle.groupby( + ['trip_duration_cohort', 'vehicleChoice']).size().reset_index(name='counts') +# plot a pie chart for each age cohort +for vehicle_type in bd_trip_duration_cohorts_vehicle['vehicleChoice'].unique(): + bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type].plot( + kind='pie', y='counts', labels=bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type]['trip_duration_cohort'], autopct='%1.1f%%', startangle=90) + plt.title('Trip duration distribution in Braunschweig in trip duration cohorts, in minutes. Number of trips: ' + str(len(bd) + ) + ' for vehicle type ' + str(dict_vehicle[vehicle_type])) + plt.savefig(os.path.join(figs_path, 'trip_duration_cohorts_' + + str(dict_vehicle[vehicle_type]) + '.png'), dpi=300) + +# draft to compute number of locations of type 6? +x = bd[bd.ActivityAfter==6].loc[:, 'loc_id_end'].nunique() +# downscaling of locations of type 6 to 2000 agents +x / (bd['personID'].nunique()/2000) x=1 diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 21c687398a..1a3a397507 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -193,7 +193,7 @@ void split_line(std::string string, std::vector* row) return longLatToInt(s); } else if (s == "null") { - return 10; // This shouldnt be too often, just assume a short time after 12:00 o'clock for now + return 43200; // This shouldnt be too often, we will take 12 o'clock as default } else { return std::stoi(s); @@ -587,7 +587,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.66; + params.get() = 0.66; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -932,7 +932,7 @@ void write_log_to_file_trip_data(const T& history) int start_index = movement_data_index - 1; using Type = std::tuple; + mio::abm::ActivityType, mio::abm::InfectionState>; while (!std::binary_search(std::begin(movement_data[start_index]), std::end(movement_data[start_index]), movement_data[movement_data_index][trip_index], [](const Type& v1, const Type& v2) { @@ -1181,8 +1181,84 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Advance the world to tmax // sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, // historyPersonInfDelta, historyInfectionStatePerAgeGroup); + + //// Advance the world with respective npis + //1. testing schemes in schools + auto testing_min_time_school = mio::abm::days(7); + auto probability_school = 1.0; + auto start_date_test_school = mio::abm::TimePoint(42); // 2021-04-12 + auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 + auto test_type_school = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters = world.parameters.get()[test_type_school]; // Test parameters + auto testing_criteria_school = mio::abm::TestingCriteria(); + auto testing_scheme_school = + mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, + end_date_test_school, test_parameters, probability_school); + world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); + + //2. testing schemes in work places for 35% of random workplaces + auto location_it = world.get_locations(); + std::vector work_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::Work) { + work_location_ids.push_back(location.get_index()); + } + } + //take 35% of work locations + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); + auto num_work_locations = (int)(0.35 * work_location_ids.size()); + std::vector work_location_ids_35(work_location_ids.begin(), + work_location_ids.begin() + num_work_locations); + auto testing_min_time_work = mio::abm::days(1); + auto probability_work = 1.0; + auto start_date_test_work = mio::abm::TimePoint(0); + auto end_date_test_work = mio::abm::TimePoint(tmax); + auto test_type_work = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_work = world.parameters.get()[test_type_work]; // Test parameters + auto testing_criteria_work = mio::abm::TestingCriteria(); + auto testing_scheme_work = + mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, + end_date_test_work, test_parameters_work, probability_work); + for (auto& location : location_it) { + if (std::find(work_location_ids_35.begin(), work_location_ids_35.end(), location.get_index()) != + work_location_ids_35.end()) { + world.get_testing_strategy().add_testing_scheme(location.get_type(), testing_scheme_work); + } + } + + //3. Mask schemes for all locations + //First set all locations to have mask usage, we need ffp2 masks + for (auto& location : location_it) { + location.set_required_mask(mio::abm::MaskType::FFP2); + if (location.get_type() == mio::abm::LocationType::Home) { + location.set_npi_active(false); + } + else { + location.set_npi_active(true); + } + } + + sim.advance(mio::abm::TimePoint(42), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + historyInfectionPerAgeGroup); + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(false); + } + } + sim.advance(mio::abm::TimePoint(72), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + historyInfectionPerAgeGroup); + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(true); + } + } sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); + + ////Advance till here + // Stop the clock after sim.advance and calculate the duration // auto stop2 = std::chrono::high_resolution_clock::now(); // auto duration2 = std::chrono::duration(stop2 - start2); From c52a212dcff1654fa1a00a68ad9bb87e80f4ed91 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Thu, 16 May 2024 11:50:07 +0200 Subject: [PATCH 111/488] Add function add_new_vaccination()in Person and optimise get_latest_protection() --- cpp/models/abm/person.cpp | 49 ++++++++++++++++++++++------------- cpp/models/abm/person.h | 6 +++++ cpp/tests/test_abm_person.cpp | 23 +++++++++++++++- 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index e47c699759..04c786efd5 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -112,6 +112,18 @@ void Person::add_new_infection(Infection&& inf) m_infections.push_back(std::move(inf)); } +void Person::add_new_vaccination(Vaccination&& vacc) +{ + // Find the correct insertion point + auto it = std::lower_bound(m_vaccinations.begin(), m_vaccinations.end(), vacc.time, + [](const Vaccination& a, const TimePoint& b) { + return a.time < b; + }); + + // Insert the new vaccination at the found position + m_vaccinations.emplace(it, std::move(vacc)); +} + Location& Person::get_location() { return *m_location; @@ -273,30 +285,31 @@ bool Person::apply_mask_intervention(RandomNumberGenerator& rng, const Location& std::pair Person::get_latest_protection(TimePoint t) const { ExposureType latest_exposure_type = ExposureType::NoProtection; - TimePoint infection_time = TimePoint(std::numeric_limits::min()); + TimePoint latest_time = TimePoint(std::numeric_limits::min()); - // Look for any Infection that happens before time t - for(const Infection& infection : m_infections) { - if (infection.get_start_date() <= t) { + // Use reverse iterators to start from the most recent infection + for (auto it = m_infections.rbegin(); it != m_infections.rend(); ++it) { + if (it->get_start_date() <= t) { latest_exposure_type = ExposureType::NaturalInfection; - infection_time = infection.get_start_date(); - } else { - break; + latest_time = it->get_start_date(); + break; // Stop once we find the latest infection before time t } } - // Look for any Vaccination that happens between the lastest Infection and time t - for(const Vaccination& vaccination : m_vaccinations) { - if (vaccination.time <= t && vaccination.time > infection_time) { - latest_exposure_type = vaccination.exposure_type; - infection_time = vaccination.time; - } - if (vaccination.time > t) { - break; - } + // Look for any Vaccination that happens after the latest Infection and before time t + for (auto it = m_vaccinations.rbegin(); it != m_vaccinations.rend(); ++it) { + if (it->time <= t) { + if (it->time > latest_time) { + latest_exposure_type = it->exposure_type; + latest_time = it->time; + } + } + else { + break; // Stop once we find a vaccination after time t + } } - - return std::make_pair(latest_exposure_type, infection_time); + + return std::make_pair(latest_exposure_type, latest_time); } ScalarType Person::get_protection_factor(TimePoint t, VirusVariant virus, const Parameters& params) const diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index ce1ba171ed..9b334ce7a0 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -214,6 +214,12 @@ class Person */ void add_new_infection(Infection&& inf); + /** + * @brief Adds a new Vaccination to the list of Vaccination%s that is sorted in vaccination time. + * @param[in] vacc The new Vaccination. + */ + void add_new_vaccination(Vaccination&& vacc); + /** * @brief Get the AgeGroup of this Person. * @return AgeGroup of the Person. diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index 74369e63ca..f8625d3acd 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -304,12 +304,18 @@ TEST(TestPerson, getLatestProtection) ASSERT_EQ(latest_protection.first, mio::abm::ExposureType::GenericVaccine); ASSERT_EQ(latest_protection.second.days(), t.days()); - t = mio::abm::TimePoint(40 * 24 * 60 * 60); + t = mio::abm::TimePoint(10 * 24 * 60 * 60); person.add_new_infection(mio::abm::Infection(prng, static_cast(0), age_group_15_to_34, params, t, mio::abm::InfectionState::Exposed)); latest_protection = person.get_latest_protection(t); ASSERT_EQ(latest_protection.first, mio::abm::ExposureType::NaturalInfection); ASSERT_EQ(latest_protection.second.days(), t.days()); + + t = mio::abm::TimePoint(20 * 24 * 60 * 60); + person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t); + latest_protection = person.get_latest_protection(mio::abm::TimePoint(20 * 24 * 60 * 60 + 1)); + ASSERT_EQ(latest_protection.first, mio::abm::ExposureType::GenericVaccine); + ASSERT_EQ(latest_protection.second.days(), t.days()); } TEST(Person, rng) @@ -327,3 +333,18 @@ TEST(Person, rng) ASSERT_EQ(p.get_rng_counter(), mio::Counter(1)); ASSERT_EQ(p_rng.get_counter(), mio::rng_totalsequence_counter(13, mio::Counter{1})); } + +TEST(TestPerson, addNewVaccination) +{ + auto rng = mio::RandomNumberGenerator(); + auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); + auto person = mio::abm::Person(rng, location, age_group_15_to_34); + + auto t1 = mio::abm::TimePoint(0); + auto t2 = mio::abm::TimePoint(7 * 24 * 60 * 60); + person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t1); + person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t2); + auto vaccinations = person.get_vaccinations(); + ASSERT_EQ(vaccinations[0].time, t1); + ASSERT_EQ(vaccinations[1].time, t2); +} \ No newline at end of file From be51186f6a7b2c35fd8268ea0af61cda4188c9db Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 16 May 2024 16:12:07 +0200 Subject: [PATCH 112/488] Update entry_allowed function to include random number generator in Location class --- cpp/models/abm/location.cpp | 7 +++---- cpp/models/abm/location.h | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 4fc9cc5fc0..269567c088 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -47,7 +47,7 @@ void Location::add_damping(TimePoint t_begin, double p) temp_npi_damping.emplace_back(t_begin, p); } -bool Location::entry_allowed(const mio::abm::TimePoint t) const +bool Location::entry_allowed(Person::RandomNumberGenerator& rng,const mio::abm::TimePoint t) const { if (temp_npi_damping.empty()) { return true; @@ -60,9 +60,8 @@ bool Location::entry_allowed(const mio::abm::TimePoint t) const }); //then we want to access the second element of it, draw a random number between 0 and 1 and check if it is smaller than the damping factor //get a random number between 0 and 1 without m_rng - // double random_number = mio::UniformDistribution::get_instance()(); - // return random_number > it->second; - return true; + ScalarType random_number = UniformDistribution::get_instance()(rng,0.0,1.0); + return random_number > it->second; } } diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index e07af276d1..b9db59a44c 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -267,7 +267,7 @@ class Location */ void add_damping(TimePoint t, double p); - bool entry_allowed(const mio::abm::TimePoint t) const; + bool entry_allowed(Person::RandomNumberGenerator& rng,const mio::abm::TimePoint t) const; /** * @brief Set the required type of mask for entering this Location. @@ -431,7 +431,7 @@ class Location MaskType m_required_mask; ///< Least secure type of Mask that is needed to enter the Location. bool m_npi_active; ///< If true requires e.g. Mask%s to enter the Location. GeographicalLocation m_geographical_location; ///< Geographical location (longitude and latitude) of the Location. - std::vector> + std::vector> temp_npi_damping; ///< Temporary storage for NPI dampings. //TODO: delete these and implement better }; From ad805633526789572a1ff00b3658ad2dd26ce2c1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 16 May 2024 16:12:39 +0200 Subject: [PATCH 113/488] Add dampings and capacity limits to locations --- cpp/simulations/paper_abm_bs_testing.cpp | 45 +++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1a3a397507..6e52a26493 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1240,6 +1240,49 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } + //4. Dampings for all kinds of places + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::School) + { + location.add_damping(mio::abm::TimePoint(0), 0.5); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(14), 0.0); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(42), 0.5); // from 2021-04-12 till 2021-05-30 (end) + } + if(location.get_type() == mio::abm::LocationType::BasicsShop) + { + location.add_damping(mio::abm::TimePoint(14), 0.8); // from 2021-03-15 + } + } + + //5. add capacity limits to some locations + //first we need two lists, one for 50% of random social event locations and the other list for the other 50% + std::vector social_event_location_ids_small; + std::vector social_event_location_ids_big; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::SocialEvent) { + social_event_location_ids_small.push_back(location.get_index()); + } + } + //take 50% of social event locations + std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); + auto num_social_event_locations_small = (int)(0.5 * social_event_location_ids_small.size()); + social_event_location_ids_big.insert(social_event_location_ids_big.end(), social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_small); + social_event_location_ids_small.erase(social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_small); + + //add capacity limits on day one + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(10,0); + } + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + location.set_capacity(0,0); + } + } + sim.advance(mio::abm::TimePoint(42), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); for (auto& location : location_it) { @@ -1346,7 +1389,7 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From b987d2b6127995f52a166d859bf29ee46f13e111 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Fri, 17 May 2024 14:37:43 +0200 Subject: [PATCH 114/488] Remove function add_new_vaccination(ExposureType v, TimePoint t) --- cpp/models/abm/person.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index 9b334ce7a0..b4a2805e96 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -446,16 +446,6 @@ class Person */ ScalarType get_protection_factor(TimePoint t, VirusVariant virus, const Parameters& params) const; - /** - * @brief Add a new #Vaccination - * @param[in] v ExposureType (i. e. vaccine) the person takes. - * @param[in] t TimePoint of the Vaccination. - */ - void add_new_vaccination(ExposureType v, TimePoint t) - { - m_vaccinations.push_back(Vaccination(v, t)); - } - /** * @brief Get the transport mode the Person used to get to its current Location. * @return TransportMode the Person used to get to its current Location. From 579a37cc332ff49f647b7e7dc7d206f981aed40e Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <4763945+khoanguyen-dev@users.noreply.github.com> Date: Fri, 17 May 2024 16:28:05 +0200 Subject: [PATCH 115/488] Fix errors for add_new_vaccination() and add filter for the Persons that have home in Braunschweig --- cpp/models/abm/common_abm_loggers.h | 73 ++++++++++++------------ cpp/models/abm/parameters.h | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- cpp/tests/test_abm_infection.cpp | 4 +- cpp/tests/test_abm_person.cpp | 14 ++--- 5 files changed, 48 insertions(+), 47 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index d7e4a130d6..1173c48839 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -166,7 +166,7 @@ struct LogDataForMovement : mio::LogAlways { */ struct LogInfectionState : mio::LogAlways { using Type = std::pair; - // std::unordered_set ids_in_bs; + std::unordered_set ids_in_bs; /** * @brief Log the TimeSeries of the number of Person%s in an #InfectionState. @@ -177,27 +177,27 @@ struct LogInfectionState : mio::LogAlways { { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::InfectionState::Count)); auto curr_time = sim.get_time(); - // auto ids_in_bs = sim.get_world().parameters.get(); + auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. - // if (ids_in_bs.size() == 0) { - // PRAGMA_OMP(parallel for) - // for (auto&& location : sim.get_world().get_locations()) { - // for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { - // sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); - // } - // } - // } + if (ids_in_bs.size() == 0) { + for (auto&& location : sim.get_world().get_locations()) { + for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { + sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); + } + } + } // Otherwise log accordingly - - for (auto&& person : sim.get_world().get_persons()) { - for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { - if (person.get_infection_state(curr_time) == mio::abm::InfectionState(inf_state)) { - sum[inf_state] += 1; + else { + for (auto&& person : sim.get_world().get_persons()) { + for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { + if (person.get_infection_state(curr_time) == mio::abm::InfectionState(inf_state) && + ids_in_bs.find(person.get_person_id()) != ids_in_bs.end()) { + sum[inf_state] += 1; + } } } } - return std::make_pair(curr_time, sum); } }; @@ -217,10 +217,10 @@ struct LogInfectionPerLocationType : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::LocationType::Count)); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - // auto ids_in_bs = sim.get_world().parameters.get(); + auto ids_in_bs = sim.get_world().parameters.get(); + // If there is no interresting person ids to logged, log all persons. - if (0 == 0) { - // PRAGMA_OMP(parallel for) + if (ids_in_bs.size() == 0) { for (auto&& person : sim.get_world().get_persons()) { if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { @@ -232,7 +232,8 @@ struct LogInfectionPerLocationType : mio::LogAlways { else { for (auto&& person : sim.get_world().get_persons()) { if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && + (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { sum[(int)(person.get_location().get_type())] += 1; } } @@ -256,27 +257,27 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - // auto ids_in_bs = sim.get_world().parameters.get(); + auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. - // if (ids_in_bs.size() == 0) { - // PRAGMA_OMP(parallel for) - // for (auto&& person : sim.get_world().get_persons()) { - // if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && - // (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { - // sum[(size_t)(person.get_age())] += 1; - // } - // } - // } + if (ids_in_bs.size() == 0) { + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + sum[(size_t)(person.get_age())] += 1; + } + } + } // Otherwise log accordingly - // else { - for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { - sum[(size_t)(person.get_age())] += 1; + else { + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && + (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { + sum[(size_t)(person.get_age())] += 1; + } } } - // } return std::make_pair(curr_time, sum); } diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 5c2776d554..dc0b1b1d08 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -669,7 +669,7 @@ using ParametersBase = QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, - TestData>; + TestData, LogAgentIds>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6e52a26493..e042888cbd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -460,7 +460,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); } world.get_trip_list().use_weekday_trips_on_weekend(); - // world.parameters.get() = ids_in_bs; + world.parameters.get() = ids_in_bs; // //Some Data about the world: // //write how many persons are in each home diff --git a/cpp/tests/test_abm_infection.cpp b/cpp/tests/test_abm_infection.cpp index 654203c152..669be80e05 100644 --- a/cpp/tests/test_abm_infection.cpp +++ b/cpp/tests/test_abm_infection.cpp @@ -121,7 +121,7 @@ TEST(TestInfection, getInfectionState) EXPECT_EQ(infection1.get_infection_state(t), mio::abm::InfectionState::Exposed); EXPECT_EQ(infection1.get_infection_state(t - mio::abm::TimeSpan(1)), mio::abm::InfectionState::Susceptible); - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 1; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 1; ScopedMockDistribution>>> mock_uniform_dist; EXPECT_CALL(mock_uniform_dist.get_mock(), invoke) .Times(testing::AtLeast(1)) @@ -228,7 +228,7 @@ TEST(TestInfection, getPersonalProtectiveFactor) auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); auto person = mio::abm::Person(rng, location, age_group_15_to_34); - person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, mio::abm::TimePoint(0)); + person.add_new_vaccination(mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, mio::abm::TimePoint(0))); auto latest_protection = person.get_latest_protection(mio::abm::TimePoint(0)); mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); diff --git a/cpp/tests/test_abm_person.cpp b/cpp/tests/test_abm_person.cpp index f8625d3acd..2e4a259694 100644 --- a/cpp/tests/test_abm_person.cpp +++ b/cpp/tests/test_abm_person.cpp @@ -299,7 +299,7 @@ TEST(TestPerson, getLatestProtection) mio::abm::Parameters params = mio::abm::Parameters(num_age_groups); auto t = mio::abm::TimePoint(0); - person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t); + person.add_new_vaccination(mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, t)); auto latest_protection = person.get_latest_protection(t); ASSERT_EQ(latest_protection.first, mio::abm::ExposureType::GenericVaccine); ASSERT_EQ(latest_protection.second.days(), t.days()); @@ -312,7 +312,7 @@ TEST(TestPerson, getLatestProtection) ASSERT_EQ(latest_protection.second.days(), t.days()); t = mio::abm::TimePoint(20 * 24 * 60 * 60); - person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t); + person.add_new_vaccination(mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, t)); latest_protection = person.get_latest_protection(mio::abm::TimePoint(20 * 24 * 60 * 60 + 1)); ASSERT_EQ(latest_protection.first, mio::abm::ExposureType::GenericVaccine); ASSERT_EQ(latest_protection.second.days(), t.days()); @@ -336,14 +336,14 @@ TEST(Person, rng) TEST(TestPerson, addNewVaccination) { - auto rng = mio::RandomNumberGenerator(); - auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); - auto person = mio::abm::Person(rng, location, age_group_15_to_34); + auto rng = mio::RandomNumberGenerator(); + auto location = mio::abm::Location(mio::abm::LocationType::School, 0, num_age_groups); + auto person = mio::abm::Person(rng, location, age_group_15_to_34); auto t1 = mio::abm::TimePoint(0); auto t2 = mio::abm::TimePoint(7 * 24 * 60 * 60); - person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t1); - person.add_new_vaccination(mio::abm::ExposureType::GenericVaccine, t2); + person.add_new_vaccination(mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, t1)); + person.add_new_vaccination(mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, t2)); auto vaccinations = person.get_vaccinations(); ASSERT_EQ(vaccinations[0].time, t1); ASSERT_EQ(vaccinations[1].time, t2); From afcd2a3a083bc03620e365a07bcee6ba96827e6f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 21 May 2024 01:10:36 +0200 Subject: [PATCH 116/488] bug MA school and ma work switched Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index de1b4aae27..dbd363ddc0 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -66,8 +66,8 @@ def main(path, n_runs): def plot_infection_per_location_type(df): # Calculate moving average for all location types df['MA_Home'] = df.Home.rolling(10, min_periods=1).mean() - df['MA_Work'] = df.Work.rolling(10, min_periods=1).mean() df['MA_School'] = df.School.rolling(10, min_periods=1).mean() + df['MA_Work'] = df.Work.rolling(10, min_periods=1).mean() df['MA_SocialEvent'] = df.SocialEvent.rolling(10, min_periods=1).mean() df['MA_BasicsShop'] = df.BasicsShop.rolling(10, min_periods=1).mean() df['MA_Hospital'] = df.Hospital.rolling(10, min_periods=1).mean() @@ -77,7 +77,7 @@ def plot_infection_per_location_type(df): 10, min_periods=1).mean() df['MA_Cemetery'] = df.Cemetery.rolling(10, min_periods=1).mean() - df.plot(x='Time', y=['MA_Home', 'MA_Work', 'MA_School', 'MA_SocialEvent', 'MA_BasicsShop', + df.plot(x='Time', y=['MA_Home', 'MA_School','MA_Work', 'MA_SocialEvent', 'MA_BasicsShop', 'MA_Hospital', 'MA_ICU', 'MA_Car', 'MA_PublicTransport', 'MA_Cemetery'], figsize=(10, 6)) # Subplots of individual location types From 7116caeb0554bc6ec1b67c486e80dff7678f17ff Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 21 May 2024 01:11:08 +0200 Subject: [PATCH 117/488] Refactor entry_allowed function in Location class to include random number generator Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 6 +++--- cpp/models/abm/world.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 269567c088..d6173ad736 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -47,7 +47,7 @@ void Location::add_damping(TimePoint t_begin, double p) temp_npi_damping.emplace_back(t_begin, p); } -bool Location::entry_allowed(Person::RandomNumberGenerator& rng,const mio::abm::TimePoint t) const +bool Location::entry_allowed(Person::RandomNumberGenerator& rng, const mio::abm::TimePoint t) const { if (temp_npi_damping.empty()) { return true; @@ -60,8 +60,8 @@ bool Location::entry_allowed(Person::RandomNumberGenerator& rng,const mio::abm:: }); //then we want to access the second element of it, draw a random number between 0 and 1 and check if it is smaller than the damping factor //get a random number between 0 and 1 without m_rng - ScalarType random_number = UniformDistribution::get_instance()(rng,0.0,1.0); - return random_number > it->second; + ScalarType random_number = UniformDistribution::get_instance()(rng, 0.0, 1.0); + return random_number < it->second; } } diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index e8c71613f4..b0fab5a18b 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -136,7 +136,8 @@ void World::migration(TimePoint t, TimeSpan dt) auto& target_location = get_individualized_location(trip.migration_destination); if (m_testing_strategy.run_strategy(personal_rng, *person, target_location, t)) { if (target_location != current_location && - target_location.get_number_persons() < target_location.get_capacity().persons) { + target_location.get_number_persons() < target_location.get_capacity().persons && + target_location.entry_allowed(personal_rng, t)) { person->apply_mask_intervention(personal_rng, target_location); person->migrate_to(target_location); } From 61abad2c42614095a1569bd74dccf745c51846ad Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 21 May 2024 01:17:29 +0200 Subject: [PATCH 118/488] add npis Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 195 ++++++++++++++--------- 1 file changed, 116 insertions(+), 79 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e042888cbd..30b6a62a8b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -81,7 +81,7 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); //std::cout << initial_infection_distribution.array() << std::endl; - //extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days + // extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days } /** @@ -437,7 +437,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, auto first_location = locations.find(first_location_id)->second; auto& person = world.add_person(first_location, determine_age_group(age)); if (home_in_bs) { - ids_in_bs.insert(person_id); + // ids_in_bs.insert(person_id); } auto home = locations.find(home_id)->second; person.set_assigned_location(home); @@ -529,6 +529,16 @@ void set_parameters(mio::abm::Parameters& params) params.get() = {TimeInfectedCriticalToRecovered_my_sigma.first, TimeInfectedCriticalToRecovered_my_sigma.second}; + //Set testing parameters + auto pcr_test_values = mio::abm::TestParameters{0.9, 0.99}; + auto antigen_test_values = mio::abm::TestParameters{0.8, 0.95}; + auto generic_test_values = mio::abm::TestParameters{0.7, 0.9}; + params.get()[mio::abm::TestType::PCR] = pcr_test_values; + params.get()[mio::abm::TestType::Antigen] = antigen_test_values; + params.get()[mio::abm::TestType::Generic] = generic_test_values; + auto test_parameters = params.get()[mio::abm::TestType::Antigen]; + mio::unused(test_parameters); + // Set percentage parameters params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.75; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.75; @@ -996,8 +1006,8 @@ void write_log_to_file_infection_per_location_type(const T& history, const fs::p { std::ofstream myfile4((result_dir / "infection_per_location_type.txt").string()); const std::vector& labels = { - "Home", "Work", "School", "SocialEvent", "BasicsShop", - "Hospital", "ICU", "Car", "PublicTransport", "TransportWithoutContact", + "Home", "School", "Work", "SocialEvent", "BasicsShop", + "Hospital", "ICU", "Car", "PublicTransport", "TransportWithoutContact", "Cemetery"}; std::get<0>(history.get_log()).print_table(labels, 12, 4, myfile4); } @@ -1037,36 +1047,36 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { } }; -template -T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) -{ - auto gathered_ensemble_vec = T{}; - - if (rank == 0) { - gathered_ensemble_vec.reserve(num_runs); - std::copy(ensemble_vec.begin(), ensemble_vec.end(), std::back_inserter(gathered_ensemble_vec)); - for (int src_rank = 1; src_rank < num_procs; ++src_rank) { - int bytes_size; - MPI_Recv(&bytes_size, 1, MPI_INT, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); - mio::ByteStream bytes(bytes_size); - MPI_Recv(bytes.data(), bytes.data_size(), MPI_BYTE, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); - - auto src_ensemble_results = mio::deserialize_binary(bytes, mio::Tag{}); - if (!src_ensemble_results) { - mio::log_error("Error receiving ensemble results from rank {}.", src_rank); - } - std::copy(src_ensemble_results.value().begin(), src_ensemble_results.value().end(), - std::back_inserter(gathered_ensemble_vec)); - } - } - else { - auto bytes = mio::serialize_binary(ensemble_vec); - auto bytes_size = int(bytes.data_size()); - MPI_Send(&bytes_size, 1, MPI_INT, 0, 0, mio::mpi::get_world()); - MPI_Send(bytes.data(), bytes.data_size(), MPI_BYTE, 0, 0, mio::mpi::get_world()); - } - return gathered_ensemble_vec; -} +// template +// T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) +// { +// auto gathered_ensemble_vec = T{}; + +// if (rank == 0) { +// gathered_ensemble_vec.reserve(num_runs); +// std::copy(ensemble_vec.begin(), ensemble_vec.end(), std::back_inserter(gathered_ensemble_vec)); +// for (int src_rank = 1; src_rank < num_procs; ++src_rank) { +// int bytes_size; +// MPI_Recv(&bytes_size, 1, MPI_INT, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); +// mio::ByteStream bytes(bytes_size); +// MPI_Recv(bytes.data(), bytes.data_size(), MPI_BYTE, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); + +// auto src_ensemble_results = mio::deserialize_binary(bytes, mio::Tag{}); +// if (!src_ensemble_results) { +// mio::log_error("Error receiving ensemble results from rank {}.", src_rank); +// } +// std::copy(src_ensemble_results.value().begin(), src_ensemble_results.value().end(), +// std::back_inserter(gathered_ensemble_vec)); +// } +// } +// else { +// auto bytes = mio::serialize_binary(ensemble_vec); +// auto bytes_size = int(bytes.data_size()); +// MPI_Send(&bytes_size, 1, MPI_INT, 0, 0, mio::mpi::get_world()); +// MPI_Send(bytes.data(), bytes.data_size(), MPI_BYTE, 0, 0, mio::mpi::get_world()); +// } +// return gathered_ensemble_vec; +// } std::vector distribute_runs(size_t num_runs, int num_procs) { @@ -1182,22 +1192,25 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, // historyPersonInfDelta, historyInfectionStatePerAgeGroup); - //// Advance the world with respective npis - //1. testing schemes in schools + auto location_it = sim.get_world().get_locations(); + // Advance the world with respective npis + // 1. testing schemes in schools auto testing_min_time_school = mio::abm::days(7); auto probability_school = 1.0; - auto start_date_test_school = mio::abm::TimePoint(42); // 2021-04-12 + auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 auto test_type_school = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = world.parameters.get()[test_type_school]; // Test parameters + auto test_parameters = + sim.get_world().parameters.get()[test_type_school]; // Test parameters auto testing_criteria_school = mio::abm::TestingCriteria(); auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, end_date_test_school, test_parameters, probability_school); - world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_school); + + // // 2. testing schemes in work places for 35% of random workplaces - //2. testing schemes in work places for 35% of random workplaces - auto location_it = world.get_locations(); std::vector work_location_ids; for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::Work) { @@ -1216,7 +1229,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_date_test_work = mio::abm::TimePoint(0); auto end_date_test_work = mio::abm::TimePoint(tmax); auto test_type_work = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_work = world.parameters.get()[test_type_work]; // Test parameters + auto test_parameters_work = + sim.get_world().parameters.get()[test_type_work]; // Test parameters auto testing_criteria_work = mio::abm::TestingCriteria(); auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, @@ -1224,12 +1238,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(work_location_ids_35.begin(), work_location_ids_35.end(), location.get_index()) != work_location_ids_35.end()) { - world.get_testing_strategy().add_testing_scheme(location.get_type(), testing_scheme_work); + sim.get_world().get_testing_strategy().add_testing_scheme(location.get_type(), testing_scheme_work); } } - //3. Mask schemes for all locations - //First set all locations to have mask usage, we need ffp2 masks + // 3. Mask schemes for all locations + // First set all locations to have mask usage, we need ffp2 masks for (auto& location : location_it) { location.set_required_mask(mio::abm::MaskType::FFP2); if (location.get_type() == mio::abm::LocationType::Home) { @@ -1240,22 +1254,24 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } - //4. Dampings for all kinds of places + // 4. Dampings for all kinds of places for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::School) - { - location.add_damping(mio::abm::TimePoint(0), 0.5); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(14), 0.0); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(42), 0.5); // from 2021-04-12 till 2021-05-30 (end) + if (location.get_type() == mio::abm::LocationType::School) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.0); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), + 0.5); // from 2021-04-12 till 2021-05-30 (end) } - if(location.get_type() == mio::abm::LocationType::BasicsShop) - { - location.add_damping(mio::abm::TimePoint(14), 0.8); // from 2021-03-15 + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } } - + //5. add capacity limits to some locations //first we need two lists, one for 50% of random social event locations and the other list for the other 50% + //1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ + // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] + // ----> Divide Social Event locations into a 50/50 split. First 50% get the restrictive capacity std::vector social_event_location_ids_small; std::vector social_event_location_ids_big; for (auto& location : location_it) { @@ -1266,32 +1282,60 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s //take 50% of social event locations std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); auto num_social_event_locations_small = (int)(0.5 * social_event_location_ids_small.size()); - social_event_location_ids_big.insert(social_event_location_ids_big.end(), social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_small); + social_event_location_ids_big.insert( + social_event_location_ids_big.end(), social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_small); social_event_location_ids_small.erase(social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_small); + social_event_location_ids_small.begin() + + num_social_event_locations_small); - //add capacity limits on day one + //add capacity limits on day one for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10,0); + location.set_capacity(10, 0); } if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(0,0); + location.set_capacity(0, 0); } } - - sim.advance(mio::abm::TimePoint(42), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, - historyInfectionPerAgeGroup); + sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + std::cout << "day 14 finished" << std::endl; + // small social events to capacity 5 + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(5, 0); + } + } + sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + std::cout << "day 42 finished" << std::endl; for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::School) { location.set_npi_active(false); } } - sim.advance(mio::abm::TimePoint(72), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, - historyInfectionPerAgeGroup); + sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(2, 0); + } + //90% of big social events get reopened and caopacity will be unlimited + int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + number_of_big_social_events--; + if (number_of_big_social_events >= 0) { + location.set_capacity(std::numeric_limits::max(), 0); + } + } + } for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::School) { location.set_npi_active(true); @@ -1299,7 +1343,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); - + std::cout << "day 90 finished" << std::endl; ////Advance till here // Stop the clock after sim.advance and calculate the duration @@ -1308,17 +1352,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; // TODO: update result of the simulation to be a vector of location result. - // auto temp_sim_infection_per_loc_tpye = - // std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_per_loc_tpye = + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; auto temp_sim_infection_per_age_group = std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; // Push result of the simulation back to the result vector - // ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); + ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); - // ensemble_params.push_back(std::vector{sim.get_world()}); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); // Option to save the current run result to file /* if (save_result_result && save_single_runs) { @@ -1370,12 +1413,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s result_dir / "infection_per_location_type/", save_single_runs)); #endif - - // BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, - // result_dir / "infection_per_location_type/", save_single_runs)); - // BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_age_group, ensemble_params, {0}, - // result_dir / "infection_per_age_group/", save_single_runs)); - printf("done.\n"); //write_txt_file_for_graphical_compartment_output(ensemble_infection_state_per_age_group); // BOOST_OUTCOME_TRY(save_result_result); @@ -1389,7 +1426,7 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -1415,7 +1452,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 1; + num_runs = 6; printf("Running with number of runs = %d.\n", (int)num_runs); } From 4cca6eecae7f7a06aea0540e8a72a72e30d5e342 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 21 May 2024 09:52:16 +0200 Subject: [PATCH 119/488] add basic shop testing Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 30b6a62a8b..8e034a5c47 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -33,6 +33,7 @@ #include "generate_graph_from_data.cpp" #include "memilio/utils/miompi.h" #include "memilio/io/binary_serializer.h" +#include "memilio/io/epi_data.h" namespace fs = boost::filesystem; @@ -154,6 +155,27 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) } } +/** + * @brief assign an vaccination state to each person according to real world data read in through the ODE secir model. + * + * @param input + * @return int + */ +// void assign_vaccination_state(mio::abm::World& world, const std::string& filename) +// { +// //Read in file with vaccination data +// auto vacc_data = mio::read_vaccination_data(filename).value(); +// for (auto& vacc_entry : vacc_data) { +// // we want to filter out branschweig +// if (vacc_entry.county_id == mio::regions::DistrictId(3101)) { +// //for every date we want to vaccinate a person within the age group +// } +// } +// // + +// mio::unused(vacc_data, world); +// } + int stringToMinutes(const std::string& input) { size_t colonPos = input.find(":"); @@ -880,6 +902,9 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign an infection state to each person. assign_infection_state(world, t0); + // Assign vaccination status to each person. + // assign_vaccination_state(world, (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").generic_string()); + //auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); // During the lockdown, 25% of people work from home and schools are closed for 90% of students. @@ -1242,6 +1267,37 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } + //2.5 plus testing schemes at 20% of basics shops + std::vector basics_shop_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + basics_shop_location_ids.push_back(location.get_index()); + } + } + //take 20% of basics shop locations + std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); + auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); + std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), + basics_shop_location_ids.begin() + num_basics_shop_locations); + auto testing_min_time_basics_shop = mio::abm::days(2); + auto probability_basics_shop = 1.0; + auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); + auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); + auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_basics_shop = + sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters + auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); + auto testing_scheme_basics_shop = mio::abm::TestingScheme( + testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, + end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); + for (auto& location : location_it) { + if (std::find(basics_shop_location_ids_20.begin(), basics_shop_location_ids_20.end(), + location.get_index()) != basics_shop_location_ids_20.end()) { + sim.get_world().get_testing_strategy().add_testing_scheme(location.get_type(), + testing_scheme_basics_shop); + } + } + // 3. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks for (auto& location : location_it) { From bc7640d972714980e55c22d3ee42d1da58d76f5a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 22 May 2024 16:06:13 +0200 Subject: [PATCH 120/488] add mpi flag and some minor changes to main.cpp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 69 ++++++++++++------------ 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8e034a5c47..adb6472958 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -558,8 +558,6 @@ void set_parameters(mio::abm::Parameters& params) params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; params.get()[mio::abm::TestType::Generic] = generic_test_values; - auto test_parameters = params.get()[mio::abm::TestType::Antigen]; - mio::unused(test_parameters); // Set percentage parameters params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.75; @@ -1071,37 +1069,38 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { return std::make_pair(curr_time, sum); } }; +#ifdef MEMILIO_ENABLE_MPI +template +T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) +{ + auto gathered_ensemble_vec = T{}; -// template -// T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) -// { -// auto gathered_ensemble_vec = T{}; - -// if (rank == 0) { -// gathered_ensemble_vec.reserve(num_runs); -// std::copy(ensemble_vec.begin(), ensemble_vec.end(), std::back_inserter(gathered_ensemble_vec)); -// for (int src_rank = 1; src_rank < num_procs; ++src_rank) { -// int bytes_size; -// MPI_Recv(&bytes_size, 1, MPI_INT, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); -// mio::ByteStream bytes(bytes_size); -// MPI_Recv(bytes.data(), bytes.data_size(), MPI_BYTE, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); - -// auto src_ensemble_results = mio::deserialize_binary(bytes, mio::Tag{}); -// if (!src_ensemble_results) { -// mio::log_error("Error receiving ensemble results from rank {}.", src_rank); -// } -// std::copy(src_ensemble_results.value().begin(), src_ensemble_results.value().end(), -// std::back_inserter(gathered_ensemble_vec)); -// } -// } -// else { -// auto bytes = mio::serialize_binary(ensemble_vec); -// auto bytes_size = int(bytes.data_size()); -// MPI_Send(&bytes_size, 1, MPI_INT, 0, 0, mio::mpi::get_world()); -// MPI_Send(bytes.data(), bytes.data_size(), MPI_BYTE, 0, 0, mio::mpi::get_world()); -// } -// return gathered_ensemble_vec; -// } + if (rank == 0) { + gathered_ensemble_vec.reserve(num_runs); + std::copy(ensemble_vec.begin(), ensemble_vec.end(), std::back_inserter(gathered_ensemble_vec)); + for (int src_rank = 1; src_rank < num_procs; ++src_rank) { + int bytes_size; + MPI_Recv(&bytes_size, 1, MPI_INT, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); + mio::ByteStream bytes(bytes_size); + MPI_Recv(bytes.data(), bytes.data_size(), MPI_BYTE, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); + + auto src_ensemble_results = mio::deserialize_binary(bytes, mio::Tag{}); + if (!src_ensemble_results) { + mio::log_error("Error receiving ensemble results from rank {}.", src_rank); + } + std::copy(src_ensemble_results.value().begin(), src_ensemble_results.value().end(), + std::back_inserter(gathered_ensemble_vec)); + } + } + else { + auto bytes = mio::serialize_binary(ensemble_vec); + auto bytes_size = int(bytes.data_size()); + MPI_Send(&bytes_size, 1, MPI_INT, 0, 0, mio::mpi::get_world()); + MPI_Send(bytes.data(), bytes.data_size(), MPI_BYTE, 0, 0, mio::mpi::get_world()); + } + return gathered_ensemble_vec; +} +#endif std::vector distribute_runs(size_t num_runs, int num_procs) { @@ -1136,7 +1135,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 23000; + auto max_num_persons = 50000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1184,7 +1183,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groupss); create_sampled_world(world, input_dir, t0, max_num_persons); - world.parameters.get() = 7; + world.parameters.get() = 10; // Stop the clock after create_sampled_world and calculate the duration // auto stop1 = std::chrono::high_resolution_clock::now(); // auto duration1 = std::chrono::duration(stop1 - start1); @@ -1508,7 +1507,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 6; + num_runs = 3; printf("Running with number of runs = %d.\n", (int)num_runs); } From 72e03df18bd3b9c364b1fb73f8d69ff235f405f8 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 22 May 2024 23:46:15 +0200 Subject: [PATCH 121/488] Refactor entry_allowed function in Location class to include random number generator Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 8 +++++++- cpp/simulations/analyze_bs_run.py | 25 +++++++++++-------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index d6173ad736..d64ca960d6 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -58,7 +58,13 @@ bool Location::entry_allowed(Person::RandomNumberGenerator& rng, const mio::abm: [](TimePoint t, const std::pair& p) { return t < p.first; }); - //then we want to access the second element of it, draw a random number between 0 and 1 and check if it is smaller than the damping factor + //we need the one entry before the upper bound + if (it == temp_npi_damping.begin()) { + return true; + } + else { + --it; + } //get a random number between 0 and 1 without m_rng ScalarType random_number = UniformDistribution::get_instance()(rng, 0.0, 1.0); return random_number < it->second; diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index dbd363ddc0..e56dc600f7 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -18,6 +18,7 @@ import matplotlib.patches as mpatches import matplotlib.lines as mlines import h5py +from scipy.ndimage.filters import gaussian_filter1d def main(path, n_runs): @@ -65,20 +66,16 @@ def main(path, n_runs): def plot_infection_per_location_type(df): # Calculate moving average for all location types - df['MA_Home'] = df.Home.rolling(10, min_periods=1).mean() - df['MA_School'] = df.School.rolling(10, min_periods=1).mean() - df['MA_Work'] = df.Work.rolling(10, min_periods=1).mean() - df['MA_SocialEvent'] = df.SocialEvent.rolling(10, min_periods=1).mean() - df['MA_BasicsShop'] = df.BasicsShop.rolling(10, min_periods=1).mean() - df['MA_Hospital'] = df.Hospital.rolling(10, min_periods=1).mean() - df['MA_ICU'] = df.ICU.rolling(10, min_periods=1).mean() - df['MA_Car'] = df.Car.rolling(10, min_periods=1).mean() - df['MA_PublicTransport'] = df.PublicTransport.rolling( - 10, min_periods=1).mean() - df['MA_Cemetery'] = df.Cemetery.rolling(10, min_periods=1).mean() - - df.plot(x='Time', y=['MA_Home', 'MA_School','MA_Work', 'MA_SocialEvent', 'MA_BasicsShop', - 'MA_Hospital', 'MA_ICU', 'MA_Car', 'MA_PublicTransport', 'MA_Cemetery'], figsize=(10, 6)) + df['MA_Home'] = gaussian_filter1d(df.Home.rolling(24*3, min_periods=1).mean(), sigma=15) + df['MA_School'] = gaussian_filter1d(df.School.rolling(24*3, min_periods=1).mean(), sigma=15) + df['MA_Work'] = gaussian_filter1d(df.Work.rolling(24*3, min_periods=1).mean(), sigma=15) + df['MA_SocialEvent'] = gaussian_filter1d(df.SocialEvent.rolling(24*3, min_periods=1).mean(), sigma=15) + df['MA_BasicsShop'] = gaussian_filter1d(df.BasicsShop.rolling(24*3, min_periods=1).mean(), sigma=15) + + df.plot(x='Time', y=['MA_Home', 'MA_School','MA_Work', 'MA_SocialEvent', 'MA_BasicsShop'], figsize=(10, 6)) + + + # Subplots of individual location types # fig, axs = plt.subplots(5, 2, constrained_layout=True) From 5bb1f45e9ed0191c1044fb9c676a021c757e8d2a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 28 May 2024 18:54:49 +0200 Subject: [PATCH 122/488] add location guess Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/check_bs_data.py | 17 +++++- cpp/simulations/cleanup_data.py | 99 ++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/check_bs_data.py b/cpp/simulations/check_bs_data.py index 843ca8a03c..7ca7622cf3 100644 --- a/cpp/simulations/check_bs_data.py +++ b/cpp/simulations/check_bs_data.py @@ -15,7 +15,7 @@ ####### minimal sanity check on data ####### bd = pd.read_csv( - '/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/modified_braunschweig_result_ffa7.csv', header=None, skiprows=1) + '/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8_modified.csv', header=None, skiprows=1) # setup dictionary for the leisure activities, and vehicle choice and column names # bd.rename( @@ -26,7 +26,7 @@ bd.rename( columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', 10: 'travelTime' , 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', 16: - 'ActivityBefore', 17: 'ActivityAfter', 18: 'age', 19:'home_in_bs'}, + 'ActivityBefore', 17: 'ActivityAfter', 18: 'age', 19: 'map_feature_key', 20: 'map_feature_value', 21: 'home_in_bs'}, inplace=True) dict_leisure = {1: 'work', 2: 'education', 3: 'Shopping', 4: 'free time', @@ -39,6 +39,19 @@ #count how many different activities are after the same location bd_same_loc = bd_same_loc.groupby(['loc_id_end']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) + +# chek how many unique map_feature_keys and values are in the data +map_feature_keys = bd[['map_feature_key']].drop_duplicates().size +map_feature_values = bd[['map_feature_value']].drop_duplicates().size +print('Number of unique map_feature_keys: ' + str(map_feature_keys) + '. Number of unique map_feature_values: ' + str(map_feature_values) + '. \n') +# same for the tuple of both +map_feature_keys_values = bd[['map_feature_key', 'map_feature_value']].drop_duplicates().size +print('Number of unique map_feature_keys and values: ' + str(map_feature_keys_values) + '. \n') + +#check if persons go to different location_ids with the same activity_after +bd_same_loc = bd[['personID', 'loc_id_end', 'ActivityAfter']].drop_duplicates() +#count how many different activities are after the same location +bd_same_loc = bd_same_loc.groupby(['personID', 'loc_id_end']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) # check if people do the same trip more than once trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 5aa71486ee..eda965ea21 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -264,8 +264,95 @@ def add_home_is_in_bs_column(pd): pd.at[index, 'home_in_bs'] = 1 return pd +def location_type_from_keys_and_values(key, value, intention): -PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result.csv" + location_type = 'SocialEvent' + if key == 'home': + location_type= 'Home' + + if key == 'education': + location_type= 'School' + + if key == 'amenity': + if value in ['fast_food', 'fuel', 'food_court']: + location_type= 'BasicsShop' + if value in ['coworking_space','office', 'craft', 'fire_station', 'hospital', 'laboratory', 'office', 'research_institute']: + location_type= 'Work' + if value in ['school', 'kindergarten', 'university', 'college','childcare', 'language_school', 'music_school', 'prep_school']: + location_type= 'School' + else: + location_type= 'SocialEvent' + + if key == 'building': + if value in ['apartments', 'bungalow', 'cabin', 'detached', 'detached_house', 'dormitory', 'double_house', 'duplex', 'dwlling_house', 'farmhouse', 'house', 'houseboat', 'nursing_home', 'residential', 'semi' 'hotel', 'house', 'residential', 'semidetached_house', 'semi_detached', 'semidetached']: + location_type= 'Home' + if value in ['college', 'kindergarten']: + location_type= 'School' + if value in ['laboratory', "bakehouse", "bank", "barracks", "brewery", "car_repair", "car_wash", "civic", "clinic", "data_center", "embassy", "factory", "farm", "fire_station", "fuel_station", "government", "hospital", "industrial", "manufacture", "mortuary", "office", "police", "post_office", "presbytery", "prison", "public", "school", "shelter", "sports_centre", "sports_hall", "stable", "warehouse", "workshop"]: + location_type= 'Work' + if value in ["commercial", "fuel", "kiosk", "shop", "supermarket"]: + location_type= 'BasicShop' + else: + location_type= 'SocialEvent' + + if key == 'craft': + location_type= 'Work' + + if key == 'healthcare': + location_type= 'Work' + + if key == 'historic': + location_type= 'SocialEvent' + + if key == 'landuse': + location_type= 'SocialEvent' + + if key == 'leisure': + location_type= 'SocialEvent' + + if key == 'office': + location_type= 'Work' + + if key == 'shop': + location_type= 'BasicShop' + + if key == 'tourism': + if value in ['apartment', 'guest_house', 'guest_house;apartment']: + location_type= 'Home' + location_type= 'SocialEvent' + + if key == 'NaN': + if intention == 1: + location_type= 'Work' + if intention == 1: + location_type= 'School' + if intention == 3: + location_type= 'BasicShop' + if intention == 4: + location_type= 'SocialEvent' + if intention == 5: + location_type= 'BasicShop' + if intention == 6: + location_type= 'SocialEvent' + if intention == 7: + location_type= 'Home' + + # map from location type string to int + location_type_dict = {'Home': 0, 'School': 2, 'Work': 1, 'BasicShop': 3, 'SocialEvent': 4} + return location_type_dict[location_type] + +def assign_location_type(pd): + if 'location_type' in pd.columns: + print("Column 'location_type' is present in DataFrame.") + # nothing tbd + else: + print("Column 'location_type' is not present in DataFrame.") + pd['location_type'] = 'SocialEvent' + for index, row in pd.iterrows(): + pd.at[index, 'location_type'] = location_type_from_keys_and_values( row['map_feature_key'], row['map_feature_value'], row['activity_end']) + return pd + +PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8.csv" bd = pd.read_csv(PATH) @@ -276,7 +363,7 @@ def add_home_is_in_bs_column(pd): column_headers = [header.strip() for header in column_headers] # check if anythiong changed since writing this script -if(column_headers[0:19] == ['puid', 'start_zone', 'end_zone', 'loc_id_start', 'loc_id_end', 'start_county', 'end_county', 'huid', 'trip_distance', 'start_time', 'travel_time_sec', 'lon_start', 'lat_start', 'lon_end', 'lat_end', 'travel_mode', 'activity_start', 'activity_end', 'age']): +if(column_headers[0:21] == ['puid', 'start_zone', 'end_zone', 'loc_id_start', 'loc_id_end', 'start_county', 'end_county', 'huid', 'trip_distance', 'start_time', 'travel_time_sec', 'lon_start', 'lat_start', 'lon_end', 'lat_end', 'travel_mode', 'activity_start', 'activity_end', 'age','map_feature_key','map_feature_value']): print("Column headers are correct") else: print("Column headers are not correct") @@ -287,8 +374,10 @@ def add_home_is_in_bs_column(pd): print('Home IDs set.') bd_new = add_school_ids(bd_new) print('School IDs set.') -bd_new = add_external_ids(bd) -print('External location IDs set.') +# bd_new = add_external_ids(bd) +# print('External location IDs set.') +bd_new = assign_location_type(bd_new) +print('Location types assigned.') # Write data back to disk -bd_new.to_csv('modified_braunschweig_result.csv', index=False) +bd_new.to_csv('braunschweig_result_ffa8_modified.csv', index=False) From 106a53c919f1e36a817951c412f2c2d6c86c45d3 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 29 May 2024 15:29:14 +0200 Subject: [PATCH 123/488] add vaccinations and enhance clenaup python file Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/memilio/io/epi_data.h | 11 +- cpp/simulations/cleanup_data.py | 2 + cpp/simulations/paper_abm_bs_testing.cpp | 196 +++++++++++++++++++---- 3 files changed, 170 insertions(+), 39 deletions(-) diff --git a/cpp/memilio/io/epi_data.h b/cpp/memilio/io/epi_data.h index 1ccc4586b9..bb0aa6f026 100644 --- a/cpp/memilio/io/epi_data.h +++ b/cpp/memilio/io/epi_data.h @@ -456,7 +456,7 @@ class VaccinationDataEntry public: static std::vector age_group_names; - double num_vaccinations_completed; + double num_vaccinations_completed, num_vaccinations_partially; Date date; AgeGroup age_group; boost::optional state_id; @@ -468,6 +468,7 @@ class VaccinationDataEntry { auto obj = io.expect_object("VaccinationDataEntry"); auto num_vaccinations_completed = obj.expect_element("Vacc_completed", Tag{}); + auto num_vaccinations_partially = obj.expect_element("Vacc_partially", 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{}); @@ -475,7 +476,8 @@ class VaccinationDataEntry auto district_id = obj.expect_optional("ID_District", Tag{}); return mio::apply( io, - [](auto nf, auto d, auto&& a_str, auto sid, auto cid, auto did) -> IOResult { + [](auto nf, auto nf2, auto d, auto&& a_str, auto sid, auto cid, + auto did) -> IOResult { auto it = std::find(age_group_names.begin(), age_group_names.end(), a_str); auto a = AgeGroup(0); if (it != age_group_names.end()) { @@ -484,9 +486,10 @@ class VaccinationDataEntry else { return failure(StatusCode::InvalidValue, "Invalid vaccination data age group."); } - return success(VaccinationDataEntry{nf, d, a, sid, cid, did}); + return success(VaccinationDataEntry{nf, nf2, d, a, sid, cid, did}); }, - num_vaccinations_completed, date, age_group_str, state_id, county_id, district_id); + num_vaccinations_completed, num_vaccinations_partially, date, age_group_str, state_id, county_id, + district_id); } }; diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index eda965ea21..f1ab923001 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -379,5 +379,7 @@ def assign_location_type(pd): bd_new = assign_location_type(bd_new) print('Location types assigned.') +# we need to delete the column map_feature_key and map_feature_value because we dont need them anymore +bd_new = bd_new.drop(columns=['map_feature_key', 'map_feature_value']) # Write data back to disk bd_new.to_csv('braunschweig_result_ffa8_modified.csv', index=False) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index adb6472958..8dd7eabeaa 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -61,6 +61,8 @@ const std::map infection_ mio::CustomIndexArray initial_infection_distribution{ {mio::AgeGroup(num_age_groupss), mio::osecir::InfectionState::Count}, 0.005}; +std::map>> vacc_map; + /** * Create extrapolation of real world data to compare with. */ @@ -155,26 +157,152 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) } } +size_t determine_age_group_from_rki(mio::AgeGroup age) +{ + if (age == mio::AgeGroup(0)) { + return 0; + } + else if (age == mio::AgeGroup(1)) { + return 1; + } + else if (age == mio::AgeGroup(2)) { + return 2; + } + else if (age == mio::AgeGroup(3)) { + return 3; + } + else if (age == mio::AgeGroup(4)) { + return 4; + } + else if (age == mio::AgeGroup(5)) { + return 5; + } + else { + return 2; + } +} + +void prepare_vaccination_state(mio::Date simulation_end, const std::string& filename) +{ + // for saving previous day of vaccination + std::vector> vacc_vector_prev(num_age_groupss); + //inizialize the vector with 0 + for (size_t i = 0; i < num_age_groupss; ++i) { + vacc_vector_prev[i] = std::make_pair(0, 0); + } + + //Read in file with vaccination data + auto vacc_data = mio::read_vaccination_data(filename).value(); + for (auto& vacc_entry : vacc_data) { + // we need ot filter out braunschweig with zip code 3101 + if (vacc_entry.county_id.value() == mio::regions::CountyId(3101)) { + //we need the vaccination from the beginning till the end of the simulaiton (2021-05-30) + if (vacc_entry.date <= simulation_end && vacc_entry.date >= mio::Date(2020, 12, 01)) { + // if the date isn't in the map we need to add a vector of size num_age_groupss + if (vacc_map.find(vacc_entry.date) == vacc_map.end()) { + vacc_map[vacc_entry.date] = std::vector>(num_age_groupss); + } + // we need to add the number of persons to the vector of the date, but these are cumulative so we need to substract the day before + vacc_map[vacc_entry.date][determine_age_group_from_rki(vacc_entry.age_group)].first = + vacc_entry.num_vaccinations_partially - + vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].first; + vacc_map[vacc_entry.date][determine_age_group_from_rki(vacc_entry.age_group)].second = + vacc_entry.num_vaccinations_completed - + vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].second; + + //update the vector for the next iteration + vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].first = + vacc_entry.num_vaccinations_partially; + vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].second = + vacc_entry.num_vaccinations_completed; + } + } + } +} + /** * @brief assign an vaccination state to each person according to real world data read in through the ODE secir model. * * @param input * @return int */ -// void assign_vaccination_state(mio::abm::World& world, const std::string& filename) -// { -// //Read in file with vaccination data -// auto vacc_data = mio::read_vaccination_data(filename).value(); -// for (auto& vacc_entry : vacc_data) { -// // we want to filter out branschweig -// if (vacc_entry.county_id == mio::regions::DistrictId(3101)) { -// //for every date we want to vaccinate a person within the age group -// } -// } -// // - -// mio::unused(vacc_data, world); -// } +void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_beginning) +{ + // we check if we even have enough people to vaccinate in each respective age group + std::vector num_persons_by_age(num_age_groupss); + for (auto& person : world.get_persons()) { + num_persons_by_age[determine_age_group_from_rki(person.get_age())]++; + } + //sum over all dates in the vacc_map to check if we have enough persons to vaccinate + std::vector num_persons_by_age_vaccinate(num_age_groupss); + for (auto& vacc_entry : vacc_map) { + for (size_t age = 0; age < vacc_entry.second.size(); ++age) { + num_persons_by_age_vaccinate[age] += vacc_entry.second[age].first; + } + } + //check + for (size_t age = 0; age < num_persons_by_age.size(); ++age) { + if (num_persons_by_age[age] < num_persons_by_age_vaccinate[age]) { + mio::log_error( + "Not enough persons to vaccinate in age group we dont vaccinate if an age group is fully vaccinated! ", + age); + } + } + + // save all persons with age groups + std::vector> persons_by_age(num_age_groupss); + + for (auto& person : world.get_persons()) { + persons_by_age[person.get_age().get()].push_back(person.get_person_id()); + } + + // vaccinate random persons according to the data and we also beforehand need to keep a list of persons which are already vaccinated and their age to vaccinate them with the second dose + + // first we need a vector with a list of ids of already vaccinated persons for each age group + std::vector> vaccinated_persons(num_age_groupss); + for (auto& vacc_entry : vacc_map) { + for (size_t age = 0; age < vacc_entry.second.size(); ++age) { + for (uint32_t i = 0; i < vacc_entry.second[age].first; ++i) { + if (persons_by_age[age].size() == 0) { + mio::log_error("Not enough persons to vaccinate in age group we dont vaccinate if an age group is"); + } + else { + // select random person and assign Vaccination + uint32_t id_rnd = persons_by_age[age][mio::UniformIntDistribution::get_instance()( + world.get_rng(), 0U, persons_by_age[age].size() - 1)]; + mio::abm::Person& person = world.get_person(id_rnd); + auto timePoint = mio::abm::TimePoint( + mio::get_offset_in_days(vacc_entry.first, simulation_beginning) * 24 * 60 * 60); + person.add_new_vaccination( + mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, timePoint)); + persons_by_age[age].erase( + std::remove(persons_by_age[age].begin(), persons_by_age[age].end(), id_rnd), + persons_by_age[age].end()); + vaccinated_persons[age].push_back(id_rnd); + } + } + for (uint32_t i = 0; i < vacc_entry.second[age].second; ++i) { + if (vaccinated_persons[age].size() == 0) { + mio::log_error("Not enough persons to vaccinate in age group we dont vaccinate if an age group is " + "fully vaccinated! "); + } + else { + // select random already vaccinated person and assign Vaccination + uint32_t id_rnd = vaccinated_persons[age][mio::UniformIntDistribution::get_instance()( + world.get_rng(), 0U, vaccinated_persons[age].size() - 1)]; + mio::abm::Person& person = world.get_person(id_rnd); + auto timePoint = mio::abm::TimePoint( + mio::get_offset_in_days(vacc_entry.first, simulation_beginning) * 24 * 60 * 60); + person.add_new_vaccination( + mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, timePoint)); + vaccinated_persons[age].erase( + std::remove(vaccinated_persons[age].begin(), vaccinated_persons[age].end(), id_rnd), + vaccinated_persons[age].end()); + } + } + } + } +} int stringToMinutes(const std::string& input) { @@ -223,10 +351,13 @@ void split_line(std::string string, std::vector* row) }); } -mio::abm::LocationType get_location_type(uint32_t acitivity_end) +mio::abm::LocationType get_location_type(const int location_type) { mio::abm::LocationType type; - switch (acitivity_end) { + switch (location_type) { + case 0: + type = mio::abm::LocationType::Home; + break; case 1: type = mio::abm::LocationType::Work; break; @@ -237,13 +368,7 @@ mio::abm::LocationType get_location_type(uint32_t acitivity_end) type = mio::abm::LocationType::BasicsShop; break; case 4: - type = mio::abm::LocationType::SocialEvent; // Freizeit - break; - case 5: - type = mio::abm::LocationType::BasicsShop; // Private Erledigung - break; - case 6: - type = mio::abm::LocationType::SocialEvent; // Sonstiges + type = mio::abm::LocationType::SocialEvent; break; default: type = mio::abm::LocationType::Home; @@ -393,7 +518,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t home_id = row[index["huid"]]; int target_location_id = row[index["loc_id_end"]]; - uint32_t activity_end = row[index["activity_end"]]; + uint32_t location_type = row[index["location_type"]]; mio::abm::GeographicalLocation location_long_lat = {(double)row[index["lon_end"]] / 1e+5, (double)row[index["lat_end"]] / 1e+5}; mio::abm::LocationId home; @@ -412,7 +537,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, target_location_id); // Check if location already exists also for home which have the same id (home_id = target_location_id) if (it_location == locations.end()) { location = world.add_location( - get_location_type(activity_end), + get_location_type(location_type), 1); // Assume one place has one activity, this may be untrue but not important for now(?) locations.insert({target_location_id, location}); world.get_individualized_location(location).set_geographical_location(location_long_lat); @@ -442,7 +567,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t trip_start = row[index["start_time"]]; uint32_t transport_mode = row[index["travel_mode"]]; - uint32_t acticity_end = row[index["activity_end"]]; + uint32_t activity_end = row[index["activity_end"]]; bool home_in_bs = true; // Add the trip to the trip list person and location must exist at this point @@ -479,7 +604,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, it_person->second.get_assigned_location_index(mio::abm::LocationType::Home), mio::abm::LocationType::Home}; world.get_trip_list().add_trip(mio::abm::Trip( it_person->second.get_person_id(), mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location, - start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(acticity_end))); + start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(activity_end))); } world.get_trip_list().use_weekday_trips_on_weekend(); world.parameters.get() = ids_in_bs; @@ -885,7 +1010,7 @@ void set_local_parameters(mio::abm::World& world) * @param t0 The start time of the Simulation. */ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, - int max_num_persons) + int max_num_persons, mio::Date start_date_sim) { //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -893,15 +1018,15 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con set_local_parameters(world); // Create the world object from statistical data. - create_world_from_data(world, (input_dir / "mobility/modified_braunschweig_result.csv").generic_string(), t0, + create_world_from_data(world, (input_dir / "mobility/braunschweig_result_ffa8_modified.csv").generic_string(), t0, max_num_persons); world.use_migration_rules(false); // Assign an infection state to each person. - assign_infection_state(world, t0); + // assign_infection_state(world, t0); // Assign vaccination status to each person. - // assign_vaccination_state(world, (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").generic_string()); + assign_vaccination_state(world, start_date_sim); //auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); @@ -1135,7 +1260,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 50000; + auto max_num_persons = 360000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1166,6 +1291,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s //Time this // auto start0 = std::chrono::high_resolution_clock::now(); determine_initial_infection_states_world(input_dir, start_date); + prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); // auto stop0 = std::chrono::high_resolution_clock::now(); // auto duration0 = std::chrono::duration(stop0 - start0); // std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" @@ -1177,12 +1304,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { - // Start the clock before create_sampled_world // auto start1 = std::chrono::high_resolution_clock::now(); // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groupss); - create_sampled_world(world, input_dir, t0, max_num_persons); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date); world.parameters.get() = 10; // Stop the clock after create_sampled_world and calculate the duration // auto stop1 = std::chrono::high_resolution_clock::now(); @@ -1507,7 +1633,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 3; + num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); } From 97b6f3f6a300a77ec5c80cdd58e19c02dc87f92c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 17:29:58 +0200 Subject: [PATCH 124/488] several fixes --- cpp/models/abm/common_abm_loggers.h | 68 +-- cpp/models/abm/parameters.h | 17 +- cpp/models/abm/person.h | 17 + cpp/simulations/analyze_bs_run.py | 16 +- cpp/simulations/check_bs_data.py | 24 +- cpp/simulations/cleanup_data.py | 44 +- cpp/simulations/paper_abm_bs_testing.cpp | 503 +++++++++++------------ 7 files changed, 355 insertions(+), 334 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index 1173c48839..9b37e722ef 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -177,27 +177,17 @@ struct LogInfectionState : mio::LogAlways { { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::InfectionState::Count)); auto curr_time = sim.get_time(); - auto ids_in_bs = sim.get_world().parameters.get(); - // If there is no interresting person ids to logged, log all persons. - if (ids_in_bs.size() == 0) { - for (auto&& location : sim.get_world().get_locations()) { - for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { - sum[inf_state] += location.get_subpopulation(curr_time, mio::abm::InfectionState(inf_state)); - } - } - } // Otherwise log accordingly - else { - for (auto&& person : sim.get_world().get_persons()) { - for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { - if (person.get_infection_state(curr_time) == mio::abm::InfectionState(inf_state) && - ids_in_bs.find(person.get_person_id()) != ids_in_bs.end()) { - sum[inf_state] += 1; - } + for (auto&& person : sim.get_world().get_persons()) { + for (uint32_t inf_state = 0; inf_state < (int)mio::abm::InfectionState::Count; inf_state++) { + if (person.get_infection_state(curr_time) == mio::abm::InfectionState(inf_state) && + person.get_should_be_logged()) { + sum[inf_state] += 1; } } } + return std::make_pair(curr_time, sum); } }; @@ -217,27 +207,19 @@ struct LogInfectionPerLocationType : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(mio::abm::LocationType::Count)); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. - if (ids_in_bs.size() == 0) { - for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { - sum[(int)(person.get_location().get_type())] += 1; - } - } - } + // Otherwise log accordingly - else { - for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && - (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { - sum[(int)(person.get_location().get_type())] += 1; - } + + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && + person.get_should_be_logged()) { + sum[(int)(person.get_location().get_type())] += 1; } } + return std::make_pair(curr_time, sum); } }; @@ -257,25 +239,15 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); auto prev_time = sim.get_prev_time(); auto curr_time = sim.get_time(); - auto ids_in_bs = sim.get_world().parameters.get(); // If there is no interresting person ids to logged, log all persons. - if (ids_in_bs.size() == 0) { - for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { - sum[(size_t)(person.get_age())] += 1; - } - } - } + // Otherwise log accordingly - else { - for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && - (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && - (ids_in_bs.find(person.get_person_id()) != ids_in_bs.end())) { - sum[(size_t)(person.get_age())] += 1; - } + for (auto&& person : sim.get_world().get_persons()) { + if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && + (person.get_should_be_logged())) { + sum[(size_t)(person.get_age())] += 1; } } diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index dc0b1b1d08..61064c69d1 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -644,21 +644,6 @@ struct AgeGroupGotoWork { } }; -/** - * @brief The set of Agent Ids to be logged. - */ -struct LogAgentIds { - using Type = std::unordered_set; - static Type get_default(AgeGroup /*num_agegroups*/) - { - return {}; - } - static std::string name() - { - return "LogAgentIds"; - } -}; - using ParametersBase = ParameterSet; + TestData>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index b4a2805e96..3f45260577 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -455,6 +455,22 @@ class Person return m_last_transport_mode; } + /** + * @brief Sett if a Person should be logged + */ + void set_should_be_logged(bool should_be_logged) + { + m_should_be_logged = should_be_logged; + } + + /** + * @brief Get if a Person should be logged + */ + bool get_should_be_logged() const + { + return m_should_be_logged; + } + /** * Get this persons RandomNumberGenerator counter. * @see mio::abm::Person::RandomNumberGenerator. @@ -522,6 +538,7 @@ class Person std::vector m_cells; ///< Vector with all Cell%s the Person visits at its current Location. mio::abm::TransportMode m_last_transport_mode; ///< TransportMode the Person used to get to its current Location. Counter m_rng_counter{0}; ///< counter for RandomNumberGenerator. + bool m_should_be_logged = true; ///< Flag to determine if the Person should be logged. }; } // namespace abm diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index e56dc600f7..ea48b9c019 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -66,13 +66,14 @@ def main(path, n_runs): def plot_infection_per_location_type(df): # Calculate moving average for all location types - df['MA_Home'] = gaussian_filter1d(df.Home.rolling(24*3, min_periods=1).mean(), sigma=15) - df['MA_School'] = gaussian_filter1d(df.School.rolling(24*3, min_periods=1).mean(), sigma=15) - df['MA_Work'] = gaussian_filter1d(df.Work.rolling(24*3, min_periods=1).mean(), sigma=15) - df['MA_SocialEvent'] = gaussian_filter1d(df.SocialEvent.rolling(24*3, min_periods=1).mean(), sigma=15) - df['MA_BasicsShop'] = gaussian_filter1d(df.BasicsShop.rolling(24*3, min_periods=1).mean(), sigma=15) - - df.plot(x='Time', y=['MA_Home', 'MA_School','MA_Work', 'MA_SocialEvent', 'MA_BasicsShop'], figsize=(10, 6)) + df['Home'] = gaussian_filter1d(df.Home.rolling(24*3, min_periods=1).mean(), sigma=15) + df['School'] = gaussian_filter1d(df.School.rolling(24*3, min_periods=1).mean(), sigma=15) + df['Work'] = gaussian_filter1d(df.Work.rolling(24*3, min_periods=1).mean(), sigma=15) + df['SocialEvent'] = gaussian_filter1d(df.SocialEvent.rolling(24*3, min_periods=1).mean(), sigma=15) + df['BasicsShop'] = gaussian_filter1d(df.BasicsShop.rolling(24*3, min_periods=1).mean(), sigma=15) + + df.plot(x='Time', y=['Home', 'School','Work', 'SocialEvent', 'BasicsShop'], figsize=(10, 6), title='Infections stratified according to location type') + @@ -131,7 +132,6 @@ def plot_results(path): f.close() # real world - # TODO f = h5py.File( path + "/Results_rki.h5", 'r') group = f['3101'] diff --git a/cpp/simulations/check_bs_data.py b/cpp/simulations/check_bs_data.py index 7ca7622cf3..dfbf054026 100644 --- a/cpp/simulations/check_bs_data.py +++ b/cpp/simulations/check_bs_data.py @@ -26,7 +26,7 @@ bd.rename( columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', 10: 'travelTime' , 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', 16: - 'ActivityBefore', 17: 'ActivityAfter', 18: 'age', 19: 'map_feature_key', 20: 'map_feature_value', 21: 'home_in_bs'}, + 'ActivityBefore', 17: 'ActivityAfter', 18: 'age', 19: 'home_in_bs', 20:'loation_type'}, inplace=True) dict_leisure = {1: 'work', 2: 'education', 3: 'Shopping', 4: 'free time', @@ -39,6 +39,28 @@ #count how many different activities are after the same location bd_same_loc = bd_same_loc.groupby(['loc_id_end']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# we want to see how many persons do a trip to another home that is not theirs +home_ids = bd[['hhID']].drop_duplicates() +# trips where the destination is a home and the person does not live there +trips_to_other_home = bd[['personID', 'hhID', 'loc_id_end']].loc[(bd['hhID']!=bd['loc_id_end']) & (bd['loc_id_end'].isin(home_ids['hhID']))] + +#check how many trips go to which location type +location_types = bd.groupby(['loation_type']).size() +location_types.plot(kind='bar') +plt.xlabel('Location type') +plt.ylabel('Number of trips') +plt.title('Number of trips to different location types') +plt.show() + + +#check how many trips go to which location type +location_types_activity_after = bd.groupby(['ActivityAfter']).size() +location_types_activity_after.plot(kind='bar') +plt.xlabel('Location type') +plt.ylabel('Number of trips') +plt.title('Number of trips to different location types') +plt.show() + # chek how many unique map_feature_keys and values are in the data map_feature_keys = bd[['map_feature_key']].drop_duplicates().size diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index f1ab923001..434608381f 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -264,7 +264,27 @@ def add_home_is_in_bs_column(pd): pd.at[index, 'home_in_bs'] = 1 return pd -def location_type_from_keys_and_values(key, value, intention): + + + +def location_type_from_keys_and_values(key, value, intention, key_value_pairs_counts_with_activity_after): + + most_probable_activity = 9999 + # we need to save for each key and value pair the amount of different activityAfter values + if key_value_pairs_counts_with_activity_after[(key_value_pairs_counts_with_activity_after['map_feature_key'] == key) & (key_value_pairs_counts_with_activity_after['map_feature_value'] == value)].shape[0] != 0: + # get the differnt activity_after values + activity_after_values = key_value_pairs_counts_with_activity_after[(key_value_pairs_counts_with_activity_after['map_feature_key'] == key) & (key_value_pairs_counts_with_activity_after['map_feature_value'] == value)] + # get the most common activity_after value + most_common_activity_after = activity_after_values[activity_after_values['counts'] == activity_after_values['counts'].max()]['activity_end'].values[0] + # if work is one of the activity_after values we assume that the location is a work location if its bigger than 30% of the total counts + # see if work is in the activity_after values + if activity_after_values[activity_after_values['activity_end'] == 1].shape[0] != 0: + if (activity_after_values[activity_after_values['activity_end'] == 1]['counts'] > 0.3 * key_value_pairs_counts_with_activity_after[(key_value_pairs_counts_with_activity_after['map_feature_key'] == key) & (key_value_pairs_counts_with_activity_after['map_feature_value'] == value)]['counts'].sum()).values[0]: + most_common_activity_after = 1 + # map the most common activity_after value to a location type + most_probable_activity = most_common_activity_after + + location_type = 'SocialEvent' if key == 'home': @@ -324,7 +344,7 @@ def location_type_from_keys_and_values(key, value, intention): if key == 'NaN': if intention == 1: location_type= 'Work' - if intention == 1: + if intention == 2: location_type= 'School' if intention == 3: location_type= 'BasicShop' @@ -337,6 +357,22 @@ def location_type_from_keys_and_values(key, value, intention): if intention == 7: location_type= 'Home' + if most_probable_activity != 9999: + if most_probable_activity == 1: + location_type = 'Work' + if most_probable_activity == 2: + location_type = 'School' + if most_probable_activity == 3: + location_type = 'BasicShop' + if most_probable_activity == 4: + location_type = 'SocialEvent' + if most_probable_activity == 5: + location_type = 'BasicShop' + if most_probable_activity == 6: + location_type = 'SocialEvent' + if most_probable_activity == 7: + location_type = 'Home' + # map from location type string to int location_type_dict = {'Home': 0, 'School': 2, 'Work': 1, 'BasicShop': 3, 'SocialEvent': 4} return location_type_dict[location_type] @@ -348,8 +384,9 @@ def assign_location_type(pd): else: print("Column 'location_type' is not present in DataFrame.") pd['location_type'] = 'SocialEvent' + test_pd = pd[['activity_end', 'map_feature_key', 'map_feature_value']].groupby(['map_feature_key', 'map_feature_value','activity_end']).size().reset_index(name='counts') for index, row in pd.iterrows(): - pd.at[index, 'location_type'] = location_type_from_keys_and_values( row['map_feature_key'], row['map_feature_value'], row['activity_end']) + pd.at[index, 'location_type'] = location_type_from_keys_and_values( row['map_feature_key'], row['map_feature_value'], row['activity_end'], test_pd) return pd PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8.csv" @@ -368,6 +405,7 @@ def assign_location_type(pd): else: print("Column headers are not correct") + bd_new = add_home_is_in_bs_column(bd) print('Added flag for persons who live in Braunschweig.') bd_new = add_home_ids(bd_new) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8dd7eabeaa..9f02897e37 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -264,7 +264,7 @@ void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_begin for (size_t age = 0; age < vacc_entry.second.size(); ++age) { for (uint32_t i = 0; i < vacc_entry.second[age].first; ++i) { if (persons_by_age[age].size() == 0) { - mio::log_error("Not enough persons to vaccinate in age group we dont vaccinate if an age group is"); + mio::log_error("Not enough to vacc people 1st time"); } else { // select random person and assign Vaccination @@ -283,8 +283,7 @@ void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_begin } for (uint32_t i = 0; i < vacc_entry.second[age].second; ++i) { if (vaccinated_persons[age].size() == 0) { - mio::log_error("Not enough persons to vaccinate in age group we dont vaccinate if an age group is " - "fully vaccinated! "); + mio::log_error("Not enough vaccinated people to vacc 2nd time! "); } else { // select random already vaccinated person and assign Vaccination @@ -462,7 +461,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); uint32_t person_id = row[index["puid"]]; - auto it_person_id = person_ids.find(person_id); + + auto it_person_id = person_ids.find(person_id); if (it_person_id == person_ids.end()) { if (number_of_persons >= max_number_persons) break; //This is okay because the data is sorted by person_id @@ -516,24 +516,32 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (person_ids.find(person_id) == person_ids.end()) break; - uint32_t home_id = row[index["huid"]]; - int target_location_id = row[index["loc_id_end"]]; - uint32_t location_type = row[index["location_type"]]; - mio::abm::GeographicalLocation location_long_lat = {(double)row[index["lon_end"]] / 1e+5, - (double)row[index["lat_end"]] / 1e+5}; + uint32_t home_id = row[index["huid"]]; + mio::abm::LocationId home; auto it_home = locations.find(home_id); if (it_home == locations.end()) { home = world.add_location(mio::abm::LocationType::Home, 1); locations.insert({home_id, home}); } - else { - home = it_home->second; - } + } - mio::abm::LocationId location; + fin.clear(); + fin.seekg(0); + std::getline(fin, line); // Skip header row + while (std::getline(fin, line)) { + row.clear(); + + // read columns in this row + split_line(line, &row); + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); - auto it_location = locations.find( + mio::abm::LocationId location; + int target_location_id = row[index["loc_id_end"]]; + uint32_t location_type = row[index["location_type"]]; + mio::abm::GeographicalLocation location_long_lat = {(double)row[index["lon_end"]] / 1e+5, + (double)row[index["lat_end"]] / 1e+5}; + auto it_location = locations.find( target_location_id); // Check if location already exists also for home which have the same id (home_id = target_location_id) if (it_location == locations.end()) { location = world.add_location( @@ -543,10 +551,10 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, world.get_individualized_location(location).set_geographical_location(location_long_lat); } } + fin.clear(); fin.seekg(0); std::getline(fin, line); // Skip header row - std::unordered_set ids_in_bs; // Add the persons and trips while (std::getline(fin, line)) { @@ -568,8 +576,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t trip_start = row[index["start_time"]]; uint32_t transport_mode = row[index["travel_mode"]]; uint32_t activity_end = row[index["activity_end"]]; - bool home_in_bs = true; - + bool home_in_bs = row[index["home_in_bs"]]; + home_in_bs = false; // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; @@ -583,19 +591,35 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, auto first_location_id = it_first_location_id->second.first; auto first_location = locations.find(first_location_id)->second; auto& person = world.add_person(first_location, determine_age_group(age)); + auto home = locations.find(home_id)->second; + //check of home is found + + if (locations.find(home_id) == locations.end()) { + mio::log_error("Home not found"); + std::cout << home_id << " " << person_id << std::endl; + } if (home_in_bs) { - // ids_in_bs.insert(person_id); + person.set_should_be_logged(true); } - auto home = locations.find(home_id)->second; + else { + person.set_should_be_logged(false); + } + person.set_assigned_location(home); person.set_assigned_location(hospital); person.set_assigned_location(icu); persons.insert({person_id, person}); it_person = persons.find(person_id); + auto test = person.get_assigned_location_index(mio::abm::LocationType::Home); + if (test == 4294967295) { + std::cout << "Home ID: " << home_id << " and person ID: " << person_id << std::endl; + } + } + if (target_location.type != mio::abm::LocationType::Home) { + it_person->second.set_assigned_location( + target_location); //This assumes that we only have in each tripchain only one location type for each person } - it_person->second.set_assigned_location( - target_location); //This assumes that we only have in each tripchain only one location type for each person // if (locations.find(start_location_id) == locations.end()) { // // For trips where the start location is not known use Home instead @@ -607,7 +631,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(activity_end))); } world.get_trip_list().use_weekday_trips_on_weekend(); - world.parameters.get() = ids_in_bs; // //Some Data about the world: // //write how many persons are in each home @@ -742,7 +765,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.66; //all masks have a 0.66 protection factor for now + params.get() = 0.33; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -1023,19 +1046,11 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con world.use_migration_rules(false); // Assign an infection state to each person. - // assign_infection_state(world, t0); + assign_infection_state(world, t0); // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); - //auto t_lockdown = mio::abm::TimePoint(0) + mio::abm::days(20); - - // During the lockdown, 25% of people work from home and schools are closed for 90% of students. - // Social events are very rare. - //mio::abm::set_home_office(t_lockdown, 0.25, world.parameters); - //mio::abm::set_school_closure(t_lockdown, 0.9, world.parameters); - //mio::abm::close_social_events(t_lockdown, 0.9, world.parameters); - // Verschiedene Fälle: //1. ohne testing scheme //2. testing scheme: Test bei Symptomen (unabh. von Location, 1x am Tag, InfectedSymptomatic, 70% der Bevölkerung) ab Tag 0 @@ -1260,7 +1275,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 360000; + auto max_num_persons = 25000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1274,50 +1289,41 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); - // auto run_idx = size_t(1); // The run index - // auto save_result_result = mio::IOResult(mio::success()); // Variable informing over successful IO operations - - // int tid = -1; - // #pragma omp parallel private(tid) // Start of parallel region: forks threads - // { - // tid = omp_get_thread_num(); // default is number of CPUs on machine - // printf("Hello World from thread = %d and rank = %d\n", tid, rank); - // if (tid == 0) { - // printf("Number of threads = %d\n", omp_get_num_threads()); - // } - // } // ** end of the the parallel: joins threads + int tid = -1; +#pragma omp parallel private(tid) // Start of parallel region: forks threads + { + tid = omp_get_thread_num(); // default is number of CPUs on machine + printf("Hello World from thread = %d and rank = %d\n", tid, rank); + if (tid == 0) { + printf("Number of threads = %d\n", omp_get_num_threads()); + } + } // ** end of the the parallel: joins threads // Determine inital infection state distribution //Time this - // auto start0 = std::chrono::high_resolution_clock::now(); + auto start0 = std::chrono::high_resolution_clock::now(); determine_initial_infection_states_world(input_dir, start_date); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - // auto stop0 = std::chrono::high_resolution_clock::now(); - // auto duration0 = std::chrono::duration(stop0 - start0); - // std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" - // << std::endl; - - // Create one world for all simulations that will be copied - // auto world = mio::abm::World(num_age_groupss); - // create_sampled_world(world, input_dir, t0, max_num_persons); + auto stop0 = std::chrono::high_resolution_clock::now(); + auto duration0 = std::chrono::duration(stop0 - start0); + std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" + << std::endl; // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { // Start the clock before create_sampled_world - // auto start1 = std::chrono::high_resolution_clock::now(); + auto start1 = std::chrono::high_resolution_clock::now(); // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groupss); create_sampled_world(world, input_dir, t0, max_num_persons, start_date); - world.parameters.get() = 10; + world.parameters.get() = 3.5; // Stop the clock after create_sampled_world and calculate the duration - // auto stop1 = std::chrono::high_resolution_clock::now(); - // auto duration1 = std::chrono::duration(stop1 - start1); - // std::cout << "Time taken by create_sampled_world: " << duration1.count() << " seconds" << std::endl; - - // auto world_copy = world; // COPY CONSTRUCTOR DOESN'T WORK. LOCATIONS AREN'T ASSIGNED! - auto sim = mio::abm::Simulation(t0, std::move(world)); - + auto stop1 = std::chrono::high_resolution_clock::now(); + auto duration1 = std::chrono::duration(stop1 - start1); + std::cout << "Time taken by create_sampled_world: " << duration1.count() << " seconds" << std::endl; + auto sim = mio::abm::Simulation(t0, std::move(world)); + bool npis_on = true; //output object // mio::History @@ -1330,207 +1336,199 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - // Collect the id of location in world. - // std::vector loc_ids; - // for (auto& location : sim.get_world().get_locations()) { - // loc_ids.push_back(location.get_index()); - // } - - // Start the clock before sim.advance - // auto start2 = std::chrono::high_resolution_clock::now(); - // Advance the world to tmax - // sim.advance(tmax, historyPersonInf, historyInfectionPerLocationType, historyInfectionPerAgeGroup, - // historyPersonInfDelta, historyInfectionStatePerAgeGroup); - - auto location_it = sim.get_world().get_locations(); - // Advance the world with respective npis - // 1. testing schemes in schools - auto testing_min_time_school = mio::abm::days(7); - auto probability_school = 1.0; - auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 - auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 - auto test_type_school = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = - sim.get_world().parameters.get()[test_type_school]; // Test parameters - auto testing_criteria_school = mio::abm::TestingCriteria(); - auto testing_scheme_school = - mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, - end_date_test_school, test_parameters, probability_school); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - testing_scheme_school); - - // // 2. testing schemes in work places for 35% of random workplaces - - std::vector work_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::Work) { - work_location_ids.push_back(location.get_index()); + // / NPIS// + auto start2 = std::chrono::high_resolution_clock::now(); + if (npis_on) { + + const auto location_it = sim.get_world().get_locations(); + // Advance the world with respective npis + // 1. testing schemes in schools + auto testing_min_time_school = mio::abm::days(7); + auto probability_school = 1.0; + auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 + auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 + auto test_type_school = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters = + sim.get_world().parameters.get()[test_type_school]; // Test parameters + auto testing_criteria_school = mio::abm::TestingCriteria(); + auto testing_scheme_school = + mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, + end_date_test_school, test_parameters, probability_school); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_school); + + // 2. testing schemes in work places for 35% of random workplaces + + std::vector work_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::Work) { + work_location_ids.push_back(location.get_index()); + } } - } - //take 35% of work locations - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); - auto num_work_locations = (int)(0.35 * work_location_ids.size()); - std::vector work_location_ids_35(work_location_ids.begin(), - work_location_ids.begin() + num_work_locations); - auto testing_min_time_work = mio::abm::days(1); - auto probability_work = 1.0; - auto start_date_test_work = mio::abm::TimePoint(0); - auto end_date_test_work = mio::abm::TimePoint(tmax); - auto test_type_work = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_work = - sim.get_world().parameters.get()[test_type_work]; // Test parameters - auto testing_criteria_work = mio::abm::TestingCriteria(); - auto testing_scheme_work = - mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, - end_date_test_work, test_parameters_work, probability_work); - for (auto& location : location_it) { - if (std::find(work_location_ids_35.begin(), work_location_ids_35.end(), location.get_index()) != - work_location_ids_35.end()) { - sim.get_world().get_testing_strategy().add_testing_scheme(location.get_type(), testing_scheme_work); + //take 35% of work locations + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); + auto num_work_locations = (int)(0.35 * work_location_ids.size()); + std::vector work_location_ids_35(work_location_ids.begin(), + work_location_ids.begin() + num_work_locations); + auto testing_min_time_work = mio::abm::days(1); + auto probability_work = 1.0; + auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); + auto end_date_test_work = mio::abm::TimePoint(tmax); + auto test_type_work = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_work = + sim.get_world().parameters.get()[test_type_work]; // Test parameters + auto testing_criteria_work = mio::abm::TestingCriteria(); + auto testing_scheme_work = + mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, + end_date_test_work, test_parameters_work, probability_work); + for (auto& location_id : work_location_ids_35) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); } - } - //2.5 plus testing schemes at 20% of basics shops - std::vector basics_shop_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - basics_shop_location_ids.push_back(location.get_index()); + // 2.5 plus testing schemes at 20 % of basics shops + std::vector basics_shop_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + basics_shop_location_ids.push_back(location.get_index()); + } } - } - //take 20% of basics shop locations - std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); - auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); - std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), - basics_shop_location_ids.begin() + num_basics_shop_locations); - auto testing_min_time_basics_shop = mio::abm::days(2); - auto probability_basics_shop = 1.0; - auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); - auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); - auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_basics_shop = - sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters - auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); - auto testing_scheme_basics_shop = mio::abm::TestingScheme( - testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, - end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); - for (auto& location : location_it) { - if (std::find(basics_shop_location_ids_20.begin(), basics_shop_location_ids_20.end(), - location.get_index()) != basics_shop_location_ids_20.end()) { - sim.get_world().get_testing_strategy().add_testing_scheme(location.get_type(), - testing_scheme_basics_shop); + //take 20% of basics shop locations + std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); + auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); + std::vector basics_shop_location_ids_20( + basics_shop_location_ids.begin(), basics_shop_location_ids.begin() + num_basics_shop_locations); + auto testing_min_time_basics_shop = mio::abm::days(2); + auto probability_basics_shop = 1.0; + auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); + auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); + auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_basics_shop = + sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters + auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); + auto testing_scheme_basics_shop = mio::abm::TestingScheme( + testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, + end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); + for (auto& location_id : basics_shop_location_ids_20) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); } - } - // 3. Mask schemes for all locations - // First set all locations to have mask usage, we need ffp2 masks - for (auto& location : location_it) { - location.set_required_mask(mio::abm::MaskType::FFP2); - if (location.get_type() == mio::abm::LocationType::Home) { - location.set_npi_active(false); - } - else { - location.set_npi_active(true); + // 3. Mask schemes for all locations + // First set all locations to have mask usage, we need ffp2 masks + for (auto& location : location_it) { + location.set_required_mask(mio::abm::MaskType::FFP2); + if (location.get_type() == mio::abm::LocationType::Home) { + location.set_npi_active(false); + } + else { + location.set_npi_active(true); + } } - } - // 4. Dampings for all kinds of places - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.0); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), - 0.5); // from 2021-04-12 till 2021-05-30 (end) - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + // // 4. Dampings for schools and Basic shops + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::School) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.0); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), + 0.5); // from 2021-04-12 till 2021-05-30 (end) + } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + } } - } - //5. add capacity limits to some locations - //first we need two lists, one for 50% of random social event locations and the other list for the other 50% - //1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ - // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] - // ----> Divide Social Event locations into a 50/50 split. First 50% get the restrictive capacity - std::vector social_event_location_ids_small; - std::vector social_event_location_ids_big; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::SocialEvent) { - social_event_location_ids_small.push_back(location.get_index()); - } - } - //take 50% of social event locations - std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); - auto num_social_event_locations_small = (int)(0.5 * social_event_location_ids_small.size()); - social_event_location_ids_big.insert( - social_event_location_ids_big.end(), social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_small); - social_event_location_ids_small.erase(social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + - num_social_event_locations_small); - - //add capacity limits on day one - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); + // 5. add capacity limits to some locations + // first we need two lists, one for 50% of random social event locations and the other list for the other 50% + // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ + // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] + // ----> Divide Social Event locations into a 50/50 split. First 50% get the restrictive capacity + std::vector social_event_location_ids_small; + std::vector social_event_location_ids_big; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::SocialEvent) { + social_event_location_ids_small.push_back(location.get_index()); + } } - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(0, 0); + //take 50% of social event locations + std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); + auto num_social_event_locations_small = (int)(0.5 * social_event_location_ids_small.size()); + social_event_location_ids_big.insert( + social_event_location_ids_big.end(), social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_small); + social_event_location_ids_small.erase(social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + + num_social_event_locations_small); + + //add capacity limits on day one + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(20, 0); + } + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + location.set_capacity(5, 0); + } } - } - sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); - std::cout << "day 14 finished" << std::endl; - // small social events to capacity 5 - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(5, 0); + sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + std::cout << "day 14 finished" << std::endl; + // small social events to capacity 5 + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(10, 0); + } } - } - sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); - std::cout << "day 42 finished" << std::endl; - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(false); + sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + std::cout << "day 42 finished" << std::endl; + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(false); + } } - } - sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); - std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(2, 0); + sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(4, 0); + } + //90% of big social events get reopened and caopacity will be unlimited + int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + number_of_big_social_events--; + if (number_of_big_social_events >= 0) { + location.set_capacity(std::numeric_limits::max(), 0); + } + } } - //90% of big social events get reopened and caopacity will be unlimited - int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - number_of_big_social_events--; - if (number_of_big_social_events >= 0) { - location.set_capacity(std::numeric_limits::max(), 0); + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(true); } } + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + historyInfectionPerAgeGroup); + std::cout << "day 90 finished" << std::endl; } - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(true); - } + else { + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + historyInfectionPerAgeGroup); } - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, - historyInfectionPerAgeGroup); - std::cout << "day 90 finished" << std::endl; ////Advance till here // Stop the clock after sim.advance and calculate the duration - // auto stop2 = std::chrono::high_resolution_clock::now(); - // auto duration2 = std::chrono::duration(stop2 - start2); - // std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; + auto stop2 = std::chrono::high_resolution_clock::now(); + auto duration2 = std::chrono::duration(stop2 - start2); + std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; // TODO: update result of the simulation to be a vector of location result. auto temp_sim_infection_per_loc_tpye = @@ -1542,19 +1540,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Push result of the simulation back to the result vector ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); - ensemble_infection_per_age_group.push_back(temp_sim_infection_per_age_group); + ensemble_infection_per_age_group.emplace_back(temp_sim_infection_per_age_group); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); // Option to save the current run result to file - /* if (save_result_result && save_single_runs) { - auto result_dir_run = result_dir / ("abm_result_run_" + std::to_string(run_idx) + ".h5"); - BOOST_OUTCOME_TRY(save_result(ensemble_results.back(), {0}, 1, result_dir_run.string())); - result_dir_run = result_dir / ("abm_result_infections_per_loc_run_" + std::to_string(run_idx) + ".h5"); - BOOST_OUTCOME_TRY( - save_result(ensemble_results_infections_per_loc.back(), loc_type_ids, 1, result_dir_run.string())); - result_dir_run = result_dir / ("abm_result_infections_per_age_run_" + std::to_string(run_idx) + ".h5"); - BOOST_OUTCOME_TRY( - save_result(ensemble_results_infections_per_age.back(), age_group_ids, 1, result_dir_run.string())); - } */ // write_log_to_file_person_and_location_data(historyPersonInf); // write_log_to_file_trip_data(historyPersonInfDelta); // write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup, result_dir); @@ -1578,13 +1566,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s //gather results auto final_ensemble_infection_state_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); - //auto final_ensemble_infection_per_loc_type = - // gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type); + auto final_ensemble_infection_per_loc_type = + gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type); if (rank == 0) { BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); - // BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type, ensemble_params, {0}, - // result_dir / "infection_per_location_type/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type, ensemble_params, {0}, + result_dir / "infection_per_location_type/", save_single_runs)); } #else @@ -1596,7 +1584,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s #endif printf("done.\n"); //write_txt_file_for_graphical_compartment_output(ensemble_infection_state_per_age_group); - // BOOST_OUTCOME_TRY(save_result_result); return mio::success(); } From b9c6a122dc61e855d0240290112b67c22bef6e00 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 17:43:13 +0200 Subject: [PATCH 125/488] minor fixes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 4 ++-- cpp/models/abm/location.h | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 12 +++++++----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index d64ca960d6..8568b8e7d6 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -55,8 +55,8 @@ bool Location::entry_allowed(Person::RandomNumberGenerator& rng, const mio::abm: else { // We want to go through the npi vector and get the last entry that is smaller than t auto it = std::upper_bound(temp_npi_damping.begin(), temp_npi_damping.end(), t, - [](TimePoint t, const std::pair& p) { - return t < p.first; + [](TimePoint tp, const std::pair& p) { + return tp < p.first; }); //we need the one entry before the upper bound if (it == temp_npi_damping.begin()) { diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index b9db59a44c..c50d47d64d 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -267,7 +267,7 @@ class Location */ void add_damping(TimePoint t, double p); - bool entry_allowed(Person::RandomNumberGenerator& rng,const mio::abm::TimePoint t) const; + bool entry_allowed(Person::RandomNumberGenerator& rng, const mio::abm::TimePoint t) const; /** * @brief Set the required type of mask for entering this Location. diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9f02897e37..26d4605678 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1200,11 +1200,13 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { // PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < persons.size(); ++i) { - auto& p = persons[i]; - auto index = (((size_t)(mio::abm::InfectionState::Count)) * ((uint32_t)p.get_age().get())) + - ((uint32_t)p.get_infection_state(curr_time)); - // PRAGMA_OMP(atomic) - sum[index] += 1; + auto& p = persons[i]; + if (p.get_should_be_logged()) { + auto index = (((size_t)(mio::abm::InfectionState::Count)) * ((uint32_t)p.get_age().get())) + + ((uint32_t)p.get_infection_state(curr_time)); + // PRAGMA_OMP(atomic) + sum[index] += 1; + } } return std::make_pair(curr_time, sum); } From 1d8931a85635fed3294f268acfa4b45a8c7d3485 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 17:54:00 +0200 Subject: [PATCH 126/488] bs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 26d4605678..20f5fedcb2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -577,7 +577,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t transport_mode = row[index["travel_mode"]]; uint32_t activity_end = row[index["activity_end"]]; bool home_in_bs = row[index["home_in_bs"]]; - home_in_bs = false; // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; From 74b40f626e5e01640f5ae1f376767873d847615d Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 31 May 2024 17:55:35 +0200 Subject: [PATCH 127/488] Allow infections to be added at any random point between two infection states --- cpp/models/abm/infection.cpp | 94 ++++++++++++++++-------- cpp/models/abm/infection.h | 9 ++- cpp/models/abm/location.cpp | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 18 ++--- 4 files changed, 75 insertions(+), 48 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 728509a86d..d987975e61 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -120,14 +120,17 @@ TimePoint Infection::draw_infection_course(Person::RandomNumberGenerator& rng, A std::pair latest_protection) { assert(age.get() < params.get_num_groups()); - TimePoint start_date = draw_infection_course_backward(rng, age, params, init_date, init_state); - draw_infection_course_forward(rng, age, params, init_date, init_state, latest_protection); + TimePoint start_of_init_state = + draw_infection_course_forward(rng, age, params, init_date, init_state, latest_protection); + TimePoint start_date = draw_infection_course_backward(rng, age, params, start_of_init_state, init_state); + return start_date; } -void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng, AgeGroup age, - const Parameters& params, TimePoint init_date, InfectionState start_state, - std::pair latest_exposure) +TimePoint Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng, AgeGroup age, + const Parameters& params, TimePoint init_date, + InfectionState start_state, + std::pair latest_exposure) { assert(age.get() < params.get_num_groups()); auto t = init_date; @@ -135,30 +138,55 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng auto time_in_state = params.get()[{ m_virus_variant, age}]; // time distribution parameters for current infection state InfectionState next_state{start_state}; // next state to enter - m_infection_course.push_back(std::pair(t, next_state)); + auto& uniform_dist = UniformDistribution::get_instance(); - ScalarType p; // uniform random draws from [0, 1] + ScalarType p = 1; // uniform random draws from [0, 1] + bool init_state = false; + TimePoint start_of_init_state = init_date; + + // helper lambda for init_state + auto determine_time_period = [&]() { + if (!init_state) { + // randomly initialize the infetion when it is not initialized at the time of transmission + p = uniform_dist(rng); // a random amount of time that has passed since begin of the initial InfectionState + auto time_draw = time_in_state.get_distribution_instance()(rng, time_in_state.params); + time_period = days(p * time_draw); + start_of_init_state = t - days((1 - p) * time_draw); + init_state = true; + } + else { + time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + } + }; + + // randomly draw the rest of the InfectionState tree while ((next_state != InfectionState::Recovered && next_state != InfectionState::Dead)) { switch (next_state) { + + case InfectionState::Susceptible: { + next_state = InfectionState::Exposed; + time_period = days(0); + init_state = true; + } case InfectionState::Exposed: { // roll out how long until infected without symptoms time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); - next_state = InfectionState::InfectedNoSymptoms; + determine_time_period(); + next_state = InfectionState::InfectedNoSymptoms; } break; case InfectionState::InfectedNoSymptoms: { // roll out next infection step p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedSymptoms; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::InfectedSymptoms; } else { - next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::Recovered; } } break; case InfectionState::InfectedSymptoms: { @@ -173,14 +201,14 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng } if (p < (1 - severity_protection_factor) * params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedSevere; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::InfectedSevere; } else { - next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::Recovered; } } break; @@ -189,14 +217,14 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::InfectedCritical; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::InfectedCritical; } else { - next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::Recovered; } } break; @@ -205,14 +233,14 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng p = uniform_dist(rng); if (p < params.get()[{m_virus_variant, age}]) { - next_state = InfectionState::Dead; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::Dead; } else { - next_state = InfectionState::Recovered; time_in_state = params.get()[{m_virus_variant, age}]; - time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); + determine_time_period(); + next_state = InfectionState::Recovered; } } break; @@ -222,6 +250,7 @@ void Infection::draw_infection_course_forward(Person::RandomNumberGenerator& rng t = t + time_period; m_infection_course.push_back({t, next_state}); } + return start_of_init_state; } TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerator& rng, AgeGroup age, @@ -229,7 +258,7 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato InfectionState init_state) { assert(age.get() < params.get_num_groups()); - auto start_date = init_date; + auto t = init_date; TimeSpan time_period{}; // time period for current infection state auto time_in_state = params.get()[{ m_virus_variant, age}]; // time distribution parameters for current infection state @@ -237,9 +266,12 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato auto& uniform_dist = UniformDistribution::get_instance(); ScalarType p; // uniform random draws from [0, 1] - while ((previous_state != InfectionState::Exposed)) { - switch (previous_state) { + if (previous_state != InfectionState::Susceptible) { + m_infection_course.insert(m_infection_course.begin(), {t, previous_state}); + } + while ((previous_state != InfectionState::Susceptible && previous_state != InfectionState::Exposed)) { + switch (previous_state) { case InfectionState::InfectedNoSymptoms: { time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); @@ -306,10 +338,10 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato default: break; } - start_date = start_date - time_period; - m_infection_course.insert(m_infection_course.begin(), {start_date, previous_state}); + t = t - time_period; + m_infection_course.insert(m_infection_course.begin(), {t, previous_state}); } - return start_date; + return t; } } // namespace abm diff --git a/cpp/models/abm/infection.h b/cpp/models/abm/infection.h index 82875be38d..273ca95ecf 100644 --- a/cpp/models/abm/infection.h +++ b/cpp/models/abm/infection.h @@ -63,7 +63,7 @@ class Infection * @param[in] detected [Default: false] If the Infection is detected. */ Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, AgeGroup age, const Parameters& params, - TimePoint init_date, InfectionState init_state = InfectionState::Exposed, + TimePoint init_date, InfectionState init_state = InfectionState::Susceptible, std::pair latest_exposure = {ExposureType::NoProtection, TimePoint(0)}, bool detected = false); @@ -140,10 +140,11 @@ class Infection * @param[in] params Parameters of the Model. * @param[in] init_date Date of initializing the Infection. * @param[in] init_state #InfectionState at time of initializing the Infection. + * @return The TimePoint when the initial #InfectionState started. */ - void draw_infection_course_forward(Person::RandomNumberGenerator& rng, AgeGroup age, const Parameters& params, - TimePoint init_date, InfectionState start_state, - std::pair latest_protection); + TimePoint draw_infection_course_forward(Person::RandomNumberGenerator& rng, AgeGroup age, const Parameters& params, + TimePoint init_date, InfectionState start_state, + std::pair latest_protection); /** * @brief Determine ViralLoad course and Infection course subsequent to the given start_state. diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index d64ca960d6..573f340db5 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -129,7 +129,7 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time local_indiv_expected_trans); // use VirusVariant::Count for no virus submission if (virus != VirusVariant::Count) { person.add_new_infection(Infection(rng, virus, age_receiver, global_params, t + dt / 2, - mio::abm::InfectionState::Exposed, person.get_latest_protection(t), + mio::abm::InfectionState::Susceptible, person.get_latest_protection(t), false)); // Starting time in first approximation } } diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8dd7eabeaa..0715b1b76b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -59,7 +59,7 @@ const std::map infection_ {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; mio::CustomIndexArray initial_infection_distribution{ - {mio::AgeGroup(num_age_groupss), mio::osecir::InfectionState::Count}, 0.005}; + {mio::AgeGroup(num_age_groupss), mio::osecir::InfectionState::Count}, 0.5}; std::map>> vacc_map; @@ -83,7 +83,6 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); - //std::cout << initial_infection_distribution.array() << std::endl; // extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days } @@ -99,14 +98,8 @@ void assign_infection_state_prob(mio::abm::World& world, mio::abm::TimePoint t) auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); - // std::cout << "INfection dist" << initial_infection_distribution.slice(person.get_age()).as_array().array() << std::endl; - - //bool detected = false; + if (infection_state != mio::osecir::InfectionState::Susceptible) { - //if (infection_state == mio::osecir::InfectionState::InfectedNoSymptomsConfirmed || - // infection_state == mio::osecir::InfectionState::InfectedSymptomsConfirmed) { - // detected = true; - //} person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), world.parameters, t, infection_state_map.at(infection_state))); } @@ -1020,10 +1013,11 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Create the world object from statistical data. create_world_from_data(world, (input_dir / "mobility/braunschweig_result_ffa8_modified.csv").generic_string(), t0, max_num_persons); + world.use_migration_rules(false); // Assign an infection state to each person. - // assign_infection_state(world, t0); + assign_infection_state(world, t0); // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); @@ -1260,7 +1254,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 360000; + auto max_num_persons = 1000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1607,7 +1601,7 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 97bcfe3f62108a2cb1bd1c1502511508a55318e2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 17:59:03 +0200 Subject: [PATCH 128/488] quick test for mpi off Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index f9cf4d29f4..80b8303034 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -15,7 +15,7 @@ option(MEMILIO_SANITIZE_ADDRESS "Enable address sanitizer." OFF) option(MEMILIO_SANITIZE_UNDEFINED "Enable undefined behavior sanitizer." OFF) option(MEMILIO_BUILD_SHARED_LIBS "Build memilio as a shared library." ON) option(MEMILIO_BUILD_STATIC_LIBS "Build memilio as a static library." ON) -option(MEMILIO_ENABLE_MPI "Build memilio with MPI." ON) +option(MEMILIO_ENABLE_MPI "Build memilio with MPI." OFF) option(MEMILIO_ENABLE_OPENMP "Enable Multithreading with OpenMP." ON) mark_as_advanced(MEMILIO_USE_BUNDLED_SPDLOG MEMILIO_SANITIZE_ADDRESS MEMILIO_SANITIZE_UNDEFINED) From acbe1def6c3cd0b47205907c388de7ffec6fd211 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 18:11:56 +0200 Subject: [PATCH 129/488] set mpi again to on Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 80b8303034..f9cf4d29f4 100644 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -15,7 +15,7 @@ option(MEMILIO_SANITIZE_ADDRESS "Enable address sanitizer." OFF) option(MEMILIO_SANITIZE_UNDEFINED "Enable undefined behavior sanitizer." OFF) option(MEMILIO_BUILD_SHARED_LIBS "Build memilio as a shared library." ON) option(MEMILIO_BUILD_STATIC_LIBS "Build memilio as a static library." ON) -option(MEMILIO_ENABLE_MPI "Build memilio with MPI." OFF) +option(MEMILIO_ENABLE_MPI "Build memilio with MPI." ON) option(MEMILIO_ENABLE_OPENMP "Enable Multithreading with OpenMP." ON) mark_as_advanced(MEMILIO_USE_BUNDLED_SPDLOG MEMILIO_SANITIZE_ADDRESS MEMILIO_SANITIZE_UNDEFINED) From 8552c8f91e0ce440dfb8ecaa5b8e6f4de6e571ee Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 18:43:47 +0200 Subject: [PATCH 130/488] quick pathfiox Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index af018fce19..2ea462e6e9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -98,7 +98,7 @@ void assign_infection_state_prob(mio::abm::World& world, mio::abm::TimePoint t) auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); - + if (infection_state != mio::osecir::InfectionState::Susceptible) { person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), world.parameters, t, infection_state_map.at(infection_state))); @@ -1589,7 +1589,7 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From b93c4639664906d86663ab84116d2d63fe9e3fad Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 19:50:40 +0200 Subject: [PATCH 131/488] bug fix exposed not added Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/common_abm_loggers.h | 2 +- cpp/models/abm/infection.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index 9b37e722ef..e7cea003a6 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -213,7 +213,7 @@ struct LogInfectionPerLocationType : mio::LogAlways { // Otherwise log accordingly for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && + if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Susceptible) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && person.get_should_be_logged()) { sum[(int)(person.get_location().get_type())] += 1; diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index d987975e61..22be615ec4 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -139,7 +139,7 @@ TimePoint Infection::draw_infection_course_forward(Person::RandomNumberGenerator m_virus_variant, age}]; // time distribution parameters for current infection state InfectionState next_state{start_state}; // next state to enter - auto& uniform_dist = UniformDistribution::get_instance(); + auto& uniform_dist = UniformDistribution::get_instance(); ScalarType p = 1; // uniform random draws from [0, 1] bool init_state = false; TimePoint start_of_init_state = init_date; @@ -165,9 +165,9 @@ TimePoint Infection::draw_infection_course_forward(Person::RandomNumberGenerator case InfectionState::Susceptible: { next_state = InfectionState::Exposed; - time_period = days(0); + time_period = mio::abm::hours(0); init_state = true; - } + } break; case InfectionState::Exposed: { // roll out how long until infected without symptoms time_in_state = params.get()[{m_virus_variant, age}]; From 1b45b8eb5c715e28185fdd5711ca28c4b62d08c9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 19:53:59 +0200 Subject: [PATCH 132/488] cluster check Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2ea462e6e9..96e5ee8042 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1270,7 +1270,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 25000; + auto max_num_persons = 500000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1589,7 +1589,7 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project/loki/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 9c4a6550ba12213ef9a83254dc65d24da3759d7e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 21:30:37 +0200 Subject: [PATCH 133/488] minor changes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/common_abm_loggers.h | 4 +- cpp/simulations/analyze_bs_run.py | 13 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 58 +++++++++--------------- 3 files changed, 30 insertions(+), 45 deletions(-) diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index e7cea003a6..3fe1602e98 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -213,7 +213,7 @@ struct LogInfectionPerLocationType : mio::LogAlways { // Otherwise log accordingly for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Susceptible) && + if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && person.get_should_be_logged()) { sum[(int)(person.get_location().get_type())] += 1; @@ -244,7 +244,7 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { // Otherwise log accordingly for (auto&& person : sim.get_world().get_persons()) { - if ((person.get_infection_state(prev_time) == mio::abm::InfectionState::Exposed) && + if ((person.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && (person.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed) && (person.get_should_be_logged())) { sum[(size_t)(person.get_age())] += 1; diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index ea48b9c019..464fed9637 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -66,11 +66,11 @@ def main(path, n_runs): def plot_infection_per_location_type(df): # Calculate moving average for all location types - df['Home'] = gaussian_filter1d(df.Home.rolling(24*3, min_periods=1).mean(), sigma=15) - df['School'] = gaussian_filter1d(df.School.rolling(24*3, min_periods=1).mean(), sigma=15) - df['Work'] = gaussian_filter1d(df.Work.rolling(24*3, min_periods=1).mean(), sigma=15) - df['SocialEvent'] = gaussian_filter1d(df.SocialEvent.rolling(24*3, min_periods=1).mean(), sigma=15) - df['BasicsShop'] = gaussian_filter1d(df.BasicsShop.rolling(24*3, min_periods=1).mean(), sigma=15) + df['Home'] = gaussian_filter1d(df.Home.rolling(24*3, min_periods=1).sum(), sigma=15) + df['School'] = gaussian_filter1d(df.School.rolling(24*3, min_periods=1).sum(), sigma=15) + df['Work'] = gaussian_filter1d(df.Work.rolling(24*3, min_periods=1).sum(), sigma=15) + df['SocialEvent'] = gaussian_filter1d(df.SocialEvent.rolling(24*3, min_periods=1).sum(), sigma=15) + df['BasicsShop'] = gaussian_filter1d(df.BasicsShop.rolling(24*3, min_periods=1).sum(), sigma=15) df.plot(x='Time', y=['Home', 'School','Work', 'SocialEvent', 'BasicsShop'], figsize=(10, 6), title='Infections stratified according to location type') @@ -246,7 +246,8 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 96e5ee8042..e16048a377 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -985,40 +985,23 @@ void set_local_parameters(mio::abm::World& world) /** * @brief Add testing strategies to the world. */ -// void add_testing_strategies(mio::abm::World& world, bool school, bool work, bool symptomatic) -// { -// // Tests in schools -// auto testing_criteria_school = mio::abm::TestingCriteria(); - -// auto testing_min_time = mio::abm::days(7); -// auto start_date = mio::abm::TimePoint(0); -// auto end_date = mio::abm::TimePoint(0) + mio::abm::days(60); -// // auto test_type = mio::abm::AntigenTest(); -// auto probability = mio::UncertainValue(); -// assign_uniform_distribution(probability, 0.5, 0.5); - -// // auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date, -// // end_date, probability.draw_sample()); -// // if (school) -// // world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); - -// // Tests in work places -// auto testing_criteria_work = mio::abm::TestingCriteria(); - -// assign_uniform_distribution(probability, 0.5, 0.5); -// // auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date, end_date, -// // test_type, probability.draw_sample()); -// // if (work) -// // world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); - -// // Test when symptomatic -// // auto testing_criteria_symptomatic = mio::abm::TestingCriteria({}, {mio::abm::InfectionState::InfectedSymptoms}); -// // auto testing_scheme_symptomatic = -// // mio::abm::TestingScheme(testing_criteria_symptomatic, testing_min_time, start_date, end_date, test_type, 0.7); - -// // if (symptomatic) -// // world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_symptomatic); -// } +void add_testing_strategies(mio::abm::World& world, bool symptomatic) +{ + if (symptomatic) { + auto testing_min_time_symptomatic = mio::abm::days(7); + auto probability_symptomatic = 1.0; + auto start_date_test_symptomatic = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 + auto end_date_test_symptomatic = mio::abm::TimePoint(mio::abm::days(90).seconds()); // 2021-05-30 + auto test_type_symptomatic = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters = world.parameters.get()[test_type_symptomatic]; // Test parameters + auto testing_criteria_symptomatic = mio::abm::TestingCriteria(); + testing_criteria_symptomatic.add_infection_state(mio::abm::InfectionState::InfectedSymptoms); + auto testing_scheme_symptomatic = mio::abm::TestingScheme( + testing_criteria_symptomatic, testing_min_time_symptomatic, start_date_test_symptomatic, + end_date_test_symptomatic, test_parameters, probability_symptomatic); + world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_symptomatic); + } +} /** * Create a sampled simulation with start time t0. @@ -1050,7 +1033,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con //3. testen in schulen und Arbeitsplätzen (unabh. von Alter, 1x am Tag, unabh. von InfectionState) ab Tag 0 //4. 2.+3. - // add_testing_strategies(world, false, false, false); + add_testing_strategies(world, true); } template @@ -1270,7 +1253,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 500000; + auto max_num_persons = 250000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1589,7 +1572,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project/loki/memilio/memilio/data"; + std::string input_dir = "/p/project/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From ba28f1af8e70733ff6b5c6a800ce9dde2602096b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 31 May 2024 22:17:18 +0200 Subject: [PATCH 134/488] add fix for logging bs people Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 46 +++++++++++++++--------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e16048a377..dfabf57bf1 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -94,14 +94,17 @@ void assign_infection_state_prob(mio::abm::World& world, mio::abm::TimePoint t) { // convert initial population to ABM initial infections for (auto& person : world.get_persons()) { - auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); + if (person.get_should_be_logged()) { + auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); - auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( - rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); + auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( + rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); - if (infection_state != mio::osecir::InfectionState::Susceptible) { - person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), - world.parameters, t, infection_state_map.at(infection_state))); + if (infection_state != mio::osecir::InfectionState::Susceptible) { + person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), + world.parameters, t, + infection_state_map.at(infection_state))); + } } } } @@ -119,7 +122,9 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) std::vector> persons_by_age(num_age_groupss); for (auto& person : world.get_persons()) { - persons_by_age[person.get_age().get()].push_back(person.get_person_id()); + if (person.get_should_be_logged()) { + persons_by_age[person.get_age().get()].push_back(person.get_person_id()); + } } for (size_t age = 0; age < num_age_groupss; ++age) { @@ -985,7 +990,7 @@ void set_local_parameters(mio::abm::World& world) /** * @brief Add testing strategies to the world. */ -void add_testing_strategies(mio::abm::World& world, bool symptomatic) +void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool social_event) { if (symptomatic) { auto testing_min_time_symptomatic = mio::abm::days(7); @@ -1001,6 +1006,19 @@ void add_testing_strategies(mio::abm::World& world, bool symptomatic) end_date_test_symptomatic, test_parameters, probability_symptomatic); world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_symptomatic); } + if (social_event) { + auto testing_min_time_socev = mio::abm::days(7); + auto probability_socev = 0.5; + auto start_date_test_socev = mio::abm::TimePoint(mio::abm::days(0).seconds()); + auto end_date_test_socev = mio::abm::TimePoint(mio::abm::days(90).seconds()); + auto test_type_socev = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters = world.parameters.get()[test_type_socev]; // Test parameters + auto testing_criteria_socev = mio::abm::TestingCriteria(); + auto testing_scheme_socev = + mio::abm::TestingScheme(testing_criteria_socev, testing_min_time_socev, start_date_test_socev, + end_date_test_socev, test_parameters, probability_socev); + world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme_socev); + } } /** @@ -1027,13 +1045,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); - // Verschiedene Fälle: - //1. ohne testing scheme - //2. testing scheme: Test bei Symptomen (unabh. von Location, 1x am Tag, InfectedSymptomatic, 70% der Bevölkerung) ab Tag 0 - //3. testen in schulen und Arbeitsplätzen (unabh. von Alter, 1x am Tag, unabh. von InfectionState) ab Tag 0 - //4. 2.+3. - - add_testing_strategies(world, true); + add_testing_strategies(world, true, false); } template @@ -1572,8 +1584,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 6a1fadf13cbd6f3ce60c2a80865f68a56d47f418 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 16:45:54 +0200 Subject: [PATCH 135/488] vacc diff Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index dfabf57bf1..9bd13b7083 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -229,7 +229,9 @@ void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_begin // we check if we even have enough people to vaccinate in each respective age group std::vector num_persons_by_age(num_age_groupss); for (auto& person : world.get_persons()) { - num_persons_by_age[determine_age_group_from_rki(person.get_age())]++; + if (person.get_should_be_logged()) { + num_persons_by_age[determine_age_group_from_rki(person.get_age())]++; + } } //sum over all dates in the vacc_map to check if we have enough persons to vaccinate std::vector num_persons_by_age_vaccinate(num_age_groupss); From 446a103c538f251a5be0fdf4f8d5e401bb962729 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 16:47:24 +0200 Subject: [PATCH 136/488] quick fixes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9bd13b7083..b367130d8e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1047,7 +1047,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); - add_testing_strategies(world, true, false); + // add_testing_strategies(world, true, false); } template @@ -1586,8 +1586,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 1fb04fdbe77aab0b5ee1ad17d7acb3d19c662508 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 16:48:42 +0200 Subject: [PATCH 137/488] change persons Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/check_bs_data.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/check_bs_data.py b/cpp/simulations/check_bs_data.py index dfbf054026..d87099df98 100644 --- a/cpp/simulations/check_bs_data.py +++ b/cpp/simulations/check_bs_data.py @@ -63,12 +63,12 @@ # chek how many unique map_feature_keys and values are in the data -map_feature_keys = bd[['map_feature_key']].drop_duplicates().size -map_feature_values = bd[['map_feature_value']].drop_duplicates().size -print('Number of unique map_feature_keys: ' + str(map_feature_keys) + '. Number of unique map_feature_values: ' + str(map_feature_values) + '. \n') -# same for the tuple of both -map_feature_keys_values = bd[['map_feature_key', 'map_feature_value']].drop_duplicates().size -print('Number of unique map_feature_keys and values: ' + str(map_feature_keys_values) + '. \n') +# map_feature_keys = bd[['map_feature_key']].drop_duplicates().size +# map_feature_values = bd[['map_feature_value']].drop_duplicates().size +# print('Number of unique map_feature_keys: ' + str(map_feature_keys) + '. Number of unique map_feature_values: ' + str(map_feature_values) + '. \n') +# # same for the tuple of both +# map_feature_keys_values = bd[['map_feature_key', 'map_feature_value']].drop_duplicates().size +# print('Number of unique map_feature_keys and values: ' + str(map_feature_keys_values) + '. \n') #check if persons go to different location_ids with the same activity_after bd_same_loc = bd[['personID', 'loc_id_end', 'ActivityAfter']].drop_duplicates() From c1903ce74498199b0b1d5676d462ab6c03e5797f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 16:49:25 +0200 Subject: [PATCH 138/488] change number of persosn Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b367130d8e..5f97c5a154 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1267,7 +1267,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 250000; + auto max_num_persons = 390000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results From 2ecb8cb21bee8a028cf0fe2b34fb8d632a72bfa4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 19:06:41 +0200 Subject: [PATCH 139/488] Refactor plot_infection_states_individual function for readability and consistency Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 48 ++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 464fed9637..377538f625 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -18,7 +18,9 @@ import matplotlib.patches as mpatches import matplotlib.lines as mlines import h5py -from scipy.ndimage.filters import gaussian_filter1d +from datetime import datetime +from matplotlib.dates import DateFormatter +from scipy.ndimage import gaussian_filter1d def main(path, n_runs): @@ -74,6 +76,8 @@ def plot_infection_per_location_type(df): df.plot(x='Time', y=['Home', 'School','Work', 'SocialEvent', 'BasicsShop'], figsize=(10, 6), title='Infections stratified according to location type') + # x axis should be titled Time in days + plt.xlabel('Time (days)') @@ -146,7 +150,10 @@ def plot_results(path): def plot_infection_states(x, y50, y25, y75): plt.figure('Infection_states') plt.title('Infection states') + + #set the x color_plot = cmx.get_cmap('Set1').colors + states_plot = [1, 2, 3, 4, 5, 7] legend_plot = ['E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Dead'] @@ -156,11 +163,44 @@ def plot_infection_states(x, y50, y25, y75): plt.legend(legend_plot) + + # plt.show() + + + for i in states_plot: plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.5, color=color_plot[i]) plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.5, color=color_plot[i]) + + + #currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in x] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + #but just take every 10th date to make it more readable + plt.gca().set_xticks(x[::150]) + plt.gca().set_xticklabels(xx[::150]) + plt.gcf().autofmt_xdate() + + + plt.xlabel('Time') + plt.ylabel('Number of individuals') + plt.show() + + + + + + + + + + + + + def plot_infection_states_individual(x, y50, y25, y75, y_real): @@ -173,7 +213,7 @@ def plot_infection_states_individual(x, y50, y25, y75, y_real): fig, ax = plt.subplots(3, 1) # Severe - ax[0].set_xlabel('time (s)') + ax[0].set_xlabel('time (days)') ax[0].plot(x, y50[:, [4]], color='tab:red', label='y50') ax[0].plot(x_real, y_real[:, [6]], color='tab:blue', label='y_real') ax[0].tick_params(axis='y') @@ -182,7 +222,7 @@ def plot_infection_states_individual(x, y50, y25, y75, y_real): fig.tight_layout() # otherwise the right y-label is slightly clipped # Critical - ax[1].set_xlabel('time (s)') + ax[1].set_xlabel('time (days)') ax[1].plot(x, y50[:, [5]], color='tab:red', label='y50') ax[1].plot(x_real, y_real[:, [7]], color='tab:blue', label='y_real') ax[1].tick_params(axis='y') @@ -191,7 +231,7 @@ def plot_infection_states_individual(x, y50, y25, y75, y_real): fig.tight_layout() # otherwise the right y-label is slightly clipped # Dead - ax[2].set_xlabel('time (s)') + ax[2].set_xlabel('time (days)') ax[2].plot(x, y50[:, [7]], color='tab:red', label='y50') ax[2].plot(x_real, y_real[:, [9]], color='tab:blue', label='y_real') ax[2].tick_params(axis='y') From 8bdc7a6e92f0d58d6063583e4602162ef4feb6c2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 19:35:17 +0200 Subject: [PATCH 140/488] Refactor assign_vaccination_state function for readability and consistency Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5f97c5a154..86fa60a1e2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -243,9 +243,9 @@ void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_begin //check for (size_t age = 0; age < num_persons_by_age.size(); ++age) { if (num_persons_by_age[age] < num_persons_by_age_vaccinate[age]) { - mio::log_error( - "Not enough persons to vaccinate in age group we dont vaccinate if an age group is fully vaccinated! ", - age); + // mio::log_error( + // "Not enough persons to vaccinate in age group we dont vaccinate if an age group is fully vaccinated! ", + // age); } } @@ -264,7 +264,7 @@ void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_begin for (size_t age = 0; age < vacc_entry.second.size(); ++age) { for (uint32_t i = 0; i < vacc_entry.second[age].first; ++i) { if (persons_by_age[age].size() == 0) { - mio::log_error("Not enough to vacc people 1st time"); + // mio::log_error("Not enough to vacc people 1st time"); } else { // select random person and assign Vaccination @@ -283,7 +283,7 @@ void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_begin } for (uint32_t i = 0; i < vacc_entry.second[age].second; ++i) { if (vaccinated_persons[age].size() == 0) { - mio::log_error("Not enough vaccinated people to vacc 2nd time! "); + // mio::log_error("Not enough vaccinated people to vacc 2nd time! "); } else { // select random already vaccinated person and assign Vaccination @@ -1586,8 +1586,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; @@ -1613,7 +1613,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 1; + num_runs = 2; printf("Running with number of runs = %d.\n", (int)num_runs); } From 4d5acbca8068742d3614773d4b3164ceba844dac Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 19:35:24 +0200 Subject: [PATCH 141/488] Refactor input directory path for consistency Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 86fa60a1e2..2d0dfc763d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1586,8 +1586,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 0d16cb751b39c9aa38ebb751e546f071892bbbe2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 20:15:57 +0200 Subject: [PATCH 142/488] for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2d0dfc763d..6571fa28f6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1047,7 +1047,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); - // add_testing_strategies(world, true, false); + add_testing_strategies(world, true, false); } template From 50f4a8a87cc5bc6c65d986111e9305c0a6cc440e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:29:36 +0200 Subject: [PATCH 143/488] change testing startegie Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6571fa28f6..d5f2b9247d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1010,7 +1010,7 @@ void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool socia } if (social_event) { auto testing_min_time_socev = mio::abm::days(7); - auto probability_socev = 0.5; + auto probability_socev = 0.8; auto start_date_test_socev = mio::abm::TimePoint(mio::abm::days(0).seconds()); auto end_date_test_socev = mio::abm::TimePoint(mio::abm::days(90).seconds()); auto test_type_socev = mio::abm::TestType::Antigen; // Antigen test @@ -1047,7 +1047,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); - add_testing_strategies(world, true, false); + add_testing_strategies(world, false, true); } template From 1123683b77b397dba1a4a549950eb0947f72dd1c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:43:53 +0200 Subject: [PATCH 144/488] Refactor add_testing_strategies function for readability and consistency Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d5f2b9247d..36d733688e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -995,6 +995,7 @@ void set_local_parameters(mio::abm::World& world) void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool social_event) { if (symptomatic) { + std::cout << "Adding symptomatic testing strategy" << std::endl; auto testing_min_time_symptomatic = mio::abm::days(7); auto probability_symptomatic = 1.0; auto start_date_test_symptomatic = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 @@ -1047,7 +1048,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); - add_testing_strategies(world, false, true); + add_testing_strategies(world, true, false); } template From 79d006d68cec4cbfd588f18f2f60d993b951847e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 2 Jun 2024 23:58:44 +0200 Subject: [PATCH 145/488] Refactor TestingStrategy::run_strategy for readability and consistency Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 91fe8fc7d9..78c8b12355 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -170,9 +170,9 @@ bool TestingStrategy::run_strategy(Person::RandomNumberGenerator& rng, Person& p TimePoint t) { // A Person is always allowed to go home and this is never called if a person is not discharged from a hospital or ICU. - if (location.get_type() == mio::abm::LocationType::Home) { - return true; - } + // if (location.get_type() == mio::abm::LocationType::Home) { + // return true; + // } //lookup schemes for this specific location as well as the location type //lookup in std::vector instead of std::map should be much faster unless for large numbers of schemes From f428b0b1b0449ec267ae87c90ca24e440198ce1f Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 5 Jun 2024 18:30:18 +0200 Subject: [PATCH 146/488] Improve plots --- cpp/simulations/analyze_bs_run.py | 144 +++++++++++++++--------------- 1 file changed, 73 insertions(+), 71 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 377538f625..121fe63f3a 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -107,53 +107,51 @@ def plot_infection_per_age_group(df): def plot_results(path): # median / 50-percentile - f = h5py.File( + f_p50 = h5py.File( path+"/infection_state_per_age_group/p50/Results.h5", 'r') # Get the HDF5 group; key needs to be a group name from above - group = f['0'] + # only one graph node saved + p50_bs = f_p50['0'] # This assumes group[some_key_inside_the_group] is a dataset, # and returns a np.array: - time = group['Time'][()] - total_50 = group['Total'][()] + time = p50_bs['Time'][()] + total_50 = p50_bs['Total'][()] - # After you are done - f.close() - - # 05-percentile - f = h5py.File( + # 25-percentile + f_p25 = h5py.File( path+"/infection_state_per_age_group/p25/Results.h5", 'r') - group = f['0'] - total_25 = group['Total'][()] - f.close() - - # 95-percentile - f = h5py.File( + p25_bs = f_p25['0'] + total_25 = p25_bs['Total'][()] + # 75-percentile + f_p75 = h5py.File( path + "/infection_state_per_age_group/p75/Results.h5", 'r') - group = f['0'] - total_75 = group['Total'][()] - f.close() + p75_bs = f_p75['0'] + total_75 = p75_bs['Total'][()] # real world - f = h5py.File( + f_real = h5py.File( path + "/Results_rki.h5", 'r') - group = f['3101'] - total_real = group['Total'][()] - f.close() + real_bs = f_real['3101'] + total_real = real_bs['Total'][()] + plot_infection_states_individual( - time, total_50, total_25, total_75, total_real) + time, p50_bs, p25_bs, p75_bs, real_bs) plot_infection_states(time, total_50, total_25, total_75) + # After you are done + f_p50.close() + f_p25.close() + f_p75.close() + f_real.close() def plot_infection_states(x, y50, y25, y75): plt.figure('Infection_states') plt.title('Infection states') - #set the x - color_plot = cmx.get_cmap('Set1').colors - + color_plot = cmx.get_cmap('Set1').colors states_plot = [1, 2, 3, 4, 5, 7] legend_plot = ['E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Dead'] @@ -190,54 +188,58 @@ def plot_infection_states(x, y50, y25, y75): plt.show() - - - - - - - +def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): + y_real_total = real_bs['Total'][()] + x_real = np.linspace(0, y_real_total.shape[0]-1, y_real_total.shape[0]) + age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] + color_plot = cmx.get_cmap('Set1').colors - - -def plot_infection_states_individual(x, y50, y25, y75, y_real): - # plt.figure('Infection_states_dead') - # # plt.plot(x, y50[:,[5,7]]) - x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) - # plt.plot(x_real, y_real[:,[2]]) - # plt.legend(['I_Crit', 'Dead']) - - fig, ax = plt.subplots(3, 1) - - # Severe - ax[0].set_xlabel('time (days)') - ax[0].plot(x, y50[:, [4]], color='tab:red', label='y50') - ax[0].plot(x_real, y_real[:, [6]], color='tab:blue', label='y_real') - ax[0].tick_params(axis='y') - ax[0].title.set_text('Severe') - ax[0].legend() - fig.tight_layout() # otherwise the right y-label is slightly clipped - - # Critical - ax[1].set_xlabel('time (days)') - ax[1].plot(x, y50[:, [5]], color='tab:red', label='y50') - ax[1].plot(x_real, y_real[:, [7]], color='tab:blue', label='y_real') - ax[1].tick_params(axis='y') - ax[1].title.set_text('Critical') - ax[1].legend() - fig.tight_layout() # otherwise the right y-label is slightly clipped - - # Dead - ax[2].set_xlabel('time (days)') - ax[2].plot(x, y50[:, [7]], color='tab:red', label='y50') - ax[2].plot(x_real, y_real[:, [9]], color='tab:blue', label='y_real') - ax[2].tick_params(axis='y') - ax[2].title.set_text('Dead') - fig.tight_layout() # otherwise the right y-label is slightly clipped - ax[2].legend() + fig, ax = plt.subplots(3, len(age_group_access), constrained_layout = True) + fig.set_figwidth(20) + fig.set_figheight(9) + for j, count in zip(age_group_access, range(len(age_group_access))): + y50 = p50_bs[j][()] + y25 = p25_bs[j][()] + y75 = p75_bs[j][()] + y_real = real_bs[j][()] + + # Severe + ax_severe = ax[0, count] + ax_severe.set_xlabel('time (days)') + ax_severe.plot(x, y50[:, 4], color=color_plot[count], label='y50') + ax_severe.plot(x_real, y_real[:, 6], '.', color=color_plot[count], label='y_real') + ax_severe.fill_between(x, y50[:, 4], y25[:, 4], alpha=0.5, color=color_plot[count]) + ax_severe.fill_between(x, y50[:, 4], y75[:, 4], alpha=0.5, color=color_plot[count]) + ax_severe.tick_params(axis='y') + ax_severe.title.set_text('Severe, Age{}'.format(j)) + ax_severe.legend(['Simulation','Real']) + + # Critical + ax_critical = ax[1, count] + ax_critical.set_xlabel('time (days)') + ax_critical.plot(x, y50[:, [5]], color=color_plot[count], label='y50') + ax_critical.plot(x_real, y_real[:, [7]], '.', color=color_plot[count], label='y_real') + ax_critical.fill_between(x, y50[:, 5], y25[:, 5], alpha=0.5, color=color_plot[count]) + ax_critical.fill_between(x, y50[:, 5], y75[:, 5], alpha=0.5, color=color_plot[count]) + ax_critical.tick_params(axis='y') + ax_critical.title.set_text('Critical, Age{}'.format(j)) + ax_critical.legend(['Simulation','Real']) + + # Dead + ax_dead = ax[2, count] + ax_dead.set_xlabel('time (days)') + ax_dead.plot(x, y50[:, [7]], color=color_plot[count], label='y50') + ax_dead.plot(x_real, y_real[:, [9]], '.', color=color_plot[count], label='y_real') + ax_dead.fill_between(x, y50[:, 7], y25[:, 7], alpha=0.5, color=color_plot[count]) + ax_dead.fill_between(x, y50[:, 7], y75[:, 7], alpha=0.5, color=color_plot[count]) + ax_dead.tick_params(axis='y') + ax_dead.title.set_text('Dead, Age{}'.format(j)) + ax_dead.legend(['Simulation','Real']) + + #fig.tight_layout() # otherwise the right y-label is slightly clipped plt.show() @@ -286,7 +288,7 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" + path = "/Users/david/Documents/HZI/memilio/data/results/" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] From 2c9ef714c8d5c0920b503d8658aff0f635205618 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 5 Jun 2024 18:43:18 +0200 Subject: [PATCH 147/488] changes for cluster run Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 36d733688e..c8ff0f58c6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -736,7 +736,8 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.6; // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 1.0; + + params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -1048,7 +1049,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); - add_testing_strategies(world, true, false); + // add_testing_strategies(world, true, false); } template @@ -1268,7 +1269,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 390000; + auto max_num_persons = 400000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1310,7 +1311,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groupss); create_sampled_world(world, input_dir, t0, max_num_persons, start_date); - world.parameters.get() = 3.5; // Stop the clock after create_sampled_world and calculate the duration auto stop1 = std::chrono::high_resolution_clock::now(); auto duration1 = std::chrono::duration(stop1 - start1); From 65c1d2d8f673f3b1504975bc8c380c01ccf5fa53 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 5 Jun 2024 21:45:31 +0200 Subject: [PATCH 148/488] change to fit? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c8ff0f58c6..8d11b7f795 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -725,19 +725,19 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.075; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.075; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.15; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.3; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.4; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.6; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.14; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.14; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.4; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.6; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.28; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.6; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 4.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { From 1341d9a6e39a8026049134d32e2e1eed3d1e8d3c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 5 Jun 2024 21:47:35 +0200 Subject: [PATCH 149/488] change some parameters for fitting Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 3 ++- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 121fe63f3a..f97d00f645 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -288,8 +288,9 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - path = "/Users/david/Documents/HZI/memilio/data/results/" + # path = "/Users/david/Documents/HZI/memilio/data/results/" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8d11b7f795..aad2fbad01 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1491,7 +1491,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(4, 0); + location.set_capacity(2, 0); } //90% of big social events get reopened and caopacity will be unlimited int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); From 369344d79baac18643fd4a92a7023c304ac8c560 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:42:51 +0200 Subject: [PATCH 150/488] chang params for fit --- cpp/simulations/paper_abm_bs_testing.cpp | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index aad2fbad01..fef55922e3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -737,7 +737,7 @@ void set_parameters(mio::abm::Parameters& params) // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 4.5; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 3; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -747,25 +747,25 @@ void set_parameters(mio::abm::Parameters& params) // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.967}, - {30, 0.975}, - {60, 0.977}, - {90, 0.974}, - {120, 0.963}, - {150, 0.947}, - {180, 0.93}, - {210, 0.929}, - {240, 0.923}, - {270, 0.908}, - {300, 0.893}, - {330, 0.887}, - {360, 0.887}, - {360, 0.5}}, + return mio::linear_interpolation_of_data_set({{0, 0.1967}, + {30, 0.1975}, + {60, 0.1977}, + {90, 0.1974}, + {120, 0.1963}, + {150, 0.1947}, + {180, 0.193}, + {210, 0.1929}, + {240, 0.1923}, + {270, 0.1908}, + {300, 0.1893}, + {330, 0.1887}, + {360, 0.1887}, + {360, 0.15}}, days); }; //Set other parameters - params.get() = 0.33; //all masks have a 0.66 protection factor for now + params.get() = 0.5; //all masks have a 0.66 protection factor for now params.get() = 0.0; } From a2bbdf440a1ca719297ef61765a8cbc92e26458d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 6 Jun 2024 14:33:38 +0200 Subject: [PATCH 151/488] change mask influence --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fef55922e3..e3ddfa0be8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -765,7 +765,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.5; //all masks have a 0.66 protection factor for now + params.get() = 0.35; //all masks have a 0.66 protection factor for now params.get() = 0.0; } From 6c1062c8ef2cb20e8a7590fe1e2941772ad8b763 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:01:38 +0200 Subject: [PATCH 152/488] Test output for real world data --- cpp/simulations/analyze_bs_run.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index f97d00f645..ca6b80700f 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -151,7 +151,7 @@ def plot_infection_states(x, y50, y25, y75): plt.figure('Infection_states') plt.title('Infection states') - color_plot = cmx.get_cmap('Set1').colors + color_plot = cmx.get_cmap('Set1').colors states_plot = [1, 2, 3, 4, 5, 7] legend_plot = ['E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Dead'] @@ -205,7 +205,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y25 = p25_bs[j][()] y75 = p75_bs[j][()] y_real = real_bs[j][()] - + print(y_real[0:5, 9]) # Severe ax_severe = ax[0, count] ax_severe.set_xlabel('time (days)') @@ -288,9 +288,9 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - # path = "/Users/david/Documents/HZI/memilio/data/results/" + path = "/Users/david/Documents/HZI/memilio/data/results/" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: From 3dce8bbd558ce9f16da6f3c75b06270aa8b05ef3 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 6 Jun 2024 23:30:15 +0200 Subject: [PATCH 153/488] plot actual infected in plot --- cpp/simulations/analyze_bs_run.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index ca6b80700f..25e30ad56a 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -139,7 +139,7 @@ def plot_results(path): plot_infection_states_individual( time, p50_bs, p25_bs, p75_bs, real_bs) - plot_infection_states(time, total_50, total_25, total_75) + plot_infection_states(time, total_50, total_25, total_75, total_real) # After you are done f_p50.close() @@ -147,18 +147,23 @@ def plot_results(path): f_p75.close() f_real.close() -def plot_infection_states(x, y50, y25, y75): +def plot_infection_states(x, y50, y25, y75, y_real=None): plt.figure('Infection_states') plt.title('Infection states') color_plot = cmx.get_cmap('Set1').colors states_plot = [1, 2, 3, 4, 5, 7] - legend_plot = ['E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Dead'] + legend_plot = ['E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Dead', 'real_infected'] for i in states_plot: plt.plot(x, y50[:, i], color=color_plot[i]) + #plot real data + if y_real is not None: + x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) + plt.plot(x_real, y_real[:,4], '.', color=color_plot[i+1]) + plt.legend(legend_plot) @@ -288,9 +293,10 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - path = "/Users/david/Documents/HZI/memilio/data/results/" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" + # path = r"C:\Users\korf_sa\Documents\rep\data\results" + path = r"C:\Users\korf_sa\Documents\rep\data\results_cluster\results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: From 62a4a27810e3ab5bc8aacae09ff540839c43dc9e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 6 Jun 2024 23:33:30 +0200 Subject: [PATCH 154/488] =?UTF-8?q?=C3=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e3ddfa0be8..cb880e625a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -737,7 +737,7 @@ void set_parameters(mio::abm::Parameters& params) // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 3; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { From 6b0481fa93e651662566646730a87733f2dd4b03 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:51:44 +0200 Subject: [PATCH 155/488] fit? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cb880e625a..8e43810cfd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -718,8 +718,8 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.0075; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.019; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.0615; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.165; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.225; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.25; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.4; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.075; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.075; @@ -737,7 +737,7 @@ void set_parameters(mio::abm::Parameters& params) // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 4; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -1460,11 +1460,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(20, 0); + location.set_capacity(30, 0); } if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(5, 0); + location.set_capacity(10, 0); } } sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, @@ -1474,7 +1474,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); + location.set_capacity(15, 0); } } sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, @@ -1491,7 +1491,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(2, 0); + location.set_capacity(5, 0); } //90% of big social events get reopened and caopacity will be unlimited int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); From 7f3e52a39c0cba7e08ff280436892abb95ab123d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 7 Jun 2024 17:08:17 +0200 Subject: [PATCH 156/488] test if fit Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8e43810cfd..f5aabdaa81 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -725,19 +725,19 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.075; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.075; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.15; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.6; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.55; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.7; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.14; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.28; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.6; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.55; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.7; // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 4; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 4.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -765,7 +765,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.35; //all masks have a 0.66 protection factor for now + params.get() = 0.4; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -1432,6 +1432,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::BasicsShop) { location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.6); // from 2021-03-15 + } } // 5. add capacity limits to some locations @@ -1474,12 +1478,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(15, 0); + location.set_capacity(10, 0); } } sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); - std::cout << "day 42 finished" << std::endl; + std::cout << "day 42 finished" << std::endl; // date 2021-04-12 for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::School) { location.set_npi_active(false); @@ -1491,7 +1495,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(5, 0); + location.set_capacity(2, 0); } //90% of big social events get reopened and caopacity will be unlimited int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); From 29b27e658d4deb35501ec5797bfa1b94f382013a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 8 Jun 2024 01:37:04 +0200 Subject: [PATCH 157/488] send it Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f5aabdaa81..06291d54b9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -737,7 +737,7 @@ void set_parameters(mio::abm::Parameters& params) // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 4.5; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 5.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -1432,9 +1432,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::BasicsShop) { location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } - if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.6); // from 2021-03-15 + if (location.get_type() == mio::abm::LocationType::Work || + location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(23).seconds()), 0.5); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.5); // from 2021-04-12 } } From 9758560fec821441d4fa8f3528069eaf5891b438 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 8 Jun 2024 10:19:35 +0200 Subject: [PATCH 158/488] fit???? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 06291d54b9..4f8865ee72 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1434,8 +1434,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } if (location.get_type() == mio::abm::LocationType::Work || location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(23).seconds()), 0.5); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.5); // from 2021-04-12 + location.add_damping(mio::abm::TimePoint(mio::abm::days(23).seconds()), 0.2); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(30).seconds()), 0.8); // from 2021-04-12 + location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.2); // from 2021-04-12 } } @@ -1490,6 +1491,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.set_npi_active(false); } } + // set infection from viral shed lower + sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + 2.5; sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; @@ -1619,7 +1623,7 @@ int main(int argc, char** argv) printf("\tRun the simulation for time(s).\n"); printf("\tStore the results in .\n"); - num_runs = 2; + num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); } From c46e0e4eb7022931bc2c2c89dd0ce63cf48b4c5a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 8 Jun 2024 14:48:35 +0200 Subject: [PATCH 159/488] fit? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4f8865ee72..26f7375d02 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -765,7 +765,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.4; //all masks have a 0.66 protection factor for now + params.get() = 0.5; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -1437,6 +1437,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(23).seconds()), 0.2); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(30).seconds()), 0.8); // from 2021-04-12 location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.2); // from 2021-04-12 + location.add_damping(mio::abm::TimePoint(mio::abm::days(72).seconds()), 1.0); // from 2021-04-12 } } @@ -1493,7 +1494,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } // set infection from viral shed lower sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 2.5; + 4.0; sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; @@ -1596,8 +1597,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 59afb320818dff1805b1fb9683c52d3e20d8410c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 9 Jun 2024 00:34:31 +0200 Subject: [PATCH 160/488] fit? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 25e30ad56a..2db6c775a1 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -293,10 +293,10 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" # path = r"C:\Users\korf_sa\Documents\rep\data\results" - path = r"C:\Users\korf_sa\Documents\rep\data\results_cluster\results" + # path = r"C:\Users\korf_sa\Documents\rep\data\results_cluster\results" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: From 362af1a6c335b3bb464516a5ef4eadc482ffbad4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 9 Jun 2024 00:36:06 +0200 Subject: [PATCH 161/488] chore: Update infection rate from viral shed to 4.5 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 26f7375d02..5d95b7ea46 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1494,7 +1494,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } // set infection from viral shed lower sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 4.0; + 4.5; sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; From fd7045c5604d2fe3d316a480e27761cee4fde718 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 9 Jun 2024 00:51:48 +0200 Subject: [PATCH 162/488] Update input directory path to use project path Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5d95b7ea46..bd40074177 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1597,8 +1597,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string result_dir = input_dir + "/results"; size_t num_runs; bool save_single_runs = true; From 7026668e51be2198ed76bdf220cac526308ac863 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:22:45 +0200 Subject: [PATCH 163/488] fit? --- cpp/simulations/paper_abm_bs_testing.cpp | 28 ++++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bd40074177..842bf68fbb 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1434,10 +1434,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } if (location.get_type() == mio::abm::LocationType::Work || location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(23).seconds()), 0.2); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(30).seconds()), 0.8); // from 2021-04-12 - location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.2); // from 2021-04-12 - location.add_damping(mio::abm::TimePoint(mio::abm::days(72).seconds()), 1.0); // from 2021-04-12 + // location.add_damping(mio::abm::TimePoint(mio::abm::days(23).seconds()), 0.2); // from 2021-03-15 + // location.add_damping(mio::abm::TimePoint(mio::abm::days(30).seconds()), 0.8); // from 2021-04-01 + // location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.2); // from 2021-04-12 + // location.add_damping(mio::abm::TimePoint(mio::abm::days(72).seconds()), 1.0); // from 2021-05-10 } } @@ -1484,6 +1484,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.set_capacity(10, 0); } } + sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + 3.5; + + sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); + sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + 5.5; + sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 42 finished" << std::endl; // date 2021-04-12 @@ -1492,19 +1502,23 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.set_npi_active(false); } } - // set infection from viral shed lower + // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 4.5; + 3.5; + sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + + sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + 5.5; for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { location.set_capacity(2, 0); } //90% of big social events get reopened and caopacity will be unlimited - int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); + int number_of_big_social_events = (int)(0.7 * social_event_location_ids_big.size()); if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; From 3fcb09ec8e837ccce25d774bf34dc47a7c90ad03 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:09:24 +0200 Subject: [PATCH 164/488] Automatic creation of new output folder --- cpp/simulations/analyze_bs_run.py | 7 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 27 ++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 2db6c775a1..dfa526643b 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -162,7 +162,7 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): #plot real data if y_real is not None: x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) - plt.plot(x_real, y_real[:,4], '.', color=color_plot[i+1]) + plt.plot(x_real, y_real[:,4], '.', color='tab:red') plt.legend(legend_plot) @@ -210,7 +210,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y25 = p25_bs[j][()] y75 = p75_bs[j][()] y_real = real_bs[j][()] - print(y_real[0:5, 9]) + # Severe ax_severe = ax[0, count] ax_severe.set_xlabel('time (days)') @@ -293,7 +293,8 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" + path = "/Users/david/Documents/HZI/memilio/data/results" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" # path = r"C:\Users\korf_sa\Documents\rep\data\results" # path = r"C:\Users\korf_sa\Documents\rep\data\results_cluster\results" diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bd40074177..962ddf0674 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -34,6 +34,7 @@ #include "memilio/utils/miompi.h" #include "memilio/io/binary_serializer.h" #include "memilio/io/epi_data.h" +#include "memilio/io/io.h" namespace fs = boost::filesystem; @@ -1590,6 +1591,25 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s return mio::success(); } +// From: https://en.cppreference.com/w/cpp/chrono/c/strftime +const std::string currentDateTime() +{ + // Example of the very popular RFC 3339 format UTC time + std::time_t time = std::time({}); + char timeString[std::size("yyyy-mm-ddThh:mm:ssZ")]; + std::strftime(std::data(timeString), std::size(timeString), "%FT%TZ", std::gmtime(&time)); + return timeString; +} + +mio::IOResult create_result_folders(std::string result_dir) +{ + BOOST_OUTCOME_TRY(auto&& created, mio::create_directory(result_dir)); + BOOST_OUTCOME_TRY(created, mio::create_directory(result_dir + "/infection_per_age_group/")); + BOOST_OUTCOME_TRY(created, mio::create_directory(result_dir + "/infection_per_location_type/")); + BOOST_OUTCOME_TRY(created, mio::create_directory(result_dir + "/infection_state_per_age_group/")); + return mio::success(); +} + int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::err); @@ -1597,9 +1617,12 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project/loki/memilio/memilio/data"; + // std::string input_dir = "/p/project/loki/memilio/memilio/data"; // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - std::string result_dir = input_dir + "/results"; + std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string result_dir = input_dir + "/results_" + currentDateTime(); + auto created = create_result_folders(result_dir); + size_t num_runs; bool save_single_runs = true; From 66b8dca6c1b82ace520e2f30c21b8e15cfd378ca Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Tue, 11 Jun 2024 10:58:25 +0200 Subject: [PATCH 165/488] Copy results into a new last_results folder --- cpp/simulations/analyze_npi.py | 14 +++++-- cpp/simulations/paper_abm_bs_testing.cpp | 48 +++++++++++++++++------- 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/cpp/simulations/analyze_npi.py b/cpp/simulations/analyze_npi.py index 723e32ffdb..4390719ca9 100644 --- a/cpp/simulations/analyze_npi.py +++ b/cpp/simulations/analyze_npi.py @@ -39,10 +39,12 @@ def summarize_dates(dates): #import the first excel file with the measures and ther abbreviations -df_abb = pd.read_excel('/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/datensatzbeschreibung_massnahmen.xlsx', sheet_name='DSB BL') +df_abb = pd.read_excel( + '/Users/david/Documents/HZI/memilio/data/npi_data/datensatzbeschreibung_massnahmen.xlsx', sheet_name='DSB BL') #read in the matrix which tells us which measure is active on which day -df_measure_matrix = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/germany_counties_npi_subcat.csv') +df_measure_matrix = pd.read_csv( + r'/Users/david/Documents/HZI/memilio/data/npi_data/germany_counties_npi_subcat.csv', header=None, skiprows=1) zip_code_brunswick = 3101 start_date = '2021-03-01' @@ -81,4 +83,10 @@ def summarize_dates(dates): f.write(measure + ': ' + str(days) + ' days ' + 'Dates: ' + str(date_ranges) + '\n\n') -x=1 +f.close() + +df_measure_matrix = df_measure_matrix.iloc[:, measure_by_days.axes[0]] +sns.heatmap(df_measure_matrix.iloc[:, 3:], cmap='coolwarm', cbar=False) +plt.show() + +x = 1 diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ee32e997b1..00a6f12524 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1615,12 +1615,25 @@ const std::string currentDateTime() return timeString; } -mio::IOResult create_result_folders(std::string result_dir) +mio::IOResult create_result_folders(std::string const& result_dir) { - BOOST_OUTCOME_TRY(auto&& created, mio::create_directory(result_dir)); - BOOST_OUTCOME_TRY(created, mio::create_directory(result_dir + "/infection_per_age_group/")); - BOOST_OUTCOME_TRY(created, mio::create_directory(result_dir + "/infection_per_location_type/")); - BOOST_OUTCOME_TRY(created, mio::create_directory(result_dir + "/infection_state_per_age_group/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir)); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_age_group/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_location_type/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_state_per_age_group/")); + return mio::success(); +} + +void copy_precomputed_results(std::string const& from_dir, std::string const& to_dir) +{ + fs::copy(from_dir + "/Results_rki.h5", to_dir, fs::copy_options::overwrite_existing); + fs::copy(from_dir + "/Results_rki_sum.h5", to_dir, fs::copy_options::overwrite_existing); +} + +mio::IOResult copy_result_folder(std::string const& from_dir, std::string const& to_dir) +{ + BOOST_OUTCOME_TRY(mio::create_directory(to_dir)); + fs::copy(from_dir, to_dir, fs::copy_options::overwrite_existing | fs::copy_options::recursive); return mio::success(); } @@ -1634,11 +1647,14 @@ int main(int argc, char** argv) // std::string input_dir = "/p/project/loki/memilio/memilio/data"; // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); - auto created = create_result_folders(result_dir); - + auto created = create_result_folders(result_dir); + if (created) { + copy_precomputed_results(precomputed_dir, result_dir); + } size_t num_runs; - bool save_single_runs = true; + //bool save_single_runs = true; if (argc == 2) { num_runs = atoi(argv[1]); @@ -1672,11 +1688,17 @@ int main(int argc, char** argv) // } // printf("\n"); - auto result = run(input_dir, result_dir, num_runs, save_single_runs); - if (!result) { - printf("%s\n", result.error().formatted_message().c_str()); - mio::mpi::finalize(); - return -1; + // auto result = run(input_dir, result_dir, num_runs, save_single_runs); + // if (!result) { + // printf("%s\n", result.error().formatted_message().c_str()); + // mio::mpi::finalize(); + // return -1; + // } + + // copy results into a fixed name folder to have easier access + if (created) { + std::string last_run_dir = input_dir + "/results_last_run"; + auto copied = copy_result_folder(result_dir, last_run_dir); } mio::mpi::finalize(); From 35fd771f42d9bf9415fad6baa994b96c5f0fd35c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 11 Jun 2024 11:50:02 +0200 Subject: [PATCH 166/488] small improvments Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 7 ++++--- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index dfa526643b..2c20ef30e3 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -78,6 +78,7 @@ def plot_infection_per_location_type(df): # x axis should be titled Time in days plt.xlabel('Time (days)') + plt.ylabel('New infections') @@ -154,7 +155,7 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): color_plot = cmx.get_cmap('Set1').colors states_plot = [1, 2, 3, 4, 5, 7] - legend_plot = ['E', 'I_NS', 'I_S', 'I_Sev', 'I_Crit', 'Dead', 'real_infected'] + legend_plot = ['E', 'I_NSymp', 'I_Symp', 'I_Sev', 'I_Crit', 'Dead', 'Sm. rep. Sympt.'] for i in states_plot: plt.plot(x, y50[:, i], color=color_plot[i]) @@ -293,9 +294,9 @@ def plot_mean_and_std(Y): if __name__ == "__main__": # path to results - path = "/Users/david/Documents/HZI/memilio/data/results" + # path = "/Users/david/Documents/HZI/memilio/data/results" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-06-10T21:35:59Z" # path = r"C:\Users\korf_sa\Documents\rep\data\results" # path = r"C:\Users\korf_sa\Documents\rep\data\results_cluster\results" if (len(sys.argv) > 1): diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 00a6f12524..d6a4b5e814 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2020-2024 MEmilio * -* Authors: Sascha Korf, Carlotta Gerstein +* Authors: Sascha Korf, David Kerkmann, Khoa Nguyen, Carlotta Gerstein * * Contact: Martin J. Kuehn * @@ -1488,8 +1488,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 3.5; - + 4.5; + sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = @@ -1505,7 +1505,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 3.5; + 4.5; sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); @@ -1646,9 +1646,9 @@ int main(int argc, char** argv) // std::string input_dir = "/p/project/loki/memilio/memilio/data"; // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; std::string precomputed_dir = input_dir + "/results"; - std::string result_dir = input_dir + "/results_" + currentDateTime(); + std::string result_dir = input_dir + "/results_" + currentDateTime(); auto created = create_result_folders(result_dir); if (created) { copy_precomputed_results(precomputed_dir, result_dir); From 796054b9b10b4be07bf68b7e331a3322a11e4e10 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:10:33 +0200 Subject: [PATCH 167/488] change tarnsition locig from hospital --- cpp/models/abm/world.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index b0fab5a18b..a49458b4d0 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for) + // PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for) + // PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -132,20 +132,23 @@ void World::migration(TimePoint t, TimeSpan dt) auto& person = m_persons[trip.person_id]; auto& current_location = person->get_location(); auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); - if (!person->is_in_quarantine(t, parameters) && person->get_infection_state(t) != InfectionState::Dead) { - auto& target_location = get_individualized_location(trip.migration_destination); - if (m_testing_strategy.run_strategy(personal_rng, *person, target_location, t)) { - if (target_location != current_location && - target_location.get_number_persons() < target_location.get_capacity().persons && - target_location.entry_allowed(personal_rng, t)) { - person->apply_mask_intervention(personal_rng, target_location); - person->migrate_to(target_location); + if (current_location.get_type() != LocationType::Hospital && current_location.get_type() != LocationType::ICU && current_location.get_type() != LocationType::Cemetery) { + if (!person->is_in_quarantine(t, parameters)) { + auto& target_location = get_individualized_location(trip.migration_destination); + if (m_testing_strategy.run_strategy(personal_rng, *person, target_location, t)) { + if (target_location != current_location && + target_location.get_number_persons() < target_location.get_capacity().persons && + target_location.entry_allowed(personal_rng, t)) { + person->apply_mask_intervention(personal_rng, target_location); + person->migrate_to(target_location); + } } } - } - m_trip_list.increase_index(); + } } + m_trip_list.increase_index(); } + if (((t).days() < std::floor((t + dt).days()))) { m_trip_list.reset_index(); } @@ -154,7 +157,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_activity_status(t); - PRAGMA_OMP(parallel for) + // PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->adjust_contact_rates(parameters.get_num_groups()); From 682da721ac24106b6894b3cb308dd4a2ba7a01b4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:36:18 +0200 Subject: [PATCH 168/488] timings --- cpp/simulations/paper_abm_bs_testing.cpp | 50 ++++++++++++++++-------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d6a4b5e814..87afe82e41 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -36,8 +36,22 @@ #include "memilio/io/epi_data.h" #include "memilio/io/io.h" +#include +#define TIME_TYPE std::chrono::steady_clock::time_point +#define TIME_NOW std::chrono::steady_clock::now() +#define PRINTABLE_TIME(_time) (std::chrono::duration_cast>(_time)).count() + +#define restart_timer(timer, description) {\ + TIME_TYPE new_time = TIME_NOW;\ + std::cout << "\r" << description << " :: " << PRINTABLE_TIME(new_time - timer) << std::endl << std::flush;\ + timer = new_time;\ +} +#define DEBUG(cout_args) std::cerr << cout_args << std::endl << std::flush; + namespace fs = boost::filesystem; +TIME_TYPE timer; + // Assign the name to general age group. size_t num_age_groupss = 6; const auto age_group_0_to_4 = mio::AgeGroup(0); @@ -203,17 +217,17 @@ void prepare_vaccination_state(mio::Date simulation_end, const std::string& file } // we need to add the number of persons to the vector of the date, but these are cumulative so we need to substract the day before vacc_map[vacc_entry.date][determine_age_group_from_rki(vacc_entry.age_group)].first = - vacc_entry.num_vaccinations_partially - - vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].first; + (int)vacc_entry.num_vaccinations_partially - + (int)vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].first; vacc_map[vacc_entry.date][determine_age_group_from_rki(vacc_entry.age_group)].second = - vacc_entry.num_vaccinations_completed - - vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].second; + (int)vacc_entry.num_vaccinations_completed - + (int)vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].second; //update the vector for the next iteration vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].first = - vacc_entry.num_vaccinations_partially; + (int)vacc_entry.num_vaccinations_partially; vacc_vector_prev[determine_age_group_from_rki(vacc_entry.age_group)].second = - vacc_entry.num_vaccinations_completed; + (int)vacc_entry.num_vaccinations_completed; } } } @@ -1034,20 +1048,24 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con int max_num_persons, mio::Date start_date_sim) { //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world - + restart_timer(timer, "till set_paraemters"); set_parameters(world.parameters); set_local_parameters(world); + // Create the world object from statistical data. + restart_timer(timer, "till create_world_from_data"); create_world_from_data(world, (input_dir / "mobility/braunschweig_result_ffa8_modified.csv").generic_string(), t0, max_num_persons); world.use_migration_rules(false); // Assign an infection state to each person. + restart_timer(timer, "till assing infection state"); assign_infection_state(world, t0); // Assign vaccination status to each person. + restart_timer(timer, "till assing vaccination state"); assign_vaccination_state(world, start_date_sim); // add_testing_strategies(world, true, false); @@ -1270,7 +1288,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 400000; + auto max_num_persons = 40000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1296,14 +1314,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution //Time this - auto start0 = std::chrono::high_resolution_clock::now(); + restart_timer(timer, "till determine_initial_infection_states_world"); determine_initial_infection_states_world(input_dir, start_date); + restart_timer(timer, "till prepare_vaccination_state"); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - auto stop0 = std::chrono::high_resolution_clock::now(); - auto duration0 = std::chrono::duration(stop0 - start0); - std::cout << "Time taken by determine_initial_infection_states_world: " << duration0.count() << " seconds" - << std::endl; // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { @@ -1646,7 +1661,8 @@ int main(int argc, char** argv) // std::string input_dir = "/p/project/loki/memilio/memilio/data"; // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); auto created = create_result_folders(result_dir); @@ -1654,7 +1670,7 @@ int main(int argc, char** argv) copy_precomputed_results(precomputed_dir, result_dir); } size_t num_runs; - //bool save_single_runs = true; + bool save_single_runs = true; if (argc == 2) { num_runs = atoi(argv[1]); @@ -1687,8 +1703,8 @@ int main(int argc, char** argv) // printf("%u, ", s); // } // printf("\n"); - - // auto result = run(input_dir, result_dir, num_runs, save_single_runs); + timer = TIME_NOW; + auto result = run(input_dir, result_dir, num_runs, save_single_runs); // if (!result) { // printf("%s\n", result.error().formatted_message().c_str()); // mio::mpi::finalize(); From 601043922909017382f587c5b0989a4e39cce347 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 15 Jun 2024 23:29:01 +0200 Subject: [PATCH 169/488] quick bug fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index a49458b4d0..f7a7ad3b38 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -132,7 +132,9 @@ void World::migration(TimePoint t, TimeSpan dt) auto& person = m_persons[trip.person_id]; auto& current_location = person->get_location(); auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); - if (current_location.get_type() != LocationType::Hospital && current_location.get_type() != LocationType::ICU && current_location.get_type() != LocationType::Cemetery) { + if (current_location.get_type() != LocationType::Hospital && + current_location.get_type() != LocationType::ICU && + current_location.get_type() != LocationType::Cemetery) { if (!person->is_in_quarantine(t, parameters)) { auto& target_location = get_individualized_location(trip.migration_destination); if (m_testing_strategy.run_strategy(personal_rng, *person, target_location, t)) { @@ -144,9 +146,9 @@ void World::migration(TimePoint t, TimeSpan dt) } } } - } + } + m_trip_list.increase_index(); } - m_trip_list.increase_index(); } if (((t).days() < std::floor((t + dt).days()))) { From 88371e0f623574f3a071892aa4d00500020c0cd3 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 16 Jun 2024 00:37:09 +0200 Subject: [PATCH 170/488] slight ode fitting for startdata Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/generate_graph_from_data.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index a8b7052fbe..413f2e55a8 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -104,10 +104,10 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) { //times const double incubationTime = 5.2; - const double serialIntervalMin = 0.5 * 2.67 + 0.5 * 5.2; - const double serialIntervalMax = 0.5 * 4.00 + 0.5 * 5.2; - const double timeInfectedSymptomsMin[] = {5.6255, 5.6255, 5.6646, 5.5631, 5.501, 5.465}; - const double timeInfectedSymptomsMax[] = {8.427, 8.427, 8.4684, 8.3139, 8.169, 8.085}; + const double serialIntervalMin = 0.1 * 2.67 + 0.4 * 5.2; + const double serialIntervalMax = 0.1 * 2.67 + 0.4 * 5.2; + const double timeInfectedSymptomsMin[] = {6.6255, 6.6255, 6.6646, 6.5631, 6.501, 6.465}; + const double timeInfectedSymptomsMax[] = {6.6255, 6.6255, 6.6646, 6.5631, 6.501, 6.465}; const double timeInfectedSevereMin[] = {3.925, 3.925, 4.85, 6.4, 7.2, 9.}; const double timeInfectedSevereMax[] = {6.075, 6.075, 7., 8.7, 9.8, 13.}; const double timeInfectedCriticalMin[] = {4.95, 4.95, 4.86, 14.14, 14.4, 10.}; @@ -134,8 +134,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.15, 0.15, 0.15, 0.15, 0.15, 0.15}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.15, 0.15, 0.15, 0.15, 0.15, 0.15}; const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.20}; const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.18, 0.25}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; From 7783662af17c82987134534f08023ae7875cd811 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 16 Jun 2024 00:37:48 +0200 Subject: [PATCH 171/488] timings for dem optimization stuff Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 51 ++++++++++-------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 2c20ef30e3..4ead49d61e 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -296,7 +296,7 @@ def plot_mean_and_std(Y): # path to results # path = "/Users/david/Documents/HZI/memilio/data/results" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-06-10T21:35:59Z" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" # path = r"C:\Users\korf_sa\Documents\rep\data\results" # path = r"C:\Users\korf_sa\Documents\rep\data\results_cluster\results" if (len(sys.argv) > 1): diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 87afe82e41..e7d913a642 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -41,11 +41,12 @@ #define TIME_NOW std::chrono::steady_clock::now() #define PRINTABLE_TIME(_time) (std::chrono::duration_cast>(_time)).count() -#define restart_timer(timer, description) {\ - TIME_TYPE new_time = TIME_NOW;\ - std::cout << "\r" << description << " :: " << PRINTABLE_TIME(new_time - timer) << std::endl << std::flush;\ - timer = new_time;\ -} +#define restart_timer(timer, description) \ + { \ + TIME_TYPE new_time = TIME_NOW; \ + std::cout << "\r" << description << " :: " << PRINTABLE_TIME(new_time - timer) << std::endl << std::flush; \ + timer = new_time; \ + } #define DEBUG(cout_args) std::cerr << cout_args << std::endl << std::flush; namespace fs = boost::filesystem; @@ -1051,7 +1052,6 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con restart_timer(timer, "till set_paraemters"); set_parameters(world.parameters); set_local_parameters(world); - // Create the world object from statistical data. restart_timer(timer, "till create_world_from_data"); @@ -1288,7 +1288,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 40000; + auto max_num_persons = 400000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1322,17 +1322,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { - // Start the clock before create_sampled_world - auto start1 = std::chrono::high_resolution_clock::now(); - // Create the sampled simulation with start time t0. auto world = mio::abm::World(num_age_groupss); + restart_timer(timer, "till create_world"); create_sampled_world(world, input_dir, t0, max_num_persons, start_date); - // Stop the clock after create_sampled_world and calculate the duration - auto stop1 = std::chrono::high_resolution_clock::now(); - auto duration1 = std::chrono::duration(stop1 - start1); - std::cout << "Time taken by create_sampled_world: " << duration1.count() << " seconds" << std::endl; auto sim = mio::abm::Simulation(t0, std::move(world)); - bool npis_on = true; + bool npis_on = false; //output object // mio::History @@ -1346,7 +1340,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; // / NPIS// - auto start2 = std::chrono::high_resolution_clock::now(); if (npis_on) { const auto location_it = sim.get_world().get_locations(); @@ -1490,6 +1483,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.set_capacity(10, 0); } } + restart_timer(timer, "till advance 14"); sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 14 finished" << std::endl; @@ -1500,16 +1494,17 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.set_capacity(10, 0); } } + restart_timer(timer, "till advance 23"); sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = 4.5; - + restart_timer(timer, "till advance 37"); sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = 5.5; - + restart_timer(timer, "till advance 42"); sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 42 finished" << std::endl; // date 2021-04-12 @@ -1521,7 +1516,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = 4.5; - + restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; @@ -1548,21 +1543,19 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.set_npi_active(true); } } + restart_timer(timer, "till advance tmax"); sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 90 finished" << std::endl; } else { - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, - historyInfectionPerAgeGroup); + sim.advance(mio::abm::TimePoint(mio::abm::days(10).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); } ////Advance till here // Stop the clock after sim.advance and calculate the duration - auto stop2 = std::chrono::high_resolution_clock::now(); - auto duration2 = std::chrono::duration(stop2 - start2); - std::cout << "Time taken by sim.advance: " << duration2.count() << " seconds" << std::endl; - + restart_timer(timer, "till data gathering"); // TODO: update result of the simulation to be a vector of location result. auto temp_sim_infection_per_loc_tpye = std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; @@ -1592,7 +1585,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } } - printf("Saving results ... "); #ifdef MEMILIO_ENABLE_MPI @@ -1615,6 +1607,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s result_dir / "infection_per_location_type/", save_single_runs)); #endif + restart_timer(timer, "till complete end of simulation"); printf("done.\n"); //write_txt_file_for_graphical_compartment_output(ensemble_infection_state_per_age_group); return mio::success(); @@ -1660,9 +1653,9 @@ int main(int argc, char** argv) #endif // std::string input_dir = "/p/project/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; - std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; + // std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); auto created = create_result_folders(result_dir); @@ -1703,7 +1696,7 @@ int main(int argc, char** argv) // printf("%u, ", s); // } // printf("\n"); - timer = TIME_NOW; + timer = TIME_NOW; auto result = run(input_dir, result_dir, num_runs, save_single_runs); // if (!result) { // printf("%s\n", result.error().formatted_message().c_str()); From 21f1452b96682e9d62b9872789079840276711c3 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 16 Jun 2024 23:49:23 +0200 Subject: [PATCH 172/488] chore: Remove unnecessary columns and sort data for better search performance Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/cleanup_data.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 434608381f..931645f1cf 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -389,6 +389,11 @@ def assign_location_type(pd): pd.at[index, 'location_type'] = location_type_from_keys_and_values( row['map_feature_key'], row['map_feature_value'], row['activity_end'], test_pd) return pd +def add_time_if_null(pd): + # if start_time is null we set it to 0 + pd['start_time'] = pd['start_time'].fillna("12:30") + return pd + PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8.csv" bd = pd.read_csv(PATH) @@ -416,8 +421,11 @@ def assign_location_type(pd): # print('External location IDs set.') bd_new = assign_location_type(bd_new) print('Location types assigned.') +bd_new = add_time_if_null(bd_new) -# we need to delete the column map_feature_key and map_feature_value because we dont need them anymore -bd_new = bd_new.drop(columns=['map_feature_key', 'map_feature_value']) +# we need to remove unnecessary columns +bd_new = bd_new.drop(columns= ['start_zone', 'end_zone', 'loc_id_start', 'start_county', 'end_county', 'trip_distance', 'travel_time_sec', 'lon_start', 'lat_start', 'travel_mode', 'activity_start', 'activity_end', 'map_feature_key','map_feature_value']) +# sort for better search performance +bd_new = bd_new.sort_values(by=['puid', 'start_time']) # Write data back to disk -bd_new.to_csv('braunschweig_result_ffa8_modified.csv', index=False) +bd_new.to_csv('braunschweig_result_ffa8_modified2.csv', index=False) From dd251f9a1b67db1ac2e87788161da42e645023e3 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 17 Jun 2024 01:01:04 +0200 Subject: [PATCH 173/488] improved performance Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/trip_list.cpp | 41 +-- cpp/models/abm/trip_list.h | 18 +- cpp/models/abm/world.cpp | 7 +- cpp/models/abm/world.h | 8 +- cpp/simulations/paper_abm_bs_testing.cpp | 340 +++++------------------ 5 files changed, 106 insertions(+), 308 deletions(-) diff --git a/cpp/models/abm/trip_list.cpp b/cpp/models/abm/trip_list.cpp index 88ef819de4..b978db939f 100644 --- a/cpp/models/abm/trip_list.cpp +++ b/cpp/models/abm/trip_list.cpp @@ -22,6 +22,7 @@ #include "abm/random_events.h" #include +#include namespace mio { @@ -29,41 +30,49 @@ namespace abm { TripList::TripList() - : m_trips_weekday({}) - , m_trips_weekend({}) + : m_trips({}) , m_current_index(0) { } -const Trip& TripList::get_next_trip(bool weekend) const +const Trip& TripList::get_next_trip() const { - return weekend ? m_trips_weekend[m_current_index] : m_trips_weekday[m_current_index]; + return m_trips[m_current_index]; } -TimePoint TripList::get_next_trip_time(bool weekend) const +TimePoint TripList::get_next_trip_time() const { - return weekend ? m_trips_weekend[m_current_index].time : m_trips_weekday[m_current_index].time; + return m_trips[m_current_index].time; } -void TripList::use_weekday_trips_on_weekend() +void TripList::add_trip(Trip trip) { - m_trips_weekend = m_trips_weekday; + //Trips are sorted by time. + //Also include the person id in the comparison so different persons can make trips at the same time. + //The same person can only make one trip at the same time. + + insert_sorted_replace(m_trips, trip, [](auto& trip1, auto& trip2) { + return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id); + }); } -void TripList::add_trip(Trip trip, bool weekend) +void TripList::add_several_trips(std::vector trip) { //Trips are sorted by time. //Also include the person id in the comparison so different persons can make trips at the same time. //The same person can only make one trip at the same time. - if (!weekend) { - insert_sorted_replace(m_trips_weekday, trip, [](auto& trip1, auto& trip2) { - return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id); - }); + + std::sort(trip.begin(), trip.end(), [](auto& trip1, auto& trip2) { + return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id); + }); + if (m_trips.empty()) { + m_trips = trip; } else { - insert_sorted_replace(m_trips_weekend, trip, [](auto& trip1, auto& trip2) { - return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id); - }); + std::merge(m_trips.begin(), m_trips.end(), trip.begin(), trip.end(), std::back_inserter(m_trips), + [](auto& trip1, auto& trip2) { + return std::tie(trip1.time, trip1.person_id) < std::tie(trip2.time, trip2.person_id); + }); } } diff --git a/cpp/models/abm/trip_list.h b/cpp/models/abm/trip_list.h index 51ce065667..d704f6c322 100644 --- a/cpp/models/abm/trip_list.h +++ b/cpp/models/abm/trip_list.h @@ -149,25 +149,26 @@ class TripList * @brief Get the next Trip. * @param weekend Whether the Trip%s during the week or on the weekend are used. */ - const Trip& get_next_trip(bool weekend) const; + const Trip& get_next_trip() const; /** * @brief Get the time at which the next Trip will happen. * @param weekend Whether the Trip%s during the week or on the weekend are used. */ - TimePoint get_next_trip_time(bool weekend) const; + TimePoint get_next_trip_time() const; /** * @brief Add a Trip to migration data. * @param[in] trip The Trip to be added. * @param[in] weekend If the Trip is made on a weekend day. */ - void add_trip(Trip trip, bool weekend = false); + void add_trip(Trip trip); /** - * @brief Use the same TripList for weekend and weekday. + * @brief Add several Trip%s to migration data. + * @param[in] trip The Trip%s to be added. */ - void use_weekday_trips_on_weekend(); + void add_several_trips(std::vector trip); /** * @brief Increment the current index to select the next Trip. @@ -189,9 +190,9 @@ class TripList * @brief Get the length of the TripList. * @param weekend Whether the Trip%s during the week or on the weekend are used. */ - size_t num_trips(bool weekend = false) const + size_t num_trips() const { - return weekend ? m_trips_weekend.size() : m_trips_weekday.size(); + return m_trips.size(); } /** @@ -203,8 +204,7 @@ class TripList } private: - std::vector m_trips_weekday; ///< The list of Trip%s a Person makes on a weekday. - std::vector m_trips_weekend; ///< The list of Trip%s a Person makes on a weekend day. + std::vector m_trips; ///< The list of Trip%s a Person makes on a weekday. uint32_t m_current_index; ///< The index of the Trip a Person makes next. }; diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index f7a7ad3b38..a438a00ccd 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -122,13 +122,12 @@ void World::migration(TimePoint t, TimeSpan dt) } // check if a person makes a trip - bool weekend = t.is_weekend(); - size_t num_trips = m_trip_list.num_trips(weekend); + size_t num_trips = m_trip_list.num_trips(); if (num_trips != 0) { while (m_trip_list.get_current_index() < num_trips && - m_trip_list.get_next_trip_time(weekend).seconds() < (t + dt).time_since_midnight().seconds()) { - auto& trip = m_trip_list.get_next_trip(weekend); + m_trip_list.get_next_trip_time().seconds() < (t + dt).time_since_midnight().seconds()) { + auto& trip = m_trip_list.get_next_trip(); auto& person = m_persons[trip.person_id]; auto& current_location = person->get_location(); auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index 70a7858964..d707045fff 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -110,13 +110,13 @@ class World obj.add_element("num_agegroups", parameters.get_num_groups()); std::vector trips; TripList trip_list = get_trip_list(); - for (size_t i = 0; i < trip_list.num_trips(false); i++) { - trips.push_back(trip_list.get_next_trip(false)); + for (size_t i = 0; i < trip_list.num_trips(); i++) { + trips.push_back(trip_list.get_next_trip()); trip_list.increase_index(); } trip_list.reset_index(); - for (size_t i = 0; i < trip_list.num_trips(true); i++) { - trips.push_back(trip_list.get_next_trip(true)); + for (size_t i = 0; i < trip_list.num_trips(); i++) { + trips.push_back(trip_list.get_next_trip()); trip_list.increase_index(); } obj.add_list("trips", trips.begin(), trips.end()); diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e7d913a642..9be2f9361e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -343,12 +343,6 @@ int longLatToInt(const std::string& input) void split_line(std::string string, std::vector* row) { std::vector strings; - - std::string x = ",,", y = ",-1,"; - size_t pos; - while ((pos = string.find(x)) != std::string::npos) { - string.replace(pos, 2, y); - } // Temporary fix to handle empty cells. boost::split(strings, string, boost::is_any_of(",")); std::transform(strings.begin(), strings.end(), std::back_inserter(*row), [&](std::string s) { if (s.find(":") != std::string::npos) { @@ -357,9 +351,6 @@ void split_line(std::string string, std::vector* row) else if (s.find(".") != std::string::npos) { return longLatToInt(s); } - else if (s == "null") { - return 43200; // This shouldnt be too often, we will take 12 o'clock as default - } else { return std::stoi(s); } @@ -417,8 +408,7 @@ mio::AgeGroup determine_age_group(uint32_t age) } } -void create_world_from_data(mio::abm::World& world, const std::string& filename, const mio::abm::TimePoint t0, - int max_number_persons) +void create_world_from_data(mio::abm::World& world, const std::string& filename, const int max_number_persons) { // Open File const fs::path p = filename; @@ -447,12 +437,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, count_of_titles++; } - std::map locations = {}; - std::map persons = {}; - - std::map person_ids = {}; - std::map> locations_before; - std::map> locations_after; + std::map locations = {}; //uint is the location id from the data file + std::map persons = {}; //uint is the person id from the data file // For the world we need: Hospitals, ICUs (for both we just create one for now), Homes for each unique householdID, One Person for each person_id with respective age and home_id. @@ -467,8 +453,10 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::numeric_limits::max()); // First we determine the persons number and their starting locations - int number_of_persons = 0; - + restart_timer(timer, "first while loop"); + // Add all home locations to the world and count persons + uint32_t last_person_id = 0; + int number_of_persons_read_in = 0; while (std::getline(fin, line)) { row.clear(); @@ -477,67 +465,20 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); uint32_t person_id = row[index["puid"]]; - - auto it_person_id = person_ids.find(person_id); - if (it_person_id == person_ids.end()) { - if (number_of_persons >= max_number_persons) - break; //This is okay because the data is sorted by person_id - person_ids.insert({person_id, number_of_persons}); - number_of_persons++; - } - - // The starting location of a person is the end location of the last trip he made, either on the same day or on - // the day before - uint32_t target_location_id = row[index["loc_id_end"]]; - int trip_start = row[index["start_time"]]; - if (trip_start < t0.hour_of_day()) { - auto it_person = locations_before.find(person_id); - if (it_person == locations_before.end()) { - locations_before.insert({person_id, std::make_pair(target_location_id, trip_start)}); - } - else { - if (it_person->second.second <= trip_start) { - it_person->second.first = target_location_id; - it_person->second.second = trip_start; - } + if (person_id != last_person_id) { + number_of_persons_read_in++; + last_person_id = person_id; + if (number_of_persons_read_in > max_number_persons) { + break; } } - else { - auto it_person = locations_after.find(person_id); - if (it_person == locations_after.end()) { - locations_after.insert({person_id, std::make_pair(target_location_id, trip_start)}); - } - else { - if (it_person->second.second <= trip_start) { - it_person->second.first = target_location_id; - it_person->second.second = trip_start; - } - } - } - } - - fin.clear(); - fin.seekg(0); - std::getline(fin, line); // Skip header row - - // Add all locations to the world - while (std::getline(fin, line)) { - row.clear(); - - // read columns in this row - split_line(line, &row); - line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); - - uint32_t person_id = row[index["puid"]]; - if (person_ids.find(person_id) == person_ids.end()) - break; uint32_t home_id = row[index["huid"]]; mio::abm::LocationId home; auto it_home = locations.find(home_id); if (it_home == locations.end()) { - home = world.add_location(mio::abm::LocationType::Home, 1); + home = world.add_location(mio::abm::LocationType::Home); locations.insert({home_id, home}); } } @@ -545,6 +486,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, fin.clear(); fin.seekg(0); std::getline(fin, line); // Skip header row + last_person_id = 0; + number_of_persons_read_in = 0; while (std::getline(fin, line)) { row.clear(); @@ -552,6 +495,15 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, split_line(line, &row); line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); + uint32_t person_id = row[index["puid"]]; + if (person_id != last_person_id) { + number_of_persons_read_in++; + last_person_id = person_id; + if (number_of_persons_read_in > max_number_persons) { + break; + } + } + mio::abm::LocationId location; int target_location_id = row[index["loc_id_end"]]; uint32_t location_type = row[index["location_type"]]; @@ -560,9 +512,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, auto it_location = locations.find( target_location_id); // Check if location already exists also for home which have the same id (home_id = target_location_id) if (it_location == locations.end()) { - location = world.add_location( - get_location_type(location_type), - 1); // Assume one place has one activity, this may be untrue but not important for now(?) + location = world.add_location(get_location_type(location_type)); locations.insert({target_location_id, location}); world.get_individualized_location(location).set_geographical_location(location_long_lat); } @@ -571,97 +521,52 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, fin.clear(); fin.seekg(0); std::getline(fin, line); // Skip header row - - // Add the persons and trips + last_person_id = 0; + number_of_persons_read_in = 0; + std::vector trip_vec; + restart_timer(timer, "last while loop"); while (std::getline(fin, line)) { row.clear(); // read columns in this row split_line(line, &row); line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); - uint32_t person_id = row[index["puid"]]; - if (person_ids.find(person_id) == person_ids.end()) - break; + if (person_id != last_person_id) { + number_of_persons_read_in++; + last_person_id = person_id; + if (number_of_persons_read_in > max_number_persons) { + break; + } + } - uint32_t age = row[index["age"]]; - uint32_t home_id = row[index["huid"]]; - int target_location_id = row[index["loc_id_end"]]; - // int start_location_id = row[index["loc_id_start"]]; + uint32_t age = row[index["age"]]; + uint32_t home_id = row[index["huid"]]; + uint32_t target_location_id = row[index["loc_id_end"]]; + uint32_t trip_start = row[index["start_time"]]; + bool home_in_bs = row[index["home_in_bs"]]; - uint32_t trip_start = row[index["start_time"]]; - uint32_t transport_mode = row[index["travel_mode"]]; - uint32_t activity_end = row[index["activity_end"]]; - bool home_in_bs = row[index["home_in_bs"]]; // Add the trip to the trip list person and location must exist at this point auto target_location = locations.find(target_location_id)->second; - - auto it_person = persons.find(person_id); - + auto it_person = persons.find(person_id); if (it_person == persons.end()) { - auto it_first_location_id = locations_before.find(person_id); - if (it_first_location_id == locations_before.end()) { - it_first_location_id = locations_after.find(person_id); - } - auto first_location_id = it_first_location_id->second.first; - auto first_location = locations.find(first_location_id)->second; - auto& person = world.add_person(first_location, determine_age_group(age)); - auto home = locations.find(home_id)->second; - //check of home is found - - if (locations.find(home_id) == locations.end()) { - mio::log_error("Home not found"); - std::cout << home_id << " " << person_id << std::endl; - } - if (home_in_bs) { - person.set_should_be_logged(true); - } - else { - person.set_should_be_logged(false); - } - + auto home = locations.find(home_id)->second; + auto& person = world.add_person(home, determine_age_group(age)); person.set_assigned_location(home); person.set_assigned_location(hospital); person.set_assigned_location(icu); persons.insert({person_id, person}); + home_in_bs ? person.set_should_be_logged(true) : person.set_should_be_logged(false); it_person = persons.find(person_id); - auto test = person.get_assigned_location_index(mio::abm::LocationType::Home); - if (test == 4294967295) { - std::cout << "Home ID: " << home_id << " and person ID: " << person_id << std::endl; - } } if (target_location.type != mio::abm::LocationType::Home) { - it_person->second.set_assigned_location( - target_location); //This assumes that we only have in each tripchain only one location type for each person + it_person->second.set_assigned_location(target_location); } - - // if (locations.find(start_location_id) == locations.end()) { - // // For trips where the start location is not known use Home instead - - // } - mio::abm::LocationId start_location = { - it_person->second.get_assigned_location_index(mio::abm::LocationType::Home), mio::abm::LocationType::Home}; - world.get_trip_list().add_trip(mio::abm::Trip( - it_person->second.get_person_id(), mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location, - start_location, mio::abm::TransportMode(transport_mode), mio::abm::ActivityType(activity_end))); + trip_vec.push_back(mio::abm::Trip(it_person->second.get_person_id(), + mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location)); } - world.get_trip_list().use_weekday_trips_on_weekend(); - - // //Some Data about the world: - // //write how many persons are in each home - // std::map persons_in_home; - // for (auto& person : world.get_persons()) { - // auto home = person.get_assigned_location_index(mio::abm::LocationType::Home); - // if (persons_in_home.find(home) == persons_in_home.end()) { - // persons_in_home.insert({home, 1}); - // } - // else { - // persons_in_home[home]++; - // } - // } - // for (auto& home : persons_in_home) { - // mio::log_info("Home ", home.first, " has ", home.second, " persons."); - // } + world.get_trip_list().add_several_trips(trip_vec); + restart_timer(timer, "end of while loops"); } std::pair get_my_and_sigma(std::pair mean_and_std) @@ -1055,14 +960,14 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Create the world object from statistical data. restart_timer(timer, "till create_world_from_data"); - create_world_from_data(world, (input_dir / "mobility/braunschweig_result_ffa8_modified.csv").generic_string(), t0, + create_world_from_data(world, (input_dir / "mobility/braunschweig_result_ffa8_modified2.csv").generic_string(), max_num_persons); world.use_migration_rules(false); // Assign an infection state to each person. restart_timer(timer, "till assing infection state"); - assign_infection_state(world, t0); + assign_infection_state_prob(world, t0); // Assign vaccination status to each person. restart_timer(timer, "till assing vaccination state"); @@ -1071,129 +976,6 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // add_testing_strategies(world, true, false); } -template -void write_log_to_file_person_and_location_data(const T& history) -{ - auto logg = history.get_log(); - auto loc_id = std::get<0>(logg)[0]; - auto agent_id = std::get<1>(logg)[0]; - // Write lo to a text file. - std::ofstream myfile("locations_lookup.txt"); - myfile << "location_id, location_type, latitude, longitude\n"; - for (uint32_t loc_id_index = 0; loc_id_index < loc_id.size(); ++loc_id_index) { - auto id = std::get<0>(loc_id[loc_id_index]); - auto location_type = (int)std::get<1>(loc_id[loc_id_index]); - auto id_longitute = std::get<2>(loc_id[loc_id_index]).longitude; - auto id_latitude = std::get<2>(loc_id[loc_id_index]).latitude; - myfile << id << ", " << location_type << ", " << id_longitute << ", " << id_latitude << "\n"; - } - myfile.close(); - - std::ofstream myfile2("agents_lookup.txt"); - myfile2 << "agent_id, home_id, age\n"; - for (uint32_t agent_id_index = 0; agent_id_index < agent_id.size(); ++agent_id_index) { - auto id = std::get<0>(agent_id[agent_id_index]); - auto home_id = std::get<1>(agent_id[agent_id_index]); - auto age = std::get<2>(agent_id[agent_id_index]); - myfile2 << id << ", " << home_id << ", " << age << "\n"; - } - myfile2.close(); -} - -template -void write_log_to_file_trip_data(const T& history) -{ - - auto movement_data = std::get<0>(history.get_log()); - std::ofstream myfile3("movement_data.txt"); - myfile3 << "agent_id, trip_id, start_location, end_location, start_time, end_time, transport_mode, activity, " - "infection_state \n"; - int trips_id = 0; - for (uint32_t movement_data_index = 2; movement_data_index < movement_data.size(); ++movement_data_index) { - myfile3 << "timestep Nr.: " << movement_data_index - 1 << "\n"; - for (uint32_t trip_index = 0; trip_index < movement_data[movement_data_index].size(); trip_index++) { - auto agent_id = (int)std::get<0>(movement_data[movement_data_index][trip_index]); - - int start_index = movement_data_index - 1; - using Type = std::tuple; - while (!std::binary_search(std::begin(movement_data[start_index]), std::end(movement_data[start_index]), - movement_data[movement_data_index][trip_index], - [](const Type& v1, const Type& v2) { - return std::get<0>(v1) < std::get<0>(v2); - })) { - start_index--; - } - auto start_location_pointer = - std::lower_bound(std::begin(movement_data[start_index]), std::end(movement_data[start_index]), - movement_data[movement_data_index][trip_index], [](const Type& v1, const Type& v2) { - return std::get<0>(v1) < std::get<0>(v2); - }); - int start_location = (int)std::get<1>(*start_location_pointer); - - auto end_location = (int)std::get<1>(movement_data[movement_data_index][trip_index]); - - auto start_time = (int)std::get<2>(movement_data[movement_data_index][trip_index]).seconds(); - auto end_time = (int)std::get<2>(movement_data[movement_data_index][trip_index]).seconds(); - - auto transport_mode = (int)std::get<3>(movement_data[movement_data_index][trip_index]); - auto activity = (int)std::get<4>(movement_data[movement_data_index][trip_index]); - auto infection_state = (int)std::get<5>(movement_data[movement_data_index][trip_index]); - myfile3 << agent_id << ", " << trips_id << ", " << start_location << " , " << end_location << " , " - << start_time << " , " << end_time << " , " << transport_mode << " , " << activity << " , " - << infection_state << "\n"; - trips_id++; - } - } - myfile3.close(); -} - -void write_txt_file_for_graphical_compartment_output(std::vector>> input_file) -{ - // mio::unused(input_file); - // In the input file is a h5 file there are multiple runs with each having the amount of people in each compartment for each timestep. - // The output folder should have the following format: - // for each run there is a file with the name "run_1.txt" and so on. - // in each file the the rows represent the timesteps and the columns represent the compartments. - // The first row is the header with the compartment names. - // Time = Time in days, S = Susceptible, E = Exposed, I_NS = InfectedNoSymptoms, I_Sy = InfectedSymptoms, I_Sev = InfectedSevere, - // I_Crit = InfectedCritical, R = Recovered, D = Dead - - // Output folder name: - std::string folderName = "folder_run_bs"; - // Create folder - fs::create_directory(folderName); - // Loop over all runs - for (int run = 0; run < (int)input_file.size(); run++) { - // Create file name - std::string fileName = folderName + "/run_" + std::to_string(run) + ".txt"; - // Create file - std::ofstream myfile; - myfile.open(fileName); - // Write header - input_file.at(run).at(0).print_table({"S", "E", "I_NS", "I_Sy", "I_Sev", "I_Crit", "R", "D"}, 7, 4, myfile); - } -} - -template -void write_log_to_file_infection_per_location_type(const T& history, const fs::path& result_dir) -{ - std::ofstream myfile4((result_dir / "infection_per_location_type.txt").string()); - const std::vector& labels = { - "Home", "School", "Work", "SocialEvent", "BasicsShop", - "Hospital", "ICU", "Car", "PublicTransport", "TransportWithoutContact", - "Cemetery"}; - std::get<0>(history.get_log()).print_table(labels, 12, 4, myfile4); -} - -template -void write_log_to_file_infection_per_age_group(const T& history, const fs::path& result_dir) -{ - std::ofstream myfile5((result_dir / "infection_per_age_group.txt").string()); - const std::vector& labels = {"0_to_4", "5_to_14", "15_to_34", "35_to_59", "60_to_79", "80_plus"}; - std::get<0>(history.get_log()).print_table(labels, 7, 4, myfile5); -} - struct LogInfectionStatePerAgeGroup : mio::LogAlways { using Type = std::pair; /** @@ -1222,6 +1004,18 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { return std::make_pair(curr_time, sum); } }; + +template +void write_log_to_file_infection_per_location_type(const T& history, const fs::path& result_dir) +{ + std::ofstream myfile4((result_dir / "infection_per_location_type.txt").string()); + const std::vector& labels = { + "Home", "School", "Work", "SocialEvent", "BasicsShop", + "Hospital", "ICU", "Car", "PublicTransport", "TransportWithoutContact", + "Cemetery"}; + std::get<0>(history.get_log()).print_table(labels, 12, 4, myfile4); +} + #ifdef MEMILIO_ENABLE_MPI template T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) @@ -1288,7 +1082,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 400000; + auto max_num_persons = 200000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1569,9 +1363,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s ensemble_infection_per_age_group.emplace_back(temp_sim_infection_per_age_group); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); // Option to save the current run result to file - // write_log_to_file_person_and_location_data(historyPersonInf); - // write_log_to_file_trip_data(historyPersonInfDelta); - // write_log_to_file_infection_per_age_group(historyInfectionPerAgeGroup, result_dir); write_log_to_file_infection_per_location_type(historyInfectionPerLocationType, result_dir); std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; @@ -1609,7 +1400,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s #endif restart_timer(timer, "till complete end of simulation"); printf("done.\n"); - //write_txt_file_for_graphical_compartment_output(ensemble_infection_state_per_age_group); return mio::success(); } From 46d6a0fedcf2f92f85accb8c6cf168b61c17016c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 17 Jun 2024 01:05:26 +0200 Subject: [PATCH 174/488] cleanup Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9be2f9361e..e9814fab3c 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1082,7 +1082,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 200000; + auto max_num_persons = 400000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1119,13 +1119,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto world = mio::abm::World(num_age_groupss); restart_timer(timer, "till create_world"); create_sampled_world(world, input_dir, t0, max_num_persons, start_date); - auto sim = mio::abm::Simulation(t0, std::move(world)); - bool npis_on = false; - //output object - // mio::History - // historyPersonInf; - // mio::History historyPersonInfDelta; + auto sim = mio::abm::Simulation(t0, std::move(world)); + + //Logger mio::History historyInfectionPerLocationType{ Eigen::Index(mio::abm::LocationType::Count)}; mio::History historyInfectionPerAgeGroup{ @@ -1134,6 +1130,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; // / NPIS// + bool npis_on = false; if (npis_on) { const auto location_it = sim.get_world().get_locations(); From f5c315cd98f84ad2855d19e33cb6cdeb93c400ee Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 17 Jun 2024 01:06:43 +0200 Subject: [PATCH 175/488] chore: Add timer for simulation run Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e9814fab3c..2e8930be6d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1119,6 +1119,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto world = mio::abm::World(num_age_groupss); restart_timer(timer, "till create_world"); create_sampled_world(world, input_dir, t0, max_num_persons, start_date); + + restart_timer(timer, "till run_simulation"); auto sim = mio::abm::Simulation(t0, std::move(world)); //Logger From cee9a4acb7a856669781176e27128b28e4b54db1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:01:20 +0200 Subject: [PATCH 176/488] feat: Add timer for simulation run --- cpp/simulations/paper_abm_bs_testing.cpp | 145 +++++++++++------------ 1 file changed, 68 insertions(+), 77 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2e8930be6d..d44f99194f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -453,7 +453,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, std::numeric_limits::max()); // First we determine the persons number and their starting locations - restart_timer(timer, "first while loop"); // Add all home locations to the world and count persons uint32_t last_person_id = 0; int number_of_persons_read_in = 0; @@ -524,7 +523,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, last_person_id = 0; number_of_persons_read_in = 0; std::vector trip_vec; - restart_timer(timer, "last while loop"); while (std::getline(fin, line)) { row.clear(); @@ -566,7 +564,6 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location)); } world.get_trip_list().add_several_trips(trip_vec); - restart_timer(timer, "end of while loops"); } std::pair get_my_and_sigma(std::pair mean_and_std) @@ -954,24 +951,24 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con int max_num_persons, mio::Date start_date_sim) { //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world - restart_timer(timer, "till set_paraemters"); + set_parameters(world.parameters); set_local_parameters(world); + restart_timer(timer, "time taken for setting up parameters and local parameters"); // Create the world object from statistical data. - restart_timer(timer, "till create_world_from_data"); create_world_from_data(world, (input_dir / "mobility/braunschweig_result_ffa8_modified2.csv").generic_string(), max_num_persons); - world.use_migration_rules(false); + restart_timer(timer, "time taken for braunschweig trip input"); // Assign an infection state to each person. - restart_timer(timer, "till assing infection state"); assign_infection_state_prob(world, t0); + restart_timer(timer, "time taken for assigning infection state"); // Assign vaccination status to each person. - restart_timer(timer, "till assing vaccination state"); assign_vaccination_state(world, start_date_sim); + restart_timer(timer, "time taken for assigning vaccination state"); // add_testing_strategies(world, true, false); } @@ -1108,19 +1105,19 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution //Time this - restart_timer(timer, "till determine_initial_infection_states_world"); + restart_timer(timer, "time for initial setup"); determine_initial_infection_states_world(input_dir, start_date); - restart_timer(timer, "till prepare_vaccination_state"); + restart_timer(timer, "time for determine_initial_infection_states_world"); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - + restart_timer(timer, "time for vaccinaiton state"); // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { auto world = mio::abm::World(num_age_groupss); - restart_timer(timer, "till create_world"); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date); - restart_timer(timer, "till run_simulation"); + restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); //Logger @@ -1132,25 +1129,25 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; // / NPIS// - bool npis_on = false; + bool npis_on = true; if (npis_on) { const auto location_it = sim.get_world().get_locations(); // Advance the world with respective npis // 1. testing schemes in schools - auto testing_min_time_school = mio::abm::days(7); - auto probability_school = 1.0; - auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 - auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 - auto test_type_school = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = - sim.get_world().parameters.get()[test_type_school]; // Test parameters - auto testing_criteria_school = mio::abm::TestingCriteria(); - auto testing_scheme_school = - mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, - end_date_test_school, test_parameters, probability_school); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - testing_scheme_school); + // auto testing_min_time_school = mio::abm::days(7); + // auto probability_school = 1.0; + // auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 + // auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 + // auto test_type_school = mio::abm::TestType::Antigen; // Antigen test + // auto test_parameters = + // sim.get_world().parameters.get()[test_type_school]; // Test parameters + // auto testing_criteria_school = mio::abm::TestingCriteria(); + // auto testing_scheme_school = + // mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, + // end_date_test_school, test_parameters, probability_school); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + // testing_scheme_school); // 2. testing schemes in work places for 35% of random workplaces @@ -1167,21 +1164,21 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto num_work_locations = (int)(0.35 * work_location_ids.size()); std::vector work_location_ids_35(work_location_ids.begin(), work_location_ids.begin() + num_work_locations); - auto testing_min_time_work = mio::abm::days(1); - auto probability_work = 1.0; - auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); - auto end_date_test_work = mio::abm::TimePoint(tmax); - auto test_type_work = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_work = - sim.get_world().parameters.get()[test_type_work]; // Test parameters - auto testing_criteria_work = mio::abm::TestingCriteria(); - auto testing_scheme_work = - mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, - end_date_test_work, test_parameters_work, probability_work); - for (auto& location_id : work_location_ids_35) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); - } + // auto testing_min_time_work = mio::abm::days(1); + // auto probability_work = 1.0; + // auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); + // auto end_date_test_work = mio::abm::TimePoint(tmax); + // auto test_type_work = mio::abm::TestType::Antigen; // Antigen test + // auto test_parameters_work = + // sim.get_world().parameters.get()[test_type_work]; // Test parameters + // auto testing_criteria_work = mio::abm::TestingCriteria(); + // auto testing_scheme_work = + // mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, + // end_date_test_work, test_parameters_work, probability_work); + // for (auto& location_id : work_location_ids_35) { + // sim.get_world().get_testing_strategy().add_testing_scheme( + // mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); + // } // 2.5 plus testing schemes at 20 % of basics shops std::vector basics_shop_location_ids; @@ -1191,25 +1188,25 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } //take 20% of basics shop locations - std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); - auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); - std::vector basics_shop_location_ids_20( - basics_shop_location_ids.begin(), basics_shop_location_ids.begin() + num_basics_shop_locations); - auto testing_min_time_basics_shop = mio::abm::days(2); - auto probability_basics_shop = 1.0; - auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); - auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); - auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_basics_shop = - sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters - auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); - auto testing_scheme_basics_shop = mio::abm::TestingScheme( - testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, - end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); - for (auto& location_id : basics_shop_location_ids_20) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); - } + // std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); + // auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); + // std::vector basics_shop_location_ids_20( + // basics_shop_location_ids.begin(), basics_shop_location_ids.begin() + num_basics_shop_locations); + // auto testing_min_time_basics_shop = mio::abm::days(2); + // auto probability_basics_shop = 1.0; + // auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); + // auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); + // auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test + // auto test_parameters_basics_shop = + // sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters + // auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); + // auto testing_scheme_basics_shop = mio::abm::TestingScheme( + // testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, + // end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); + // for (auto& location_id : basics_shop_location_ids_20) { + // sim.get_world().get_testing_strategy().add_testing_scheme( + // mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); + // } // 3. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks @@ -1234,13 +1231,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::BasicsShop) { location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } - if (location.get_type() == mio::abm::LocationType::Work || - location.get_type() == mio::abm::LocationType::BasicsShop) { - // location.add_damping(mio::abm::TimePoint(mio::abm::days(23).seconds()), 0.2); // from 2021-03-15 - // location.add_damping(mio::abm::TimePoint(mio::abm::days(30).seconds()), 0.8); // from 2021-04-01 - // location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.2); // from 2021-04-12 - // location.add_damping(mio::abm::TimePoint(mio::abm::days(72).seconds()), 1.0); // from 2021-05-10 - } + } // 5. add capacity limits to some locations @@ -1342,13 +1333,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::cout << "day 90 finished" << std::endl; } else { - sim.advance(mio::abm::TimePoint(mio::abm::days(10).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); + sim.advance(mio::abm::TimePoint(mio::abm::days(1).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + historyInfectionPerAgeGroup); } ////Advance till here // Stop the clock after sim.advance and calculate the duration - restart_timer(timer, "till data gathering"); + restart_timer(timer, "time taken for simulation end"); // TODO: update result of the simulation to be a vector of location result. auto temp_sim_infection_per_loc_tpye = std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; @@ -1397,7 +1388,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s result_dir / "infection_per_location_type/", save_single_runs)); #endif - restart_timer(timer, "till complete end of simulation"); + restart_timer(timer, "time taken for data gathering and saving results"); printf("done.\n"); return mio::success(); } @@ -1408,7 +1399,7 @@ const std::string currentDateTime() // Example of the very popular RFC 3339 format UTC time std::time_t time = std::time({}); char timeString[std::size("yyyy-mm-ddThh:mm:ssZ")]; - std::strftime(std::data(timeString), std::size(timeString), "%FT%TZ", std::gmtime(&time)); + std::strftime(std::data(timeString), std::size(timeString), "%F%H%M%S", std::gmtime(&time)); return timeString; } @@ -1441,10 +1432,10 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; - // std::string input_dir = "C:\\Users\\korf_sa\\Documents\\rep\\data"; + // std::string input_dir = "/p/project/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); auto created = create_result_folders(result_dir); From 073371d72e86c704931f90d71547c983e0c1c44d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 17 Jun 2024 23:07:19 +0200 Subject: [PATCH 177/488] short fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 135 +++++++++++------------ 1 file changed, 67 insertions(+), 68 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d44f99194f..be678cbacc 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -951,7 +951,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con int max_num_persons, mio::Date start_date_sim) { //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world - + set_parameters(world.parameters); set_local_parameters(world); restart_timer(timer, "time taken for setting up parameters and local parameters"); @@ -1114,7 +1114,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { auto world = mio::abm::World(num_age_groupss); - + create_sampled_world(world, input_dir, t0, max_num_persons, start_date); restart_timer(timer, "time taken for create sampled world"); @@ -1231,7 +1231,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::BasicsShop) { location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } - } // 5. add capacity limits to some locations @@ -1271,70 +1270,70 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, historyInfectionPerAgeGroup); std::cout << "day 14 finished" << std::endl; - // small social events to capacity 5 - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); - } - } - restart_timer(timer, "till advance 23"); - sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); - sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 4.5; - restart_timer(timer, "till advance 37"); - sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); - sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 5.5; - restart_timer(timer, "till advance 42"); - sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); - std::cout << "day 42 finished" << std::endl; // date 2021-04-12 - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(false); - } - } - // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter - sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 4.5; - restart_timer(timer, "till advance 72"); - sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); - std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - - sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - 5.5; - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(2, 0); - } - //90% of big social events get reopened and caopacity will be unlimited - int number_of_big_social_events = (int)(0.7 * social_event_location_ids_big.size()); - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - number_of_big_social_events--; - if (number_of_big_social_events >= 0) { - location.set_capacity(std::numeric_limits::max(), 0); - } - } - } - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(true); - } - } - restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, - historyInfectionPerAgeGroup); - std::cout << "day 90 finished" << std::endl; + // // small social events to capacity 5 + // for (auto& location : location_it) { + // if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + // location.get_index()) != social_event_location_ids_small.end()) { + // location.set_capacity(10, 0); + // } + // } + // restart_timer(timer, "till advance 23"); + // sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, + // historyInfectionPerLocationType, historyInfectionPerAgeGroup); + // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + // 4.5; + // restart_timer(timer, "till advance 37"); + // sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, + // historyInfectionPerLocationType, historyInfectionPerAgeGroup); + // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + // 5.5; + // restart_timer(timer, "till advance 42"); + // sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, + // historyInfectionPerLocationType, historyInfectionPerAgeGroup); + // std::cout << "day 42 finished" << std::endl; // date 2021-04-12 + // for (auto& location : location_it) { + // if (location.get_type() != mio::abm::LocationType::School) { + // location.set_npi_active(false); + // } + // } + // // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter + // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + // 4.5; + // restart_timer(timer, "till advance 72"); + // sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, + // historyInfectionPerLocationType, historyInfectionPerAgeGroup); + // std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + + // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = + // 5.5; + // for (auto& location : location_it) { + // if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + // location.get_index()) != social_event_location_ids_small.end()) { + // location.set_capacity(2, 0); + // } + // //90% of big social events get reopened and caopacity will be unlimited + // int number_of_big_social_events = (int)(0.7 * social_event_location_ids_big.size()); + // if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + // location.get_index()) != social_event_location_ids_big.end()) { + // number_of_big_social_events--; + // if (number_of_big_social_events >= 0) { + // location.set_capacity(std::numeric_limits::max(), 0); + // } + // } + // } + // for (auto& location : location_it) { + // if (location.get_type() != mio::abm::LocationType::School) { + // location.set_npi_active(true); + // } + // } + // restart_timer(timer, "till advance tmax"); + // sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + // historyInfectionPerAgeGroup); + // std::cout << "day 90 finished" << std::endl; } else { - sim.advance(mio::abm::TimePoint(mio::abm::days(1).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, - historyInfectionPerAgeGroup); + sim.advance(mio::abm::TimePoint(mio::abm::days(1).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType, historyInfectionPerAgeGroup); } ////Advance till here @@ -1398,7 +1397,7 @@ const std::string currentDateTime() { // Example of the very popular RFC 3339 format UTC time std::time_t time = std::time({}); - char timeString[std::size("yyyy-mm-ddThh:mm:ssZ")]; + char timeString[std::size("yyyy-mm-dddddddd")]; std::strftime(std::data(timeString), std::size(timeString), "%F%H%M%S", std::gmtime(&time)); return timeString; } @@ -1433,9 +1432,9 @@ int main(int argc, char** argv) #endif // std::string input_dir = "/p/project/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; - std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; + // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); auto created = create_result_folders(result_dir); From 754d8716a7a40294da72580c8129b5fff9d1fea6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:22:00 +0200 Subject: [PATCH 178/488] enable openmp again, ups Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index a438a00ccd..e33e26f54c 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - // PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - // PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -158,7 +158,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_activity_status(t); - // PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->adjust_contact_rates(parameters.get_num_groups()); From 3a43fb8bb78e1c670f335125d51e2d8cbc0430de Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:58:45 +0200 Subject: [PATCH 179/488] par fitting and cleanup Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 8 ++++---- cpp/simulations/generate_graph_from_data.cpp | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 4ead49d61e..5a47e04530 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -53,10 +53,10 @@ def main(path, n_runs): # read in txt file if file.startswith("infection_per_location_type.txt"): - df = pd.read_csv(file_path, delim_whitespace=True) + df = pd.read_csv(file_path, sep='\s+') plot_infection_per_location_type(df) if file.startswith("infection_per_age_group.txt"): - df = pd.read_csv(file_path, delim_whitespace=True) + df = pd.read_csv(file_path,sep='\s+') # plot_infection_per_age_group(df) # if file.startswith("run_"): # convert to numpy array @@ -152,7 +152,7 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): plt.figure('Infection_states') plt.title('Infection states') - color_plot = cmx.get_cmap('Set1').colors + color_plot = matplotlib.colormaps.get_cmap('Set1').colors states_plot = [1, 2, 3, 4, 5, 7] legend_plot = ['E', 'I_NSymp', 'I_Symp', 'I_Sev', 'I_Crit', 'Dead', 'Sm. rep. Sympt.'] @@ -201,7 +201,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] - color_plot = cmx.get_cmap('Set1').colors + color_plot = matplotlib.colormaps.get_cmap('Set1').colors fig, ax = plt.subplots(3, len(age_group_access), constrained_layout = True) fig.set_figwidth(20) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 413f2e55a8..dafa638bd0 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -104,8 +104,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) { //times const double incubationTime = 5.2; - const double serialIntervalMin = 0.1 * 2.67 + 0.4 * 5.2; - const double serialIntervalMax = 0.1 * 2.67 + 0.4 * 5.2; + const double serialIntervalMin = 1.1; + const double serialIntervalMax = 1.1; const double timeInfectedSymptomsMin[] = {6.6255, 6.6255, 6.6646, 6.5631, 6.501, 6.465}; const double timeInfectedSymptomsMax[] = {6.6255, 6.6255, 6.6646, 6.5631, 6.501, 6.465}; const double timeInfectedSevereMin[] = {3.925, 3.925, 4.85, 6.4, 7.2, 9.}; From 5062afe868296e54b8ebde103f62fa10cc1fab32 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:24:48 +0200 Subject: [PATCH 180/488] bug fix..imdumb Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/generate_graph_from_data.cpp | 8 ++++---- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index dafa638bd0..199165fe2d 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -106,8 +106,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double incubationTime = 5.2; const double serialIntervalMin = 1.1; const double serialIntervalMax = 1.1; - const double timeInfectedSymptomsMin[] = {6.6255, 6.6255, 6.6646, 6.5631, 6.501, 6.465}; - const double timeInfectedSymptomsMax[] = {6.6255, 6.6255, 6.6646, 6.5631, 6.501, 6.465}; + const double timeInfectedSymptomsMin[] = {5.6255, 5.6255, 5.6646, 5.5631, 5.501, 5.465}; + const double timeInfectedSymptomsMax[] = {8.427, 8.427, 8.4684, 8.3139, 8.169, 8.085}; const double timeInfectedSevereMin[] = {3.925, 3.925, 4.85, 6.4, 7.2, 9.}; const double timeInfectedSevereMax[] = {6.075, 6.075, 7., 8.7, 9.8, 13.}; const double timeInfectedCriticalMin[] = {4.95, 4.95, 4.86, 14.14, 14.4, 10.}; @@ -134,8 +134,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.15, 0.15, 0.15, 0.15, 0.15, 0.15}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.15, 0.15, 0.15, 0.15, 0.15, 0.15}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.20}; const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.18, 0.25}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index be678cbacc..3a96190a9a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -963,7 +963,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con restart_timer(timer, "time taken for braunschweig trip input"); // Assign an infection state to each person. - assign_infection_state_prob(world, t0); + assign_infection_state(world, t0); restart_timer(timer, "time taken for assigning infection state"); // Assign vaccination status to each person. From d1089c485c47c363f9edfd474f4d58a60746bee8 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Jun 2024 02:11:38 +0200 Subject: [PATCH 181/488] mobilityrestriction factor Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 8 +++++--- cpp/models/abm/parameters.h | 25 ++++++++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 2677a7d08c..3d191e5a9e 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -109,8 +109,9 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time const Parameters& global_params) const { // TODO: we need to define what a cell is used for, as the loop may lead to incorrect results for multiple cells - auto age_receiver = person.get_age(); - ScalarType mask_protection = person.get_mask_protective_factor(global_params); + auto age_receiver = person.get_age(); + ScalarType mask_protection = person.get_mask_protective_factor(global_params); + ScalarType mobility_damping_factor = global_params.get(); assert(person.get_cells().size() && "Person is in multiple cells. Interact logic is incorrect at the moment."); for (auto cell_index : person.get_cells()) { // TODO: the logic here is incorrect in case a person is in multiple cells @@ -118,7 +119,8 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time for (uint32_t v = 0; v != static_cast(VirusVariant::Count); ++v) { VirusVariant virus = static_cast(v); ScalarType local_indiv_expected_trans_v = - (transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups()) + + (mobility_damping_factor * + transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups()) + transmission_air_per_day(cell_index, virus, global_params)) * (1 - mask_protection) * (1 - person.get_protection_factor(t, virus, global_params)); diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 61064c69d1..da97711f44 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -348,6 +348,21 @@ struct InfectionRateFromViralShed { } }; +/** + * @brief Determines the infection rate by viral shed. Used as a linear factor. +*/ +struct MobilityRestrictionParameter { + using Type = ScalarType; + static Type get_default(AgeGroup /*size*/) + { + return Type(1.0); + } + static std::string name() + { + return "MobilityRestrictionParameter"; + } +}; + /** * @brief Aerosol transmission rates. */ @@ -650,11 +665,11 @@ using ParametersBase = TimeInfectedSevereToRecovered, TimeInfectedCriticalToDead, TimeInfectedCriticalToRecovered, SymptomsPerInfectedNoSymptoms, SeverePerInfectedSymptoms, CriticalPerInfectedSevere, DeathsPerInfectedCritical, ViralLoadDistributions, InfectivityDistributions, VirusShedFactor, - DetectInfection, MaskProtection, InfectionRateFromViralShed, AerosolTransmissionRates, LockdownDate, - QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, - GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, - AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, - TestData>; + DetectInfection, MaskProtection, InfectionRateFromViralShed, MobilityRestrictionParameter, + AerosolTransmissionRates, LockdownDate, QuarantineDuration, SocialEventRate, BasicShoppingRate, + WorkRatio, SchoolRatio, GotoWorkTimeMinimum, GotoWorkTimeMaximum, GotoSchoolTimeMinimum, + GotoSchoolTimeMaximum, AgeGroupGotoSchool, AgeGroupGotoWork, InfectionProtectionFactor, + SeverityProtectionFactor, HighViralLoadProtectionFactor, TestData>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. From 688327810b125c1fadc0a06ed7ce1e3f58fc983e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Jun 2024 02:16:54 +0200 Subject: [PATCH 182/488] huge plot and logger cleanup Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 204 ++++++++--------------- cpp/simulations/paper_abm_bs_testing.cpp | 201 +++++++++++----------- 2 files changed, 165 insertions(+), 240 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 5a47e04530..eec7854f01 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -23,103 +23,75 @@ from scipy.ndimage import gaussian_filter1d -def main(path, n_runs): - # get first_file in folder - # first_file = os.listdir(path)[0] - # file_path = os.path.join(path, first_file) - # read in txt file - # df = pd.read_csv(file_path, delim_whitespace=True) - # convert to numpy array - # df_np = df.to_numpy() - # get the number of rows and columns - # num_rows = df_np.shape[0] - # num_cols = df_np.shape[1] - # get the number of compartments - # num_compartments = num_cols - 1 - # get the number of time steps - # num_time_steps = num_rows-1 - # get the compartment names - # compartment_names = df.columns[1:] - # get the time steps - # time_steps = df_np[:, 0] - - # get number of files in folder - # num_files = len([entry for entry in os.listdir(path)]) - # read in each txt file and convert to numpy array - # df_np_3d = np.empty((num_rows, num_cols, n_runs)) - # print(os.listdir(path)) - for file in os.listdir(path): - file_path = os.path.join(path, file) - # read in txt file +def plot_infections_loc_types_avarage(path): + # 50-percentile + f_p50 = h5py.File( + path+"/infection_per_location_type/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] - if file.startswith("infection_per_location_type.txt"): - df = pd.read_csv(file_path, sep='\s+') - plot_infection_per_location_type(df) - if file.startswith("infection_per_age_group.txt"): - df = pd.read_csv(file_path,sep='\s+') - # plot_infection_per_age_group(df) - # if file.startswith("run_"): - # convert to numpy array - # df_np = df.to_numpy() - # attach to array - # df_np_3d[:, :, i] = df_np - # plot_mean_and_std(df_np_3d) - - -def plot_infection_per_location_type(df): - # Calculate moving average for all location types - df['Home'] = gaussian_filter1d(df.Home.rolling(24*3, min_periods=1).sum(), sigma=15) - df['School'] = gaussian_filter1d(df.School.rolling(24*3, min_periods=1).sum(), sigma=15) - df['Work'] = gaussian_filter1d(df.Work.rolling(24*3, min_periods=1).sum(), sigma=15) - df['SocialEvent'] = gaussian_filter1d(df.SocialEvent.rolling(24*3, min_periods=1).sum(), sigma=15) - df['BasicsShop'] = gaussian_filter1d(df.BasicsShop.rolling(24*3, min_periods=1).sum(), sigma=15) - - df.plot(x='Time', y=['Home', 'School','Work', 'SocialEvent', 'BasicsShop'], figsize=(10, 6), title='Infections stratified according to location type') - - # x axis should be titled Time in days - plt.xlabel('Time (days)') - plt.ylabel('New infections') + # 25-percentile + f_p25 = h5py.File( + path+"/infection_per_location_type/p25/Results.h5", 'r') + p25_bs = f_p25['0'] + total_25 = p25_bs['Total'][()] + + # 75-percentile + f_p75 = h5py.File( + path + "/infection_per_location_type/p75/Results.h5", 'r') + p75_bs = f_p75['0'] + total_75 = p75_bs['Total'][()] + + time = p50_bs['Time'][()] + + plot_infection_per_location_type_mean( + time, total_50, total_25, total_75) +def plot_infection_per_location_type_mean(x, y50, y25, y75): + plt.figure('Infection_states_location_types') + plt.title('Infection states per location types avaraged over all runs') + color_plot = matplotlib.colormaps.get_cmap('Set1').colors - # Subplots of individual location types - # fig, axs = plt.subplots(5, 2, constrained_layout=True) - # df.plot(x='Time', y='MA_Home', color='tab:blue', ax=axs[0, 0]) - # df.plot(x='Time', y='MA_Work', color='tab:green', ax=axs[0, 1]) - # df.plot(x='Time', y='MA_School', color='tab:red', ax=axs[1, 0]) - # df.plot(x='Time', y='MA_SocialEvent', color='tab:orange', ax=axs[1, 1]) - # df.plot(x='Time', y='MA_BasicsShop', color='tab:purple', ax=axs[2, 0]) - # df.plot(x='Time', y='MA_Hospital', color='tab:brown', ax=axs[2, 1]) - # df.plot(x='Time', y='MA_ICU', color='tab:pink', ax=axs[3, 0]) - # df.plot(x='Time', y='MA_Car', color='tab:gray', ax=axs[3, 1]) - # df.plot(x='Time', y='MA_PublicTransport', color='tab:olive', ax=axs[4, 0]) - # df.plot(x='Time', y='MA_Cemetery', color='tab:cyan', ax=axs[4, 1]) + states_plot = [0,1,2,3,4] + legend_plot = ['Home', 'School', 'Work', 'SocialEvent', 'BasicsShop', 'Hospital', 'ICU'] - plt.show() + for i in states_plot: + #rolling average + plt.plot(x, gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15), color=color_plot[i]) + plt.legend(legend_plot) -def plot_infection_per_age_group(df): - df.plot(x='Time', y=['0_to_4', '5_to_14', '15_to_34', - '35_to_59', '60_to_79', '80_plus'], figsize=(10, 6)) + for i in states_plot: + y50_smoothed= gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15).flatten() + y25_smoothed= gaussian_filter1d(pd.DataFrame(y25[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15).flatten() + y75_smoothed= gaussian_filter1d(pd.DataFrame(y75[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15).flatten() + plt.fill_between(x, y50_smoothed, y25_smoothed , + alpha=0.5, color=color_plot[i]) + plt.fill_between(x, y50_smoothed, y75_smoothed, + alpha=0.5, color=color_plot[i]) + + #currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in x] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + #but just take every 10th date to make it more readable + plt.gca().set_xticks(x[::150]) + plt.gca().set_xticklabels(xx[::150]) + plt.gcf().autofmt_xdate() - plt.show() + plt.xlabel('Time') + plt.ylabel('Number of individuals') + plt.show() -def plot_results(path): - # median / 50-percentile +def plot_infectoin_states_results(path): + # 50-percentile f_p50 = h5py.File( path+"/infection_state_per_age_group/p50/Results.h5", 'r') - - # Get the HDF5 group; key needs to be a group name from above - # only one graph node saved p50_bs = f_p50['0'] - - # This assumes group[some_key_inside_the_group] is a dataset, - # and returns a np.array: - time = p50_bs['Time'][()] total_50 = p50_bs['Total'][()] - # 25-percentile f_p25 = h5py.File( path+"/infection_state_per_age_group/p25/Results.h5", 'r') @@ -131,6 +103,8 @@ def plot_results(path): p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] + time = p50_bs['Time'][()] + # real world f_real = h5py.File( path + "/Results_rki.h5", 'r') @@ -142,12 +116,6 @@ def plot_results(path): time, p50_bs, p25_bs, p75_bs, real_bs) plot_infection_states(time, total_50, total_25, total_75, total_real) - # After you are done - f_p50.close() - f_p25.close() - f_p75.close() - f_real.close() - def plot_infection_states(x, y50, y25, y75, y_real=None): plt.figure('Infection_states') plt.title('Infection states') @@ -193,7 +161,6 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): plt.ylabel('Number of individuals') plt.show() - def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y_real_total = real_bs['Total'][()] @@ -249,60 +216,23 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): plt.show() -def plot_infections_per_age_group(path): - f = h5py.File( - path+"/infection_per_age_group/p50/Results.h5", 'r') - - # Get the HDF5 group; key needs to be a group name from above - group = f['0'] - - # This assumes group[some_key_inside_the_group] is a dataset, - # and returns a np.array: - time = group['Time'][()] - - plt.figure('Age_Group') - for g in ['Group' + str(n) for n in range(1, 7)]: - gr = group[g][()] - plt.plot(time, gr) - - plt.legend(['0-4', '5-14', '15-34', '35-59', '60-79', '80+']) - - # After you are done - f.close() - - -def plot_mean_and_std(Y): - - x_plot = Y[:, 0, 0] - compartments = Y[:, 1:, 1:] - # average value - compartments_avg = np.mean(compartments, axis=2) - # plot average - for i in range(compartments_avg.shape[1]): - plt.plot(x_plot, compartments_avg[:, i]) - - # plt.plot(x_plot,compartments_avg) - # legend - plt.legend(['S', 'E', 'I_NS', 'I_Sy', 'I_Sev', 'I_Crit', 'R', 'D']) - plt.show() - # standard deviation - # compartments_std = np.std(compartments,axis=2) - # plt.plot(x_plot,compartments_avg + compartments_std) - # plt.plot(x_plot,compartments_avg - compartments_std) - # plt.show() if __name__ == "__main__": - # path to results - # path = "/Users/david/Documents/HZI/memilio/data/results" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results/cluster/results" + # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - # path = r"C:\Users\korf_sa\Documents\rep\data\results" - # path = r"C:\Users\korf_sa\Documents\rep\data\results_cluster\results" + # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" + if (len(sys.argv) > 1): n_runs = sys.argv[1] else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_results(path) - main(path, n_runs) + plot_infectoin_states_results(path) + plot_infections_loc_types_avarage(path) + + for file in os.listdir(path): + file_path = os.path.join(path, file) + if file.startswith("infection_per_location_type.txt"): + df = pd.read_csv(file_path, sep='\s+') + plot_infection_per_location_type(df) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3a96190a9a..e51df6e747 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1002,16 +1002,38 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { } }; -template -void write_log_to_file_infection_per_location_type(const T& history, const fs::path& result_dir) -{ - std::ofstream myfile4((result_dir / "infection_per_location_type.txt").string()); - const std::vector& labels = { - "Home", "School", "Work", "SocialEvent", "BasicsShop", - "Hospital", "ICU", "Car", "PublicTransport", "TransportWithoutContact", - "Cemetery"}; - std::get<0>(history.get_log()).print_table(labels, 12, 4, myfile4); -} +struct LogInfectionPerLocationTypePerAgeGroup : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the number of Person%s in an #InfectionState. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the number of Person%s in an #InfectionState. + */ + static Type log(const mio::abm::Simulation& sim) + { + + Eigen::VectorXd sum = Eigen::VectorXd::Zero( + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())); + auto curr_time = sim.get_time(); + auto prev_time = sim.get_prev_time(); + const auto persons = sim.get_world().get_persons(); + + // PRAGMA_OMP(parallel for) + for (auto i = size_t(0); i < persons.size(); ++i) { + auto& p = persons[i]; + if (p.get_should_be_logged()) { + // PRAGMA_OMP(atomic) + if ((p.get_infection_state(prev_time) != mio::abm::InfectionState::Exposed) && + (p.get_infection_state(curr_time) == mio::abm::InfectionState::Exposed)) { + auto index = (((size_t)(mio::abm::LocationType::Count)) * ((uint32_t)p.get_age().get())) + + ((uint32_t)p.get_location().get_type()); + sum[index] += 1; + } + } + } + return std::make_pair(curr_time, sum); + } +}; #ifdef MEMILIO_ENABLE_MPI template @@ -1079,17 +1101,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 400000; + auto max_num_persons = 200000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results ensemble_infection_per_loc_type.reserve(size_t(num_runs)); - auto ensemble_infection_per_age_group = - std::vector>>{}; // Vector of infection per age group results - ensemble_infection_per_age_group.reserve(size_t(num_runs)); + auto ensemble_infection_state_per_age_group = std::vector>>{}; // Vector of infection state per age group results ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); + auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); @@ -1104,7 +1125,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } // ** end of the the parallel: joins threads // Determine inital infection state distribution - //Time this restart_timer(timer, "time for initial setup"); determine_initial_infection_states_world(input_dir, start_date); restart_timer(timer, "time for determine_initial_infection_states_world"); @@ -1121,33 +1141,32 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto sim = mio::abm::Simulation(t0, std::move(world)); //Logger - mio::History historyInfectionPerLocationType{ - Eigen::Index(mio::abm::LocationType::Count)}; - mio::History historyInfectionPerAgeGroup{ - Eigen::Index(sim.get_world().parameters.get_num_groups())}; + mio::History + historyInfectionPerLocationType{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; // / NPIS// - bool npis_on = true; + bool npis_on = false; if (npis_on) { const auto location_it = sim.get_world().get_locations(); // Advance the world with respective npis // 1. testing schemes in schools - // auto testing_min_time_school = mio::abm::days(7); - // auto probability_school = 1.0; - // auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 - // auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 - // auto test_type_school = mio::abm::TestType::Antigen; // Antigen test - // auto test_parameters = - // sim.get_world().parameters.get()[test_type_school]; // Test parameters - // auto testing_criteria_school = mio::abm::TestingCriteria(); - // auto testing_scheme_school = - // mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, - // end_date_test_school, test_parameters, probability_school); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - // testing_scheme_school); + auto testing_min_time_school = mio::abm::days(7); + auto probability_school = 1.0; + auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 + auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 + auto test_type_school = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters = + sim.get_world().parameters.get()[test_type_school]; // Test parameters + auto testing_criteria_school = mio::abm::TestingCriteria(); + auto testing_scheme_school = + mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, + end_date_test_school, test_parameters, probability_school); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_school); // 2. testing schemes in work places for 35% of random workplaces @@ -1164,21 +1183,21 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto num_work_locations = (int)(0.35 * work_location_ids.size()); std::vector work_location_ids_35(work_location_ids.begin(), work_location_ids.begin() + num_work_locations); - // auto testing_min_time_work = mio::abm::days(1); - // auto probability_work = 1.0; - // auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); - // auto end_date_test_work = mio::abm::TimePoint(tmax); - // auto test_type_work = mio::abm::TestType::Antigen; // Antigen test - // auto test_parameters_work = - // sim.get_world().parameters.get()[test_type_work]; // Test parameters - // auto testing_criteria_work = mio::abm::TestingCriteria(); - // auto testing_scheme_work = - // mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, - // end_date_test_work, test_parameters_work, probability_work); - // for (auto& location_id : work_location_ids_35) { - // sim.get_world().get_testing_strategy().add_testing_scheme( - // mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); - // } + auto testing_min_time_work = mio::abm::days(1); + auto probability_work = 1.0; + auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); + auto end_date_test_work = mio::abm::TimePoint(tmax); + auto test_type_work = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_work = + sim.get_world().parameters.get()[test_type_work]; // Test parameters + auto testing_criteria_work = mio::abm::TestingCriteria(); + auto testing_scheme_work = + mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, + end_date_test_work, test_parameters_work, probability_work); + for (auto& location_id : work_location_ids_35) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); + } // 2.5 plus testing schemes at 20 % of basics shops std::vector basics_shop_location_ids; @@ -1188,25 +1207,25 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } //take 20% of basics shop locations - // std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); - // auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); - // std::vector basics_shop_location_ids_20( - // basics_shop_location_ids.begin(), basics_shop_location_ids.begin() + num_basics_shop_locations); - // auto testing_min_time_basics_shop = mio::abm::days(2); - // auto probability_basics_shop = 1.0; - // auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); - // auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); - // auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test - // auto test_parameters_basics_shop = - // sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters - // auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); - // auto testing_scheme_basics_shop = mio::abm::TestingScheme( - // testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, - // end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); - // for (auto& location_id : basics_shop_location_ids_20) { - // sim.get_world().get_testing_strategy().add_testing_scheme( - // mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); - // } + std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); + auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); + std::vector basics_shop_location_ids_20( + basics_shop_location_ids.begin(), basics_shop_location_ids.begin() + num_basics_shop_locations); + auto testing_min_time_basics_shop = mio::abm::days(2); + auto probability_basics_shop = 1.0; + auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); + auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); + auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_basics_shop = + sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters + auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); + auto testing_scheme_basics_shop = mio::abm::TestingScheme( + testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, + end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); + for (auto& location_id : basics_shop_location_ids_20) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); + } // 3. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks @@ -1268,9 +1287,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } restart_timer(timer, "till advance 14"); sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); + historyInfectionPerLocationType); std::cout << "day 14 finished" << std::endl; - // // small social events to capacity 5 + // small social events to capacity 5 // for (auto& location : location_it) { // if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), // location.get_index()) != social_event_location_ids_small.end()) { @@ -1279,17 +1298,15 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // } // restart_timer(timer, "till advance 23"); // sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType, historyInfectionPerAgeGroup); - // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - // 4.5; + // historyInfectionPerLocationType); + // sim.get_world().parameters.get() = 0.8; // restart_timer(timer, "till advance 37"); // sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType, historyInfectionPerAgeGroup); - // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - // 5.5; + // historyInfectionPerLocationType); + // sim.get_world().parameters.get() = 1.0; // restart_timer(timer, "till advance 42"); // sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType, historyInfectionPerAgeGroup); + // historyInfectionPerLocationType); // std::cout << "day 42 finished" << std::endl; // date 2021-04-12 // for (auto& location : location_it) { // if (location.get_type() != mio::abm::LocationType::School) { @@ -1297,15 +1314,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // } // } // // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter - // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - // 4.5; + // sim.get_world().parameters.get() = 0.8; // restart_timer(timer, "till advance 72"); // sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType, historyInfectionPerAgeGroup); + // historyInfectionPerLocationType); // std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - // sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype}] = - // 5.5; + // sim.get_world().parameters.get() = 1.0; // for (auto& location : location_it) { // if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), // location.get_index()) != social_event_location_ids_small.end()) { @@ -1332,27 +1347,20 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // std::cout << "day 90 finished" << std::endl; } else { - sim.advance(mio::abm::TimePoint(mio::abm::days(1).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyInfectionPerAgeGroup); + sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); } ////Advance till here - // Stop the clock after sim.advance and calculate the duration restart_timer(timer, "time taken for simulation end"); // TODO: update result of the simulation to be a vector of location result. auto temp_sim_infection_per_loc_tpye = std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; - auto temp_sim_infection_per_age_group = - std::vector>{std::get<0>(historyInfectionPerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - // Push result of the simulation back to the result vector ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); - ensemble_infection_per_age_group.emplace_back(temp_sim_infection_per_age_group); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); - // Option to save the current run result to file - write_log_to_file_infection_per_location_type(historyInfectionPerLocationType, result_dir); std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; @@ -1405,7 +1413,6 @@ const std::string currentDateTime() mio::IOResult create_result_folders(std::string const& result_dir) { BOOST_OUTCOME_TRY(mio::create_directory(result_dir)); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_age_group/")); BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_location_type/")); BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_state_per_age_group/")); return mio::success(); @@ -1469,20 +1476,8 @@ int main(int argc, char** argv) printf("Running with number of runs = %d.\n", (int)num_runs); } - // mio::thread_local_rng().seed({...}); //set seeds, e.g., for debugging - // printf("Seeds: "); - // for (auto s : mio::thread_local_rng().get_seeds()) { - // printf("%u, ", s); - // } - // printf("\n"); timer = TIME_NOW; auto result = run(input_dir, result_dir, num_runs, save_single_runs); - // if (!result) { - // printf("%s\n", result.error().formatted_message().c_str()); - // mio::mpi::finalize(); - // return -1; - // } - // copy results into a fixed name folder to have easier access if (created) { std::string last_run_dir = input_dir + "/results_last_run"; From 01d64a4703a52ebed3ae48487862705c25f05752 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Jun 2024 02:26:21 +0200 Subject: [PATCH 183/488] cleanuop for sim on lcuster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 6 -- cpp/simulations/paper_abm_bs_testing.cpp | 117 +++++++++++------------ 2 files changed, 58 insertions(+), 65 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index eec7854f01..ede62c4c75 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -230,9 +230,3 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) plot_infections_loc_types_avarage(path) - - for file in os.listdir(path): - file_path = os.path.join(path, file) - if file.startswith("infection_per_location_type.txt"): - df = pd.read_csv(file_path, sep='\s+') - plot_infection_per_location_type(df) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e51df6e747..6a18bd0be1 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1101,7 +1101,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation - auto max_num_persons = 200000; + auto max_num_persons = 400000; auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1148,7 +1148,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; // / NPIS// - bool npis_on = false; + bool npis_on = true; if (npis_on) { const auto location_it = sim.get_world().get_locations(); @@ -1290,61 +1290,60 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s historyInfectionPerLocationType); std::cout << "day 14 finished" << std::endl; // small social events to capacity 5 - // for (auto& location : location_it) { - // if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - // location.get_index()) != social_event_location_ids_small.end()) { - // location.set_capacity(10, 0); - // } - // } - // restart_timer(timer, "till advance 23"); - // sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType); - // sim.get_world().parameters.get() = 0.8; - // restart_timer(timer, "till advance 37"); - // sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType); - // sim.get_world().parameters.get() = 1.0; - // restart_timer(timer, "till advance 42"); - // sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType); - // std::cout << "day 42 finished" << std::endl; // date 2021-04-12 - // for (auto& location : location_it) { - // if (location.get_type() != mio::abm::LocationType::School) { - // location.set_npi_active(false); - // } - // } - // // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter - // sim.get_world().parameters.get() = 0.8; - // restart_timer(timer, "till advance 72"); - // sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, - // historyInfectionPerLocationType); - // std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - - // sim.get_world().parameters.get() = 1.0; - // for (auto& location : location_it) { - // if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - // location.get_index()) != social_event_location_ids_small.end()) { - // location.set_capacity(2, 0); - // } - // //90% of big social events get reopened and caopacity will be unlimited - // int number_of_big_social_events = (int)(0.7 * social_event_location_ids_big.size()); - // if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - // location.get_index()) != social_event_location_ids_big.end()) { - // number_of_big_social_events--; - // if (number_of_big_social_events >= 0) { - // location.set_capacity(std::numeric_limits::max(), 0); - // } - // } - // } - // for (auto& location : location_it) { - // if (location.get_type() != mio::abm::LocationType::School) { - // location.set_npi_active(true); - // } - // } - // restart_timer(timer, "till advance tmax"); - // sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, - // historyInfectionPerAgeGroup); - // std::cout << "day 90 finished" << std::endl; + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(10, 0); + } + } + restart_timer(timer, "till advance 23"); + sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + sim.get_world().parameters.get() = 0.8; + restart_timer(timer, "till advance 37"); + sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + sim.get_world().parameters.get() = 1.0; + restart_timer(timer, "till advance 42"); + sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 42 finished" << std::endl; // date 2021-04-12 + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(false); + } + } + // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter + sim.get_world().parameters.get() = 0.8; + restart_timer(timer, "till advance 72"); + sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + + sim.get_world().parameters.get() = 1.0; + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(2, 0); + } + //90% of big social events get reopened and caopacity will be unlimited + int number_of_big_social_events = (int)(0.7 * social_event_location_ids_big.size()); + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + number_of_big_social_events--; + if (number_of_big_social_events >= 0) { + location.set_capacity(std::numeric_limits::max(), 0); + } + } + } + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(true); + } + } + restart_timer(timer, "till advance tmax"); + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + std::cout << "day 90 finished" << std::endl; } else { sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionStatePerAgeGroup, @@ -1438,8 +1437,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From 0363d65a2b24a8db85e2a6641372086185d092ec Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Jun 2024 16:38:59 +0200 Subject: [PATCH 184/488] slight changes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/parameters.h | 2 +- cpp/models/abm/simulation.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index da97711f44..b6509d7292 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -349,7 +349,7 @@ struct InfectionRateFromViralShed { }; /** - * @brief Determines the infection rate by viral shed. Used as a linear factor. + * @brief Determines the MobilityRestrictionParameter. */ struct MobilityRestrictionParameter { using Type = ScalarType; diff --git a/cpp/models/abm/simulation.cpp b/cpp/models/abm/simulation.cpp index d10ae971e1..47dc9ae740 100644 --- a/cpp/models/abm/simulation.cpp +++ b/cpp/models/abm/simulation.cpp @@ -41,6 +41,7 @@ void Simulation::evolve_world(TimePoint tmax) m_world.evolve(m_t, dt); m_prev_t = m_t; m_t += m_dt; + std::cout << "Simulation::evolve_world: " << m_t.days() << std::endl; } } // namespace abm From 39d6beba79caf8b822eb782eb56e49c99bba5721 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Jun 2024 17:51:47 +0200 Subject: [PATCH 185/488] strategie optimization Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 15 +++-- cpp/models/abm/location.h | 8 +-- cpp/models/abm/testing_strategy.cpp | 76 +----------------------- cpp/models/abm/testing_strategy.h | 77 ++++++------------------ cpp/models/abm/world.cpp | 91 ++++++++++++++++++++++++----- cpp/models/abm/world.h | 20 ++----- cpp/simulations/analyze_bs_run.py | 3 +- 7 files changed, 115 insertions(+), 175 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 3d191e5a9e..ce7883c237 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -44,28 +44,27 @@ Location::Location(LocationId loc_id, size_t num_agegroups, uint32_t num_cells) void Location::add_damping(TimePoint t_begin, double p) { - temp_npi_damping.emplace_back(t_begin, p); + m_npi_damping.emplace_back(t_begin, p); } -bool Location::entry_allowed(Person::RandomNumberGenerator& rng, const mio::abm::TimePoint t) const +bool Location::entry_allowed_dampings(Person::RandomNumberGenerator& rng, const mio::abm::TimePoint t) { - if (temp_npi_damping.empty()) { + if (m_npi_damping.empty()) { return true; } else { // We want to go through the npi vector and get the last entry that is smaller than t - auto it = std::upper_bound(temp_npi_damping.begin(), temp_npi_damping.end(), t, + auto it = std::upper_bound(m_npi_damping.begin(), m_npi_damping.end(), t, [](TimePoint tp, const std::pair& p) { return tp < p.first; }); - //we need the one entry before the upper bound - if (it == temp_npi_damping.begin()) { + //get a random number between 0 and 1 without m_rng + if (it == m_npi_damping.begin()) { return true; } else { - --it; + it--; } - //get a random number between 0 and 1 without m_rng ScalarType random_number = UniformDistribution::get_instance()(rng, 0.0, 1.0); return random_number < it->second; } diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index c50d47d64d..706339a3f6 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -26,12 +26,13 @@ #include "abm/location_type.h" #include "abm/infection_state.h" #include "abm/vaccine.h" +#include "abm/time.h" #include "memilio/epidemiology/age_group.h" #include "memilio/math/eigen.h" #include "memilio/utils/custom_index_array.h" #include "memilio/utils/time_series.h" #include "memilio/utils/memory.h" -#include "abm/time.h" +#include "memilio/utils/random_number_generator.h" #include #include #include @@ -267,7 +268,7 @@ class Location */ void add_damping(TimePoint t, double p); - bool entry_allowed(Person::RandomNumberGenerator& rng, const mio::abm::TimePoint t) const; + bool entry_allowed_dampings(Person::RandomNumberGenerator& rng, const mio::abm::TimePoint t); /** * @brief Set the required type of mask for entering this Location. @@ -426,13 +427,12 @@ class Location bool m_capacity_adapted_transmission_risk; /**< If true considers the LocationCapacity for the computation of the transmission risk.*/ LocalInfectionParameters m_parameters; ///< Infection parameters for the Location. + std::vector> m_npi_damping; ///< Temporary storage for NPI dampings. std::vector> m_persons{}; ///< A vector of all Person%s at the Location. std::vector m_cells{}; ///< A vector of all Cell%s that the Location is divided in. MaskType m_required_mask; ///< Least secure type of Mask that is needed to enter the Location. bool m_npi_active; ///< If true requires e.g. Mask%s to enter the Location. GeographicalLocation m_geographical_location; ///< Geographical location (longitude and latitude) of the Location. - std::vector> - temp_npi_damping; ///< Temporary storage for NPI dampings. //TODO: delete these and implement better }; } // namespace abm diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 78c8b12355..5c3f2c974f 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -19,7 +19,6 @@ */ #include "abm/testing_strategy.h" -#include "memilio/utils/random_number_generator.h" namespace mio { @@ -46,21 +45,11 @@ void TestingCriteria::add_age_group(const AgeGroup age_group) m_ages.set(static_cast(age_group), true); } -void TestingCriteria::remove_age_group(const AgeGroup age_group) -{ - m_ages.set(static_cast(age_group), false); -} - void TestingCriteria::add_infection_state(const InfectionState infection_state) { m_infection_states.set(static_cast(infection_state), true); } -void TestingCriteria::remove_infection_state(const InfectionState infection_state) -{ - m_infection_states.set(static_cast(infection_state), false); -} - bool TestingCriteria::evaluate(const Person& p, TimePoint t) const { // An empty vector of ages or none bitset of #InfectionStates% means that no condition on the corresponding property is set. @@ -91,14 +80,9 @@ bool TestingScheme::operator==(const TestingScheme& other) const //To be adjusted and also TestType should be static. } -bool TestingScheme::is_active() const -{ - return m_is_active; -} - -void TestingScheme::update_activity_status(TimePoint t) +bool TestingScheme::is_active(const TimePoint t) const { - m_is_active = (m_start_date <= t && t <= m_end_date); + return (m_start_date <= t && t <= m_end_date); } bool TestingScheme::run_scheme(Person::RandomNumberGenerator& rng, Person& person, TimePoint t) const @@ -139,61 +123,5 @@ void TestingStrategy::add_testing_scheme(const LocationId& loc_id, const Testing } } -void TestingStrategy::remove_testing_scheme(const LocationId& loc_id, const TestingScheme& scheme) -{ - auto iter_schemes = - std::find_if(m_location_to_schemes_map.begin(), m_location_to_schemes_map.end(), [loc_id](auto& p) { - return p.first == loc_id; - }); - if (iter_schemes != m_location_to_schemes_map.end()) { - //remove the scheme from the list - auto& schemes_vector = iter_schemes->second; - auto last = std::remove(schemes_vector.begin(), schemes_vector.end(), scheme); - schemes_vector.erase(last, schemes_vector.end()); - //delete the list of schemes for this location if no schemes left - if (schemes_vector.empty()) { - m_location_to_schemes_map.erase(iter_schemes); - } - } -} - -void TestingStrategy::update_activity_status(TimePoint t) -{ - for (auto& [_, testing_schemes] : m_location_to_schemes_map) { - for (auto& scheme : testing_schemes) { - scheme.update_activity_status(t); - } - } -} - -bool TestingStrategy::run_strategy(Person::RandomNumberGenerator& rng, Person& person, const Location& location, - TimePoint t) -{ - // A Person is always allowed to go home and this is never called if a person is not discharged from a hospital or ICU. - // if (location.get_type() == mio::abm::LocationType::Home) { - // return true; - // } - - //lookup schemes for this specific location as well as the location type - //lookup in std::vector instead of std::map should be much faster unless for large numbers of schemes - for (auto loc_key : {LocationId{location.get_index(), location.get_type()}, - LocationId{INVALID_LOCATION_INDEX, location.get_type()}}) { - auto iter_schemes = - std::find_if(m_location_to_schemes_map.begin(), m_location_to_schemes_map.end(), [loc_key](auto& p) { - return p.first == loc_key; - }); - if (iter_schemes != m_location_to_schemes_map.end()) { - //apply all testing schemes that are found - auto& schemes = iter_schemes->second; - if (!std::all_of(schemes.begin(), schemes.end(), [&rng, &person, t](TestingScheme& ts) { - return !ts.is_active() || ts.run_scheme(rng, person, t); - })) { - return false; - } - } - } - return true; -} - } // namespace abm } // namespace mio diff --git a/cpp/models/abm/testing_strategy.h b/cpp/models/abm/testing_strategy.h index ffb678fb53..8b425b12ce 100644 --- a/cpp/models/abm/testing_strategy.h +++ b/cpp/models/abm/testing_strategy.h @@ -21,9 +21,7 @@ #define EPI_ABM_TESTING_SCHEME_H #include "abm/config.h" -#include "abm/parameters.h" #include "abm/person.h" -#include "abm/location.h" #include "abm/time.h" #include "memilio/utils/random_number_generator.h" #include @@ -65,25 +63,12 @@ class TestingCriteria */ void add_age_group(const AgeGroup age_group); - /** - * @brief Remove an AgeGroup from the set of AgeGroup%s that are either allowed or required to be tested. - * @param[in] age_group AgeGroup to be removed. - */ - void remove_age_group(const AgeGroup age_group); - /** * @brief Add an #InfectionState to the set of #InfectionState%s that are either allowed or required to be tested. * @param[in] infection_state #InfectionState to be added. */ void add_infection_state(const InfectionState infection_state); - /** - * @brief Remove an #InfectionState from the set of #InfectionState%s that are either allowed or required to be - * tested. - * @param[in] infection_state #InfectionState to be removed. - */ - void remove_infection_state(const InfectionState infection_state); - /** * @brief Check if a Person and a Location meet all the required properties to get tested. * @param[in] p Person to be checked. @@ -126,13 +111,7 @@ class TestingScheme * @brief Get the activity status of the scheme. * @return Whether the TestingScheme is currently active. */ - bool is_active() const; - - /** - * @brief Checks if the scheme is active at a given time and updates activity status. - * @param[in] t TimePoint to be updated at. - */ - void update_activity_status(TimePoint t); + bool is_active(const TimePoint t) const; /** * @brief Runs the TestingScheme and potentially tests a Person. @@ -143,6 +122,15 @@ class TestingScheme */ bool run_scheme(Person::RandomNumberGenerator& rng, Person& person, TimePoint t) const; + mio::abm::TimePoint get_start_date() const + { + return m_start_date; + } + mio::abm::TimePoint get_end_date() const + { + return m_end_date; + } + private: TestingCriteria m_testing_criteria; ///< TestingCriteria of the scheme. TimeSpan m_minimal_time_since_last_test; ///< Shortest period of time between two tests. @@ -150,7 +138,6 @@ class TestingScheme TimePoint m_end_date; ///< Ending date of the scheme. TestParameters m_test_parameters; ///< Parameters of the test. ScalarType m_probability; ///< Probability of performing the test. - bool m_is_active = false; ///< Whether the scheme is currently active. }; /** @@ -164,14 +151,15 @@ class TestingStrategy * @param[in] testing_schemes Vector of TestingSchemes that are checked for testing. */ TestingStrategy() = default; - explicit TestingStrategy(const std::unordered_map>& location_to_schemes_map); + explicit TestingStrategy( + const std::unordered_map>& location_to_schemes_map); /** * @brief Add a TestingScheme to the set of schemes that are checked for testing at a certain Location. * @param[in] loc_id LocationId key for TestingScheme to be added. * @param[in] scheme TestingScheme to be added. */ - void add_testing_scheme(const LocationId& loc_id, const TestingScheme& scheme); + void add_testing_scheme(const LocationId& loc_id, const mio::abm::TestingScheme& scheme); /** * @brief Add a TestingScheme to the set of schemes that are checked for testing at a certain LocationType. @@ -180,49 +168,22 @@ class TestingStrategy * @param[in] loc_type LocationId key for TestingScheme to be added. * @param[in] scheme TestingScheme to be added. */ - void add_testing_scheme(const LocationType& loc_type, const TestingScheme& scheme) + void add_testing_scheme(const LocationType& loc_type, const mio::abm::TestingScheme& scheme) { add_testing_scheme(LocationId{INVALID_LOCATION_INDEX, loc_type}, scheme); } /** - * @brief Remove a TestingScheme from the set of schemes that are checked for testing at a certain Location. - * @param[in] loc_id LocationId key for TestingScheme to be remove. - * @param[in] scheme TestingScheme to be removed. + * @brief Get the TestingSchemes that are checked for testing at a certain Location. + * @return Vector of TestingScheme%s that are checked for testing at the Location. */ - void remove_testing_scheme(const LocationId& loc_id, const TestingScheme& scheme); - - /** - * @brief Remove a TestingScheme from the set of schemes that are checked for testing at a certain Location. - * A TestingScheme applies to all Location of the same type is store in - * LocationId{INVALID_LOCATION_INDEX, location_type} of m_location_to_schemes_map. - * @param[in] loc_type LocationType key for TestingScheme to be remove. - * @param[in] scheme TestingScheme to be removed. - */ - void remove_testing_scheme(const LocationType& loc_type, const TestingScheme& scheme) + const std::vector>>& get_testing_schemes() const { - remove_testing_scheme(LocationId{INVALID_LOCATION_INDEX, loc_type}, scheme); + return m_location_to_schemes_map; } - /** - * @brief Checks if the given TimePoint is within the interval of start and end date of each TestingScheme and then - * changes the activity status for each TestingScheme accordingly. - * @param t TimePoint to check the activity status of each TestingScheme. - */ - void update_activity_status(const TimePoint t); - - /** - * @brief Runs the TestingStrategy and potentially tests a Person. - * @param[inout] rng Person::RandomNumberGenerator for the Person being tested. - * @param[in] person Person to check. - * @param[in] location Location to check. - * @param[in] t TimePoint when to run the strategy. - * @return If the Person is allowed to enter the Location. - */ - bool run_strategy(Person::RandomNumberGenerator& rng, Person& person, const Location& location, TimePoint t); - private: - std::vector>> + std::vector>> m_location_to_schemes_map; ///< Set of schemes that are checked for testing. }; diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index e33e26f54c..5400937825 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -85,15 +85,13 @@ void World::migration(TimePoint t, TimeSpan dt) auto target_type = rule(personal_rng, *person, t, dt, parameters); auto& target_location = find_location(target_type, *person); auto& current_location = person->get_location(); - if (m_testing_strategy.run_strategy(personal_rng, *person, target_location, t)) { - if (target_location != current_location && - target_location.get_number_persons() < target_location.get_capacity().persons) { - bool wears_mask = person->apply_mask_intervention(personal_rng, target_location); - if (wears_mask) { - person->migrate_to(target_location); - } - return true; + if (target_location != current_location && + target_location.get_number_persons() < target_location.get_capacity().persons) { + bool wears_mask = person->apply_mask_intervention(personal_rng, target_location); + if (wears_mask) { + person->migrate_to(target_location); } + return true; } return false; }; @@ -136,13 +134,12 @@ void World::migration(TimePoint t, TimeSpan dt) current_location.get_type() != LocationType::Cemetery) { if (!person->is_in_quarantine(t, parameters)) { auto& target_location = get_individualized_location(trip.migration_destination); - if (m_testing_strategy.run_strategy(personal_rng, *person, target_location, t)) { - if (target_location != current_location && - target_location.get_number_persons() < target_location.get_capacity().persons && - target_location.entry_allowed(personal_rng, t)) { - person->apply_mask_intervention(personal_rng, target_location); - person->migrate_to(target_location); - } + if (target_location != current_location && + target_location.entry_allowed_dampings(personal_rng, t) && + entry_allowed_testing_schemes(personal_rng, *person, target_location.get_index(), t) && + target_location.get_number_persons() < target_location.get_capacity().persons) { + person->apply_mask_intervention(personal_rng, target_location); + person->migrate_to(target_location); } } } @@ -157,7 +154,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { - m_testing_strategy.update_activity_status(t); + update_location_testing_schemes(t); PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; @@ -252,5 +249,67 @@ const TestingStrategy& World::get_testing_strategy() const return m_testing_strategy; } +bool World::entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, + const mio::abm::TimePoint t) +{ + if (m_testing_schemes_per_location.at(id).empty()) { + return true; + } + else { + for (auto&& scheme : m_testing_schemes_per_location.at(id)) { + if (scheme.run_scheme(rng, person, t)) { + return false; + } + } + return true; + } +} + +void World::update_location_testing_schemes(TimePoint t) +{ + if (m_testing_schemes_per_location.empty()) { + for (auto i = size_t(0); i < m_locations.size(); ++i) { + m_testing_schemes_per_location.push_back({}); + } + for (auto&& schemes : m_testing_strategy.get_testing_schemes()) { + for (auto&& scheme : schemes.second) { + auto start_date = scheme.get_start_date(); + auto end_date = scheme.get_end_date(); + if (std::find_if(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), [start_date](auto& p) { + return p == start_date; + }) == m_update_ts_scheduler.end()) { + m_update_ts_scheduler.push_back(start_date); + } + if (std::find_if(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), [end_date](auto& p) { + return p == end_date; + }) == m_update_ts_scheduler.end()) { + m_update_ts_scheduler.push_back(end_date); + } + } + } + std::sort(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end()); + } + + if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { +#pragma omp parallel for + for (auto i = size_t(0); i < m_locations.size(); ++i) { + auto& location = m_locations[i]; + auto loc_id = location->get_index(); + auto& schemes = m_testing_strategy.get_testing_schemes(); + + auto iter_schemes = std::find_if(schemes.begin(), schemes.end(), [loc_id](auto& p) { + return p.first.index == loc_id; + }); + if (iter_schemes != schemes.end()) { + m_testing_schemes_per_location[i].clear(); + for (auto&& scheme : iter_schemes->second) { + if (scheme.is_active(t)) { + m_testing_schemes_per_location[i].push_back(scheme); + } + } + } + } + } +} } // namespace abm } // namespace mio diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index d707045fff..74bdd2317c 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -292,21 +292,10 @@ class World return m_rng; } - /** - * @brief Add a TestingScheme to the set of schemes that are checked for testing at all Locations that have - * the LocationType. - * @param[in] loc_type LocationId key for TestingScheme to be added. - * @param[in] scheme TestingScheme to be added. - */ - void add_testing_scheme(const LocationType& loc_type, const TestingScheme& scheme); + void update_location_testing_schemes(TimePoint t); - /** - * @brief Remove a TestingScheme from the set of schemes that are checked for testing at all Locations that have - * the LocationType. - * @param[in] loc_type LocationId key for TestingScheme to be added. - * @param[in] scheme TestingScheme to be added. - */ - void remove_testing_scheme(const LocationType& loc_type, const TestingScheme& scheme); + bool entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, + const mio::abm::TimePoint t); private: /** @@ -327,6 +316,9 @@ class World std::bitset m_has_locations; ///< Flags for each LocationType, set if a Location of that type exists. TestingStrategy m_testing_strategy; ///< List of TestingScheme%s that are checked for testing. + std::vector> + m_testing_schemes_per_location; ///< List of TestingScheme%s that are checked for testing. + std::vector m_update_ts_scheduler; ///< List of TimePoint%s when to update the TestingScheme. TripList m_trip_list; ///< List of all Trip%s the Person%s do. bool m_use_migration_rules; ///< Whether migration rules are considered. std::vector 1): From 28c857949f3498e6408ff86e40b466784a9306fe Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Jun 2024 23:43:18 +0200 Subject: [PATCH 186/488] bug fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/simulation.cpp | 1 - cpp/models/abm/world.cpp | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/simulation.cpp b/cpp/models/abm/simulation.cpp index 47dc9ae740..d10ae971e1 100644 --- a/cpp/models/abm/simulation.cpp +++ b/cpp/models/abm/simulation.cpp @@ -41,7 +41,6 @@ void Simulation::evolve_world(TimePoint tmax) m_world.evolve(m_t, dt); m_prev_t = m_t; m_t += m_dt; - std::cout << "Simulation::evolve_world: " << m_t.days() << std::endl; } } // namespace abm diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 5400937825..bb43f59c9f 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -291,14 +291,16 @@ void World::update_location_testing_schemes(TimePoint t) } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { + std::cout << "Updating testing schemes at time " << t.days() << std::endl; #pragma omp parallel for for (auto i = size_t(0); i < m_locations.size(); ++i) { auto& location = m_locations[i]; auto loc_id = location->get_index(); auto& schemes = m_testing_strategy.get_testing_schemes(); - auto iter_schemes = std::find_if(schemes.begin(), schemes.end(), [loc_id](auto& p) { - return p.first.index == loc_id; + auto iter_schemes = std::find_if(schemes.begin(), schemes.end(), [loc_id, &location](auto& p) { + return p.first.index == loc_id || + (p.first.index == INVALID_LOCATION_INDEX && p.first.type == location->get_type()); }); if (iter_schemes != schemes.end()) { m_testing_schemes_per_location[i].clear(); From 083b2f9b1197be5701eae9331487f823ebf3948e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 21 Jun 2024 13:12:04 +0200 Subject: [PATCH 187/488] shift testing things from world to strategy Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 66 +++++++++++++++++++++++++++ cpp/models/abm/testing_strategy.h | 10 +++++ cpp/models/abm/world.cpp | 70 ++--------------------------- cpp/models/abm/world.h | 8 ---- 4 files changed, 79 insertions(+), 75 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 5c3f2c974f..f7df3dd109 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -19,6 +19,7 @@ */ #include "abm/testing_strategy.h" +#include "abm/location.h" namespace mio { @@ -123,5 +124,70 @@ void TestingStrategy::add_testing_scheme(const LocationId& loc_id, const Testing } } +bool TestingStrategy::entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, + const mio::abm::TimePoint t) +{ + if (m_testing_schemes_per_location.at(id).empty()) { + return true; + } + + for (auto&& scheme : m_testing_schemes_per_location.at(id)) { + if (scheme.run_scheme(rng, person, t)) { + return false; + } + } + return true; +} + +void TestingStrategy::update_location_testing_schemes( + TimePoint t, mio::Range> locations) +{ + if (m_testing_schemes_per_location.empty()) { + for (auto i = size_t(0); i < locations.size(); ++i) { + m_testing_schemes_per_location.push_back({}); + } + for (auto&& schemes : m_location_to_schemes_map) { + for (auto&& scheme : schemes.second) { + auto start_date = scheme.get_start_date(); + auto end_date = scheme.get_end_date(); + if (std::find_if(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), [start_date](auto& p) { + return p == start_date; + }) == m_update_ts_scheduler.end()) { + m_update_ts_scheduler.push_back(start_date); + } + if (std::find_if(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), [end_date](auto& p) { + return p == end_date; + }) == m_update_ts_scheduler.end()) { + m_update_ts_scheduler.push_back(end_date); + } + } + } + std::sort(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end()); + } + + if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { + std::cout << "Updating testing schemes at time " << t.days() << std::endl; +#pragma omp parallel for + for (auto i = size_t(0); i < locations.size(); ++i) { + auto& location = locations[i]; + auto loc_id = location.get_index(); + auto& schemes = m_location_to_schemes_map; + + auto iter_schemes = std::find_if(schemes.begin(), schemes.end(), [loc_id, &location](auto& p) { + return p.first.index == loc_id || + (p.first.index == INVALID_LOCATION_INDEX && p.first.type == location.get_type()); + }); + if (iter_schemes != schemes.end()) { + m_testing_schemes_per_location[i].clear(); + for (auto&& scheme : iter_schemes->second) { + if (scheme.is_active(t)) { + m_testing_schemes_per_location[i].push_back(scheme); + } + } + } + } + } +} + } // namespace abm } // namespace mio diff --git a/cpp/models/abm/testing_strategy.h b/cpp/models/abm/testing_strategy.h index 8b425b12ce..36c510ecca 100644 --- a/cpp/models/abm/testing_strategy.h +++ b/cpp/models/abm/testing_strategy.h @@ -26,6 +26,7 @@ #include "memilio/utils/random_number_generator.h" #include #include +#include "memilio/utils/pointer_dereferencing_iterator.h" namespace mio { @@ -181,10 +182,19 @@ class TestingStrategy { return m_location_to_schemes_map; } + using ConstLocationIterator = PointerDereferencingIterator>::const_iterator>; + void update_location_testing_schemes(TimePoint t, + mio::Range> locations); + + bool entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, + const mio::abm::TimePoint t); private: std::vector>> m_location_to_schemes_map; ///< Set of schemes that are checked for testing. + std::vector> + m_testing_schemes_per_location; ///< List of TestingScheme%s that are checked for testing. + std::vector m_update_ts_scheduler; ///< List of TimePoint%s when to update the TestingScheme. }; } // namespace abm diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index bb43f59c9f..9f2ad3b858 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -136,7 +136,8 @@ void World::migration(TimePoint t, TimeSpan dt) auto& target_location = get_individualized_location(trip.migration_destination); if (target_location != current_location && target_location.entry_allowed_dampings(personal_rng, t) && - entry_allowed_testing_schemes(personal_rng, *person, target_location.get_index(), t) && + m_testing_strategy.entry_allowed_testing_schemes(personal_rng, *person, + target_location.get_index(), t) && target_location.get_number_persons() < target_location.get_capacity().persons) { person->apply_mask_intervention(personal_rng, target_location); person->migrate_to(target_location); @@ -154,7 +155,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { - update_location_testing_schemes(t); + m_testing_strategy.update_location_testing_schemes(t, get_locations()); PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; @@ -248,70 +249,5 @@ const TestingStrategy& World::get_testing_strategy() const { return m_testing_strategy; } - -bool World::entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, - const mio::abm::TimePoint t) -{ - if (m_testing_schemes_per_location.at(id).empty()) { - return true; - } - else { - for (auto&& scheme : m_testing_schemes_per_location.at(id)) { - if (scheme.run_scheme(rng, person, t)) { - return false; - } - } - return true; - } -} - -void World::update_location_testing_schemes(TimePoint t) -{ - if (m_testing_schemes_per_location.empty()) { - for (auto i = size_t(0); i < m_locations.size(); ++i) { - m_testing_schemes_per_location.push_back({}); - } - for (auto&& schemes : m_testing_strategy.get_testing_schemes()) { - for (auto&& scheme : schemes.second) { - auto start_date = scheme.get_start_date(); - auto end_date = scheme.get_end_date(); - if (std::find_if(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), [start_date](auto& p) { - return p == start_date; - }) == m_update_ts_scheduler.end()) { - m_update_ts_scheduler.push_back(start_date); - } - if (std::find_if(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), [end_date](auto& p) { - return p == end_date; - }) == m_update_ts_scheduler.end()) { - m_update_ts_scheduler.push_back(end_date); - } - } - } - std::sort(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end()); - } - - if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { - std::cout << "Updating testing schemes at time " << t.days() << std::endl; -#pragma omp parallel for - for (auto i = size_t(0); i < m_locations.size(); ++i) { - auto& location = m_locations[i]; - auto loc_id = location->get_index(); - auto& schemes = m_testing_strategy.get_testing_schemes(); - - auto iter_schemes = std::find_if(schemes.begin(), schemes.end(), [loc_id, &location](auto& p) { - return p.first.index == loc_id || - (p.first.index == INVALID_LOCATION_INDEX && p.first.type == location->get_type()); - }); - if (iter_schemes != schemes.end()) { - m_testing_schemes_per_location[i].clear(); - for (auto&& scheme : iter_schemes->second) { - if (scheme.is_active(t)) { - m_testing_schemes_per_location[i].push_back(scheme); - } - } - } - } - } -} } // namespace abm } // namespace mio diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index 74bdd2317c..d9b2e0b552 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -292,11 +292,6 @@ class World return m_rng; } - void update_location_testing_schemes(TimePoint t); - - bool entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, - const mio::abm::TimePoint t); - private: /** * @brief Person%s interact at their Location and may become infected. @@ -316,9 +311,6 @@ class World std::bitset m_has_locations; ///< Flags for each LocationType, set if a Location of that type exists. TestingStrategy m_testing_strategy; ///< List of TestingScheme%s that are checked for testing. - std::vector> - m_testing_schemes_per_location; ///< List of TestingScheme%s that are checked for testing. - std::vector m_update_ts_scheduler; ///< List of TimePoint%s when to update the TestingScheme. TripList m_trip_list; ///< List of all Trip%s the Person%s do. bool m_use_migration_rules; ///< Whether migration rules are considered. std::vector Date: Tue, 2 Jul 2024 10:59:22 +0200 Subject: [PATCH 188/488] Fix bug in cli --- cpp/simulations/paper_abm_bs_testing.cpp | 28 ++++++++++++++---------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6a18bd0be1..21e35019f9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1443,23 +1443,20 @@ int main(int argc, char** argv) // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); - auto created = create_result_folders(result_dir); - if (created) { - copy_precomputed_results(precomputed_dir, result_dir); - } + size_t num_runs; bool save_single_runs = true; if (argc == 2) { num_runs = atoi(argv[1]); - printf("Number of run is %s.\n", argv[1]); - printf("Saving results to the current directory.\n"); + printf("Running with number of runs = %d.\n", (int)num_runs); + printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { num_runs = atoi(argv[1]); result_dir = argv[2]; - printf("Number of run is %s.\n", argv[1]); + printf("Running with number of runs = %.\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); } else { @@ -1473,15 +1470,24 @@ int main(int argc, char** argv) num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); + printf("Saving results to \"%s\".\n", result_dir.c_str()); + } + + auto created = create_result_folders(result_dir); + if (created) { + copy_precomputed_results(precomputed_dir, result_dir); + } + else { + std::cout << result.error().formatted_message(); + return result.error().code().value(); } timer = TIME_NOW; auto result = run(input_dir, result_dir, num_runs, save_single_runs); + // copy results into a fixed name folder to have easier access - if (created) { - std::string last_run_dir = input_dir + "/results_last_run"; - auto copied = copy_result_folder(result_dir, last_run_dir); - } + std::string last_run_dir = input_dir + "/results_last_run"; + auto copied = copy_result_folder(result_dir, last_run_dir); mio::mpi::finalize(); return 0; From 1faef83fd9192fe5c802ce1542eaee31eae243e9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:59:37 +0200 Subject: [PATCH 189/488] add setup file Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/setup.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 cpp/simulations/setup.md diff --git a/cpp/simulations/setup.md b/cpp/simulations/setup.md new file mode 100644 index 0000000000..96125eaf3d --- /dev/null +++ b/cpp/simulations/setup.md @@ -0,0 +1,13 @@ +# How to setup the paper simulation from brunswick + +1. You need the file "braunschweig_result_ffa8.csv" downloadable a this URL: +2. You need to save this file into the folder:"/memilio/data/mobility/braunschweig_result_ffa8.csv" +3. You need to run cleanup_data.py (install numpy and pandas beforehand) please change the folders +4. You need to download the simulation files. Please follow the installation instructions at "" +5. Run "python getSimulationData.py -s 2021-01-01 -e 2021-07-01 -m 7" +6. Copy the Germany folder into data/mobility/Germany +7. mkdir data/results +8. Put rki files in results +9. Change the folder in paper_abm_testing to your data folder. +10. cmake --build /Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/build --config Release --target paper_abm_bs_testing -j 6 -- +11. ./memilio/cpp/build/bin/paper_abm_bs_testing From c4e06fad4fd2cbd68524cac9bb28a3cd1b06a543 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 2 Jul 2024 16:04:00 +0200 Subject: [PATCH 190/488] quick fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 21e35019f9..68392777dc 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1456,7 +1456,7 @@ int main(int argc, char** argv) else if (argc == 3) { num_runs = atoi(argv[1]); result_dir = argv[2]; - printf("Running with number of runs = %.\n", (int)num_runs); + printf("Running with number of runs = %d\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); } else { @@ -1478,8 +1478,8 @@ int main(int argc, char** argv) copy_precomputed_results(precomputed_dir, result_dir); } else { - std::cout << result.error().formatted_message(); - return result.error().code().value(); + std::cout << created.error().formatted_message(); + return created.error().code().value(); } timer = TIME_NOW; From bc17a66403f55f50c0a5eba227164e680f357922 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 2 Jul 2024 21:30:56 +0200 Subject: [PATCH 191/488] enhanncing some things Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 49 +++++++++++++++-- cpp/simulations/cleanup_data.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 67 ++++++++++++------------ 3 files changed, 79 insertions(+), 39 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 3a0640c5a9..4f4ac4125e 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -128,10 +128,11 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): for i in states_plot: plt.plot(x, y50[:, i], color=color_plot[i]) - #plot real data + #plot real data for comparison, symptomatic and infected daily if y_real is not None: x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) - plt.plot(x_real, y_real[:,4], '.', color='tab:red') + plt.plot(x_real, y_real[:,4], '.', color='tab:purple') + plt.plot(x_real, y_real[:,1], '.', color='tab:blue') plt.legend(legend_plot) @@ -161,6 +162,44 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): plt.ylabel('Number of individuals') plt.show() + # we will have a seperate plot the cumulative infected individuals, cumulative symptomatic individuals and cumulative dead individual + + cum_dead = y50[:, 7] #dead are already cumulative + #for the simulation we just need the 90 days and just take the first one for each day (every 24th value) + cum_dead_inter_day = cum_dead[::24] + + cum_dead_real = y_real[:,9] #dead are already cumulative + # we also calculate the MSR + # we need to extra + mse_dead=((cum_dead_real - cum_dead_inter_day[0:90])**2).mean() + + + + plt.figure('dead individuals and the MSE') + plt.plot(x, cum_dead,color='tab:red') + plt.plot(x_real, cum_dead_real,'.',color='tab:red') + # we want a text in the plot with the MSE value + plt.text(0.25, 0.8, 'MSE: '+str( float("{:.2f}".format(mse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + plt.title('Dead individuals: Simulation vs Real') + plt.xlabel('Time') + plt.ylabel('Number of individuals') + plt.show() + + + + + + + + + + + + + + + + def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y_real_total = real_bs['Total'][()] @@ -220,8 +259,8 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): @@ -230,4 +269,4 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) - plot_infections_loc_types_avarage(path) + # plot_infections_loc_types_avarage(path) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 931645f1cf..694eced5db 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -428,4 +428,4 @@ def add_time_if_null(pd): # sort for better search performance bd_new = bd_new.sort_values(by=['puid', 'start_time']) # Write data back to disk -bd_new.to_csv('braunschweig_result_ffa8_modified2.csv', index=False) +bd_new.to_csv('/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8_modified2.csv', index=False) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 68392777dc..8185ce4294 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -550,6 +550,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (it_person == persons.end()) { auto home = locations.find(home_id)->second; auto& person = world.add_person(home, determine_age_group(age)); + person.set_mask_preferences({0.0, 0.5, 0.5, 0.5, 0.5, 0.5}); person.set_assigned_location(home); person.set_assigned_location(hospital); person.set_assigned_location(icu); @@ -632,30 +633,30 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.8; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.0075; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.0075; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.019; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.0615; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.25; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.4; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.075; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.075; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.075; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.15; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.55; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.7; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.01; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.01; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.07; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.3; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.6; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.1; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.1; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.1; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.17; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.6; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.055; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.055; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.14; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.28; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.55; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.7; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.75; // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 5.5; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 5.6; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -683,7 +684,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.5; //all masks have a 0.66 protection factor for now + params.get() = 0.38; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -970,7 +971,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con assign_vaccination_state(world, start_date_sim); restart_timer(timer, "time taken for assigning vaccination state"); - // add_testing_strategies(world, true, false); + // add_testing_strategies(world, true, true); } struct LogInfectionStatePerAgeGroup : mio::LogAlways { @@ -1169,7 +1170,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s testing_scheme_school); // 2. testing schemes in work places for 35% of random workplaces - std::vector work_location_ids; for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::Work) { @@ -1274,7 +1274,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s social_event_location_ids_small.begin() + num_social_event_locations_small); - //add capacity limits on day one + // add capacity limits on day one for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { @@ -1282,7 +1282,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(10, 0); + location.set_capacity(5, 0); } } restart_timer(timer, "till advance 14"); @@ -1293,13 +1293,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); + location.set_capacity(20, 0); } } restart_timer(timer, "till advance 23"); sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - sim.get_world().parameters.get() = 0.8; + sim.get_world().parameters.get() = 0.7; restart_timer(timer, "till advance 37"); sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); @@ -1314,7 +1314,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter - sim.get_world().parameters.get() = 0.8; + sim.get_world().parameters.get() = 0.7 * 0.7; restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); @@ -1326,18 +1326,19 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.get_index()) != social_event_location_ids_small.end()) { location.set_capacity(2, 0); } - //90% of big social events get reopened and caopacity will be unlimited - int number_of_big_social_events = (int)(0.7 * social_event_location_ids_big.size()); + //50% of big social events get reopened and caopacity will be unlimited + int number_of_big_social_events = (int)(0.5 * social_event_location_ids_big.size()); if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { - location.set_capacity(std::numeric_limits::max(), 0); + location.set_capacity(5, 0); } } } for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { + if (location.get_type() != mio::abm::LocationType::School && + location.get_type() != mio::abm::LocationType::Home) { location.set_npi_active(true); } } @@ -1346,7 +1347,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::cout << "day 90 finished" << std::endl; } else { - sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(90).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); } ////Advance till here @@ -1437,8 +1438,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From d72c730889ed626f63ede1f6a45a03a440359a40 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:18:27 +0200 Subject: [PATCH 192/488] performance enhancements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 23 ++++++++++++++--------- cpp/models/abm/world.cpp | 14 +++++++++++--- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index ce7883c237..7aa9ddd599 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -40,6 +40,10 @@ Location::Location(LocationId loc_id, size_t num_agegroups, uint32_t num_cells) , m_npi_active(false) { assert(num_cells > 0 && "Number of cells has to be larger than 0."); + for (auto& cell : m_cells) { + cell.m_cached_exposure_rate_contacts = {{VirusVariant::Count, AgeGroup(num_agegroups)}, 0.}; + cell.m_cached_exposure_rate_air = {{VirusVariant::Count}, 0.}; + } } void Location::add_damping(TimePoint t_begin, double p) @@ -138,8 +142,12 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time void Location::adjust_contact_rates(size_t num_agegroups) { - ScalarType total_contacts = 0.; + if (m_parameters.get() == std::numeric_limits::max()) { + return; + } + for (auto contact_from = AgeGroup(0); contact_from < AgeGroup(num_agegroups); contact_from++) { + ScalarType total_contacts = 0.; // slizing would be preferred but is problematic since both Tags of ContactRates are AgeGroup for (auto contact_to = AgeGroup(0); contact_to < AgeGroup(num_agegroups); contact_to++) { total_contacts += m_parameters.get()[{contact_from, contact_to}]; @@ -151,10 +159,6 @@ void Location::adjust_contact_rates(size_t num_agegroups) total_contacts; } } - total_contacts = 0; - //auto contact_rates_slice = m_parameters.get().slice(AgeGroup(contact_from)); - //auto total_contacts = std::accumulate(contact_rates_slice.begin(), contact_rates_slice.end(), 0.); - //contact_rates_slice = std::min(1., m_parameters.get() / total_contacts) * contact_rates_slice; } } @@ -162,9 +166,10 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou { //cache for next step so it stays constant during the step while subpopulations change //otherwise we would have to cache all state changes during a step which uses more memory + const TimePoint t_middlepoint = t + dt / 2; for (auto& cell : m_cells) { - cell.m_cached_exposure_rate_contacts = {{VirusVariant::Count, AgeGroup(num_agegroups)}, 0.}; - cell.m_cached_exposure_rate_air = {{VirusVariant::Count}, 0.}; + cell.m_cached_exposure_rate_contacts.array().setZero(); + cell.m_cached_exposure_rate_air.array().setZero(); for (auto&& p : cell.m_persons) { if (p->is_infected(t)) { auto& inf = p->get_infection(); @@ -174,9 +179,9 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou * to second order accuracy using midpoint rule */ cell.m_cached_exposure_rate_contacts[{virus, age}] += - params.get()[{virus}] * inf.get_viral_shed(t + dt / 2); + params.get()[{virus}] * inf.get_viral_shed(t_middlepoint); cell.m_cached_exposure_rate_air[{virus}] += - inf.get_viral_shed(t + dt / 2); // TODO: Adapt function/factor for air transmission. + inf.get_viral_shed(t_middlepoint); // TODO: Adapt function/factor for air transmission. } } diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 9f2ad3b858..2604a2366b 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -77,7 +77,13 @@ void World::migration(TimePoint t, TimeSpan dt) { PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { - auto&& person = m_persons[i]; + auto&& person = m_persons[i]; + auto current_infection_state = person->get_infection_state(t); + if (current_infection_state == mio::abm::InfectionState::Susceptible && !m_use_migration_rules && + !person->is_in_quarantine(t, parameters)) { + continue; + } + auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); auto try_migration_rule = [&](auto rule) -> bool { @@ -110,7 +116,7 @@ void World::migration(TimePoint t, TimeSpan dt) (has_locations({LocationType::Home}) && try_migration_rule(&go_to_quarantine)); } else { - //no daily routine migration, just infection related + // no daily routine migration, just infection related (has_locations({LocationType::Cemetery}) && try_migration_rule(&get_buried)) || (has_locations({LocationType::Home}) && try_migration_rule(&return_home_when_recovered)) || (has_locations({LocationType::Hospital}) && try_migration_rule(&go_to_hospital)) || @@ -133,7 +139,9 @@ void World::migration(TimePoint t, TimeSpan dt) current_location.get_type() != LocationType::ICU && current_location.get_type() != LocationType::Cemetery) { if (!person->is_in_quarantine(t, parameters)) { - auto& target_location = get_individualized_location(trip.migration_destination); + auto& target_location = get_individualized_location( + {person->get_assigned_location_index(trip.migration_destination.type), + trip.migration_destination.type}); if (target_location != current_location && target_location.entry_allowed_dampings(personal_rng, t) && m_testing_strategy.entry_allowed_testing_schemes(personal_rng, *person, From 7094509a296359b7ca76a78c80fb59583298aea8 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 10 Jul 2024 22:55:50 +0200 Subject: [PATCH 193/488] analyze npi bundesland Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_npi_bundesland.py | 94 +++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 cpp/simulations/analyze_npi_bundesland.py diff --git a/cpp/simulations/analyze_npi_bundesland.py b/cpp/simulations/analyze_npi_bundesland.py new file mode 100644 index 0000000000..1cbd34a2c9 --- /dev/null +++ b/cpp/simulations/analyze_npi_bundesland.py @@ -0,0 +1,94 @@ +import pandas as pd +import matplotlib +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import os +import openpyxl + + +#define a function which takes in a list of dates in the form yyyy-mm-dd and summarizes them in a range of dates where the dates are consecutive, e.g. [2021-01-01, 2021-01-02, 2021-01-03, 2021-01-05] -> [2021-01-01 to 2021-01-03, 2021-01-05] +def summarize_dates(dates): + #sort the list of dates + dates.sort() + #initialize the list of ranges + ranges = [] + #initialize the start of the range + start = dates[0] + #initialize the end of the range + end = dates[0] + #iterate through the list of dates + for i in range(1, len(dates)): + #if the date is the next day of the previous date + if pd.to_datetime(dates[i]) == pd.to_datetime(dates[i-1]) + pd.DateOffset(days=1): + #set the end of the range to the current date + end = dates[i] + #if the date is not the next day of the previous date + else: + #append the range to the list of ranges + ranges.append(str(start) + ' to ' + str(end)) + #set the start of the range to the current date + start = dates[i] + #set the end of the range to the current date + end = dates[i] + #append the last range to the list of ranges + ranges.append(str(start) + ' to ' + str(end)) + return ranges + + + +#import the first excel file with the measures and ther abbreviations +df_abb = pd.read_excel( + 'simulations/datensatzbeschreibung_massnahmen.xlsx', sheet_name='DSB BL') + +#read in the matrix which tells us which measure is active on which day +df_measure_matrix = pd.read_csv( + r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/maßnahmen_oberkategorien_bundesländer.csv') + + + +name_bundesland = "Niedersachsen" +start_date = '2021-03-01' +end_date = '2021-05-31' + + +one_day_after = pd.to_datetime(start_date) + pd.DateOffset(days=1) +#now we want to shorten the matrix to the zip code of Brunswick and the time period of interest +#delete all files with different zip code +df_measure_matrix = df_measure_matrix[df_measure_matrix['bundesland'] == name_bundesland] +#also delete all files with different date +df_measure_matrix = df_measure_matrix[(df_measure_matrix['datum']>= start_date) & (df_measure_matrix['datum'] <= end_date)] +#delete all the columns that just contain zeros +df_measure_matrix = df_measure_matrix.loc[:, (df_measure_matrix != 0).any(axis=0)] + + +#rename the first column from the abbreviation to the full explanation +# create a map from the short name to the explanation +dict_measure = {} +for i in range(len(df_abb)): + dict_measure[df_abb['Variablenname'][i]] = df_abb['Beschreibung'][i] +df_measure_matrix = df_measure_matrix.rename(columns=dict_measure) + + +# now we need create a txt file with the measures and the number of days they were active and the full explanation +f = open('measures_active_days_bl.txt', 'w') +# for every measure +for measure in df_measure_matrix.axes[1][4:]: + # count the days it was active + days = df_measure_matrix[measure].sum() + # get the dates it was active on in one list + dates = df_measure_matrix['datum'][df_measure_matrix[measure] == 1].tolist() + # summarize the dates in ranges + date_ranges = summarize_dates(dates) + # write the measure and the number of days it was active in the txt file also write down each date the measure was active + f.write(measure + ': ' + str(days) + ' days ' + 'Dates: ' + str(date_ranges) + '\n\n') + + +f.close() + +# df_measure_matrix = df_measure_matrix.iloc[:, measure_by_days.axes[0]] +# sns.heatmap(df_measure_matrix.iloc[:, 3:], cmap='coolwarm', cbar=False) +# plt.show() + +x = 1 From d1412ee7ff768dcb6840d2210b0bd0784dc0582b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 14 Jul 2024 23:35:44 +0200 Subject: [PATCH 194/488] overhaul of parameters and plots Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 358 ++++++++++-- cpp/simulations/generate_graph_from_data.cpp | 15 +- cpp/simulations/paper_abm_bs_testing.cpp | 580 +++++++++++++++++-- 3 files changed, 827 insertions(+), 126 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 4f4ac4125e..837f617448 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -64,13 +64,13 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): plt.legend(legend_plot) for i in states_plot: - y50_smoothed= gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15).flatten() - y25_smoothed= gaussian_filter1d(pd.DataFrame(y25[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15).flatten() - y75_smoothed= gaussian_filter1d(pd.DataFrame(y75[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15).flatten() - plt.fill_between(x, y50_smoothed, y25_smoothed , - alpha=0.5, color=color_plot[i]) - plt.fill_between(x, y50_smoothed, y75_smoothed, - alpha=0.5, color=color_plot[i]) + y50_smoothed= gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24*3).sum(), sigma=15).flatten() + y25_smoothed= gaussian_filter1d(pd.DataFrame(y25[:, i]).rolling(24*3).sum(), sigma=15).flatten() + y75_smoothed= gaussian_filter1d(pd.DataFrame(y75[:, i]).rolling(24*3).sum(), sigma=15).flatten() + # plt.fill_between(x, y50_smoothed, y25_smoothed , + # alpha=0.5, color=color_plot[i]) + # plt.fill_between(x, y50_smoothed, y75_smoothed, + # alpha=0.5, color=color_plot[i]) #currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') @@ -123,7 +123,7 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): color_plot = matplotlib.colormaps.get_cmap('Set1').colors states_plot = [1, 2, 3, 4, 5, 7] - legend_plot = ['E', 'I_NSymp', 'I_Symp', 'I_Sev', 'I_Crit', 'Dead', 'Sm. rep. Sympt.'] + legend_plot = ['E', 'I_NSymp', 'I_Symp', 'I_Sev', 'I_Crit', 'Dead', 'Sm. re. pos.'] for i in states_plot: plt.plot(x, y50[:, i], color=color_plot[i]) @@ -131,16 +131,10 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): #plot real data for comparison, symptomatic and infected daily if y_real is not None: x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) - plt.plot(x_real, y_real[:,4], '.', color='tab:purple') plt.plot(x_real, y_real[:,1], '.', color='tab:blue') plt.legend(legend_plot) - - # plt.show() - - - for i in states_plot: plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.5, color=color_plot[i]) @@ -161,44 +155,7 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): plt.xlabel('Time') plt.ylabel('Number of individuals') plt.show() - - # we will have a seperate plot the cumulative infected individuals, cumulative symptomatic individuals and cumulative dead individual - - cum_dead = y50[:, 7] #dead are already cumulative - #for the simulation we just need the 90 days and just take the first one for each day (every 24th value) - cum_dead_inter_day = cum_dead[::24] - - cum_dead_real = y_real[:,9] #dead are already cumulative - # we also calculate the MSR - # we need to extra - mse_dead=((cum_dead_real - cum_dead_inter_day[0:90])**2).mean() - - - - plt.figure('dead individuals and the MSE') - plt.plot(x, cum_dead,color='tab:red') - plt.plot(x_real, cum_dead_real,'.',color='tab:red') - # we want a text in the plot with the MSE value - plt.text(0.25, 0.8, 'MSE: '+str( float("{:.2f}".format(mse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) - plt.title('Dead individuals: Simulation vs Real') - plt.xlabel('Time') - plt.ylabel('Number of individuals') - plt.show() - - - - - - - - - - - - - - - + def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): @@ -209,7 +166,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): color_plot = matplotlib.colormaps.get_cmap('Set1').colors - fig, ax = plt.subplots(3, len(age_group_access), constrained_layout = True) + fig, ax = plt.subplots(5, len(age_group_access), constrained_layout = True) fig.set_figwidth(20) fig.set_figheight(9) for j, count in zip(age_group_access, range(len(age_group_access))): @@ -217,9 +174,31 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y25 = p25_bs[j][()] y75 = p75_bs[j][()] y_real = real_bs[j][()] + + #infeced no symptoms + ax_infected_no_symptoms = ax[0, count] + ax_infected_no_symptoms.set_xlabel('time (days)') + ax_infected_no_symptoms.plot(x, y50[:, 1], color=color_plot[count], label='y50') + ax_infected_no_symptoms.plot(x_real, y_real[:, 3], '.', color=color_plot[count], label='y_real') + ax_infected_no_symptoms.fill_between(x, y50[:, 1], y25[:, 1], alpha=0.5, color=color_plot[count]) + ax_infected_no_symptoms.fill_between(x, y50[:, 1], y75[:, 1], alpha=0.5, color=color_plot[count]) + ax_infected_no_symptoms.tick_params(axis='y') + ax_infected_no_symptoms.title.set_text('Infected_no_symptoms, Age{}'.format(j)) + ax_infected_no_symptoms.legend(['Simulation','Real']) + + #Infected_symptoms + ax_infected_symptoms = ax[1, count] + ax_infected_symptoms.set_xlabel('time (days)') + ax_infected_symptoms.plot(x, y50[:, 2], color=color_plot[count], label='y50') + ax_infected_symptoms.plot(x_real, y_real[:, 4], '.', color=color_plot[count], label='y_real') + ax_infected_symptoms.fill_between(x, y50[:, 2], y25[:, 2], alpha=0.5, color=color_plot[count]) + ax_infected_symptoms.fill_between(x, y50[:, 2], y75[:, 2], alpha=0.5, color=color_plot[count]) + ax_infected_symptoms.tick_params(axis='y') + ax_infected_symptoms.title.set_text('Infected_symptoms, Age{}'.format(j)) + ax_infected_symptoms.legend(['Simulation','Real']) # Severe - ax_severe = ax[0, count] + ax_severe = ax[2, count] ax_severe.set_xlabel('time (days)') ax_severe.plot(x, y50[:, 4], color=color_plot[count], label='y50') ax_severe.plot(x_real, y_real[:, 6], '.', color=color_plot[count], label='y_real') @@ -230,7 +209,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): ax_severe.legend(['Simulation','Real']) # Critical - ax_critical = ax[1, count] + ax_critical = ax[3, count] ax_critical.set_xlabel('time (days)') ax_critical.plot(x, y50[:, [5]], color=color_plot[count], label='y50') ax_critical.plot(x_real, y_real[:, [7]], '.', color=color_plot[count], label='y_real') @@ -241,7 +220,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): ax_critical.legend(['Simulation','Real']) # Dead - ax_dead = ax[2, count] + ax_dead = ax[4, count] ax_dead.set_xlabel('time (days)') ax_dead.plot(x, y50[:, [7]], color=color_plot[count], label='y50') ax_dead.plot(x_real, y_real[:, [9]], '.', color=color_plot[count], label='y_real') @@ -255,6 +234,267 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): plt.show() +def plot_dead(path): + #we will have a seperate plot the cumulative infected individuals, cumulative symptomatic individuals and cumulative dead individual + # we need to load the data + f_p50 = h5py.File( + path+"/infection_state_per_age_group/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + # we need just every 24th value + total_50 = total_50[::24] + # we just take the first 90 days + total_50 = total_50[0:90] + + # we need the real data + f_real = h5py.File( + path + "/Results_rki.h5", 'r') + real_bs = f_real['3101'] + y_real = real_bs['Total'][()] + # we just take the first 90 days + y_real = y_real[0:90] + + # we calculate the RMSE + rmse_dead=np.sqrt(((y_real[:,9] - total_50[:,7])**2).mean()) + + + # we plot this + fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the tests positive and the real cases + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + ax.plot(xx, total_50[:,7], color='tab:red') + ax.plot(xx, y_real[:,9], color='tab:blue') + # we also write the rmse + ax.text(0.25, 0.8, 'RMSE: '+str( float("{:.2f}".format(rmse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of dead') + ax.title.set_text('Dead') + ax.legend(['Dead','Real dead']) + plt.show() + + +def plot_icu(path): + df_abb = pd.read_json(path+"/pydata/Germany/county_divi_ma7.json") + # we just need the columns ICU_low and ICU_hig + df_abb = df_abb[['ID_County','ICU', 'Date']] + + df_abb= df_abb[df_abb['ID_County'] == 3101] + # we need just the dates bewteen 2021-03-01 and 2021-06-01 + df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] + + # we plot this against this the Amount of persons in the ICU from our model + f_p50 = h5py.File( + path+"/results_last_run/infection_state_per_age_group/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + # we need just every 24th value + total_50 = total_50[::24] + # we just take the first 90 days + total_50 = total_50[0:90]*0.3 + + # we calculate the RMSE + rmse_ICU=np.sqrt(((df_abb['ICU'][0:90] - total_50[:,5])**2).mean()) + + # plot the ICU beds and the ICU beds taken + fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the ICU_low and the ICU_high + ax.plot(df_abb['Date'][0:90], df_abb['ICU'][0:90], color='tab:blue') + ax.plot(df_abb['Date'][0:90], total_50[:,5], color='tab:red') + # we also write the rmse + ax.text(0.25, 0.8, 'RMSE: '+str( float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of ICU beds') + ax.title.set_text('ICU beds and ICU beds taken') + ax.legend(['ICU beds','ICU beds taken']) + plt.show() + +def plot_tests(path): + + df_abb = pd.read_excel(path+"/pydata/Germany/SARS-CoV-2-PCR-Testungen_in_Deutschland.xlsx") + # in the week row the format is YYYY-WX where X is the week number and Y is the year number + # We need the week number and the year number and just take 2021-W9 to 2021-W21 + # we just Take the rows where YYYY is 2021 and X is between 9 and 21 + df_abb['Year'] = df_abb['date'].str.split('-').str[0] + df_abb['Week'] = df_abb['date'].str.split('-').str[1] + df_abb['Week'] = df_abb['Week'].str.split('W').str[1] + df_abb['Week'] = df_abb['Week'].astype(int) + df_abb['Year'] = df_abb['Year'].astype(int) + # we just take the rows where the year is 2021 and the week is between 9 and 21 + df_abb = df_abb[(df_abb['Year'] == 2021) & (df_abb['Week'] >= 9) & (df_abb['Week'] <= 21)] + # We just need the columns tests total, tests accumulated, tests positive + df_abb = df_abb[['date','tests_total', 'tests_total_accumulated', 'tests_positive','tests_positive_accumulated','tests_positive_ratio']]# + # we assumethe tests get distributed over the week, so we divide the tests by 7 for each day, but we also need to infer the amount of tests in brunswick + # as brunswick has around 250.000 persons, we take the 250.000/80.000.000 = 1/320 of the tests + df_abb[['tests_total', 'tests_total_accumulated', 'tests_positive','tests_positive_accumulated']] = df_abb[['tests_total', 'tests_total_accumulated', 'tests_positive','tests_positive_accumulated']]/320 + + # we model this the following way + # we know the amount of people who PCR test themselves positive and in general the amount of people who test themselves positive + # as well as the amount of people who test themselves through other means + # now we assume: the majority of people who are symptomatic (I_Isymp, I_Sev, I_Crit) will test themselves (80%) + # the majority of people who are asymptomatic (I_NSymp) will not test themselves (8%) + # and there is an amount of recently infected, which test themselves netherless (1%) + + # first thing we can do, is that we PCR test an amount of + # we divide the persons into 2 groups: asymptomatic and symptomatic + # we assume that the symptomatic persons will test themselves with an x time higher probability than the asymptomatic persons + + ratio_testing_symptomatic_vs_asymptomatic = 0.1 + + f_p50 = h5py.File( + path+"/results_last_run/infection_state_per_age_group/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + total_50 = total_50[::24] + total_50 = total_50[0:90] + + # we make a np array with the amount of symptomatic and asymptomatic persons + # first we calculate the amount of positive tests, and assume PCR is perfect + # the amount of tests done on each day is; + PCR_tests = df_abb['tests_total'].to_numpy() + PCR_tests = np.repeat(PCR_tests, 7) + PCR_tests = PCR_tests/7 + PCR_tests = PCR_tests[0:90] + + PCR_tests_positive = df_abb['tests_positive'].to_numpy() + PCR_tests_positive = np.repeat(PCR_tests_positive, 7) + PCR_tests_positive = PCR_tests_positive/7 + PCR_tests_positive = PCR_tests_positive[0:90] + + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + + #plot these + fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the tests positive and the real cases + ax.plot(xx, PCR_tests, color='tab:red') + ax.plot(xx, PCR_tests_positive, color='tab:blue') + ax.set_xlabel('time (days)') + + # The amount of persons, who do tests on a day is: + PCR_tests_symptomatic = np.zeros(90) + PCR_tests_asymptomatic = np.zeros(90) + PCR_tests_symptomatic = PCR_tests * (1/(1+(1/ratio_testing_symptomatic_vs_asymptomatic))) + PCR_tests_asymptomatic = PCR_tests - PCR_tests_symptomatic + + # the real amount of positive tested persons is: + #likelihood of being poisiitve is (E+I_NSymp)/(S+E+I_NSymp) + lik_being_positive_asymptomatic = (total_50[:,1]+total_50[:,2])/(total_50[:,0]+total_50[:,1]+total_50[:,2]) + + tests_positive = (lik_being_positive_asymptomatic*PCR_tests_asymptomatic)+PCR_tests_symptomatic + # we need to plot this + ax.plot(xx, tests_positive, color='tab:green') + ax.set_ylabel('Number of tests') + ax.title.set_text('Tests positive PCR and real confirmedcases from any source') + ax.legend(['Tests','Tests positive','Tests positive inferred']) + plt.show() + + # new plot which is showing the amount of symptomatic persons + sympt_persons = total_50[:,3]+total_50[:,4]+total_50[:,5] + # we plot this + fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the tests positive and the real cases + ax.plot(xx, sympt_persons, color='tab:red') + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of symptomatic persons') + ax.title.set_text('Symptomatic persons') + ax.legend(['Symptomatic persons']) + plt.show() + + # also the amount of asymptomatic persons with the amount of persons infected + asympt_persons = total_50[:,2]+total_50[:,1]+total_50[:,0] + asympt_positive = total_50[:,2]+total_50[:,1] + # we plot this + fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the tests positive and the real cases + ax.plot(xx, asympt_persons, color='tab:red') + ax.plot(xx, asympt_positive, color='tab:blue') + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of asymptomatic persons') + ax.title.set_text('Asymptomatic persons') + ax.legend(['Asymptomatic persons','Asymptomatic persons positive']) + plt.show() + + +def infer_positive_tests(path): + # First way: we just take x amount of eahc compartment and fit this to the positive tested category. + # A few assumptions: + # 1. The specificities of the tests are 99.9% this means that we have 0.1% false positives. We just assme, that nonsymptomatics test themselves very rarely, e.g. we just take a fraction of symptomatic persons. + # 2. We just have a around 60% sensitivity, this means that we have 40% false negatives. + # 3. We assume that it is way more likely to test yourself if you are symptomatic than if you are asymptomatic + + + # we need every compartment of the model + f_p50 = h5py.File( + path+"/infection_state_per_age_group/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + total_50 = total_50[::24] + total_50 = total_50[0:90] + + # we need the real positive tests + # real world + f_real = h5py.File( + path + "/Results_rki.h5", 'r') + real_bs = f_real['3101'] + total_real = real_bs['Total'][()] + total_real = total_real[0:90] + + # we take a fraction from each compartment and fit this to the positive tests + # we take the symptomatic persons + sympt_persons = total_50[:,3]+total_50[:,4]+total_50[:,5] + # we take the asymptomatic persons + asympt_persons = total_50[:,2]+total_50[:,1]+total_50[:,0] + # we assume r_sns = 20 so symptomatic persons are 20 times more likely to test themselves + r_sns = 40 + # we say the likelyhood to test yourself is 0.8 for symptomatic persons and therefore 0.04 for asymptomatic persons + lt_sympt = 0.3 + lt_asympt = lt_sympt/r_sns + sensitivity = 0.6 + specificity = 0.99 + + # therefore the amount of pisitive tests is: + # symptomatic persons + inferred_positive_tests_sympt = (total_50[:,3]*lt_sympt+total_50[:,4]*lt_sympt+total_50[:,5]*lt_sympt)*sensitivity + # asymptomatic persons + inferred_positive_tests_asympt = (total_50[:,0]*lt_asympt)*(1-specificity)+((total_50[:,1]+total_50[:,2])*lt_asympt)*sensitivity + + # we save the assumed tests done + assumed__amount_of_test = (total_50[:,3]*lt_sympt+total_50[:,4]*lt_sympt+total_50[:,5]*lt_sympt)+(total_50[:,0]*lt_asympt)+(total_50[:,1]+total_50[:,2])*lt_asympt + # we plot this + fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the tests positive and the real cases + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + ax.plot(xx, inferred_positive_tests_sympt, color='tab:red') + ax.plot(xx, inferred_positive_tests_asympt, color='tab:blue') + ax.plot(xx, inferred_positive_tests_asympt+inferred_positive_tests_sympt, color='tab:green') + ax.plot(xx, total_real[:,1], color='tab:orange') + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of positive tests') + ax.title.set_text('Inferred positive tests') + ax.legend(['Symptomatic persons','Asymptomatic persons','Symptomatic and Asymptomatic persons','Real positive tests']) + + # we also write the rmse + rmse_sympt=np.sqrt(((total_real[:,1] - (inferred_positive_tests_sympt+inferred_positive_tests_asympt))**2).mean()) + ax.text(0.25, 0.8, 'RMSE: '+str( float("{:.2f}".format(rmse_sympt))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + plt.show() + if __name__ == "__main__": @@ -269,4 +509,8 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) - # plot_infections_loc_types_avarage(path) + plot_infections_loc_types_avarage(path) + plot_icu(path+"/..") + plot_dead(path) + # plot_tests(path+"/..") + infer_positive_tests(path) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 199165fe2d..118cc211da 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -134,10 +134,10 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; - const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.20}; - const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.18, 0.25}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.8}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.8}; + const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.05}; + const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.15, 0.05}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; @@ -227,8 +227,9 @@ mio::IOResult> get_graph(mio::Date start_date, c for (auto& node : nodes) { node.parameters = params; } - auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 1.0); - auto scaling_factor_icu = 1.0; + auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 5.0); + scaling_factor_infected[5] = 2.0; + auto scaling_factor_icu = 4.8; const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, @@ -254,7 +255,7 @@ mio::IOResult generate_extrapolated_data(std::vector n BOOST_OUTCOME_TRY(export_input_data_county_timeseries( nodes, data_dir.string(), node_ids, start_date, scaling_factor_infected, scaling_factor_icu, num_days, mio::path_join(data_dir.string(), "pydata/Germany", "county_divi_ma7.json"), - mio::path_join(data_dir.string(), "pydata/Germany", "cases_all_county_age_ma7.json"), + mio::path_join(data_dir.string(), "pydata/Germany", "cases_all_county_age_repdate_ma7.json"), mio::path_join(data_dir.string(), "pydata/Germany", "county_current_population.json"))); return mio::success(); diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8185ce4294..3be76a3d14 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -626,37 +626,39 @@ void set_parameters(mio::abm::Parameters& params) params.get()[mio::abm::TestType::Generic] = generic_test_values; // Set percentage parameters - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.75; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.75; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.8; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.8; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.8; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.01; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.01; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.5; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.55; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.6; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = + 0.65; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = + 0.65; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.02; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.02; params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.07; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.3; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.6; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.1; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.17; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.6; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.055; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.14; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.28; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.55; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.75; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.08; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.30; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.55; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.08; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.12; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.22; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.45; + + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.05; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.10; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.25; + params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.6; // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 5.6; + params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -684,7 +686,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.38; //all masks have a 0.66 protection factor for now + params.get() = 0.33; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -888,22 +890,27 @@ void set_local_parameters(mio::abm::World& world) case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; loc.get_infection_parameters().get().array() *= - 1.8; // scaling due to beeing at school 1/1.8 * 100% of the time + 0.45; // scaling due to beeing at school 1/1.8 * 100% of the time break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; loc.get_infection_parameters().get().array() *= - 4.8; // scaling due to beeing at school 1/4.8 * 100% of the time + 4.5; // scaling due to beeing at school 1/4.8 * 100% of the time break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; loc.get_infection_parameters().get().array() *= - 3.5; // scaling due to beeing at school 1/3.5 * 100% of the time + 1.1; // scaling due to beeing at Work 1/3.5 * 100% of the time + break; + case mio::abm::LocationType::SocialEvent: + loc.get_infection_parameters().get() = contacts_other; + loc.get_infection_parameters().get().array() *= + 32; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher ocntact rate break; default: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= - 5.2675; // scaling due to beeing at school 1/5.2675 * 100% of the time + 4.0; // scaling due to beeing at other 1/5.2675 * 100% of the time break; } } @@ -944,6 +951,89 @@ void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool socia } } +std::pair calculate_rmse_from_results(const fs::path& results_dir, int max_num_days) +{ + + // We need to read in the results from the results directory + auto real_data = mio::read_result((results_dir / "Results_rki.h5").generic_string()).value()[0].get_totals(); + auto sim_data = mio::read_result((results_dir / "/infection_state_per_age_group/p50/Results.h5").generic_string()) + .value()[0] + .get_totals(); + + // we change the format to two vectors of the same length, in this case for debugging reasons, we just use the first 3 + // for the simulation data we need to take only the first of each day, so just every 24th element + std::vector> real_data_vec; + std::vector> sim_data_vec; + for (int i = 0; i < max_num_days; i++) { + real_data_vec.push_back(std::make_pair(real_data[i]((size_t)mio::osecir::InfectionState::Dead), + real_data[i]((size_t)mio::osecir::InfectionState::Exposed))); + } + for (int i = 0; i < max_num_days * 24; i += 24) { + sim_data_vec.push_back(std::make_pair(sim_data[i]((size_t)mio::abm::InfectionState::Dead), + sim_data[i]((size_t)mio::abm::InfectionState::Exposed))); + } + + // now we calculate the RMSE + double rmse_dead = 0; + double rmse_exposed = 0; + for (size_t i = 0; i < real_data_vec.size(); i++) { + rmse_dead += pow(real_data_vec[i].first - sim_data_vec[i].first, 2); + rmse_exposed += pow(real_data_vec[i].second - sim_data_vec[i].second, 2); + } + rmse_dead = sqrt(rmse_dead / real_data_vec.size()); + rmse_exposed = sqrt(rmse_exposed / real_data_vec.size()); + + return std::make_pair(rmse_dead, rmse_exposed); +} + +/** + * @brief Calculate a grid search for a given set of parameters. + * @input std::vector where size is the amount of parameters, and the first entry is the min and the second is the max value + */ +std::vector> grid_points(std::vector> parameters, int number_of_points) +{ + std::vector> grid; + for (size_t i = 0; i < parameters.size(); i++) { + std::vector temp; + double step = (parameters[i].second - parameters[i].first) / (number_of_points - 1); + for (int j = 0; j < number_of_points + 1; j++) { + temp.push_back(parameters[i].first + j * step); + } + grid.push_back(temp); + } + return grid; +} + +/** + * @brief Distribute the grid search over the MPI ranks. + */ +std::vector> distribute_grid_search(int rank, int num_procs, std::vector> grid) +{ + //Calculate how many grid points there are, assuming that each parameter has the same amount of points + int number_of_points = std::pow(grid[0].size(), grid.size()); + //Calculate how many points each rank should calculate + int points_per_rank = number_of_points / num_procs; + //leftover points goes to the last rank + if (rank == num_procs - 1) { + points_per_rank = number_of_points - points_per_rank * (num_procs - 1); + } + // we calculate every possible combination of the grid, independently of the rank + std::vector> grid_search; + for (int i = 0; i < (int)grid.size(); i++) { + std::vector temp; + for (int j = 0; j < (int)grid[i].size(); j++) { + temp.push_back(grid[i][j]); + } + grid_search.push_back(temp); + } + // we calculate the grid search for the rank + std::vector> grid_search_rank; + for (int i = 0; i < points_per_rank; i++) { + grid_search_rank.push_back(grid_search[i + rank * points_per_rank]); + } + return grid_search_rank; +} + /** * Create a sampled simulation with start time t0. * @param t0 The start time of the Simulation. @@ -954,7 +1044,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world set_parameters(world.parameters); - set_local_parameters(world); + restart_timer(timer, "time taken for setting up parameters and local parameters"); // Create the world object from statistical data. @@ -970,7 +1060,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con // Assign vaccination status to each person. assign_vaccination_state(world, start_date_sim); restart_timer(timer, "time taken for assigning vaccination state"); - + set_local_parameters(world); // add_testing_strategies(world, true, true); } @@ -1083,6 +1173,304 @@ std::vector distribute_runs(size_t num_runs, int num_procs) return run_distribution; } +mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, + std::vector grid_params, bool save_single_runs = true) +{ + mio::Date start_date{2021, 3, 1}; + int max_num_days = 90; + auto max_num_persons = std::numeric_limits::max(); + + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation + + //ENSEMBLE RESULTS + auto ensemble_infection_per_loc_type = + std::vector>>{}; // Vector of infection per location type results + ensemble_infection_per_loc_type.reserve(size_t(num_runs)); + auto ensemble_infection_state_per_age_group = + std::vector>>{}; // Vector of infection state per age group results + ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); + auto ensemble_params = std::vector>{}; // Vector of all worlds + ensemble_params.reserve(size_t(num_runs)); + restart_timer(timer, "time for initial setup"); + + // Determine inital infection state distribution + determine_initial_infection_states_world(input_dir, start_date); + restart_timer(timer, "time for determine_initial_infection_states_world"); + // Prepare vaccination state + prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); + restart_timer(timer, "time for vaccinaiton state"); + + // Loop over a number of runs + for (size_t run_idx = 0; run_idx < num_runs; run_idx++) { + auto world = mio::abm::World(num_age_groupss); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date); + restart_timer(timer, "time taken for create sampled world"); + + auto sim = mio::abm::Simulation(t0, std::move(world)); + + // Setup parameters for the simulation + sim.get_world().parameters.get() = grid_params[0]; + sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype, + age_group_80_plus}] = grid_params[1]; + sim.get_world().parameters.get() = grid_params[2]; + + //Logger + mio::History + historyInfectionPerLocationType{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyInfectionStatePerAgeGroup{ + Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + + const auto location_it = sim.get_world().get_locations(); + + //Spontanaeus testing at home + // auto testing_min_time_home = mio::abm::days(7); + // auto probability_home = 0.05; + // auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(0).seconds()); + // auto end_date_test_home = mio::abm::TimePoint(tmax); + // auto test_type_home = mio::abm::TestType::Antigen; // Antigen test + // auto test_parameters_home = + // sim.get_world().parameters.get()[test_type_home]; // Test parameters + // auto testing_criteria_home = mio::abm::TestingCriteria(); + // auto testing_scheme_home = + // mio::abm::TestingScheme(testing_criteria_home, testing_min_time_home, start_date_test_home, + // end_date_test_home, test_parameters_home, probability_home); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_home); + + // 1. testing schemes in schools + auto testing_min_time_school = mio::abm::days(7); + auto probability_school = 1.0; + auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 + auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 + auto test_type_school = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters = + sim.get_world().parameters.get()[test_type_school]; // Test parameters + auto testing_criteria_school = mio::abm::TestingCriteria(); + auto testing_scheme_school = + mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, + end_date_test_school, test_parameters, probability_school); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_school); + + // 2. testing schemes in work places for 35% of random workplaces + std::vector work_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::Work) { + work_location_ids.push_back(location.get_index()); + } + } + //take 35% of work locations + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); + auto num_work_locations = (int)(0.35 * work_location_ids.size()); + std::vector work_location_ids_35(work_location_ids.begin(), + work_location_ids.begin() + num_work_locations); + auto testing_min_time_work = mio::abm::days(1); + auto probability_work = 1.0; + auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); + auto end_date_test_work = mio::abm::TimePoint(tmax); + auto test_type_work = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_work = + sim.get_world().parameters.get()[test_type_work]; // Test parameters + auto testing_criteria_work = mio::abm::TestingCriteria(); + auto testing_scheme_work = + mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, + end_date_test_work, test_parameters_work, probability_work); + for (auto& location_id : work_location_ids_35) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); + } + + // 2.5 plus testing schemes at 20 % of basics shops + std::vector basics_shop_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + basics_shop_location_ids.push_back(location.get_index()); + } + } + //take 20% of basics shop locations + std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); + auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); + std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), + basics_shop_location_ids.begin() + num_basics_shop_locations); + auto testing_min_time_basics_shop = mio::abm::days(2); + auto probability_basics_shop = 1.0; + auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); + auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); + auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_basics_shop = + sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters + auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); + auto testing_scheme_basics_shop = mio::abm::TestingScheme( + testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, + end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); + for (auto& location_id : basics_shop_location_ids_20) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); + } + + // 3. Mask schemes for all locations + // First set all locations to have mask usage, we need ffp2 masks + for (auto& location : location_it) { + location.set_required_mask(mio::abm::MaskType::FFP2); + if (location.get_type() == mio::abm::LocationType::Home) { + location.set_npi_active(false); + } + else { + location.set_npi_active(true); + } + } + + // // 4. Dampings for schools and Basic shops + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::School) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.6); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.0); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), + 0.6); // from 2021-04-12 till 2021-05-30 (end) + } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.65); // from 2021-03-01 + } + } + + // 5. add capacity limits to some locations + // first we need two lists, one for 50% of random social event locations and the other list for the other 50% + // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ + // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] + // ----> Divide Social Event locations into a 50/50 split. First 50% get the restrictive capacity + std::vector social_event_location_ids_small; + std::vector social_event_location_ids_big; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::SocialEvent) { + social_event_location_ids_small.push_back(location.get_index()); + } + } + //take 50% of social event locations + std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); + auto num_social_event_locations_small = (int)(0.75 * social_event_location_ids_small.size()); + social_event_location_ids_big.insert( + social_event_location_ids_big.end(), social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_small); + social_event_location_ids_small.erase(social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + + num_social_event_locations_small); + + // add capacity limits on day one + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(50, 0); + } + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + location.set_capacity(5, 0); + } + } + + restart_timer(timer, "till advance 14"); + sim.get_world().parameters.get() = 3.0; + sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 14 finished" << std::endl; + + // small social events to capacity 5 + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(20, 0); + } + } + + restart_timer(timer, "till advance 30 (eastern starts)"); + sim.get_world().parameters.get() = 2.5; + sim.advance(mio::abm::TimePoint(mio::abm::days(30).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + + restart_timer(timer, "till advance 37 (eastern ends)"); + sim.get_world().parameters.get() = 3.5; + sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + + restart_timer(timer, "till advance 42"); + sim.get_world().parameters.get() = 2.5; + sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 42 finished" << std::endl; // date 2021-04-12 + + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(false); + } + } + restart_timer(timer, "till advance 72"); + sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(10, 0); + } + //50% of big social events get reopened and capacity will be limited to xx + int number_of_big_social_events = (int)(0.5 * social_event_location_ids_big.size()); + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + number_of_big_social_events--; + if (number_of_big_social_events >= 0) { + location.set_capacity(10, 0); + } + } + } + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School && + location.get_type() != mio::abm::LocationType::Home) { + location.set_npi_active(true); + } + } + sim.get_world().parameters.get() = 2.0; + restart_timer(timer, "till advance tmax"); + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + std::cout << "day 90 finished" << std::endl; + + ////Advance till here + // Stop the clock after sim.advance and calculate the duration + restart_timer(timer, "time taken for simulation end"); + // TODO: update result of the simulation to be a vector of location result. + auto temp_sim_infection_per_loc_tpye = + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_state_per_age_group = + std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + // Push result of the simulation back to the result vector + ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); + ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); + ensemble_params.emplace_back(std::vector{sim.get_world()}); + + std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; + printf("Saving results ... "); + } + + BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, + result_dir / "infection_state_per_age_group/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, + result_dir / "infection_per_location_type/", save_single_runs)); + restart_timer(timer, "time taken for data gathering and saving results"); + + auto rmse = calculate_rmse_from_results(result_dir, max_num_days); + std::cout << "RMSE Dead: " << rmse.first << " RMSE Exposed: " << rmse.second << std::endl; + restart_timer(timer, "time taken for calculating RMSE"); + + printf("done.\n"); + return mio::success(); +} + mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { @@ -1100,9 +1488,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; mio::Date start_date{2021, 3, 1}; - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(90); // End time per simulation + int max_num_days = 90; auto max_num_persons = 400000; + bool npis_on = true; + + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation auto ensemble_infection_per_loc_type = std::vector>>{}; // Vector of infection per location type results @@ -1149,11 +1540,25 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; // / NPIS// - bool npis_on = true; if (npis_on) { const auto location_it = sim.get_world().get_locations(); - // Advance the world with respective npis + + //Spontanaeus testing at home + // auto testing_min_time_home = mio::abm::days(7); + // auto probability_home = 0.05; + // auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(0).seconds()); + // auto end_date_test_home = mio::abm::TimePoint(tmax); + // auto test_type_home = mio::abm::TestType::Antigen; // Antigen test + // auto test_parameters_home = + // sim.get_world().parameters.get()[test_type_home]; // Test parameters + // auto testing_criteria_home = mio::abm::TestingCriteria(); + // auto testing_scheme_home = + // mio::abm::TestingScheme(testing_criteria_home, testing_min_time_home, start_date_test_home, + // end_date_test_home, test_parameters_home, probability_home); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, + // testing_scheme_home); + // 1. testing schemes in schools auto testing_min_time_school = mio::abm::days(7); auto probability_school = 1.0; @@ -1242,13 +1647,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // // 4. Dampings for schools and Basic shops for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.0); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.6); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), - 0.5); // from 2021-04-12 till 2021-05-30 (end) + 0.6); // from 2021-04-12 till 2021-05-30 (end) } if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.4); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.65); // from 2021-03-01 } } @@ -1266,7 +1674,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } //take 50% of social event locations std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); - auto num_social_event_locations_small = (int)(0.5 * social_event_location_ids_small.size()); + auto num_social_event_locations_small = (int)(0.75 * social_event_location_ids_small.size()); social_event_location_ids_big.insert( social_event_location_ids_big.end(), social_event_location_ids_small.begin(), social_event_location_ids_small.begin() + num_social_event_locations_small); @@ -1278,61 +1686,95 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(30, 0); + location.set_capacity(15, 0); } if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(5, 0); + location.set_capacity(7, 0); } } + restart_timer(timer, "till advance 14"); + double normal_infection_viral_shed = 4.0; + sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 14 finished" << std::endl; + // small social events to capacity 5 for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(20, 0); + location.set_capacity(5, 0); + location.get_infection_parameters().get().array() *= 0.3; + } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.get_infection_parameters().get().array() *= 0.5; } } - restart_timer(timer, "till advance 23"); - sim.advance(mio::abm::TimePoint(mio::abm::days(23).seconds()), historyInfectionStatePerAgeGroup, + + restart_timer(timer, "till advance 30 (eastern starts)"); + sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - sim.get_world().parameters.get() = 0.7; - restart_timer(timer, "till advance 37"); - sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, + + restart_timer(timer, "till advance 37 (eastern ends)"); + double seasonality_april = 0.85; + sim.get_world().parameters.get() = + normal_infection_viral_shed * seasonality_april; + double eastern_bonus = 4.0; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::Home || + location.get_type() == mio::abm::LocationType::BasicsShop || + location.get_type() == mio::abm::LocationType::SocialEvent) { + location.get_infection_parameters().get().array() *= eastern_bonus; + } + } + sim.advance(mio::abm::TimePoint(mio::abm::days(34).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - sim.get_world().parameters.get() = 1.0; + + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::Home || + location.get_type() == mio::abm::LocationType::BasicsShop || + location.get_type() == mio::abm::LocationType::SocialEvent) { + location.get_infection_parameters().get().array() /= eastern_bonus; + } + } restart_timer(timer, "till advance 42"); + sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 42 finished" << std::endl; // date 2021-04-12 + + restart_timer(timer, "till advance 60"); + sim.advance(mio::abm::TimePoint(mio::abm::days(62).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 62 finished (date 2021-05-01)" << std::endl; + double seasonality_may = 0.5; + sim.get_world().parameters.get() = + normal_infection_viral_shed * seasonality_may; + for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::School) { location.set_npi_active(false); } } - // set infection from viral shed lower //Todo: change this "change of InfectionRateFromViralShed" to a parameter - sim.get_world().parameters.get() = 0.7 * 0.7; restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - sim.get_world().parameters.get() = 1.0; for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(2, 0); + location.get_infection_parameters().set(2); } - //50% of big social events get reopened and caopacity will be unlimited + //50% of big social events get reopened and capacity will be limited to xx int number_of_big_social_events = (int)(0.5 * social_event_location_ids_big.size()); if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { - location.set_capacity(5, 0); + location.get_infection_parameters().set(10); } } } @@ -1347,7 +1789,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::cout << "day 90 finished" << std::endl; } else { - sim.advance(mio::abm::TimePoint(mio::abm::days(90).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(max_num_days).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); } ////Advance till here @@ -1396,6 +1838,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s #endif restart_timer(timer, "time taken for data gathering and saving results"); + if (rank == 0) { + auto rmse = calculate_rmse_from_results(result_dir, max_num_days); + std::cout << "RMSE Dead: " << rmse.first << " RMSE Exposed: " << rmse.second << std::endl; + restart_timer(timer, "time taken for calculating RMSE"); + } + printf("done.\n"); return mio::success(); } @@ -1434,6 +1882,7 @@ mio::IOResult copy_result_folder(std::string const& from_dir, std::string int main(int argc, char** argv) { mio::set_log_level(mio::LogLevel::err); + auto start = std::chrono::system_clock::now(); #ifdef MEMILIO_ENABLE_MPI mio::mpi::init(); #endif @@ -1446,7 +1895,6 @@ int main(int argc, char** argv) std::string result_dir = input_dir + "/results_" + currentDateTime(); size_t num_runs; - bool save_single_runs = true; if (argc == 2) { num_runs = atoi(argv[1]); @@ -1482,14 +1930,22 @@ int main(int argc, char** argv) std::cout << created.error().formatted_message(); return created.error().code().value(); } + timer = TIME_NOW; + // grid search + // std::vector> grid = {{4.0, 6.0}, {0.6, 0.8}, {0.5, 0.9}, {0.7, 0.5}}; - timer = TIME_NOW; - auto result = run(input_dir, result_dir, num_runs, save_single_runs); + auto result = run(input_dir, result_dir, num_runs); // copy results into a fixed name folder to have easier access std::string last_run_dir = input_dir + "/results_last_run"; auto copied = copy_result_folder(result_dir, last_run_dir); mio::mpi::finalize(); + + auto end = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = end - start; + //print time taken + std::cout << "Time taken: " << elapsed_seconds.count() << "s\n"; + return 0; } From 9f1ab1792c46dc420db9b90949594391d6b20705 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 15 Jul 2024 00:15:40 +0200 Subject: [PATCH 195/488] bug fix going home test positive Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 9 ++++++--- cpp/models/abm/testing_strategy.h | 2 +- cpp/models/abm/world.cpp | 4 ++-- cpp/simulations/analyze_bs_run.py | 4 ++-- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index f7df3dd109..bccbd4144e 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -124,15 +124,18 @@ void TestingStrategy::add_testing_scheme(const LocationId& loc_id, const Testing } } -bool TestingStrategy::entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, +bool TestingStrategy::entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, LocationId id, const mio::abm::TimePoint t) { - if (m_testing_schemes_per_location.at(id).empty()) { + if (m_testing_schemes_per_location.at(id.index).empty()) { return true; } - for (auto&& scheme : m_testing_schemes_per_location.at(id)) { + for (auto&& scheme : m_testing_schemes_per_location.at(id.index)) { if (scheme.run_scheme(rng, person, t)) { + if (id.type == LocationType::Home) { + return true; + } return false; } } diff --git a/cpp/models/abm/testing_strategy.h b/cpp/models/abm/testing_strategy.h index 36c510ecca..f095eb742e 100644 --- a/cpp/models/abm/testing_strategy.h +++ b/cpp/models/abm/testing_strategy.h @@ -186,7 +186,7 @@ class TestingStrategy void update_location_testing_schemes(TimePoint t, mio::Range> locations); - bool entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, unsigned id, + bool entry_allowed_testing_schemes(Person::RandomNumberGenerator& rng, Person& person, LocationId id, const mio::abm::TimePoint t); private: diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 2604a2366b..ecbef71545 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -144,8 +144,8 @@ void World::migration(TimePoint t, TimeSpan dt) trip.migration_destination.type}); if (target_location != current_location && target_location.entry_allowed_dampings(personal_rng, t) && - m_testing_strategy.entry_allowed_testing_schemes(personal_rng, *person, - target_location.get_index(), t) && + m_testing_strategy.entry_allowed_testing_schemes( + personal_rng, *person, {target_location.get_index(), target_location.get_type()}, t) && target_location.get_number_persons() < target_location.get_capacity().persons) { person->apply_mask_intervention(personal_rng, target_location); person->migrate_to(target_location); diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 837f617448..aa746824e6 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -510,7 +510,7 @@ def infer_positive_tests(path): if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) plot_infections_loc_types_avarage(path) - plot_icu(path+"/..") + # plot_icu(path+"/..") plot_dead(path) # plot_tests(path+"/..") - infer_positive_tests(path) + # infer_positive_tests(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3be76a3d14..84d2d94d7a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1061,7 +1061,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con assign_vaccination_state(world, start_date_sim); restart_timer(timer, "time taken for assigning vaccination state"); set_local_parameters(world); - // add_testing_strategies(world, true, true); + add_testing_strategies(world, true, false); } struct LogInfectionStatePerAgeGroup : mio::LogAlways { From 9bc99cdd7c78dc0f189d7b0046712d36f29bf247 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 16 Jul 2024 15:36:32 +0200 Subject: [PATCH 196/488] deleted old files Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- .../memilio/epidata/analyze_bs_run.py | 106 ---- .../memilio/epidata/check_bs_data.py | 547 ------------------ 2 files changed, 653 deletions(-) delete mode 100644 pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py delete mode 100644 pycode/memilio-epidata/memilio/epidata/check_bs_data.py diff --git a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py b/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py deleted file mode 100644 index 965a937276..0000000000 --- a/pycode/memilio-epidata/memilio/epidata/analyze_bs_run.py +++ /dev/null @@ -1,106 +0,0 @@ -# Python script to analyze bs runs -# input is a bs run folder with the following structure: -# bs_run_folder has a txt file for each bs run -# each txt file has a line for each time step -# each line has a column for each compartment as well as the timestep -# each column has the number of individuals in that compartment -# the first line of each txt file is the header - -import sys -import argparse -import os -import pandas as pd -import numpy as np -import matplotlib.pyplot as plt -import matplotlib -import matplotlib.colors as colors -import matplotlib.cm as cmx -import matplotlib.patches as mpatches -import matplotlib.lines as mlines -from mpm_plotter import read_from_terminal, plot_populations - -def main(n_runs): - # read in folder and convert txt files to numpy arrays - # folder path - folder_path = "memilio/epidata/folder_run_bs" - - # get first_file in folder - first_file = os.listdir(folder_path)[0] - file_path = os.path.join(folder_path, first_file) - # read in txt file - df = pd.read_csv(file_path, delim_whitespace=True) - # convert to numpy array - df_np = df.to_numpy() - # get the number of rows and columns - num_rows = df_np.shape[0] - num_cols = df_np.shape[1] - # get the number of compartments - num_compartments = num_cols - 1 - # get the number of time steps - num_time_steps = num_rows-1 - # get the compartment names - compartment_names = df.columns[1:] - # get the time steps - time_steps = df_np[:, 0] - - # get number of files in folder - num_files = len([entry for entry in os.listdir(folder_path)]) - # read in each txt file and convert to numpy array - df_np_3d = np.empty((num_rows, num_cols, n_runs)) - for (file, i) in zip(os.listdir(folder_path), range(n_runs)): - file_path = os.path.join(folder_path, file) - # read in txt file - df = pd.read_csv(file_path, delim_whitespace=True) - if file.startswith("infection_per_location_type"): - plot_infection_per_location_type(df) - if file.startswith("infection_per_age_group"): - plot_infection_per_age_group(df) - if file.startswith("run_"): - # convert to numpy array - df_np = df.to_numpy() - # attach to array - df_np_3d[:, :, i] = df_np - plot_mean_and_std(df_np_3d) - - -def plot_infection_per_location_type(df): - df.plot(x='Time', y=['Home', 'Work', 'School', 'SocialEvent', 'BasicsShop', 'Hospital', - 'ICU', 'Car', 'PublicTransport', 'TransportWithoutContact', 'Cemetery'], figsize=(10, 6)) - plt.show() - - -def plot_infection_per_age_group(df): - df.plot(x='Time', y=['0_to_4', '5_to_14', '15_to_34', - '35_to_59', '60_to_79', '80_plus'], figsize=(10, 6)) - plt.show() - - -def plot_mean_and_std(Y): - - x_plot = Y[:, 0, 0] - compartments = Y[:,1:,1:] - # average value - compartments_avg = np.mean(compartments,axis=2) - #plot average - for i in range(compartments_avg.shape[1]): - plt.plot(x_plot,compartments_avg[:,i]) - - #plt.plot(x_plot,compartments_avg) - #legend - plt.legend(['S', 'E', 'I_NS', 'I_Sy', 'I_Sev', 'I_Crit', 'R', 'D']) - plt.show() - # standard deviation - # compartments_std = np.std(compartments,axis=2) - # plt.plot(x_plot,compartments_avg + compartments_std) - # plt.plot(x_plot,compartments_avg - compartments_std) - # plt.show() - - -if __name__ == "__main__": - if (len(sys.argv) > 1): - n_runs = sys.argv[1] - else: - folder_path = "memilio/epidata/folder_run_bs" - n_runs = len([entry for entry in os.listdir(folder_path) - if os.path.isfile(os.path.join(folder_path, entry))]) - main(n_runs) diff --git a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py b/pycode/memilio-epidata/memilio/epidata/check_bs_data.py deleted file mode 100644 index 8dbcf183b5..0000000000 --- a/pycode/memilio-epidata/memilio/epidata/check_bs_data.py +++ /dev/null @@ -1,547 +0,0 @@ -import pandas as pd -import matplotlib -matplotlib.use('TkAgg') -import matplotlib.pyplot as plt -import seaborn as sns -import numpy as np -import os - -import sys -if sys.version_info[0] == 3: - import tkinter as tk -else: - import Tkinter as tk - - -####### minimal sanity check on data ####### -bd = pd.read_csv(r'/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/pycode/memilio-epidata/memilio/epidata/bs_und_umgebung.csv', header=None, skiprows=1) - -# setup dictionary for the leisure activities, and vehicle choice and column names -# bd.rename( -# columns={0: 'idTrafficZone', 1: 'tripID', 2: 'personID', 3: 'tripChain', 4: 'startZone', 5: 'destZone', 6: 'loc_id_start', 7: 'loc_id_end', -# 8: 'countyStart', 9: 'countyEnd', 10: 'hhID', 11: 'tripChainID', 12: 'tripDistance', 13: 'startTime', 14: 'travelTime', 19: 'vehicleChoice', 20: -# 'ActivityBefore', 21: 'ActivityAfter', 15: 'loCs', 16: 'laCs', 17: 'loCe', 18: 'laCe', 22: 'age'}, -# inplace=True) -bd.rename( - columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', - 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', 10: 'travelTime' , 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', 16: - 'ActivityBefore', 17: 'ActivityAfter', 18: 'age'}, - inplace=True) - -dict_leisure = {1: 'work', 2: 'education', 3: 'Shopping', 4: 'free time', - 5: 'private matters', 6: 'others', 7: 'home', 0: 'not specified'} -dict_vehicle = {1: 'bicyle', 2: 'car_driver', - 3: 'car_codriver', 4: 'public transport', 5: 'walk'} - -# # check if people do the same trip more than once -# trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime']] -# duplicate_trips = trips.duplicated() -# if (duplicate_trips.any()): -# print('Error: The Person does the "same" trip more than once (or dos 2 things in 5 mins). Number of duplicate trips: ' + str(duplicate_trips[duplicate_trips==True].size)) -# # if (~bd[['tripID']].duplicated().any()): -# # print('There are no duplicate TripIDs. There are multiple TripIDs for the same Trip. \n') -# activities_after_duplicate_trips = bd[['personID', 'loc_id_start', 'loc_id_end', 'startTime', 'ActivityAfter']].loc[trips.duplicated(keep=False)] -# if (~activities_after_duplicate_trips.duplicated(keep=False).all()): -# print('Error: Multiple activities after the same trip. \n') - -# # check if persons have more than one home -# person_homes = bd[['personID', 'loc_id_end', 'ActivityAfter']].loc[bd['ActivityAfter']==7] -# person_homes = person_homes.drop_duplicates().groupby(['personID']).size().reset_index(name='counts') -# person_homes.drop(person_homes.loc[person_homes['counts']<2].index, inplace=True) -# if(person_homes.size > 0): -# print('Error: There are people that have more than one home. \n') - -# # check if the proportion of single-person-households is too high -# households = bd[['personID', 'hhID']].drop_duplicates().groupby(['hhID']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) - -# # check if the proportion of single-person-households is too high -# if (households.loc[households['counts']==1]['counts'].size)/(households['counts'].size) > 0.5: -# print("Error: The proportion of single-person-households is too high: " + -# str((households.loc[households['counts']==1]['counts'].size)/(households['counts'].size))) - -# # check if there are invalid entries -# # if not bd['idTrafficZone'].ge(30000000).all(): -# # print('Error: There is an entry in "tripID" that is not assignable. \n') -# # # number of entries that are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripID'].ge(30000000)].size) + '. \n') -# if not bd['personID'].ge(100000000).all(): -# print('Error: There is an entry in "personID" that is not assignable. \n') -# # number of entries that are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['personID'].ge(100000000)].size) + '. \n') -# # if not bd['tripChain'].between(1, 100).all(): -# # print('Error: There is an entry in "tripChain" that is not assignable. \n') -# # # number of entries that are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['tripChain'].between(1, 100)].size) + '. \n') -# # # max assigned value -# # print('Max assigned value: ' + str(bd['tripChain'].max()) + '. \n') -# # if not bd['countyStart'].ge(30000000).all(): -# # print('Error: There is an entry in "countyStart" that is not assignable. \n') -# # # which ones are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyStart'].ge(30000000)].size) + '. \n') -# # if not bd['countyEnd'].ge(30000000).all(): -# # print('Error: There is an entry in "countyEnd" that is not assignable. \n') -# # # which ones are not assignable -# # print('Number of entries that are not assignable: ' + str(bd.loc[~bd['countyEnd'].ge(30000000)].size) + '. \n') -# # if not bd['hhID'].ge(100000000).all(): -# # print('Error: There is an entry in "hhID" that is not assignable. \n') -# # if not bd['tripChainID'].between(-1, -1).all(): -# # print('Error: There is an entry in "tripChainID" that is not assignable. \n') -# if not bd['vehicleChoice'].between(1, 5).all(): -# print('Error: There is an entry in "vehicleChoice" that is not assignable. \n') -# #print number of entries that are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['vehicleChoice'].between(1, 5)].size) + '. \n') -# if not bd['ActivityAfter'].between(0, 7).all(): -# print('Error: There is an entry in "ActivityAfter" that is not assignable. \n') -# #print number of entries that are not assignable -# print('Number of entries that are not assignable: ' + str(bd.loc[~bd['ActivityAfter'].between(0, 7)].size) + '. \n') - -# # check if there are empty cells -# for header in bd.columns: -# if (bd[header].isna().any()): -# print('Error: ' + str(len(bd[bd[header].isna()])) + ' empty entries in column' + str(header) + '. \n') - -# # check age groups with schools -# number_of_people = bd[['personID']].drop_duplicates().size -# print(str(number_of_people) + ' are people. \n') - -# # number_of_trips = bd[['tripID']].drop_duplicates().size -# # print(str(number_of_trips) + ' trips. \n') - - -# students = bd[['personID', 'loc_id_end', 'age']].loc[bd['ActivityAfter']==2] -# print('Minimal age of people going to school: ' + str(students['age'].min()) + '. Maximal age of people going to school: ' + str(students['age'].max()) + '.\n') -# print(str(students.loc[students['age'] > 20].size) + ' trips of ' + str(students.size) + ' trips going to school are in a higher age group than 10. \n') - -# children = bd[['personID','ActivityAfter']].loc[(bd['age']<=16) & (bd['age']>=7)] -# number_of_children = children['personID'].drop_duplicates().size -# number_of_children_school = children[children['ActivityAfter'] == 2]['personID'].drop_duplicates().size -# print(str(number_of_children - number_of_children_school) + ' of ' + str(number_of_children) + ' children do not go to school. \n') - - -# workers = bd[['personID','ActivityAfter']].loc[(bd['age']>30)] -# number_of_workers = workers['personID'].drop_duplicates().size -# number_of_workers_work = workers[workers['ActivityAfter'] == 1]['personID'].drop_duplicates().size -# print(str(number_of_workers - number_of_workers_work) + ' of ' + str(number_of_workers) + ' workers do not go to work. \n') - - - -# ############################################### - - -# ####### visual check on values in data frame ####### - -# # def get_trip_chain_activity_after(person_id): -# # bd_persons_trip_chain_activity_after = bd.loc[bd['personID'] == person_id, [ -# # 'tripChain', 'ActivityAfter']] -# # bd_persons_trip_chain_activity_after = bd_persons_trip_chain_activity_after.sort_values( -# # by=['tripChain'], ascending=True, ignore_index=True) -# # bd_persons_trip_chain_activity_after['ActivityAfter'] = bd_persons_trip_chain_activity_after['ActivityAfter'].map( -# # dict_leisure) -# # # and vehicle choice -# # bd_persons_trip_chain_vehicle_choice = bd.loc[bd['personID'] == person_id, [ -# # 'tripChain', 'vehicleChoice']] -# # bd_persons_trip_chain_vehicle_choice = bd_persons_trip_chain_vehicle_choice.sort_values( -# # by=['tripChain'], ascending=True, ignore_index=True) -# # bd_persons_trip_chain_vehicle_choice['vehicleChoice'] = bd_persons_trip_chain_vehicle_choice['vehicleChoice'].map( -# # dict_vehicle) -# # return bd_persons_trip_chain_activity_after, bd_persons_trip_chain_vehicle_choice - - -# # read in the data -# if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'figs_bs_data')): -# os.makedirs(os.path.join(os.path.dirname( -# os.path.abspath(__file__)), 'figs_bs_data')) -# figs_path = os.path.join(os.path.dirname( -# os.path.abspath(__file__)), 'figs_bs_data') - -# # check whether first start location is the last end location -# first_trip = bd[['personID','loc_id_start']].drop_duplicates(subset=['personID'], keep='first').reset_index(drop=True) -# last_trip = bd[['personID', 'loc_id_end']].drop_duplicates(subset=['personID'], keep='last').reset_index(drop=True) -# print("Number of persons where first start location is home: " + str(first_trip.loc[first_trip['loc_id_start']==-1]['loc_id_start'].size)+ ".") -# print("Number of persons where last end location is home: " + str(last_trip.loc[last_trip['loc_id_end']==-1]['loc_id_end'].size)+ ".") - -# # check what persons are doing which only do one trip -# # location_types = last_trip.groupby(['ActivityAfter']).size() - -# # location_types.plot(kind='bar') -# # plt.xlabel('Activity') -# # plt.ylabel('Number of persons') -# # plt.savefig(os.path.join(figs_path, 'last_activity_of_day.png'), dpi=300) - -# # probably the traffic zones that are in braunschweig because in idTrafficzones the people of bs are located -# # bd_tz_bs = bd.groupby(['idTrafficZone']).size().reset_index( -# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# # # Count traffic zones where person is residing and longitude and latuitude of this in "EPSG:3035" format -# # bd_traffic_zones_persons = bd.groupby(['idTrafficZone']).size().reset_index( -# # name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# # for row in bd_traffic_zones_persons.iterrows(): -# # bd_traffic_zones_persons.loc[row[0], ['longitude', 'latitude'] -# # ] = bd.loc[bd_traffic_zones_persons.loc[row[0], 'idTrafficZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] -# # print(bd_traffic_zones_persons) - -# #### Counting people #### -# bd_persons = bd.groupby(['personID']).size().reset_index( -# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# # Get the frequency of each number in the 'numbers' column -# bd_personss = bd_persons['counts'].value_counts().sort_index() -# # Plot the frequency of each number -# bd_personss.plot(kind='bar') -# plt.xlabel('Number of trips per day') -# plt.ylabel('Number of persons') -# plt.title('Number of trips per person tripcount (Braunschweig)') -# plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) - -# bd_persons_ages = bd[['personID', 'age']].drop_duplicates() -# bd_persons_ages['AgeCohort'] = pd.cut(bd_persons_ages['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ -# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -# bd_persons_ages_cohorts = bd_persons_ages.groupby( -# ['AgeCohort']).size().reset_index(name='counts') -# bd_persons_ages_cohorts.index = bd_persons_ages_cohorts['AgeCohort'].to_list() -# bd_persons_ages_cohorts.plot.bar(figsize=( -# 10, 7), title='Age distribution', xlabel='Age cohorts', ylabel='Number of persons', legend=None) -# plt.savefig(os.path.join(figs_path, 'age_distribution.png'), dpi=300) - -# # get the id with the persons with the highest number and print them -# # [id_person_max_trips, id_person_max_1_trips] = [ -# # bd_persons['personID'][0], bd_persons['personID'][1]] -# # print(get_trip_chain_activity_after(id_person_max_trips)) - -# # select internal and external trips (from/to Braunschweig) -# # bd_persons_inside_bs = bd.loc[bd['startZone'].isin( -# # bd_tz_bs['idTrafficZone']) & bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] -# # bd_persons_outside_bs = bd.loc[~bd['startZone'].isin( -# # bd_tz_bs['idTrafficZone']) & ~bd['destZone'].isin(bd_tz_bs['idTrafficZone'])] - -# # check how many trips are in the same traffic zone -# bd_taz_start = bd.groupby('startZone').size().reset_index(name='counts') -# #bd_same_taz = bd.loc[bd['startZone'] == bd['destZone']] -# bd_different_taz = bd.loc[bd['startZone'] != bd['destZone']] -# #bd_same_taz = bd_same_taz.groupby(['startZone']).size().reset_index(name='counts') -# bd_different_taz = bd_different_taz.groupby( -# ['startZone']).size().reset_index(name='counts') -# #bd_same_taz['percentage'] = bd_same_taz['counts']/bd_taz_start['counts'] -# bd_different_taz['complement_counts'] = bd_taz_start['counts'] - \ -# bd_different_taz['counts'] -# bd_different_taz['total_counts'] = bd_taz_start['counts'] -# bd_different_taz = (bd_different_taz.sort_values( -# by='total_counts', ascending=False, ignore_index=True)) -# plt.figure() -# plt.plot(bd_different_taz['counts']) -# plt.plot(bd_different_taz['complement_counts']) -# plt.legend(['different TAZ', 'same TAZ']) -# plt.xlabel('Traffic analysis zones') -# plt.ylabel('Amount of trips inside/outside a TAZ') -# plt.savefig(os.path.join(figs_path, 'TAZ_distribution.png'), dpi=300) - -# # which age takes which mode of transport -# bd_persons_age_vehicle_choice = bd.loc[:, ['personID', 'age', 'vehicleChoice']].sort_values( -# by=['age'], ascending=True, ignore_index=True) -# bd_persons_age_vehicle_choice['vehicleChoice'] = bd_persons_age_vehicle_choice['vehicleChoice'].map( -# dict_vehicle) -# # accumulate the number of trips per age and vehicle choice -# bd_persons_age_vehicle_choice = bd_persons_age_vehicle_choice.groupby( -# ['age', 'vehicleChoice']).size().reset_index( -# name='counts').sort_values( -# by=['age'], -# ascending=True, ignore_index=True) -# # assign each age to an age cohort -# bd_persons_age_vehicle_choice['ageCohort'] = pd.cut(bd_persons_age_vehicle_choice['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ -# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -# # plot a cake chart for each age cohort -# bd_persons_age_vehicle_choice_cake = bd_persons_age_vehicle_choice.groupby( -# ['ageCohort', 'vehicleChoice']).sum().reset_index() -# bd_persons_age_vehicle_choice_cake_age_veh = bd_persons_age_vehicle_choice_cake.pivot( -# index='ageCohort', columns='vehicleChoice', values='counts') -# bd_persons_age_vehicle_choice_cake_age_veh.plot.pie(subplots=True, layout=(3, 2), figsize=( -# 10, 10), title=bd_persons_age_vehicle_choice_cake_age_veh.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'vehicle_choice_per_age.png'), dpi=300) - -# # switch age cohort and vehicle choice -# bd_persons_age_vehicle_choice_cake_veh_age = bd_persons_age_vehicle_choice_cake.pivot( -# index='vehicleChoice', columns='ageCohort', values='counts') -# bd_persons_age_vehicle_choice_cake_veh_age.plot.pie(subplots=True, layout=(3, 3), figsize=( -# 20, 10), title=bd_persons_age_vehicle_choice_cake_veh_age.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'vehicle_choice_reversed.png'), dpi=300) - -# # Analyse trip purposes per age cohort -# bd_persons_age_purpose = bd.loc[:, ['personID', 'age', 'ActivityAfter']] -# bd_persons_age_purpose['ActivityAfter'] = bd_persons_age_purpose['ActivityAfter'].map( -# dict_leisure) -# bd_persons_age_purpose['ageCohort'] = pd.cut(bd_persons_age_purpose['age'], bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 105], labels=[ -# '0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86+',]) -# bd_persons_age_purpose_acc = bd_persons_age_purpose.groupby( -# ['ActivityAfter', 'ageCohort']).size().reset_index(name='counts') -# bd_persons_age_purpose_cake = bd_persons_age_purpose_acc.pivot( -# index='ageCohort', columns='ActivityAfter', values='counts') -# bd_persons_age_purpose_cake.plot.pie(subplots=True, layout=(2, 4), figsize=( -# 15, 5), title=bd_persons_age_purpose_cake.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'trip_purpose.png'), dpi=300) - -# # switch age cohorts and purpose -# bd_persons_age_purpose_cake_reversed = bd_persons_age_purpose_acc.pivot( -# index='ActivityAfter', columns='ageCohort', values='counts') -# bd_persons_age_purpose_cake_reversed.plot.pie(subplots=True, layout=(2, 5), figsize=( -# 15, 5), title=bd_persons_age_purpose_cake_reversed.columns.to_list(), legend=False, ylabel='') -# plt.savefig(os.path.join(figs_path, 'trip_purpose_reversed.png'), dpi=300) - -# # Count traffic zones where people are starting their trips -# bd_traffic_zones_start = bd.groupby(['startZone']).size().reset_index( -# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# for row in bd_traffic_zones_start.iterrows(): -# bd_traffic_zones_start.loc[row[0], ['longitude', 'latitude'] -# ] = bd.loc[bd_traffic_zones_start.loc[row[0], 'startZone'] == bd['startZone'], ['loCs', 'laCs']].values[0] -# print(bd_traffic_zones_start) - -# # plot longitude and latitude of traffic zones -# bd_traffic_zones_start.plot( -# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_start['counts'] / 100, figsize=(10, 15), -# title='Traffic zones where people are starting their trips (Braunschweig)') -# plt.savefig(os.path.join(figs_path, 'traffic_zones_start.png'), dpi=300) - -# # Count traffic zones where people are going and leaving -# bd_traffic_zones_end = bd.groupby(['destZone']).size().reset_index( -# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) -# for row in bd_traffic_zones_end.iterrows(): -# bd_traffic_zones_end.loc[row[0], ['longitude', 'latitude'] -# ] = bd.loc[bd_traffic_zones_end.loc[row[0], 'destZone'] == bd['destZone'], ['loCs', 'laCs']].values[0] -# print(bd_traffic_zones_end) - -# # plot longitude and latitude of traffic zones -# bd_traffic_zones_end.plot( -# kind='scatter', x='longitude', y='latitude', s=bd_traffic_zones_end['counts'] / 100, figsize=(10, 10), -# title='Traffic zones where people are ending their trips (Braunschweig)') -# plt.savefig(os.path.join(figs_path, 'traffic_zones_end.png'), dpi=300) - -# # Time analyzing -# # Time of day -# bd_time = bd.groupby(['startTime']).size().reset_index(name='counts') -# print(bd_time) -# bd_time.plot(kind='line', x='startTime', y='counts') -# plt.xlabel('Time of day') -# plt.ylabel('Number of trips') -# plt.title('Time of day (Braunschweig)' + ' (n = ' + str(len(bd)) + ' trips)') -# plt.savefig(os.path.join(figs_path, 'time_of_day.png'), dpi=300) - -# # time of day rolling average -# bd_time['rolling_mean'] = bd_time['counts'].rolling(window=7).mean() -# bd_time.plot(kind='line', x='startTime', y='rolling_mean') -# plt.xlabel('Time of day') -# plt.ylabel('Number of trips') -# plt.title('Time of day (Braunschweig)' + ' (n = ' + -# str(len(bd)) + ' trips), rolling mean with window size 7') -# plt.savefig(os.path.join(figs_path, 'time_of_day_rolling.png'), dpi=300) - -# # Frequency matrix of trips between traffic zones -# matrix_freq = pd.crosstab(bd['startZone'], bd['destZone']) -# nnz_matrix_freq = np.count_nonzero(matrix_freq) -# subset_matrix_freq = matrix_freq.iloc[0:30, 0:30] -# nnz_sub_matrix_freq = np.count_nonzero(subset_matrix_freq) -# sns.heatmap(subset_matrix_freq, cmap="Blues", vmin=0) -# plt.xlabel('Destination traffic zone') -# plt.ylabel('Start traffic zone') -# plt.title('Number of non-zero entries in frequency matrix: ' + str(nnz_sub_matrix_freq) + ' out of ' + str(subset_matrix_freq.size) + ' entries (' + -# str(round(nnz_sub_matrix_freq / subset_matrix_freq.size * 100, 2)) + '%)') -# plt.savefig(os.path.join(figs_path, 'heatmap.png'), dpi=300) - -# # frequency matrix of trips from which leisure activity to which leisure activity - -# # check if all activities of bd activity before are in the dictionary -# if bd['ActivityBefore'].isin(dict_leisure.keys()).all(): -# print('All activities in dictionary') -# # check if there is a activity missing that is in the dictionary -# if not set(dict_leisure.keys()).issubset(set(bd['ActivityBefore'].unique())): -# print('There is an activity missing that is in the dictionary:') -# for key in (set(dict_leisure.keys()).difference(set(bd['ActivityBefore'].unique()))): -# print(key, dict_leisure[key]) - - -# matrix_frqu_leisure = pd.crosstab( -# bd['ActivityBefore'], -# bd['ActivityAfter'], -# normalize='index') -# sns.heatmap(matrix_frqu_leisure, vmin=0, xticklabels=dict_leisure.values(), -# yticklabels=dict_leisure.values()) -# plt.xlabel('Leisure activity after trip') -# plt.ylabel('Leisure activity before trip') -# plt.title('Frequency of trips from which leisure activity to which leisure activity') -# plt.savefig(os.path.join(figs_path, 'heatmap_leisure.png'), dpi=300) - - -# # quick check if a data point in the matrix is correct -# check = bd.loc[(bd['startZone'] == 31010011) & ( -# bd['destZone'] == 31010011), 'startZone'].count() - - -# # plotting the duration of trips -# fig, axs = plt.subplots(2) -# axs[0].hist(bd['travelTime']/60/60, bins=100, -# range=(0, max(bd['travelTime'])*1.2/60/60)) -# axs[0].set_title('Trip duration (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips)') -# axs[0].set_xlabel('Trip duration in hours') -# axs[0].set_ylabel('Number of trips') -# axs[1].hist(bd['travelTime']/60/60, bins=100, -# range=(0, max(bd['travelTime'])*1.2/60/60)) -# axs[1].set_yscale('log') -# axs[1].set_title('Trip duration (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips) log scale') -# axs[1].set_xlabel('Trip duration in hours') -# axs[1].set_ylabel('Number of trips') - -# # same thing with the distance of the trips -# fig2, axs2 = plt.subplots(2) -# axs2[0].hist(bd['tripDistance'], bins=100, -# range=(0, max(bd['tripDistance'])*1.2,)) -# axs2[0].set_title('Trip distance (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips)') -# axs2[0].set_xlabel('Trip distance in Kilometers') -# axs2[0].set_ylabel('Number of trips') -# axs2[1].hist(bd['tripDistance'], bins=100, -# range=(0, max(bd['tripDistance'])*1.2,)) -# axs2[1].set_yscale('log') -# axs2[1].set_title('Trip distance (Braunschweig)' + -# ' (n = ' + str(len(bd)) + ' trips) log scale') -# axs2[1].set_xlabel('Trip distance in Kilometers') -# axs2[1].set_ylabel('Number of trips') - - -# # analyze age distribution with age cohorts -# bd_persons_id_and_age = bd[['personID', 'age']].drop_duplicates() -# bd_age_cohorts = pd.cut( -# bd_persons_id_and_age['age'], -# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95, 106], -# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95', '96-105']).reset_index( -# name='age_cohort').groupby( -# ['age_cohort']).size().reset_index( -# name='counts') -# bd_age_cohorts.plot(kind='bar', x='age_cohort', y='counts') -# plt.xlabel('Age cohort') -# plt.ylabel('Number of persons') -# plt.title('Age distribution of persons in Braunschweig in age cohorts, number ') -# plt.savefig(os.path.join(figs_path, 'age_cohorts.png'), dpi=300) - -# # relation between age and trip duration in minutes and hours -# bd_age_duration = bd.groupby(['age']).mean().reset_index() -# bd_age_duration['travelTime'] = bd_age_duration['travelTime'] / 60 -# bd_age_duration.plot(kind='bar', x='age', y='travelTime') - -# # also do this for trip distance -# bd_age_distance = bd.groupby(['age']).mean().reset_index() -# bd_age_distance.plot(kind='bar', x='age', y='tripDistance') - -# # analyze trip distance in distance cohort -# bd_trip_distance_cohorts = pd.cut( -# bd['tripDistance'], -# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], -# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( -# name='trip_distance_cohort').groupby( -# ['trip_distance_cohort']).size().reset_index( -# name='counts') -# bd_trip_distance_cohorts.plot(kind='bar', x='trip_distance_cohort', y='counts') -# plt.xlabel('Trip distance cohort in km') -# plt.ylabel('Number of trips') -# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + str(len(bd))) -# plt.savefig(os.path.join(figs_path, 'trip_distance_cohorts.png'), dpi=300) - -# # pie diagram of trip distance cohorts for each age cohort -# bd_trip_distance_cohorts_vehicle = pd.cut( -# bd['tripDistance'], -# bins=[-1, 1, 2, 5, 10, 20, 50, 423789798324], -# labels=['0-1', '1-2', '2-5', '5-10', '10-20', '20-50', '50+']).reset_index( -# name='trip_distance_cohort') -# bd_age_cohorts = pd.cut(bd['age'], -# bins=[-1, 18, 25, 35, 45, 55, 65, 75, 85, 95], -# labels=['0-18', '19-25', '26-35', '36-45', '46-55', '56-65', '66-75', '76-85', '86-95']).reset_index( -# name='age_cohort') -# # attach the age cohort to the dataframe -# bd_trip_distance_cohorts_vehicle = pd.concat( -# [bd_trip_distance_cohorts_vehicle['trip_distance_cohort'], bd_age_cohorts['age_cohort']], axis=1) -# # group by age cohort and distance cohort -# bd_trip_distance_cohorts_vehicle = bd_trip_distance_cohorts_vehicle.groupby( -# ['trip_distance_cohort', 'age_cohort']).size().reset_index(name='counts') -# # plot a pie chart for each age cohort -# for age_cohort in bd_trip_distance_cohorts_vehicle['age_cohort'].unique(): -# bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort].plot( -# kind='pie', y='counts', labels=bd_trip_distance_cohorts_vehicle[bd_trip_distance_cohorts_vehicle['age_cohort'] == age_cohort]['trip_distance_cohort'], autopct='%1.1f%%', startangle=90) -# plt.title('Trip distance distribution in Braunschweig in trip distance cohorts, in km. Number of trips: ' + -# str(len(bd)) + ' for age cohort ' + age_cohort) -# plt.savefig(os.path.join( -# figs_path, 'trip_distance_cohorts_' + age_cohort + '.png'), dpi=300) - -# # now the same for trip duration vs vehicle type -# bd_trip_duration_cohorts_vehicle = pd.cut( -# bd['travelTime'], -# bins=[-1, 500, 1000, 5000, 10000, 423789798324], -# labels=['0-500', '500-1000', '1000-5000', '5000-10000', '10000+']).reset_index( -# name='trip_duration_cohort') -# bd_vehicle_type = bd['vehicleChoice'].reset_index(name='vehicleChoice') -# # attach the age cohort to the dataframe -# bd_trip_duration_cohorts_vehicle = pd.concat( -# [bd_trip_duration_cohorts_vehicle['trip_duration_cohort'], bd_vehicle_type['vehicleChoice']], axis=1) -# # group by age cohort and distance cohort -# bd_trip_duration_cohorts_vehicle = bd_trip_duration_cohorts_vehicle.groupby( -# ['trip_duration_cohort', 'vehicleChoice']).size().reset_index(name='counts') -# # plot a pie chart for each age cohort -# for vehicle_type in bd_trip_duration_cohorts_vehicle['vehicleChoice'].unique(): -# bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type].plot( -# kind='pie', y='counts', labels=bd_trip_duration_cohorts_vehicle[bd_trip_duration_cohorts_vehicle['vehicleChoice'] == vehicle_type]['trip_duration_cohort'], autopct='%1.1f%%', startangle=90) -# plt.title('Trip duration distribution in Braunschweig in trip duration cohorts, in minutes. Number of trips: ' + str(len(bd) -# ) + ' for vehicle type ' + str(dict_vehicle[vehicle_type])) -# plt.savefig(os.path.join(figs_path, 'trip_duration_cohorts_' + -# str(dict_vehicle[vehicle_type]) + '.png'), dpi=300) - - -# # also do a scatter plot of trip duration and trip distance with a regression line -# bd_age_distance.plot(kind='scatter', x='age', y='tripDistance') -# plt.plot(np.unique(bd_age_distance['age']), np.poly1d(np.polyfit(bd_age_distance['age'], -# bd_age_distance['tripDistance'], 1))(np.unique(bd_age_distance['age']))) -# bd_age_duration.plot(kind='scatter', x='age', y='travelTime') -# plt.plot(np.unique(bd_age_duration['age']), np.poly1d(np.polyfit( -# bd_age_duration['age'], bd_age_duration['travelTime'], 1))(np.unique(bd_age_duration['age']))) -# plt.show() - -# ### draft to compute number of locations of type 6? -# x = bd[bd.ActivityAfter==6].loc[:, 'loc_id_end'].nunique() -# # downscaling of locations of type 6 to 2000 agents -# x / (bd['personID'].nunique()/2000) - -# x = 42 - - - - -## draft to add collumn to check if the location in Braunschweig -bd['home_in_bs'] = 0 -#list of persons who are in braunschweig -list_person_in_bs = np.array([]) -for index, row in bd.iterrows(): - if((row['countyStart']==3101 and row['ActivityBefore'] == 7) or (row['countyEnd']==3101 and row['ActivityAfter'] == 7)): - list_person_in_bs = np.append(list_person_in_bs, row['personID']) -#drop duplicates -list_person_in_bs = np.unique(list_person_in_bs) -for index, row in bd.iterrows(): - if row['personID'] in list_person_in_bs: - bd.at[index, 'home_in_bs'] = 1 - - -bd.to_csv('modified_braunschweig_result.csv', index=False) - -#count number of trips which are in braunschweig -# bs_trip_count = 0 -# for index, row in bd.iterrows(): -# if ((row['countyStart']==3101) or (row['countyEnd']==3101 )): -# bs_trip_count = bs_trip_count+1 - -# #percentage of trips in braunschweigx -# bs_trip_count/len(bd)*100 - -# count how many persons are in braunschweig -bs_person_count = 0 -# collapse all persons to one trip and check if the trip is in braunschweig -persons_in_bs = bd[['personID', 'home_in_bs']].drop_duplicates().groupby(['personID']).aggregate('sum').reset_index() -# percentage number of persons in braunschweig is persons with not zero home_in_bs / all persons -persons_in_bs.loc[persons_in_bs['home_in_bs']==0].size/persons_in_bs.size*100 - - - -x=1 From 0f190ed6d577329220fe514443986122cdaeeb70 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:57:49 +0200 Subject: [PATCH 197/488] change some things Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index aa746824e6..1630182189 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -59,18 +59,9 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): for i in states_plot: #rolling average - plt.plot(x, gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24*3, min_periods=1).sum(), sigma=15), color=color_plot[i]) + plt.plot(x, gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24, min_periods=1).sum(), sigma=15), color=color_plot[i]) plt.legend(legend_plot) - - for i in states_plot: - y50_smoothed= gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24*3).sum(), sigma=15).flatten() - y25_smoothed= gaussian_filter1d(pd.DataFrame(y25[:, i]).rolling(24*3).sum(), sigma=15).flatten() - y75_smoothed= gaussian_filter1d(pd.DataFrame(y75[:, i]).rolling(24*3).sum(), sigma=15).flatten() - # plt.fill_between(x, y50_smoothed, y25_smoothed , - # alpha=0.5, color=color_plot[i]) - # plt.fill_between(x, y50_smoothed, y75_smoothed, - # alpha=0.5, color=color_plot[i]) #currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') @@ -294,7 +285,7 @@ def plot_icu(path): # we need just every 24th value total_50 = total_50[::24] # we just take the first 90 days - total_50 = total_50[0:90]*0.3 + total_50 = total_50[0:90]*0.4 # we calculate the RMSE rmse_ICU=np.sqrt(((df_abb['ICU'][0:90] - total_50[:,5])**2).mean()) @@ -510,7 +501,7 @@ def infer_positive_tests(path): if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) plot_infections_loc_types_avarage(path) - # plot_icu(path+"/..") + plot_icu(path+"/..") plot_dead(path) # plot_tests(path+"/..") - # infer_positive_tests(path) + infer_positive_tests(path) From 32e0c02c86b2f51f31f26e099e7594834c4072c0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 17 Jul 2024 22:58:09 +0200 Subject: [PATCH 198/488] change some things in paper abm cpp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 84d2d94d7a..9e55b28944 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -620,7 +620,7 @@ void set_parameters(mio::abm::Parameters& params) //Set testing parameters auto pcr_test_values = mio::abm::TestParameters{0.9, 0.99}; auto antigen_test_values = mio::abm::TestParameters{0.8, 0.95}; - auto generic_test_values = mio::abm::TestParameters{0.7, 0.9}; + auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; params.get()[mio::abm::TestType::Generic] = generic_test_values; @@ -658,7 +658,7 @@ void set_parameters(mio::abm::Parameters& params) // Set infection parameters - params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; + // params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -1061,7 +1061,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con assign_vaccination_state(world, start_date_sim); restart_timer(timer, "time taken for assigning vaccination state"); set_local_parameters(world); - add_testing_strategies(world, true, false); + // add_testing_strategies(world, true, false); } struct LogInfectionStatePerAgeGroup : mio::LogAlways { @@ -1647,16 +1647,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // // 4. Dampings for schools and Basic shops for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.6); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), - 0.6); // from 2021-04-12 till 2021-05-30 (end) + 0.5); // from 2021-04-12 till 2021-05-30 (end) } if (location.get_type() == mio::abm::LocationType::BasicsShop) { location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.4); // from 2021-03-15 } if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.65); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 } } @@ -1686,11 +1686,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(15, 0); + location.set_capacity(10, 0); } if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(7, 0); + location.set_capacity(5, 0); } } @@ -1718,7 +1718,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s historyInfectionPerLocationType); restart_timer(timer, "till advance 37 (eastern ends)"); - double seasonality_april = 0.85; + double seasonality_april = 0.95; sim.get_world().parameters.get() = normal_infection_viral_shed * seasonality_april; double eastern_bonus = 4.0; @@ -1753,20 +1753,20 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.get_world().parameters.get() = normal_infection_viral_shed * seasonality_may; - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(false); - } - } restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(false); + } + } for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.get_infection_parameters().set(2); + location.set_capacity(5, 0); } //50% of big social events get reopened and capacity will be limited to xx int number_of_big_social_events = (int)(0.5 * social_event_location_ids_big.size()); @@ -1774,7 +1774,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { - location.get_infection_parameters().set(10); + location.set_capacity(10, 0); } } } From dc556d6d6bcaa2279cae73797ef0ccc5535a7ef4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 21 Jul 2024 22:59:27 +0200 Subject: [PATCH 199/488] refactor: Update positive test inference logic and remove unused code Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 44 ++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 1630182189..7322284c71 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -435,13 +435,27 @@ def infer_positive_tests(path): total_50 = total_50[::24] total_50 = total_50[0:90] - # we need the real positive tests - # real world - f_real = h5py.File( - path + "/Results_rki.h5", 'r') - real_bs = f_real['3101'] - total_real = real_bs['Total'][()] - total_real = total_real[0:90] + # # we need the real positive tests + # # real world + # f_real = h5py.File( + # path + "/Results_rki.h5", 'r') + # real_bs = f_real['3101'] + # total_real = real_bs['Total'][()] + # total_real = total_real[0:90] + + # we need the real data from the json file cases_all_county_age_repdate_ma7.json + df_abb = pd.read_json(path+"/../pydata/Germany/cases_infected_county_repdate_ma7.json") + # we just need the columns cases and date + df_abb = df_abb[['Date','Confirmed', 'ID_County']] + # we need just the dates bewteen 2021-03-01 and 2021-06-01 + df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] + # we just need the cases with id 3101 + df_abb = df_abb[df_abb['ID_County'] == 3101] + # we just take the first 90 days + df_abb = df_abb[0:90] + # we need the amount of new positive tests each day insetad of cumulative + df_abb['Confirmed'] = df_abb['Confirmed'].diff() + # we take a fraction from each compartment and fit this to the positive tests # we take the symptomatic persons @@ -449,9 +463,9 @@ def infer_positive_tests(path): # we take the asymptomatic persons asympt_persons = total_50[:,2]+total_50[:,1]+total_50[:,0] # we assume r_sns = 20 so symptomatic persons are 20 times more likely to test themselves - r_sns = 40 + r_sns = 20 # we say the likelyhood to test yourself is 0.8 for symptomatic persons and therefore 0.04 for asymptomatic persons - lt_sympt = 0.3 + lt_sympt = 0.08 lt_asympt = lt_sympt/r_sns sensitivity = 0.6 specificity = 0.99 @@ -475,14 +489,14 @@ def infer_positive_tests(path): ax.plot(xx, inferred_positive_tests_sympt, color='tab:red') ax.plot(xx, inferred_positive_tests_asympt, color='tab:blue') ax.plot(xx, inferred_positive_tests_asympt+inferred_positive_tests_sympt, color='tab:green') - ax.plot(xx, total_real[:,1], color='tab:orange') + ax.plot(xx, df_abb['Confirmed'], color='tab:orange') ax.set_xlabel('time (days)') ax.set_ylabel('Number of positive tests') ax.title.set_text('Inferred positive tests') ax.legend(['Symptomatic persons','Asymptomatic persons','Symptomatic and Asymptomatic persons','Real positive tests']) # we also write the rmse - rmse_sympt=np.sqrt(((total_real[:,1] - (inferred_positive_tests_sympt+inferred_positive_tests_asympt))**2).mean()) + rmse_sympt=np.sqrt(((df_abb['Confirmed'] - (inferred_positive_tests_sympt+inferred_positive_tests_asympt))**2).mean()) ax.text(0.25, 0.8, 'RMSE: '+str( float("{:.2f}".format(rmse_sympt))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) plt.show() @@ -500,8 +514,8 @@ def infer_positive_tests(path): n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) - plot_infections_loc_types_avarage(path) - plot_icu(path+"/..") - plot_dead(path) + # plot_infections_loc_types_avarage(path) + # plot_icu(path+"/..") + # plot_dead(path) # plot_tests(path+"/..") - infer_positive_tests(path) + # infer_positive_tests(path) From c9bf4ad2bc63bcac5a2c1f91687655d8e43e8930 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 22 Jul 2024 11:31:28 +0200 Subject: [PATCH 200/488] Change virus parameters to new findings --- cpp/models/abm/simulation.h | 4 + cpp/models/abm/virus_variant.h | 2 +- cpp/simulations/analyze_bs_run.py | 379 ++++++++++--------- cpp/simulations/generate_graph_from_data.cpp | 16 +- cpp/simulations/paper_abm_bs_testing.cpp | 71 ++-- 5 files changed, 257 insertions(+), 215 deletions(-) diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index 6349cb2a61..0a0cd97491 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -71,9 +71,13 @@ class Simulation while (m_t < tmax) { evolve_world(tmax); double start, end; + #ifdef MEMILIO_ENABLE_OPENMP start = omp_get_wtime(); + #endif (history.log(*this), ...); + #ifdef MEMILIO_ENABLE_OPENMP end = omp_get_wtime(); + #endif sum = sum + (end - start); } std::cout << "Time spent on logging: " << sum << std::endl; diff --git a/cpp/models/abm/virus_variant.h b/cpp/models/abm/virus_variant.h index 080cde1fbd..8c4a6e011b 100644 --- a/cpp/models/abm/virus_variant.h +++ b/cpp/models/abm/virus_variant.h @@ -37,7 +37,7 @@ namespace abm enum class VirusVariant : std::uint32_t { Wildtype = 0, - + Alpha = 1, Count // last!! }; diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 7322284c71..e0bfce35bd 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -46,7 +46,8 @@ def plot_infections_loc_types_avarage(path): plot_infection_per_location_type_mean( time, total_50, total_25, total_75) - + + def plot_infection_per_location_type_mean(x, y50, y25, y75): plt.figure('Infection_states_location_types') @@ -54,29 +55,31 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): color_plot = matplotlib.colormaps.get_cmap('Set1').colors - states_plot = [0,1,2,3,4] - legend_plot = ['Home', 'School', 'Work', 'SocialEvent', 'BasicsShop', 'Hospital', 'ICU'] + states_plot = [0, 1, 2, 3, 4] + legend_plot = ['Home', 'School', 'Work', + 'SocialEvent', 'BasicsShop', 'Hospital', 'ICU'] for i in states_plot: - #rolling average - plt.plot(x, gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling(24, min_periods=1).sum(), sigma=15), color=color_plot[i]) + # rolling average + plt.plot(x, gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling( + 24, min_periods=1).sum(), sigma=15), color=color_plot[i]) plt.legend(legend_plot) - - #currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates + + # currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') xx = [start_date + pd.Timedelta(days=int(i)) for i in x] xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - #but just take every 10th date to make it more readable + # but just take every 10th date to make it more readable plt.gca().set_xticks(x[::150]) plt.gca().set_xticklabels(xx[::150]) plt.gcf().autofmt_xdate() - plt.xlabel('Time') plt.ylabel('Number of individuals') plt.show() + def plot_infectoin_states_results(path): # 50-percentile f_p50 = h5py.File( @@ -101,12 +104,12 @@ def plot_infectoin_states_results(path): path + "/Results_rki.h5", 'r') real_bs = f_real['3101'] total_real = real_bs['Total'][()] - plot_infection_states_individual( time, p50_bs, p25_bs, p75_bs, real_bs) plot_infection_states(time, total_50, total_25, total_75, total_real) + def plot_infection_states(x, y50, y25, y75, y_real=None): plt.figure('Infection_states') plt.title('Infection states') @@ -114,15 +117,16 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): color_plot = matplotlib.colormaps.get_cmap('Set1').colors states_plot = [1, 2, 3, 4, 5, 7] - legend_plot = ['E', 'I_NSymp', 'I_Symp', 'I_Sev', 'I_Crit', 'Dead', 'Sm. re. pos.'] + legend_plot = ['E', 'I_NSymp', 'I_Symp', + 'I_Sev', 'I_Crit', 'Dead', 'Sm. re. pos.'] for i in states_plot: plt.plot(x, y50[:, i], color=color_plot[i]) - #plot real data for comparison, symptomatic and infected daily + # plot real data for comparison, symptomatic and infected daily if y_real is not None: x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) - plt.plot(x_real, y_real[:,1], '.', color='tab:blue') + plt.plot(x_real, y_real[:, 1], '.', color='tab:blue') plt.legend(legend_plot) @@ -131,33 +135,32 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): alpha=0.5, color=color_plot[i]) plt.fill_between(x, y50[:, i], y75[:, i], alpha=0.5, color=color_plot[i]) - - - #currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates + + # currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') xx = [start_date + pd.Timedelta(days=int(i)) for i in x] xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - #but just take every 10th date to make it more readable + # but just take every 10th date to make it more readable plt.gca().set_xticks(x[::150]) plt.gca().set_xticklabels(xx[::150]) plt.gcf().autofmt_xdate() - plt.xlabel('Time') plt.ylabel('Number of individuals') plt.show() - + def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y_real_total = real_bs['Total'][()] x_real = np.linspace(0, y_real_total.shape[0]-1, y_real_total.shape[0]) - age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] + age_group_access = ['Group1', 'Group2', 'Group3', + 'Group4', 'Group5', 'Group6', 'Total'] color_plot = matplotlib.colormaps.get_cmap('Set1').colors - fig, ax = plt.subplots(5, len(age_group_access), constrained_layout = True) + fig, ax = plt.subplots(5, len(age_group_access), constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) for j, count in zip(age_group_access, range(len(age_group_access))): @@ -166,67 +169,86 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y75 = p75_bs[j][()] y_real = real_bs[j][()] - #infeced no symptoms + # infeced no symptoms ax_infected_no_symptoms = ax[0, count] ax_infected_no_symptoms.set_xlabel('time (days)') - ax_infected_no_symptoms.plot(x, y50[:, 1], color=color_plot[count], label='y50') - ax_infected_no_symptoms.plot(x_real, y_real[:, 3], '.', color=color_plot[count], label='y_real') - ax_infected_no_symptoms.fill_between(x, y50[:, 1], y25[:, 1], alpha=0.5, color=color_plot[count]) - ax_infected_no_symptoms.fill_between(x, y50[:, 1], y75[:, 1], alpha=0.5, color=color_plot[count]) + ax_infected_no_symptoms.plot( + x, y50[:, 1], color=color_plot[count], label='y50') + ax_infected_no_symptoms.plot( + x_real, y_real[:, 3], '.', color=color_plot[count], label='y_real') + ax_infected_no_symptoms.fill_between( + x, y50[:, 1], y25[:, 1], alpha=0.5, color=color_plot[count]) + ax_infected_no_symptoms.fill_between( + x, y50[:, 1], y75[:, 1], alpha=0.5, color=color_plot[count]) ax_infected_no_symptoms.tick_params(axis='y') - ax_infected_no_symptoms.title.set_text('Infected_no_symptoms, Age{}'.format(j)) - ax_infected_no_symptoms.legend(['Simulation','Real']) + ax_infected_no_symptoms.title.set_text( + 'Infected_no_symptoms, Age{}'.format(j)) + ax_infected_no_symptoms.legend(['Simulation', 'Real']) - #Infected_symptoms + # Infected_symptoms ax_infected_symptoms = ax[1, count] ax_infected_symptoms.set_xlabel('time (days)') - ax_infected_symptoms.plot(x, y50[:, 2], color=color_plot[count], label='y50') - ax_infected_symptoms.plot(x_real, y_real[:, 4], '.', color=color_plot[count], label='y_real') - ax_infected_symptoms.fill_between(x, y50[:, 2], y25[:, 2], alpha=0.5, color=color_plot[count]) - ax_infected_symptoms.fill_between(x, y50[:, 2], y75[:, 2], alpha=0.5, color=color_plot[count]) + ax_infected_symptoms.plot( + x, y50[:, 2], color=color_plot[count], label='y50') + ax_infected_symptoms.plot( + x_real, y_real[:, 4], '.', color=color_plot[count], label='y_real') + ax_infected_symptoms.fill_between( + x, y50[:, 2], y25[:, 2], alpha=0.5, color=color_plot[count]) + ax_infected_symptoms.fill_between( + x, y50[:, 2], y75[:, 2], alpha=0.5, color=color_plot[count]) ax_infected_symptoms.tick_params(axis='y') - ax_infected_symptoms.title.set_text('Infected_symptoms, Age{}'.format(j)) - ax_infected_symptoms.legend(['Simulation','Real']) - + ax_infected_symptoms.title.set_text( + 'Infected_symptoms, Age{}'.format(j)) + ax_infected_symptoms.legend(['Simulation', 'Real']) + # Severe ax_severe = ax[2, count] ax_severe.set_xlabel('time (days)') ax_severe.plot(x, y50[:, 4], color=color_plot[count], label='y50') - ax_severe.plot(x_real, y_real[:, 6], '.', color=color_plot[count], label='y_real') - ax_severe.fill_between(x, y50[:, 4], y25[:, 4], alpha=0.5, color=color_plot[count]) - ax_severe.fill_between(x, y50[:, 4], y75[:, 4], alpha=0.5, color=color_plot[count]) + ax_severe.plot(x_real, y_real[:, 6], '.', + color=color_plot[count], label='y_real') + ax_severe.fill_between( + x, y50[:, 4], y25[:, 4], alpha=0.5, color=color_plot[count]) + ax_severe.fill_between( + x, y50[:, 4], y75[:, 4], alpha=0.5, color=color_plot[count]) ax_severe.tick_params(axis='y') ax_severe.title.set_text('Severe, Age{}'.format(j)) - ax_severe.legend(['Simulation','Real']) + ax_severe.legend(['Simulation', 'Real']) # Critical ax_critical = ax[3, count] ax_critical.set_xlabel('time (days)') ax_critical.plot(x, y50[:, [5]], color=color_plot[count], label='y50') - ax_critical.plot(x_real, y_real[:, [7]], '.', color=color_plot[count], label='y_real') - ax_critical.fill_between(x, y50[:, 5], y25[:, 5], alpha=0.5, color=color_plot[count]) - ax_critical.fill_between(x, y50[:, 5], y75[:, 5], alpha=0.5, color=color_plot[count]) + ax_critical.plot( + x_real, y_real[:, [7]], '.', color=color_plot[count], label='y_real') + ax_critical.fill_between( + x, y50[:, 5], y25[:, 5], alpha=0.5, color=color_plot[count]) + ax_critical.fill_between( + x, y50[:, 5], y75[:, 5], alpha=0.5, color=color_plot[count]) ax_critical.tick_params(axis='y') ax_critical.title.set_text('Critical, Age{}'.format(j)) - ax_critical.legend(['Simulation','Real']) + ax_critical.legend(['Simulation', 'Real']) # Dead ax_dead = ax[4, count] ax_dead.set_xlabel('time (days)') ax_dead.plot(x, y50[:, [7]], color=color_plot[count], label='y50') - ax_dead.plot(x_real, y_real[:, [9]], '.', color=color_plot[count], label='y_real') - ax_dead.fill_between(x, y50[:, 7], y25[:, 7], alpha=0.5, color=color_plot[count]) - ax_dead.fill_between(x, y50[:, 7], y75[:, 7], alpha=0.5, color=color_plot[count]) + ax_dead.plot(x_real, y_real[:, [9]], '.', + color=color_plot[count], label='y_real') + ax_dead.fill_between(x, y50[:, 7], y25[:, 7], + alpha=0.5, color=color_plot[count]) + ax_dead.fill_between(x, y50[:, 7], y75[:, 7], + alpha=0.5, color=color_plot[count]) ax_dead.tick_params(axis='y') ax_dead.title.set_text('Dead, Age{}'.format(j)) - ax_dead.legend(['Simulation','Real']) - - #fig.tight_layout() # otherwise the right y-label is slightly clipped + ax_dead.legend(['Simulation', 'Real']) + + # fig.tight_layout() # otherwise the right y-label is slightly clipped plt.show() def plot_dead(path): - #we will have a seperate plot the cumulative infected individuals, cumulative symptomatic individuals and cumulative dead individual + # we will have a seperate plot the cumulative infected individuals, cumulative symptomatic individuals and cumulative dead individual # we need to load the data f_p50 = h5py.File( path+"/infection_state_per_age_group/p50/Results.h5", 'r') @@ -246,36 +268,37 @@ def plot_dead(path): y_real = y_real[0:90] # we calculate the RMSE - rmse_dead=np.sqrt(((y_real[:,9] - total_50[:,7])**2).mean()) - + rmse_dead = np.sqrt(((y_real[:, 9] - total_50[:, 7])**2).mean()) # we plot this - fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig, ax = plt.subplots(1, 1, constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) # we plot the tests positive and the real cases start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - ax.plot(xx, total_50[:,7], color='tab:red') - ax.plot(xx, y_real[:,9], color='tab:blue') + ax.plot(xx, total_50[:, 7], color='tab:red') + ax.plot(xx, y_real[:, 9], color='tab:blue') # we also write the rmse - ax.text(0.25, 0.8, 'RMSE: '+str( float("{:.2f}".format(rmse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_dead))), horizontalalignment='center', + verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) ax.set_xlabel('time (days)') ax.set_ylabel('Number of dead') ax.title.set_text('Dead') - ax.legend(['Dead','Real dead']) + ax.legend(['Dead', 'Real dead']) plt.show() - + def plot_icu(path): df_abb = pd.read_json(path+"/pydata/Germany/county_divi_ma7.json") # we just need the columns ICU_low and ICU_hig - df_abb = df_abb[['ID_County','ICU', 'Date']] + df_abb = df_abb[['ID_County', 'ICU', 'Date']] - df_abb= df_abb[df_abb['ID_County'] == 3101] + df_abb = df_abb[df_abb['ID_County'] == 3101] # we need just the dates bewteen 2021-03-01 and 2021-06-01 - df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] + df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & + (df_abb['Date'] <= '2021-06-01')] # we plot this against this the Amount of persons in the ICU from our model f_p50 = h5py.File( @@ -288,26 +311,29 @@ def plot_icu(path): total_50 = total_50[0:90]*0.4 # we calculate the RMSE - rmse_ICU=np.sqrt(((df_abb['ICU'][0:90] - total_50[:,5])**2).mean()) + rmse_ICU = np.sqrt(((df_abb['ICU'][0:90] - total_50[:, 5])**2).mean()) # plot the ICU beds and the ICU beds taken - fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig, ax = plt.subplots(1, 1, constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) # we plot the ICU_low and the ICU_high ax.plot(df_abb['Date'][0:90], df_abb['ICU'][0:90], color='tab:blue') - ax.plot(df_abb['Date'][0:90], total_50[:,5], color='tab:red') + ax.plot(df_abb['Date'][0:90], total_50[:, 5], color='tab:red') # we also write the rmse - ax.text(0.25, 0.8, 'RMSE: '+str( float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', + verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) ax.set_xlabel('time (days)') ax.set_ylabel('Number of ICU beds') ax.title.set_text('ICU beds and ICU beds taken') - ax.legend(['ICU beds','ICU beds taken']) + ax.legend(['ICU beds', 'ICU beds taken']) plt.show() + def plot_tests(path): - df_abb = pd.read_excel(path+"/pydata/Germany/SARS-CoV-2-PCR-Testungen_in_Deutschland.xlsx") + df_abb = pd.read_excel( + path+"/pydata/Germany/SARS-CoV-2-PCR-Testungen_in_Deutschland.xlsx") # in the week row the format is YYYY-WX where X is the week number and Y is the year number # We need the week number and the year number and just take 2021-W9 to 2021-W21 # we just Take the rows where YYYY is 2021 and X is between 9 and 21 @@ -317,13 +343,16 @@ def plot_tests(path): df_abb['Week'] = df_abb['Week'].astype(int) df_abb['Year'] = df_abb['Year'].astype(int) # we just take the rows where the year is 2021 and the week is between 9 and 21 - df_abb = df_abb[(df_abb['Year'] == 2021) & (df_abb['Week'] >= 9) & (df_abb['Week'] <= 21)] - # We just need the columns tests total, tests accumulated, tests positive - df_abb = df_abb[['date','tests_total', 'tests_total_accumulated', 'tests_positive','tests_positive_accumulated','tests_positive_ratio']]# + df_abb = df_abb[(df_abb['Year'] == 2021) & ( + df_abb['Week'] >= 9) & (df_abb['Week'] <= 21)] + # We just need the columns tests total, tests accumulated, tests positive + df_abb = df_abb[['date', 'tests_total', 'tests_total_accumulated', + 'tests_positive', 'tests_positive_accumulated', 'tests_positive_ratio']] # we assumethe tests get distributed over the week, so we divide the tests by 7 for each day, but we also need to infer the amount of tests in brunswick # as brunswick has around 250.000 persons, we take the 250.000/80.000.000 = 1/320 of the tests - df_abb[['tests_total', 'tests_total_accumulated', 'tests_positive','tests_positive_accumulated']] = df_abb[['tests_total', 'tests_total_accumulated', 'tests_positive','tests_positive_accumulated']]/320 - + df_abb[['tests_total', 'tests_total_accumulated', 'tests_positive', 'tests_positive_accumulated']] = df_abb[[ + 'tests_total', 'tests_total_accumulated', 'tests_positive', 'tests_positive_accumulated']]/320 + # we model this the following way # we know the amount of people who PCR test themselves positive and in general the amount of people who test themselves positive # as well as the amount of people who test themselves through other means @@ -331,7 +360,7 @@ def plot_tests(path): # the majority of people who are asymptomatic (I_NSymp) will not test themselves (8%) # and there is an amount of recently infected, which test themselves netherless (1%) - # first thing we can do, is that we PCR test an amount of + # first thing we can do, is that we PCR test an amount of # we divide the persons into 2 groups: asymptomatic and symptomatic # we assume that the symptomatic persons will test themselves with an x time higher probability than the asymptomatic persons @@ -361,8 +390,8 @@ def plot_tests(path): xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - #plot these - fig, ax = plt.subplots(1, 1, constrained_layout = True) + # plot these + fig, ax = plt.subplots(1, 1, constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) # we plot the tests positive and the real cases @@ -373,25 +402,29 @@ def plot_tests(path): # The amount of persons, who do tests on a day is: PCR_tests_symptomatic = np.zeros(90) PCR_tests_asymptomatic = np.zeros(90) - PCR_tests_symptomatic = PCR_tests * (1/(1+(1/ratio_testing_symptomatic_vs_asymptomatic))) + PCR_tests_symptomatic = PCR_tests * \ + (1/(1+(1/ratio_testing_symptomatic_vs_asymptomatic))) PCR_tests_asymptomatic = PCR_tests - PCR_tests_symptomatic # the real amount of positive tested persons is: - #likelihood of being poisiitve is (E+I_NSymp)/(S+E+I_NSymp) - lik_being_positive_asymptomatic = (total_50[:,1]+total_50[:,2])/(total_50[:,0]+total_50[:,1]+total_50[:,2]) + # likelihood of being poisiitve is (E+I_NSymp)/(S+E+I_NSymp) + lik_being_positive_asymptomatic = ( + total_50[:, 1]+total_50[:, 2])/(total_50[:, 0]+total_50[:, 1]+total_50[:, 2]) - tests_positive = (lik_being_positive_asymptomatic*PCR_tests_asymptomatic)+PCR_tests_symptomatic + tests_positive = (lik_being_positive_asymptomatic * + PCR_tests_asymptomatic)+PCR_tests_symptomatic # we need to plot this ax.plot(xx, tests_positive, color='tab:green') ax.set_ylabel('Number of tests') - ax.title.set_text('Tests positive PCR and real confirmedcases from any source') - ax.legend(['Tests','Tests positive','Tests positive inferred']) + ax.title.set_text( + 'Tests positive PCR and real confirmedcases from any source') + ax.legend(['Tests', 'Tests positive', 'Tests positive inferred']) plt.show() # new plot which is showing the amount of symptomatic persons - sympt_persons = total_50[:,3]+total_50[:,4]+total_50[:,5] + sympt_persons = total_50[:, 3]+total_50[:, 4]+total_50[:, 5] # we plot this - fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig, ax = plt.subplots(1, 1, constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) # we plot the tests positive and the real cases @@ -403,10 +436,10 @@ def plot_tests(path): plt.show() # also the amount of asymptomatic persons with the amount of persons infected - asympt_persons = total_50[:,2]+total_50[:,1]+total_50[:,0] - asympt_positive = total_50[:,2]+total_50[:,1] + asympt_persons = total_50[:, 2]+total_50[:, 1]+total_50[:, 0] + asympt_positive = total_50[:, 2]+total_50[:, 1] # we plot this - fig, ax = plt.subplots(1, 1, constrained_layout = True) + fig, ax = plt.subplots(1, 1, constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) # we plot the tests positive and the real cases @@ -415,96 +448,102 @@ def plot_tests(path): ax.set_xlabel('time (days)') ax.set_ylabel('Number of asymptomatic persons') ax.title.set_text('Asymptomatic persons') - ax.legend(['Asymptomatic persons','Asymptomatic persons positive']) + ax.legend(['Asymptomatic persons', 'Asymptomatic persons positive']) plt.show() def infer_positive_tests(path): - # First way: we just take x amount of eahc compartment and fit this to the positive tested category. - # A few assumptions: - # 1. The specificities of the tests are 99.9% this means that we have 0.1% false positives. We just assme, that nonsymptomatics test themselves very rarely, e.g. we just take a fraction of symptomatic persons. - # 2. We just have a around 60% sensitivity, this means that we have 40% false negatives. - # 3. We assume that it is way more likely to test yourself if you are symptomatic than if you are asymptomatic - - - # we need every compartment of the model - f_p50 = h5py.File( - path+"/infection_state_per_age_group/p50/Results.h5", 'r') - p50_bs = f_p50['0'] - total_50 = p50_bs['Total'][()] - total_50 = total_50[::24] - total_50 = total_50[0:90] - - # # we need the real positive tests - # # real world - # f_real = h5py.File( - # path + "/Results_rki.h5", 'r') - # real_bs = f_real['3101'] - # total_real = real_bs['Total'][()] - # total_real = total_real[0:90] - - # we need the real data from the json file cases_all_county_age_repdate_ma7.json - df_abb = pd.read_json(path+"/../pydata/Germany/cases_infected_county_repdate_ma7.json") - # we just need the columns cases and date - df_abb = df_abb[['Date','Confirmed', 'ID_County']] - # we need just the dates bewteen 2021-03-01 and 2021-06-01 - df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] - # we just need the cases with id 3101 - df_abb = df_abb[df_abb['ID_County'] == 3101] - # we just take the first 90 days - df_abb = df_abb[0:90] - # we need the amount of new positive tests each day insetad of cumulative - df_abb['Confirmed'] = df_abb['Confirmed'].diff() - - - # we take a fraction from each compartment and fit this to the positive tests - # we take the symptomatic persons - sympt_persons = total_50[:,3]+total_50[:,4]+total_50[:,5] - # we take the asymptomatic persons - asympt_persons = total_50[:,2]+total_50[:,1]+total_50[:,0] - # we assume r_sns = 20 so symptomatic persons are 20 times more likely to test themselves - r_sns = 20 - # we say the likelyhood to test yourself is 0.8 for symptomatic persons and therefore 0.04 for asymptomatic persons - lt_sympt = 0.08 - lt_asympt = lt_sympt/r_sns - sensitivity = 0.6 - specificity = 0.99 - - # therefore the amount of pisitive tests is: - # symptomatic persons - inferred_positive_tests_sympt = (total_50[:,3]*lt_sympt+total_50[:,4]*lt_sympt+total_50[:,5]*lt_sympt)*sensitivity - # asymptomatic persons - inferred_positive_tests_asympt = (total_50[:,0]*lt_asympt)*(1-specificity)+((total_50[:,1]+total_50[:,2])*lt_asympt)*sensitivity - - # we save the assumed tests done - assumed__amount_of_test = (total_50[:,3]*lt_sympt+total_50[:,4]*lt_sympt+total_50[:,5]*lt_sympt)+(total_50[:,0]*lt_asympt)+(total_50[:,1]+total_50[:,2])*lt_asympt - # we plot this - fig, ax = plt.subplots(1, 1, constrained_layout = True) - fig.set_figwidth(20) - fig.set_figheight(9) - # we plot the tests positive and the real cases - start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') - xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] - xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - ax.plot(xx, inferred_positive_tests_sympt, color='tab:red') - ax.plot(xx, inferred_positive_tests_asympt, color='tab:blue') - ax.plot(xx, inferred_positive_tests_asympt+inferred_positive_tests_sympt, color='tab:green') - ax.plot(xx, df_abb['Confirmed'], color='tab:orange') - ax.set_xlabel('time (days)') - ax.set_ylabel('Number of positive tests') - ax.title.set_text('Inferred positive tests') - ax.legend(['Symptomatic persons','Asymptomatic persons','Symptomatic and Asymptomatic persons','Real positive tests']) - - # we also write the rmse - rmse_sympt=np.sqrt(((df_abb['Confirmed'] - (inferred_positive_tests_sympt+inferred_positive_tests_asympt))**2).mean()) - ax.text(0.25, 0.8, 'RMSE: '+str( float("{:.2f}".format(rmse_sympt))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) - plt.show() + # First way: we just take x amount of eahc compartment and fit this to the positive tested category. + # A few assumptions: + # 1. The specificities of the tests are 99.9% this means that we have 0.1% false positives. We just assme, that nonsymptomatics test themselves very rarely, e.g. we just take a fraction of symptomatic persons. + # 2. We just have a around 60% sensitivity, this means that we have 40% false negatives. + # 3. We assume that it is way more likely to test yourself if you are symptomatic than if you are asymptomatic + # we need every compartment of the model + f_p50 = h5py.File( + path+"/infection_state_per_age_group/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + total_50 = total_50[::24] + total_50 = total_50[0:90] + + # # we need the real positive tests + # # real world + # f_real = h5py.File( + # path + "/Results_rki.h5", 'r') + # real_bs = f_real['3101'] + # total_real = real_bs['Total'][()] + # total_real = total_real[0:90] + + # we need the real data from the json file cases_all_county_age_repdate_ma7.json + df_abb = pd.read_json( + path+"/../pydata/Germany/cases_infected_county_repdate_ma7.json") + # we just need the columns cases and date + df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] + # we need just the dates bewteen 2021-03-01 and 2021-06-01 + df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & + (df_abb['Date'] <= '2021-06-01')] + # we just need the cases with id 3101 + df_abb = df_abb[df_abb['ID_County'] == 3101] + # we just take the first 90 days + df_abb = df_abb[0:90] + # we need the amount of new positive tests each day insetad of cumulative + df_abb['Confirmed'] = df_abb['Confirmed'].diff() + + # we take a fraction from each compartment and fit this to the positive tests + # we take the symptomatic persons + sympt_persons = total_50[:, 3]+total_50[:, 4]+total_50[:, 5] + # we take the asymptomatic persons + asympt_persons = total_50[:, 2]+total_50[:, 1]+total_50[:, 0] + # we assume r_sns = 20 so symptomatic persons are 20 times more likely to test themselves + r_sns = 20 + # we say the likelyhood to test yourself is 0.8 for symptomatic persons and therefore 0.04 for asymptomatic persons + lt_sympt = 0.08 + lt_asympt = lt_sympt/r_sns + sensitivity = 0.6 + specificity = 0.99 + + # therefore the amount of pisitive tests is: + # symptomatic persons + inferred_positive_tests_sympt = ( + total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)*sensitivity + # asymptomatic persons + inferred_positive_tests_asympt = (total_50[:, 0]*lt_asympt)*( + 1-specificity)+((total_50[:, 1]+total_50[:, 2])*lt_asympt)*sensitivity + + # we save the assumed tests done + assumed__amount_of_test = (total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)+( + total_50[:, 0]*lt_asympt)+(total_50[:, 1]+total_50[:, 2])*lt_asympt + # we plot this + fig, ax = plt.subplots(1, 1, constrained_layout=True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the tests positive and the real cases + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + ax.plot(xx, inferred_positive_tests_sympt, color='tab:red') + ax.plot(xx, inferred_positive_tests_asympt, color='tab:blue') + ax.plot(xx, inferred_positive_tests_asympt + + inferred_positive_tests_sympt, color='tab:green') + ax.plot(xx, df_abb['Confirmed'], color='tab:orange') + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of positive tests') + ax.title.set_text('Inferred positive tests') + ax.legend(['Symptomatic persons', 'Asymptomatic persons', + 'Symptomatic and Asymptomatic persons', 'Real positive tests']) + + # we also write the rmse + rmse_sympt = np.sqrt( + ((df_abb['Confirmed'] - (inferred_positive_tests_sympt+inferred_positive_tests_asympt))**2).mean()) + ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_sympt))), horizontalalignment='center', + verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + plt.show() if __name__ == "__main__": - # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + path = "/Users/david/Documents/HZI/memilio/data/results_last_run_last_run" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" @@ -518,4 +557,4 @@ def infer_positive_tests(path): # plot_icu(path+"/..") # plot_dead(path) # plot_tests(path+"/..") - # infer_positive_tests(path) + # infer_positive_tests(path) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 118cc211da..fa68f2f23a 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -134,14 +134,14 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.8}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.8}; - const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.05}; - const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.15, 0.05}; - const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; - const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; - const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; - const double deathsPerCriticalMax[] = {0.10, 0.10, 0.18, 0.18, 0.50, 0.7}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.5, 0.45, 0.4, 0.3, 0.175, 0.1}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.5, 0.45, 0.4, 0.3, 0.175, 0.1}; + const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.45, 0.55}; + const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.45, 0.55}; + const double criticalPerSevereMin[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.62}; + const double criticalPerSevereMax[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.62}; + const double deathsPerCriticalMin[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; + const double deathsPerCriticalMax[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; array_assign_uniform_distribution(params.get(), transmissionProbabilityOnContactMin, transmissionProbabilityOnContactMax); diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9e55b28944..5679809815 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -117,7 +117,7 @@ void assign_infection_state_prob(mio::abm::World& world, mio::abm::TimePoint t) rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); if (infection_state != mio::osecir::InfectionState::Susceptible) { - person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), + person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Alpha, person.get_age(), world.parameters, t, infection_state_map.at(infection_state))); } @@ -160,7 +160,7 @@ void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) world.get_rng(), 0U, persons_by_age[age_grp].size() - 1)]; mio::abm::Person& person = world.get_person(id_rnd); auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); - person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, person.get_age(), + person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Alpha, person.get_age(), world.parameters, t, infection_state_map.at(mio::osecir::InfectionState(i)))); persons_by_age[age_grp].erase( @@ -626,39 +626,37 @@ void set_parameters(mio::abm::Parameters& params) params.get()[mio::abm::TestType::Generic] = generic_test_values; // Set percentage parameters - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.5; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.55; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.6; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = - 0.65; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = - 0.65; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.8; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.02; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.08; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.30; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.55; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.08; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.12; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.22; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.45; - - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_0_to_4}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_5_to_14}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_15_to_34}] = 0.05; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_35_to_59}] = 0.10; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_60_to_79}] = 0.25; - params.get()[{mio::abm::VirusVariant::Wildtype, age_group_80_plus}] = 0.6; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.5; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.55; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.6; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.7; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.825; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.9; + + params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.03; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.03; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.04; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.17; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.45; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.55; + + params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.1; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.11; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.12; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.14; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.33; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.62; + + params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.12; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.13; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.15; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.29; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.4; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.48; // Set infection parameters - // params.get()[{mio::abm::VirusVariant::Wildtype}] = 3.5; + // params.get()[{mio::abm::VirusVariant::Alpha}] = 3.5; // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { @@ -1211,10 +1209,11 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa auto sim = mio::abm::Simulation(t0, std::move(world)); // Setup parameters for the simulation - sim.get_world().parameters.get() = grid_params[0]; - sim.get_world().parameters.get()[{mio::abm::VirusVariant::Wildtype, - age_group_80_plus}] = grid_params[1]; - sim.get_world().parameters.get() = grid_params[2]; + sim.get_world().parameters.get() = grid_params[0]; + sim.get_world() + .parameters.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = + grid_params[1]; + sim.get_world().parameters.get() = grid_params[2]; //Logger mio::History From 448c53f3b69aa979e1ffedc5b32281b4947b07bd Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 22 Jul 2024 12:42:15 +0200 Subject: [PATCH 201/488] Add logger for detected infections --- cpp/simulations/cleanup_data.py | 131 ++++++++++++----------- cpp/simulations/paper_abm_bs_testing.cpp | 46 +++++++- 2 files changed, 110 insertions(+), 67 deletions(-) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 694eced5db..3aa399b691 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -37,7 +37,7 @@ def add_external_ids(pd): start_or_end_zone = 'start_zone' start_or_end_activity = 'activity_start' found = False - if (row[start_or_end_activity] == 1): # work places + if (row[start_or_end_activity] == 1): # work places if (not row['puid'] in person_to_work_place_dict.keys()): # check if a work place is already available and not full if (row[start_or_end_zone] in work_places_dict.keys()): @@ -236,9 +236,9 @@ def add_home_ids(pd): # every row where loc_id_start or loc_id_end is -1 and activity_start or activity_end is 7 is a person who goes /comes from home # there we change the loc_id_start and loc_id_end to huid for index, row in pd.iterrows(): - if(row['loc_id_start'] == -1 and row['activity_start'] == 7): + if (row['loc_id_start'] == -1 and row['activity_start'] == 7): pd.at[index, 'loc_id_start'] = row['huid'] - if(row['loc_id_end'] == -1 and row['activity_end'] == 7): + if (row['loc_id_end'] == -1 and row['activity_end'] == 7): pd.at[index, 'loc_id_end'] = row['huid'] return pd @@ -252,12 +252,13 @@ def add_home_is_in_bs_column(pd): print("Column 'home_in_bs' is not present in DataFrame.") # add column home_in_bs pd['home_in_bs'] = 0 - #list of persons who are in braunschweig + # list of persons who are in braunschweig list_person_in_bs = np.array([]) for index, row in pd.iterrows(): - if ((row['start_county'] == 3101 and row['activity_start'] == 7) or (row['end_county'] == 3101 and row['activity_end'] == 7)): # this assumes he goes to his home, but could be another persons home + # this assumes he goes to his home, but could be another persons home + if ((row['start_county'] == 3101 and row['activity_start'] == 7) or (row['end_county'] == 3101 and row['activity_end'] == 7)): list_person_in_bs = np.append(list_person_in_bs, row['puid']) - #drop duplicates + # drop duplicates list_person_in_bs = np.unique(list_person_in_bs) for index, row in pd.iterrows(): if row['puid'] in list_person_in_bs: @@ -265,97 +266,95 @@ def add_home_is_in_bs_column(pd): return pd - - def location_type_from_keys_and_values(key, value, intention, key_value_pairs_counts_with_activity_after): - most_probable_activity = 9999 + most_probable_activity = 9999 # we need to save for each key and value pair the amount of different activityAfter values if key_value_pairs_counts_with_activity_after[(key_value_pairs_counts_with_activity_after['map_feature_key'] == key) & (key_value_pairs_counts_with_activity_after['map_feature_value'] == value)].shape[0] != 0: # get the differnt activity_after values - activity_after_values = key_value_pairs_counts_with_activity_after[(key_value_pairs_counts_with_activity_after['map_feature_key'] == key) & (key_value_pairs_counts_with_activity_after['map_feature_value'] == value)] + activity_after_values = key_value_pairs_counts_with_activity_after[(key_value_pairs_counts_with_activity_after['map_feature_key'] == key) & ( + key_value_pairs_counts_with_activity_after['map_feature_value'] == value)] # get the most common activity_after value - most_common_activity_after = activity_after_values[activity_after_values['counts'] == activity_after_values['counts'].max()]['activity_end'].values[0] + most_common_activity_after = activity_after_values[activity_after_values['counts'] + == activity_after_values['counts'].max()]['activity_end'].values[0] # if work is one of the activity_after values we assume that the location is a work location if its bigger than 30% of the total counts # see if work is in the activity_after values if activity_after_values[activity_after_values['activity_end'] == 1].shape[0] != 0: if (activity_after_values[activity_after_values['activity_end'] == 1]['counts'] > 0.3 * key_value_pairs_counts_with_activity_after[(key_value_pairs_counts_with_activity_after['map_feature_key'] == key) & (key_value_pairs_counts_with_activity_after['map_feature_value'] == value)]['counts'].sum()).values[0]: - most_common_activity_after = 1 + most_common_activity_after = 1 # map the most common activity_after value to a location type most_probable_activity = most_common_activity_after - - location_type = 'SocialEvent' if key == 'home': - location_type= 'Home' - + location_type = 'Home' + if key == 'education': - location_type= 'School' + location_type = 'School' if key == 'amenity': if value in ['fast_food', 'fuel', 'food_court']: - location_type= 'BasicsShop' - if value in ['coworking_space','office', 'craft', 'fire_station', 'hospital', 'laboratory', 'office', 'research_institute']: - location_type= 'Work' - if value in ['school', 'kindergarten', 'university', 'college','childcare', 'language_school', 'music_school', 'prep_school']: - location_type= 'School' + location_type = 'BasicsShop' + if value in ['coworking_space', 'office', 'craft', 'fire_station', 'hospital', 'laboratory', 'office', 'research_institute']: + location_type = 'Work' + if value in ['school', 'kindergarten', 'university', 'college', 'childcare', 'language_school', 'music_school', 'prep_school']: + location_type = 'School' else: - location_type= 'SocialEvent' - + location_type = 'SocialEvent' + if key == 'building': if value in ['apartments', 'bungalow', 'cabin', 'detached', 'detached_house', 'dormitory', 'double_house', 'duplex', 'dwlling_house', 'farmhouse', 'house', 'houseboat', 'nursing_home', 'residential', 'semi' 'hotel', 'house', 'residential', 'semidetached_house', 'semi_detached', 'semidetached']: - location_type= 'Home' + location_type = 'Home' if value in ['college', 'kindergarten']: - location_type= 'School' + location_type = 'School' if value in ['laboratory', "bakehouse", "bank", "barracks", "brewery", "car_repair", "car_wash", "civic", "clinic", "data_center", "embassy", "factory", "farm", "fire_station", "fuel_station", "government", "hospital", "industrial", "manufacture", "mortuary", "office", "police", "post_office", "presbytery", "prison", "public", "school", "shelter", "sports_centre", "sports_hall", "stable", "warehouse", "workshop"]: - location_type= 'Work' + location_type = 'Work' if value in ["commercial", "fuel", "kiosk", "shop", "supermarket"]: - location_type= 'BasicShop' + location_type = 'BasicShop' else: - location_type= 'SocialEvent' - + location_type = 'SocialEvent' + if key == 'craft': - location_type= 'Work' - + location_type = 'Work' + if key == 'healthcare': - location_type= 'Work' + location_type = 'Work' if key == 'historic': - location_type= 'SocialEvent' - + location_type = 'SocialEvent' + if key == 'landuse': - location_type= 'SocialEvent' + location_type = 'SocialEvent' if key == 'leisure': - location_type= 'SocialEvent' - + location_type = 'SocialEvent' + if key == 'office': - location_type= 'Work' - + location_type = 'Work' + if key == 'shop': - location_type= 'BasicShop' - + location_type = 'BasicShop' + if key == 'tourism': if value in ['apartment', 'guest_house', 'guest_house;apartment']: - location_type= 'Home' - location_type= 'SocialEvent' - + location_type = 'Home' + location_type = 'SocialEvent' + if key == 'NaN': if intention == 1: - location_type= 'Work' + location_type = 'Work' if intention == 2: - location_type= 'School' + location_type = 'School' if intention == 3: - location_type= 'BasicShop' + location_type = 'BasicShop' if intention == 4: - location_type= 'SocialEvent' + location_type = 'SocialEvent' if intention == 5: - location_type= 'BasicShop' + location_type = 'BasicShop' if intention == 6: - location_type= 'SocialEvent' + location_type = 'SocialEvent' if intention == 7: - location_type= 'Home' + location_type = 'Home' if most_probable_activity != 9999: if most_probable_activity == 1: @@ -374,9 +373,11 @@ def location_type_from_keys_and_values(key, value, intention, key_value_pairs_co location_type = 'Home' # map from location type string to int - location_type_dict = {'Home': 0, 'School': 2, 'Work': 1, 'BasicShop': 3, 'SocialEvent': 4} + location_type_dict = {'Home': 0, 'School': 2, + 'Work': 1, 'BasicShop': 3, 'SocialEvent': 4} return location_type_dict[location_type] - + + def assign_location_type(pd): if 'location_type' in pd.columns: print("Column 'location_type' is present in DataFrame.") @@ -384,28 +385,33 @@ def assign_location_type(pd): else: print("Column 'location_type' is not present in DataFrame.") pd['location_type'] = 'SocialEvent' - test_pd = pd[['activity_end', 'map_feature_key', 'map_feature_value']].groupby(['map_feature_key', 'map_feature_value','activity_end']).size().reset_index(name='counts') + test_pd = pd[['activity_end', 'map_feature_key', 'map_feature_value']].groupby( + ['map_feature_key', 'map_feature_value', 'activity_end']).size().reset_index(name='counts') for index, row in pd.iterrows(): - pd.at[index, 'location_type'] = location_type_from_keys_and_values( row['map_feature_key'], row['map_feature_value'], row['activity_end'], test_pd) + pd.at[index, 'location_type'] = location_type_from_keys_and_values( + row['map_feature_key'], row['map_feature_value'], row['activity_end'], test_pd) return pd + def add_time_if_null(pd): # if start_time is null we set it to 0 pd['start_time'] = pd['start_time'].fillna("12:30") return pd -PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8.csv" -bd = pd.read_csv(PATH) +# PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/" +PATH = "/Users/david/Documents/HZI/memilio/data/mobility/" +FILE = PATH + "braunschweig_result_ffa8.csv" +bd = pd.read_csv(FILE) # read in column headers from first line of csv file -with open(PATH, 'r') as file: +with open(FILE, 'r') as file: first_line = file.readline() column_headers = first_line.split(',') column_headers = [header.strip() for header in column_headers] # check if anythiong changed since writing this script -if(column_headers[0:21] == ['puid', 'start_zone', 'end_zone', 'loc_id_start', 'loc_id_end', 'start_county', 'end_county', 'huid', 'trip_distance', 'start_time', 'travel_time_sec', 'lon_start', 'lat_start', 'lon_end', 'lat_end', 'travel_mode', 'activity_start', 'activity_end', 'age','map_feature_key','map_feature_value']): +if (column_headers[0:21] == ['puid', 'start_zone', 'end_zone', 'loc_id_start', 'loc_id_end', 'start_county', 'end_county', 'huid', 'trip_distance', 'start_time', 'travel_time_sec', 'lon_start', 'lat_start', 'lon_end', 'lat_end', 'travel_mode', 'activity_start', 'activity_end', 'age', 'map_feature_key', 'map_feature_value']): print("Column headers are correct") else: print("Column headers are not correct") @@ -424,8 +430,9 @@ def add_time_if_null(pd): bd_new = add_time_if_null(bd_new) # we need to remove unnecessary columns -bd_new = bd_new.drop(columns= ['start_zone', 'end_zone', 'loc_id_start', 'start_county', 'end_county', 'trip_distance', 'travel_time_sec', 'lon_start', 'lat_start', 'travel_mode', 'activity_start', 'activity_end', 'map_feature_key','map_feature_value']) +bd_new = bd_new.drop(columns=['start_zone', 'end_zone', 'loc_id_start', 'start_county', 'end_county', 'trip_distance', 'travel_time_sec', + 'lon_start', 'lat_start', 'travel_mode', 'activity_start', 'activity_end', 'map_feature_key', 'map_feature_value']) # sort for better search performance bd_new = bd_new.sort_values(by=['puid', 'start_time']) # Write data back to disk -bd_new.to_csv('/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8_modified2.csv', index=False) +bd_new.to_csv(PATH + "braunschweig_result_ffa8_modified2.csv", index=False) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5679809815..42327d3fc0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -99,7 +99,7 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); - // extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days + extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days } /** @@ -1124,6 +1124,36 @@ struct LogInfectionPerLocationTypePerAgeGroup : mio::LogAlways { } }; +struct LogCumulativeDetectedInfections : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the number of Person%s in an #InfectionState. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the number of Person%s in an #InfectionState. + */ + static Type log(const mio::abm::Simulation& sim) + { + + Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); + auto curr_time = sim.get_time(); + auto prev_time = sim.get_prev_time(); + const auto persons = sim.get_world().get_persons(); + + // PRAGMA_OMP(parallel for) + for (auto i = size_t(0); i < persons.size(); ++i) { + auto& p = persons[i]; + if (p.get_should_be_logged()) { + // PRAGMA_OMP(atomic) + if (p.get_infection().is_detected()) { + uint32_t index = p.get_age().get(); + sum[index] += 1; + } + } + } + return std::make_pair(curr_time, sum); + } +}; + #ifdef MEMILIO_ENABLE_MPI template T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) @@ -1198,7 +1228,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Prepare vaccination state prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - restart_timer(timer, "time for vaccinaiton state"); + restart_timer(timer, "time for vaccination state"); // Loop over a number of runs for (size_t run_idx = 0; run_idx < num_runs; run_idx++) { @@ -1487,7 +1517,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; mio::Date start_date{2021, 3, 1}; - int max_num_days = 90; + int max_num_days = 0; auto max_num_persons = 400000; bool npis_on = true; @@ -1502,6 +1532,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>>{}; // Vector of infection state per age group results ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); + auto ensemble_cumulative_detected_infections = + std::vector>>{}; // Vector of cumulative detected infections + ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); + auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); @@ -1537,6 +1571,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyCumulativeDetectedInfections{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; // / NPIS// if (npis_on) { @@ -1887,8 +1923,8 @@ int main(int argc, char** argv) #endif // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); From 1cd254da46e01cd06894e481c70248156f1feff1 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:25:33 +0200 Subject: [PATCH 202/488] change back some variables --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 42327d3fc0..96b079c713 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -99,7 +99,7 @@ void determine_initial_infection_states_world(const fs::path& input_dir, const m auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); - extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days + // extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days } /** @@ -1517,7 +1517,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; mio::Date start_date{2021, 3, 1}; - int max_num_days = 0; + int max_num_days = 90; auto max_num_persons = 400000; bool npis_on = true; From 867da80355dd5242c7b45fb13cd2ab8431e88d59 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Wed, 24 Jul 2024 11:14:37 +0200 Subject: [PATCH 203/488] Adjust hospitalization rates --- cpp/simulations/paper_abm_bs_testing.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 96b079c713..b698c4caf6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -633,12 +633,12 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.825; params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.9; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.03; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.03; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.04; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.17; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.45; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.55; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.0180; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.0237; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.0373; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.0795; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.1664; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.2374; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.1; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.11; @@ -1136,7 +1136,6 @@ struct LogCumulativeDetectedInfections : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); auto curr_time = sim.get_time(); - auto prev_time = sim.get_prev_time(); const auto persons = sim.get_world().get_persons(); // PRAGMA_OMP(parallel for) From f6d9f34f03a5a483105bac6dccf705dfeb3d7982 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 24 Jul 2024 18:43:19 +0200 Subject: [PATCH 204/488] change some parameters Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/ode_secir/parameters_io.cpp | 7 ++- cpp/models/ode_secir/parameters_io.h | 9 +-- cpp/simulations/analyze_bs_run.py | 16 ++--- cpp/simulations/generate_graph_from_data.cpp | 19 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 65 ++++++++++++-------- 5 files changed, 65 insertions(+), 51 deletions(-) diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index 4b051b49c3..44073b410c 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -318,7 +318,7 @@ IOResult read_divi_data(const std::string& path, const std::vector& v 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()); @@ -390,7 +390,7 @@ IOResult set_population_data(std::vector& model, const std::string& } IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu) + Date date, const std::vector& scaling_factor_icu) { std::vector sum_mu_I_U(vregion.size(), 0); std::vector> mu_I_U{model.size()}; @@ -408,9 +408,10 @@ IOResult set_divi_data(std::vector& model, const std::string& path, for (size_t region = 0; region < vregion.size(); region++) { auto num_groups = model[region].parameters.get_num_groups(); + int agg = 0; 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]; + scaling_factor_icu[agg++] * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region]; } } diff --git a/cpp/models/ode_secir/parameters_io.h b/cpp/models/ode_secir/parameters_io.h index 35279228b2..989f83dcbb 100644 --- a/cpp/models/ode_secir/parameters_io.h +++ b/cpp/models/ode_secir/parameters_io.h @@ -113,7 +113,7 @@ IOResult read_divi_data(const std::string& path, const std::vector& v * @param scaling_factor_icu factor by which to scale the icu cases of divi data */ IOResult set_divi_data(std::vector& model, const std::string& path, const std::vector& vregion, - Date date, double scaling_factor_icu); + Date date, const std::vector& scaling_factor_icu); /** * @brief Reads population data from census data @@ -350,8 +350,9 @@ IOResult read_input_data_state(std::vector& model, Date date, std:: */ 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& dir, int num_days = 0, bool export_time_series = false) + const std::vector& scaling_factor_inf, + const std::vector& scaling_factor_icu, const std::string& dir, + int num_days = 0, bool export_time_series = false) { if (date > Date(2020, 4, 23)) { BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(dir, "pydata/Germany", "county_divi_ma7.json"), @@ -372,7 +373,7 @@ IOResult read_input_data_county(std::vector& model, Date date, cons 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, dir, county, date, scaling_factor_inf, scaling_factor_icu, + export_input_data_county_timeseries(model, dir, county, date, scaling_factor_inf, scaling_factor_icu[0], num_days, path_join(dir, "pydata/Germany", "county_divi_ma7.json"), path_join(dir, "pydata/Germany", "cases_all_county_age_ma7.json"), path_join(dir, "pydata/Germany", "county_current_population.json"))); diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index e0bfce35bd..e78c811c21 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -175,7 +175,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): ax_infected_no_symptoms.plot( x, y50[:, 1], color=color_plot[count], label='y50') ax_infected_no_symptoms.plot( - x_real, y_real[:, 3], '.', color=color_plot[count], label='y_real') + x_real, y_real[:, 2], '.', color=color_plot[count], label='y_real') ax_infected_no_symptoms.fill_between( x, y50[:, 1], y25[:, 1], alpha=0.5, color=color_plot[count]) ax_infected_no_symptoms.fill_between( @@ -498,7 +498,7 @@ def infer_positive_tests(path): # we assume r_sns = 20 so symptomatic persons are 20 times more likely to test themselves r_sns = 20 # we say the likelyhood to test yourself is 0.8 for symptomatic persons and therefore 0.04 for asymptomatic persons - lt_sympt = 0.08 + lt_sympt = 0.06 lt_asympt = lt_sympt/r_sns sensitivity = 0.6 specificity = 0.99 @@ -542,8 +542,8 @@ def infer_positive_tests(path): if __name__ == "__main__": - path = "/Users/david/Documents/HZI/memilio/data/results_last_run_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + # path = "/Users/david/Documents/HZI/memilio/data/results_last_run_last_run" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" @@ -553,8 +553,8 @@ def infer_positive_tests(path): n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) - # plot_infections_loc_types_avarage(path) - # plot_icu(path+"/..") - # plot_dead(path) + plot_infections_loc_types_avarage(path) + plot_icu(path+"/..") + plot_dead(path) # plot_tests(path+"/..") - # infer_positive_tests(path) + infer_positive_tests(path) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index fa68f2f23a..643528154e 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -134,12 +134,12 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.5, 0.45, 0.4, 0.3, 0.175, 0.1}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.5, 0.45, 0.4, 0.3, 0.175, 0.1}; - const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.45, 0.55}; - const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.45, 0.55}; - const double criticalPerSevereMin[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.62}; - const double criticalPerSevereMax[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.62}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; + const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.3, 0.2}; + const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.3, 0.2}; + const double criticalPerSevereMin[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; + const double criticalPerSevereMax[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; const double deathsPerCriticalMin[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; const double deathsPerCriticalMax[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; @@ -227,9 +227,10 @@ mio::IOResult> get_graph(mio::Date start_date, c for (auto& node : nodes) { node.parameters = params; } - auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 5.0); - scaling_factor_infected[5] = 2.0; - auto scaling_factor_icu = 4.8; + auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 1.5); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 0.5); + scaling_factor_icu[4] = 5.0; + scaling_factor_icu[5] = 5.0; const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b698c4caf6..d2fe886b7b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -888,27 +888,37 @@ void set_local_parameters(mio::abm::World& world) case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; loc.get_infection_parameters().get().array() *= - 0.45; // scaling due to beeing at school 1/1.8 * 100% of the time + 1.8; // scaling due to beeing at school 1/1.8 * 100% of the time + loc.get_infection_parameters().get().array() *= + 0.25; // scaling likelihood of home infection break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; loc.get_infection_parameters().get().array() *= - 4.5; // scaling due to beeing at school 1/4.8 * 100% of the time + 4.8; // scaling due to beeing at school 1/4.8 * 100% of the time + loc.get_infection_parameters().get().array() *= + 0.9375; // scaling likelihood of School infection break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; loc.get_infection_parameters().get().array() *= - 1.1; // scaling due to beeing at Work 1/3.5 * 100% of the time + 3.5; // scaling due to beeing at Work 1/3.5 * 100% of the time + loc.get_infection_parameters().get().array() *= + 0.23; // scaling likelihood of Work infection break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= - 32; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher ocntact rate + 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher ocntact rate + loc.get_infection_parameters().get().array() *= + 6.1; // scaling likelihood of SocialEvent infection break; default: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= - 4.0; // scaling due to beeing at other 1/5.2675 * 100% of the time + 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher ocntact rate + loc.get_infection_parameters().get().array() *= + 0.3; // scaling likelihood of basicshopping infection break; } } @@ -1403,7 +1413,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa } restart_timer(timer, "till advance 14"); - sim.get_world().parameters.get() = 3.0; + sim.get_world().parameters.get() = 5.5; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 14 finished" << std::endl; @@ -1687,7 +1697,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s 0.5); // from 2021-04-12 till 2021-05-30 (end) } if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.4); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 @@ -1724,12 +1734,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(5, 0); + location.set_capacity(0, 0); } } restart_timer(timer, "till advance 14"); - double normal_infection_viral_shed = 4.0; + double normal_infection_viral_shed = 6.5; sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); @@ -1740,35 +1750,33 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { location.set_capacity(5, 0); - location.get_infection_parameters().get().array() *= 0.3; + location.get_infection_parameters().get().array() *= 0.33; } if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.get_infection_parameters().get().array() *= 0.5; + location.get_infection_parameters().get().array() *= 0.33; } } restart_timer(timer, "till advance 30 (eastern starts)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(30).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); restart_timer(timer, "till advance 37 (eastern ends)"); - double seasonality_april = 0.95; + double seasonality_april = 0.9; sim.get_world().parameters.get() = normal_infection_viral_shed * seasonality_april; - double eastern_bonus = 4.0; + double eastern_bonus = 7; for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::Home || - location.get_type() == mio::abm::LocationType::BasicsShop || location.get_type() == mio::abm::LocationType::SocialEvent) { location.get_infection_parameters().get().array() *= eastern_bonus; } } - sim.advance(mio::abm::TimePoint(mio::abm::days(34).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::Home || - location.get_type() == mio::abm::LocationType::BasicsShop || location.get_type() == mio::abm::LocationType::SocialEvent) { location.get_infection_parameters().get().array() /= eastern_bonus; } @@ -1777,7 +1785,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - std::cout << "day 42 finished" << std::endl; // date 2021-04-12 + std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 + + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(false); + } + } restart_timer(timer, "till advance 60"); sim.advance(mio::abm::TimePoint(mio::abm::days(62).seconds()), historyInfectionStatePerAgeGroup, @@ -1792,22 +1806,19 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s historyInfectionPerLocationType); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(false); - } - } for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(5, 0); + location.set_capacity(2, 0); + location.get_infection_parameters().get().array() *= 0.5; } //50% of big social events get reopened and capacity will be limited to xx - int number_of_big_social_events = (int)(0.5 * social_event_location_ids_big.size()); + int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { + location.get_infection_parameters().get().array() *= 0.5; location.set_capacity(10, 0); } } @@ -1922,8 +1933,8 @@ int main(int argc, char** argv) #endif // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); From 7bec023744ea8aab55b52dc145b486b13cfee5f8 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:42:25 +0200 Subject: [PATCH 205/488] fix typos --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d2fe886b7b..9d6813a9fd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -888,7 +888,7 @@ void set_local_parameters(mio::abm::World& world) case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; loc.get_infection_parameters().get().array() *= - 1.8; // scaling due to beeing at school 1/1.8 * 100% of the time + 1.8; // scaling due to beeing at home 1/1.8 * 100% of the time loc.get_infection_parameters().get().array() *= 0.25; // scaling likelihood of home infection break; @@ -909,14 +909,14 @@ void set_local_parameters(mio::abm::World& world) case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= - 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher ocntact rate + 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher contact rate loc.get_infection_parameters().get().array() *= 6.1; // scaling likelihood of SocialEvent infection break; default: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= - 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher ocntact rate + 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher contact rate loc.get_infection_parameters().get().array() *= 0.3; // scaling likelihood of basicshopping infection break; From 50c5f26a04cd43c44e741807e2db5466f865a3db Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 26 Jul 2024 09:28:44 +0200 Subject: [PATCH 206/488] some parameter fixings --- cpp/simulations/generate_graph_from_data.cpp | 8 +- cpp/simulations/paper_abm_bs_testing.cpp | 103 ++++++++----------- 2 files changed, 49 insertions(+), 62 deletions(-) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 643528154e..f08b33000a 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -136,8 +136,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double maxRiskOfInfectionFromSymptomaticMax = 0.5; const double recoveredPerInfectedNoSymptomsMin[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; const double recoveredPerInfectedNoSymptomsMax[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; - const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.3, 0.2}; - const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.3, 0.2}; + const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.05, 0.08}; + const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.05, 0.08}; const double criticalPerSevereMin[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; const double criticalPerSevereMax[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; const double deathsPerCriticalMin[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; @@ -227,9 +227,9 @@ mio::IOResult> get_graph(mio::Date start_date, c for (auto& node : nodes) { node.parameters = params; } - auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 1.5); + auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 2.8); auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 0.5); - scaling_factor_icu[4] = 5.0; + scaling_factor_icu[4] = 30.0; scaling_factor_icu[5] = 5.0; const auto& read_function_nodes = mio::osecir::read_input_data_county; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9d6813a9fd..17c303eb78 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -661,30 +661,30 @@ void set_parameters(mio::abm::Parameters& params) // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { return mio::linear_interpolation_of_data_set( - {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); + {{0, 0.00863}, {1, 0.00969}, {7, 0.0029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); }; // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.1967}, - {30, 0.1975}, - {60, 0.1977}, - {90, 0.1974}, - {120, 0.1963}, - {150, 0.1947}, - {180, 0.193}, - {210, 0.1929}, - {240, 0.1923}, - {270, 0.1908}, - {300, 0.1893}, - {330, 0.1887}, - {360, 0.1887}, - {360, 0.15}}, + return mio::linear_interpolation_of_data_set({{0, 0.01967}, + {30, 0.01975}, + {60, 0.01977}, + {90, 0.01974}, + {120, 0.01963}, + {150, 0.01947}, + {180, 0.0193}, + {210, 0.01929}, + {240, 0.01923}, + {270, 0.01908}, + {300, 0.01893}, + {330, 0.01887}, + {360, 0.01887}, + {360, 0.015}}, days); }; //Set other parameters - params.get() = 0.33; //all masks have a 0.66 protection factor for now + params.get() = 0.5; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -884,27 +884,28 @@ void set_local_parameters(mio::abm::World& world) contacts_other[{age_group_80_plus, age_group_80_plus}] = 0.0180; for (auto& loc : world.get_locations()) { + // # we assume that a 20:4:4:1:1 ratio of contacts is made at home:school:work:SocialEv:basicshopping + // First line: Sclaing according to which Timespan the contatcs have to be made + // Second Line: Normalizing to 24 hours + // Third Line: Scaling according intensity of contacts switch (loc.get_type()) { case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; - loc.get_infection_parameters().get().array() *= - 1.8; // scaling due to beeing at home 1/1.8 * 100% of the time - loc.get_infection_parameters().get().array() *= - 0.25; // scaling likelihood of home infection + loc.get_infection_parameters().get().array() *= 1; + loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 1; break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; - loc.get_infection_parameters().get().array() *= - 4.8; // scaling due to beeing at school 1/4.8 * 100% of the time - loc.get_infection_parameters().get().array() *= - 0.9375; // scaling likelihood of School infection + loc.get_infection_parameters().get().array() *= 5; + loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 1; break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; - loc.get_infection_parameters().get().array() *= - 3.5; // scaling due to beeing at Work 1/3.5 * 100% of the time - loc.get_infection_parameters().get().array() *= - 0.23; // scaling likelihood of Work infection + loc.get_infection_parameters().get().array() *= 5; + loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 0.33; // 1/3 break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; @@ -1018,7 +1019,7 @@ std::vector> grid_points(std::vector> distribute_grid_search(int rank, int num_procs, std::vector> grid) { //Calculate how many grid points there are, assuming that each parameter has the same amount of points - int number_of_points = std::pow(grid[0].size(), grid.size()); + int number_of_points = (int)std::pow(grid[0].size(), grid.size()); //Calculate how many points each rank should calculate int points_per_rank = number_of_points / num_procs; //leftover points goes to the last rank @@ -1154,7 +1155,7 @@ struct LogCumulativeDetectedInfections : mio::LogAlways { if (p.get_should_be_logged()) { // PRAGMA_OMP(atomic) if (p.get_infection().is_detected()) { - uint32_t index = p.get_age().get(); + uint32_t index = (uint32_t)p.get_age().get(); sum[index] += 1; } } @@ -1588,21 +1589,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto location_it = sim.get_world().get_locations(); - //Spontanaeus testing at home - // auto testing_min_time_home = mio::abm::days(7); - // auto probability_home = 0.05; - // auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(0).seconds()); - // auto end_date_test_home = mio::abm::TimePoint(tmax); - // auto test_type_home = mio::abm::TestType::Antigen; // Antigen test - // auto test_parameters_home = - // sim.get_world().parameters.get()[test_type_home]; // Test parameters - // auto testing_criteria_home = mio::abm::TestingCriteria(); - // auto testing_scheme_home = - // mio::abm::TestingScheme(testing_criteria_home, testing_min_time_home, start_date_test_home, - // end_date_test_home, test_parameters_home, probability_home); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, - // testing_scheme_home); - // 1. testing schemes in schools auto testing_min_time_school = mio::abm::days(7); auto probability_school = 1.0; @@ -1694,13 +1680,14 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), - 0.5); // from 2021-04-12 till 2021-05-30 (end) + 0.5); // from 2021-04-12 till 2021-05-30 } if (location.get_type() == mio::abm::LocationType::BasicsShop) { location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 + location.get_infection_parameters().get().array() *= 0.7; } } @@ -1718,13 +1705,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } //take 50% of social event locations std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); - auto num_social_event_locations_small = (int)(0.75 * social_event_location_ids_small.size()); + auto num_social_event_locations_big = (int)(0.25 * social_event_location_ids_small.size()); social_event_location_ids_big.insert( social_event_location_ids_big.end(), social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_small); + social_event_location_ids_small.begin() + num_social_event_locations_big); social_event_location_ids_small.erase(social_event_location_ids_small.begin(), social_event_location_ids_small.begin() + - num_social_event_locations_small); + num_social_event_locations_big); // add capacity limits on day one for (auto& location : location_it) { @@ -1739,7 +1726,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } restart_timer(timer, "till advance 14"); - double normal_infection_viral_shed = 6.5; + double normal_infection_viral_shed = 3.5; sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); @@ -1750,22 +1737,22 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { location.set_capacity(5, 0); - location.get_infection_parameters().get().array() *= 0.33; + location.get_infection_parameters().get().array() *= 0.75; } if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.get_infection_parameters().get().array() *= 0.33; + location.get_infection_parameters().get().array() *= 0.75; } } restart_timer(timer, "till advance 30 (eastern starts)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(30).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); restart_timer(timer, "till advance 37 (eastern ends)"); double seasonality_april = 0.9; sim.get_world().parameters.get() = normal_infection_viral_shed * seasonality_april; - double eastern_bonus = 7; + double eastern_bonus = 5; for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::Home || location.get_type() == mio::abm::LocationType::SocialEvent) { @@ -1797,7 +1784,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.advance(mio::abm::TimePoint(mio::abm::days(62).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 62 finished (date 2021-05-01)" << std::endl; - double seasonality_may = 0.5; + double seasonality_may = 0.65; sim.get_world().parameters.get() = normal_infection_viral_shed * seasonality_may; @@ -1819,7 +1806,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s number_of_big_social_events--; if (number_of_big_social_events >= 0) { location.get_infection_parameters().get().array() *= 0.5; - location.set_capacity(10, 0); + location.set_capacity(15, 0); } } } @@ -1933,9 +1920,9 @@ int main(int argc, char** argv) #endif // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; - // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; + std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); From 1a093813b2b0e1732d8a19b1dce655c649d39a7f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 26 Jul 2024 09:30:51 +0200 Subject: [PATCH 207/488] fix some par --- cpp/simulations/paper_abm_bs_testing.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 17c303eb78..10e8d28193 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -909,17 +909,18 @@ void set_local_parameters(mio::abm::World& world) break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; - loc.get_infection_parameters().get().array() *= - 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher contact rate - loc.get_infection_parameters().get().array() *= - 6.1; // scaling likelihood of SocialEvent infection + loc.get_infection_parameters().get().array() *= 30; + loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 4; + break; + case mio::abm::LocationType::BasicsShop: + loc.get_infection_parameters().get() = contacts_other; + loc.get_infection_parameters().get().array() *= 30; + loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 0.14; // 1/7 break; default: loc.get_infection_parameters().get() = contacts_other; - loc.get_infection_parameters().get().array() *= - 5.2675; // scaling due to beeing at other 1/5.2675 * 100% of the time but a way higher contact rate - loc.get_infection_parameters().get().array() *= - 0.3; // scaling likelihood of basicshopping infection break; } } From 587fc68800c686083647340f391279db982740c0 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:48:33 +0200 Subject: [PATCH 208/488] Added flag for home trips and trips for people who dont go home --- cpp/simulations/cleanup_data.py | 26 ++++++++++++++++++++++++ cpp/simulations/paper_abm_bs_testing.cpp | 9 +++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 3aa399b691..0e7dbeff4f 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -266,6 +266,30 @@ def add_home_is_in_bs_column(pd): return pd +def add_has_home_trip_column(pd): + # check if csv file has column has_home_trip + if 'has_home_trip' in pd.columns: + print("Column 'has_home_trip' is present in DataFrame.") + # nothing tbd + else: + print("Column 'has_home_trip' is not present in DataFrame.") + # add column has_home_trip + pd['has_home_trip'] = 0 + # list of persons who are in braunschweig + list_persons_with_home_trip = np.array([]) + for index, row in pd.iterrows(): + # persons that have a home trip + if (row['activity_end'] == 7): + list_persons_with_home_trip = np.append( + list_persons_with_home_trip, row['puid']) + # drop duplicates + list_persons_with_home_trip = np.unique(list_persons_with_home_trip) + for index, row in pd.iterrows(): + if row['puid'] in list_persons_with_home_trip: + pd.at[index, 'has_home_trip'] = 1 + return pd + + def location_type_from_keys_and_values(key, value, intention, key_value_pairs_counts_with_activity_after): most_probable_activity = 9999 @@ -419,6 +443,8 @@ def add_time_if_null(pd): bd_new = add_home_is_in_bs_column(bd) print('Added flag for persons who live in Braunschweig.') +bd_new = add_has_home_trip_column(bd_new) +print('Added flag for persons who have a home trip.') bd_new = add_home_ids(bd_new) print('Home IDs set.') bd_new = add_school_ids(bd_new) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9d6813a9fd..15ecf6da44 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -536,6 +536,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (number_of_persons_read_in > max_number_persons) { break; } + + bool has_home_trip = row[index["has_home_trip"]]; } uint32_t age = row[index["age"]]; @@ -544,7 +546,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, uint32_t trip_start = row[index["start_time"]]; bool home_in_bs = row[index["home_in_bs"]]; - // Add the trip to the trip list person and location must exist at this point + // Add the trip to the trip list, person and location must exist at this point auto target_location = locations.find(target_location_id)->second; auto it_person = persons.find(person_id); if (it_person == persons.end()) { @@ -563,6 +565,11 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, } trip_vec.push_back(mio::abm::Trip(it_person->second.get_person_id(), mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location)); + if (!has_home_trip) { + trip_vec.push_back(mio::abm::Trip(it_person->second.get_person_id(), + mio::abm::TimePoint(0) + mio::abm::hours(17), locations.find(home_id)->second)); + has_home_trip = true; + } } world.get_trip_list().add_several_trips(trip_vec); } From 2a3a1cbc11dffd90d12a337922f86cc4d29aa183 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 27 Jul 2024 10:06:31 +0200 Subject: [PATCH 209/488] change some parameters Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 9 ++++--- cpp/models/abm/location_type.h | 1 + cpp/models/abm/parameters.h | 25 ++++---------------- cpp/simulations/analyze_bs_run.py | 8 +++---- cpp/simulations/cleanup_data.py | 8 +++---- cpp/simulations/generate_graph_from_data.cpp | 2 +- 6 files changed, 19 insertions(+), 34 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 7aa9ddd599..d2d016bef1 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -112,18 +112,17 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time const Parameters& global_params) const { // TODO: we need to define what a cell is used for, as the loop may lead to incorrect results for multiple cells - auto age_receiver = person.get_age(); - ScalarType mask_protection = person.get_mask_protective_factor(global_params); - ScalarType mobility_damping_factor = global_params.get(); + auto age_receiver = person.get_age(); + ScalarType mask_protection = person.get_mask_protective_factor(global_params); assert(person.get_cells().size() && "Person is in multiple cells. Interact logic is incorrect at the moment."); + for (auto cell_index : person.get_cells()) { // TODO: the logic here is incorrect in case a person is in multiple cells std::pair local_indiv_expected_trans[static_cast(VirusVariant::Count)]; for (uint32_t v = 0; v != static_cast(VirusVariant::Count); ++v) { VirusVariant virus = static_cast(v); ScalarType local_indiv_expected_trans_v = - (mobility_damping_factor * - transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups()) + + (transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups()) + transmission_air_per_day(cell_index, virus, global_params)) * (1 - mask_protection) * (1 - person.get_protection_factor(t, virus, global_params)); diff --git a/cpp/models/abm/location_type.h b/cpp/models/abm/location_type.h index 9b685a9a7a..39b9383583 100644 --- a/cpp/models/abm/location_type.h +++ b/cpp/models/abm/location_type.h @@ -44,6 +44,7 @@ enum class LocationType : std::uint32_t Car, PublicTransport, TransportWithoutContact, // all ways of travel with no contact to other people, e.g. biking or walking + Event, Cemetery, // Location for all the dead persons. It is created once for the World. Count //last! diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index b6509d7292..61064c69d1 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -348,21 +348,6 @@ struct InfectionRateFromViralShed { } }; -/** - * @brief Determines the MobilityRestrictionParameter. -*/ -struct MobilityRestrictionParameter { - using Type = ScalarType; - static Type get_default(AgeGroup /*size*/) - { - return Type(1.0); - } - static std::string name() - { - return "MobilityRestrictionParameter"; - } -}; - /** * @brief Aerosol transmission rates. */ @@ -665,11 +650,11 @@ using ParametersBase = TimeInfectedSevereToRecovered, TimeInfectedCriticalToDead, TimeInfectedCriticalToRecovered, SymptomsPerInfectedNoSymptoms, SeverePerInfectedSymptoms, CriticalPerInfectedSevere, DeathsPerInfectedCritical, ViralLoadDistributions, InfectivityDistributions, VirusShedFactor, - DetectInfection, MaskProtection, InfectionRateFromViralShed, MobilityRestrictionParameter, - AerosolTransmissionRates, LockdownDate, QuarantineDuration, SocialEventRate, BasicShoppingRate, - WorkRatio, SchoolRatio, GotoWorkTimeMinimum, GotoWorkTimeMaximum, GotoSchoolTimeMinimum, - GotoSchoolTimeMaximum, AgeGroupGotoSchool, AgeGroupGotoWork, InfectionProtectionFactor, - SeverityProtectionFactor, HighViralLoadProtectionFactor, TestData>; + DetectInfection, MaskProtection, InfectionRateFromViralShed, AerosolTransmissionRates, LockdownDate, + QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, + GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, + AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, + TestData>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index e78c811c21..1ee0af8884 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -55,14 +55,14 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): color_plot = matplotlib.colormaps.get_cmap('Set1').colors - states_plot = [0, 1, 2, 3, 4] + states_plot = [0, 1, 2, 3, 4, 10] legend_plot = ['Home', 'School', 'Work', - 'SocialEvent', 'BasicsShop', 'Hospital', 'ICU'] + 'SocialEvent', 'BasicsShop','Event'] for i in states_plot: # rolling average plt.plot(x, gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling( - 24, min_periods=1).sum(), sigma=15), color=color_plot[i]) + 24, min_periods=1).sum(), sigma=15), color=color_plot[i%7]) plt.legend(legend_plot) @@ -500,7 +500,7 @@ def infer_positive_tests(path): # we say the likelyhood to test yourself is 0.8 for symptomatic persons and therefore 0.04 for asymptomatic persons lt_sympt = 0.06 lt_asympt = lt_sympt/r_sns - sensitivity = 0.6 + sensitivity = 0.69 specificity = 0.99 # therefore the amount of pisitive tests is: diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 0e7dbeff4f..c250ca151a 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -423,8 +423,8 @@ def add_time_if_null(pd): return pd -# PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/" -PATH = "/Users/david/Documents/HZI/memilio/data/mobility/" +PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/" +# PATH = "/Users/david/Documents/HZI/memilio/data/mobility/" FILE = PATH + "braunschweig_result_ffa8.csv" bd = pd.read_csv(FILE) @@ -449,8 +449,8 @@ def add_time_if_null(pd): print('Home IDs set.') bd_new = add_school_ids(bd_new) print('School IDs set.') -# bd_new = add_external_ids(bd) -# print('External location IDs set.') +bd_new = add_external_ids(bd) +print('External location IDs set.') bd_new = assign_location_type(bd_new) print('Location types assigned.') bd_new = add_time_if_null(bd_new) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index f08b33000a..73d82e8762 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -229,7 +229,7 @@ mio::IOResult> get_graph(mio::Date start_date, c } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 2.8); auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 0.5); - scaling_factor_icu[4] = 30.0; + scaling_factor_icu[4] = 25.0; scaling_factor_icu[5] = 5.0; const auto& read_function_nodes = mio::osecir::read_input_data_county; From 948dd9b44bed1e8c763f8c2f9207871a33d00fc5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 27 Jul 2024 16:35:02 +0200 Subject: [PATCH 210/488] easter event succ implemented and several improvmeents Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 4 + cpp/models/abm/migration_rules.cpp | 17 ++ cpp/models/abm/migration_rules.h | 7 +- cpp/models/abm/person.h | 13 +- cpp/models/abm/world.cpp | 20 +- cpp/simulations/analyze_bs_run.py | 245 +++++++++++-------- cpp/simulations/generate_graph_from_data.cpp | 46 ---- cpp/simulations/paper_abm_bs_testing.cpp | 120 +++++---- 8 files changed, 276 insertions(+), 196 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index d2d016bef1..629c281422 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -116,6 +116,10 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time ScalarType mask_protection = person.get_mask_protective_factor(global_params); assert(person.get_cells().size() && "Person is in multiple cells. Interact logic is incorrect at the moment."); + if (person.get_infection_state(t) != InfectionState::Susceptible && m_id.type == LocationType::Event) { + std::cout << "Person is not susc at event" << std::endl; + } + for (auto cell_index : person.get_cells()) { // TODO: the logic here is incorrect in case a person is in multiple cells std::pair local_indiv_expected_trans[static_cast(VirusVariant::Count)]; diff --git a/cpp/models/abm/migration_rules.cpp b/cpp/models/abm/migration_rules.cpp index ab7d4cc6d1..09bd322b6a 100644 --- a/cpp/models/abm/migration_rules.cpp +++ b/cpp/models/abm/migration_rules.cpp @@ -179,5 +179,22 @@ LocationType get_buried(Person::RandomNumberGenerator& /*rng*/, const Person& pe return current_loc; } +LocationType easter_party(Person::RandomNumberGenerator& /*rng*/, const Person& person, const TimePoint t, + TimeSpan /*dt*/, const Parameters& params) +{ + auto current_loc = person.get_location().get_type(); + //leave + if (person.get_goes_to_easter() && t.days() > 34.0 && t.days() < 36.0 && (t.hour_of_day() >= 12) && + (t.hour_of_day() <= 22) && !person.is_in_quarantine(t, params)) { + return LocationType::Event; + } + + //return home + if ((person.get_time_at_location() >= hours(6))) { + return LocationType::Home; + } + return current_loc; +} + } // namespace abm } // namespace mio diff --git a/cpp/models/abm/migration_rules.h b/cpp/models/abm/migration_rules.h index b6f395d197..03bd7b6ff5 100644 --- a/cpp/models/abm/migration_rules.h +++ b/cpp/models/abm/migration_rules.h @@ -101,7 +101,12 @@ LocationType return_home_when_recovered(Person::RandomNumberGenerator& rng, cons */ LocationType get_buried(Person::RandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, const Parameters& params); -/**@}*/ + +/** + * @brief Persons have a party on eastern. + */ +LocationType easter_party(Person::RandomNumberGenerator& rng, const Person& person, TimePoint t, TimeSpan dt, + const Parameters& params); } // namespace abm } // namespace mio diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index 3f45260577..c9f271a6b7 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -517,6 +517,16 @@ class Person loc, age, id); } + bool get_goes_to_easter() const + { + return m_goes_to_easter_event; + } + + void set_goes_to_easter(bool goes_to_easter) + { + m_goes_to_easter_event = goes_to_easter; + } + private: observer_ptr m_location; ///< Current Location of the Person. std::vector m_assigned_locations; /**! Vector with the indices of the assigned Locations so that the @@ -538,7 +548,8 @@ class Person std::vector m_cells; ///< Vector with all Cell%s the Person visits at its current Location. mio::abm::TransportMode m_last_transport_mode; ///< TransportMode the Person used to get to its current Location. Counter m_rng_counter{0}; ///< counter for RandomNumberGenerator. - bool m_should_be_logged = true; ///< Flag to determine if the Person should be logged. + bool m_should_be_logged = true; ///< Flag to determine if the Person should be logged. + bool m_goes_to_easter_event = false; ///< Flag to determine if the Person goes to an Easter event. }; } // namespace abm diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index ecbef71545..48e53c2b90 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -77,12 +77,7 @@ void World::migration(TimePoint t, TimeSpan dt) { PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { - auto&& person = m_persons[i]; - auto current_infection_state = person->get_infection_state(t); - if (current_infection_state == mio::abm::InfectionState::Susceptible && !m_use_migration_rules && - !person->is_in_quarantine(t, parameters)) { - continue; - } + auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -102,6 +97,12 @@ void World::migration(TimePoint t, TimeSpan dt) return false; }; + // auto current_infection_state = person->get_infection_state(t); + // if (current_infection_state == mio::abm::InfectionState::Susceptible && !m_use_migration_rules && + // !person->is_in_quarantine(t, parameters)) { + // continue; + // } + //run migration rules one after the other if the corresponding location type exists //shortcutting of bool operators ensures the rules stop after the first rule is applied if (m_use_migration_rules) { @@ -117,11 +118,13 @@ void World::migration(TimePoint t, TimeSpan dt) } else { // no daily routine migration, just infection related + (has_locations({LocationType::Cemetery}) && try_migration_rule(&get_buried)) || (has_locations({LocationType::Home}) && try_migration_rule(&return_home_when_recovered)) || (has_locations({LocationType::Hospital}) && try_migration_rule(&go_to_hospital)) || (has_locations({LocationType::ICU}) && try_migration_rule(&go_to_icu)) || - (has_locations({LocationType::Home}) && try_migration_rule(&go_to_quarantine)); + (has_locations({LocationType::Home}) && try_migration_rule(&go_to_quarantine)) || + (has_locations({LocationType::Event}) && try_migration_rule(&easter_party)); } } @@ -137,7 +140,8 @@ void World::migration(TimePoint t, TimeSpan dt) auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); if (current_location.get_type() != LocationType::Hospital && current_location.get_type() != LocationType::ICU && - current_location.get_type() != LocationType::Cemetery) { + current_location.get_type() != LocationType::Cemetery && + current_location.get_type() != LocationType::Event) { if (!person->is_in_quarantine(t, parameters)) { auto& target_location = get_individualized_location( {person->get_assigned_location_index(trip.migration_destination.type), diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 1ee0af8884..f55fbcf26c 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -21,6 +21,7 @@ from datetime import datetime from matplotlib.dates import DateFormatter from scipy.ndimage import gaussian_filter1d +from scipy.signal import savgol_filter def plot_infections_loc_types_avarage(path): @@ -50,8 +51,8 @@ def plot_infections_loc_types_avarage(path): def plot_infection_per_location_type_mean(x, y50, y25, y75): - plt.figure('Infection_states_location_types') - plt.title('Infection states per location types avaraged over all runs') + plt.figure('Infection_location_types') + plt.title('At which location type an infection happened, avaraged over all runs') color_plot = matplotlib.colormaps.get_cmap('Set1').colors @@ -60,9 +61,19 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): 'SocialEvent', 'BasicsShop','Event'] for i in states_plot: - # rolling average - plt.plot(x, gaussian_filter1d(pd.DataFrame(y50[:, i]).rolling( - 24, min_periods=1).sum(), sigma=15), color=color_plot[i%7]) + # rolling average# + ac_color = color_plot[i%len(color_plot)] + if(i > len(color_plot)): + ac_color = "black" + + # we need to sum up every 24 hours + indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=24) + np_y50 = pd.DataFrame(y50[:, i]).rolling(window=indexer, min_periods=1).sum().to_numpy() + np_y50=np_y50[0::24].flatten() + # now smoothen this with a gaussian filter + np_y50 = gaussian_filter1d(np_y50, sigma=1, mode='nearest') + + plt.plot(x[0::24], np_y50, color=ac_color) plt.legend(legend_plot) @@ -75,7 +86,7 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): plt.gca().set_xticklabels(xx[::150]) plt.gcf().autofmt_xdate() - plt.xlabel('Time') + plt.xlabel('Date') plt.ylabel('Number of individuals') plt.show() @@ -123,13 +134,8 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): for i in states_plot: plt.plot(x, y50[:, i], color=color_plot[i]) - # plot real data for comparison, symptomatic and infected daily - if y_real is not None: - x_real = np.linspace(0, y_real.shape[0]-1, y_real.shape[0]) - plt.plot(x_real, y_real[:, 1], '.', color='tab:blue') plt.legend(legend_plot) - for i in states_plot: plt.fill_between(x, y50[:, i], y25[:, i], alpha=0.5, color=color_plot[i]) @@ -160,74 +166,66 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): color_plot = matplotlib.colormaps.get_cmap('Set1').colors - fig, ax = plt.subplots(5, len(age_group_access), constrained_layout=True) + fig, ax = plt.subplots(6, len(age_group_access), constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) for j, count in zip(age_group_access, range(len(age_group_access))): y50 = p50_bs[j][()] y25 = p25_bs[j][()] y75 = p75_bs[j][()] - y_real = real_bs[j][()] + y_real = np.floor(real_bs[j][()]) # infeced no symptoms ax_infected_no_symptoms = ax[0, count] ax_infected_no_symptoms.set_xlabel('time (days)') ax_infected_no_symptoms.plot( x, y50[:, 1], color=color_plot[count], label='y50') - ax_infected_no_symptoms.plot( - x_real, y_real[:, 2], '.', color=color_plot[count], label='y_real') ax_infected_no_symptoms.fill_between( x, y50[:, 1], y25[:, 1], alpha=0.5, color=color_plot[count]) ax_infected_no_symptoms.fill_between( x, y50[:, 1], y75[:, 1], alpha=0.5, color=color_plot[count]) ax_infected_no_symptoms.tick_params(axis='y') ax_infected_no_symptoms.title.set_text( - 'Infected_no_symptoms, Age{}'.format(j)) - ax_infected_no_symptoms.legend(['Simulation', 'Real']) + '#Infected_no_symptoms, Age{}'.format(j)) + ax_infected_no_symptoms.legend(['Simulation']) # Infected_symptoms ax_infected_symptoms = ax[1, count] ax_infected_symptoms.set_xlabel('time (days)') ax_infected_symptoms.plot( x, y50[:, 2], color=color_plot[count], label='y50') - ax_infected_symptoms.plot( - x_real, y_real[:, 4], '.', color=color_plot[count], label='y_real') ax_infected_symptoms.fill_between( x, y50[:, 2], y25[:, 2], alpha=0.5, color=color_plot[count]) ax_infected_symptoms.fill_between( x, y50[:, 2], y75[:, 2], alpha=0.5, color=color_plot[count]) ax_infected_symptoms.tick_params(axis='y') ax_infected_symptoms.title.set_text( - 'Infected_symptoms, Age{}'.format(j)) - ax_infected_symptoms.legend(['Simulation', 'Real']) + '#Infected_symptoms, Age{}'.format(j)) + ax_infected_symptoms.legend(['Simulation']) # Severe ax_severe = ax[2, count] ax_severe.set_xlabel('time (days)') ax_severe.plot(x, y50[:, 4], color=color_plot[count], label='y50') - ax_severe.plot(x_real, y_real[:, 6], '.', - color=color_plot[count], label='y_real') ax_severe.fill_between( x, y50[:, 4], y25[:, 4], alpha=0.5, color=color_plot[count]) ax_severe.fill_between( x, y50[:, 4], y75[:, 4], alpha=0.5, color=color_plot[count]) ax_severe.tick_params(axis='y') - ax_severe.title.set_text('Severe, Age{}'.format(j)) - ax_severe.legend(['Simulation', 'Real']) + ax_severe.title.set_text('#Severe, Age{}'.format(j)) + ax_severe.legend(['Simulation']) # Critical ax_critical = ax[3, count] ax_critical.set_xlabel('time (days)') ax_critical.plot(x, y50[:, [5]], color=color_plot[count], label='y50') - ax_critical.plot( - x_real, y_real[:, [7]], '.', color=color_plot[count], label='y_real') ax_critical.fill_between( x, y50[:, 5], y25[:, 5], alpha=0.5, color=color_plot[count]) ax_critical.fill_between( x, y50[:, 5], y75[:, 5], alpha=0.5, color=color_plot[count]) ax_critical.tick_params(axis='y') - ax_critical.title.set_text('Critical, Age{}'.format(j)) - ax_critical.legend(['Simulation', 'Real']) + ax_critical.title.set_text('#Critical, Age{}'.format(j)) + ax_critical.legend(['Simulation']) # Dead ax_dead = ax[4, count] @@ -240,9 +238,21 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): ax_dead.fill_between(x, y50[:, 7], y75[:, 7], alpha=0.5, color=color_plot[count]) ax_dead.tick_params(axis='y') - ax_dead.title.set_text('Dead, Age{}'.format(j)) + ax_dead.title.set_text('#Dead, Age{}'.format(j)) ax_dead.legend(['Simulation', 'Real']) + # Recovered + ax_dead = ax[5, count] + ax_dead.set_xlabel('time (days)') + ax_dead.plot(x, y50[:, [6]], color=color_plot[count], label='y50') + ax_dead.fill_between(x, y50[:, 6], y25[:, 6], + alpha=0.5, color=color_plot[count]) + ax_dead.fill_between(x, y50[:, 6], y75[:, 6], + alpha=0.5, color=color_plot[count]) + ax_dead.tick_params(axis='y') + ax_dead.title.set_text('#Recovered, Age{}'.format(j)) + ax_dead.legend(['Simulation']) + # fig.tight_layout() # otherwise the right y-label is slightly clipped plt.show() @@ -259,16 +269,23 @@ def plot_dead(path): # we just take the first 90 days total_50 = total_50[0:90] - # we need the real data - f_real = h5py.File( - path + "/Results_rki.h5", 'r') - real_bs = f_real['3101'] - y_real = real_bs['Total'][()] + # we need the real data json file cases_all_state_repdate_ma7 + df_abb = pd.read_json( + path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + # we just need the columns cases and date + df_abb = df_abb[['Date', 'Deaths', 'ID_County']] + # we need just the dates bewteen 2021-03-01 and 2021-06-01 + df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & + (df_abb['Date'] <= '2021-06-01')] + # we just need the cases with id 3101 + df_abb = df_abb[df_abb['ID_County'] == 3101] # we just take the first 90 days - y_real = y_real[0:90] + df_abb = df_abb[0:90] + y_real = df_abb['Deaths'].to_numpy() + # we calculate the RMSE - rmse_dead = np.sqrt(((y_real[:, 9] - total_50[:, 7])**2).mean()) + rmse_dead = np.sqrt(((y_real- total_50[:, 7])**2).mean()) # we plot this fig, ax = plt.subplots(1, 1, constrained_layout=True) @@ -276,22 +293,22 @@ def plot_dead(path): fig.set_figheight(9) # we plot the tests positive and the real cases start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') - xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] - xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - ax.plot(xx, total_50[:, 7], color='tab:red') - ax.plot(xx, y_real[:, 9], color='tab:blue') + ax.plot(df_abb['Date'], total_50[:, 7], color='tab:red') + ax.plot(df_abb['Date'], y_real, color='tab:blue') # we also write the rmse ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) - ax.set_xlabel('time (days)') + ax.set_xlabel('Date') ax.set_ylabel('Number of dead') - ax.title.set_text('Dead') - ax.legend(['Dead', 'Real dead']) + ax.title.set_text('Cumulative Dead') + ax.legend(['Dead Simulated', 'Real dead']) plt.show() def plot_icu(path): df_abb = pd.read_json(path+"/pydata/Germany/county_divi_ma7.json") + perc_of_critical_in_icu = 0.3 + # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] @@ -308,25 +325,34 @@ def plot_icu(path): # we need just every 24th value total_50 = total_50[::24] # we just take the first 90 days - total_50 = total_50[0:90]*0.4 + total_50 = total_50[0:90] + + ICU_Simulation = total_50[:, 5]*perc_of_critical_in_icu + ICU_Real = df_abb['ICU'][0:90] + + #smooth the data + ICU_Real = gaussian_filter1d(ICU_Real, sigma=1, mode='nearest') + ICU_Simulation = gaussian_filter1d(ICU_Simulation, sigma=1, mode='nearest') + + # we calculate the RMSE - rmse_ICU = np.sqrt(((df_abb['ICU'][0:90] - total_50[:, 5])**2).mean()) + rmse_ICU = np.sqrt(((ICU_Real - ICU_Simulation)**2).mean()) # plot the ICU beds and the ICU beds taken fig, ax = plt.subplots(1, 1, constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) # we plot the ICU_low and the ICU_high - ax.plot(df_abb['Date'][0:90], df_abb['ICU'][0:90], color='tab:blue') - ax.plot(df_abb['Date'][0:90], total_50[:, 5], color='tab:red') + ax.plot(df_abb['Date'][0:90], ICU_Real, color='tab:blue') + ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:red') # we also write the rmse ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) - ax.set_xlabel('time (days)') - ax.set_ylabel('Number of ICU beds') - ax.title.set_text('ICU beds and ICU beds taken') - ax.legend(['ICU beds', 'ICU beds taken']) + ax.set_xlabel('Date') + ax.set_ylabel('Number of persons in an ICU') + ax.title.set_text('Simulated and real ICU beds occupied') + ax.legend(['Real in ICU, smoothed','Simulated in ICU, Perc of Critical:'+str(perc_of_critical_in_icu)]) plt.show() @@ -397,7 +423,7 @@ def plot_tests(path): # we plot the tests positive and the real cases ax.plot(xx, PCR_tests, color='tab:red') ax.plot(xx, PCR_tests_positive, color='tab:blue') - ax.set_xlabel('time (days)') + ax.set_xlabel('Date') # The amount of persons, who do tests on a day is: PCR_tests_symptomatic = np.zeros(90) @@ -429,7 +455,7 @@ def plot_tests(path): fig.set_figheight(9) # we plot the tests positive and the real cases ax.plot(xx, sympt_persons, color='tab:red') - ax.set_xlabel('time (days)') + ax.set_xlabel('Date') ax.set_ylabel('Number of symptomatic persons') ax.title.set_text('Symptomatic persons') ax.legend(['Symptomatic persons']) @@ -452,6 +478,16 @@ def plot_tests(path): plt.show() +def calc_positive_tests_overall(infection_states, sensitivity, specificity, r_sns, lt_sympt): + + lt_asympt = lt_sympt/r_sns + inferred_positive_tests_sympt = ( + infection_states[:, 3]*lt_sympt+infection_states[:, 4]*lt_sympt+infection_states[:, 5]*lt_sympt)*sensitivity + # asymptomatic persons + inferred_positive_tests_asympt = (infection_states[:, 0]*lt_asympt)*( + 1-specificity)+((infection_states[:, 1]+infection_states[:, 2])*lt_asympt)*sensitivity + return inferred_positive_tests_sympt+inferred_positive_tests_asympt, inferred_positive_tests_sympt, inferred_positive_tests_asympt + def infer_positive_tests(path): # First way: we just take x amount of eahc compartment and fit this to the positive tested category. # A few assumptions: @@ -466,6 +502,10 @@ def infer_positive_tests(path): total_50 = p50_bs['Total'][()] total_50 = total_50[::24] total_50 = total_50[0:90] + time = p50_bs['Time'][()] + time = time[::24] + time = time[0:90] + # # we need the real positive tests # # real world @@ -489,55 +529,63 @@ def infer_positive_tests(path): df_abb = df_abb[0:90] # we need the amount of new positive tests each day insetad of cumulative df_abb['Confirmed'] = df_abb['Confirmed'].diff() - - # we take a fraction from each compartment and fit this to the positive tests - # we take the symptomatic persons - sympt_persons = total_50[:, 3]+total_50[:, 4]+total_50[:, 5] - # we take the asymptomatic persons - asympt_persons = total_50[:, 2]+total_50[:, 1]+total_50[:, 0] - # we assume r_sns = 20 so symptomatic persons are 20 times more likely to test themselves - r_sns = 20 - # we say the likelyhood to test yourself is 0.8 for symptomatic persons and therefore 0.04 for asymptomatic persons - lt_sympt = 0.06 - lt_asympt = lt_sympt/r_sns + sensitivity = 0.69 - specificity = 0.99 + specificity = 0.95 + # we need to derive the lowest rmse for the real positive tests and the inferred positive tests we use a grid search + # we need to find the best r_sns and lt_sympt + best_rmse = 1000000000 + best_r_sns = 0 + best_lt_sympt = 0 + for r_sns in np.linspace(1, 100, 100): + for lt_sympt in np.linspace(0.005, 0.1, 100): + total_positive_tests, inferred_positive_tests_sympt, inferred_positive_tests_asympt = calc_positive_tests_overall(total_50, sensitivity, specificity, r_sns, lt_sympt) + rmse = np.sqrt(((df_abb['Confirmed'] - total_positive_tests)**2).mean()) + if rmse < best_rmse: + best_rmse = rmse + best_r_sns = r_sns + best_lt_sympt = lt_sympt + + print("Best RMSE: ", best_rmse) + print("Best r_sns: ", best_r_sns) + print("Best lt_sympt: ", best_lt_sympt) + + + total_positive_tests, inferred_positive_tests_sympt, inferred_positive_tests_asympt = calc_positive_tests_overall(total_50, sensitivity, specificity, best_r_sns, best_lt_sympt) - # therefore the amount of pisitive tests is: - # symptomatic persons - inferred_positive_tests_sympt = ( - total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)*sensitivity - # asymptomatic persons - inferred_positive_tests_asympt = (total_50[:, 0]*lt_asympt)*( - 1-specificity)+((total_50[:, 1]+total_50[:, 2])*lt_asympt)*sensitivity # we save the assumed tests done - assumed__amount_of_test = (total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)+( - total_50[:, 0]*lt_asympt)+(total_50[:, 1]+total_50[:, 2])*lt_asympt + # assumed__amount_of_test = (total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)+( + # total_50[:, 0]*lt_asympt)+(total_50[:, 1]+total_50[:, 2])*lt_asympt + + + # we plot this - fig, ax = plt.subplots(1, 1, constrained_layout=True) - fig.set_figwidth(20) - fig.set_figheight(9) # we plot the tests positive and the real cases start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') - xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] + xx = [start_date + pd.Timedelta(days=int(i)) for i in time] xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - ax.plot(xx, inferred_positive_tests_sympt, color='tab:red') - ax.plot(xx, inferred_positive_tests_asympt, color='tab:blue') - ax.plot(xx, inferred_positive_tests_asympt + - inferred_positive_tests_sympt, color='tab:green') - ax.plot(xx, df_abb['Confirmed'], color='tab:orange') - ax.set_xlabel('time (days)') - ax.set_ylabel('Number of positive tests') - ax.title.set_text('Inferred positive tests') - ax.legend(['Symptomatic persons', 'Asymptomatic persons', - 'Symptomatic and Asymptomatic persons', 'Real positive tests']) - # we also write the rmse - rmse_sympt = np.sqrt( - ((df_abb['Confirmed'] - (inferred_positive_tests_sympt+inferred_positive_tests_asympt))**2).mean()) - ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_sympt))), horizontalalignment='center', - verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + plt.gca().set_xticks(time[::5]) + plt.gca().set_xticklabels(xx[::5]) + plt.gcf().autofmt_xdate() + + + + plt.plot(xx, inferred_positive_tests_sympt, color='tab:red') + plt.plot(xx, inferred_positive_tests_asympt, color='tab:blue') + plt.plot(xx, total_positive_tests, color='tab:green') + plt.plot(xx, df_abb['Confirmed'], color='tab:orange') + plt.xlabel('time (days)') + plt.ylabel('Number of positive tests') + plt.legend(['Assumed positive from Symptomatic', 'Assumed positive from Asymptomatic', + 'Assumed positive from all Persons', 'Real positive tests']) + + # we also write calculated best rmse, r_sns and lt_sympt into the title + plt.title('Positive tests inferred from model and real positive tests, RMSE: '+str(float("{:.2f}".format(best_rmse)))+' r_sns: '+str(float("{:.2f}".format(best_r_sns)))+' lt_sympt: '+str(float("{:.3f}".format(best_lt_sympt)))) + + + plt.show() @@ -552,9 +600,8 @@ def infer_positive_tests(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infectoin_states_results(path) - plot_infections_loc_types_avarage(path) - plot_icu(path+"/..") - plot_dead(path) - # plot_tests(path+"/..") + # plot_infectoin_states_results(path) + # plot_infections_loc_types_avarage(path) + # plot_icu(path+"/..") + # plot_dead(path) infer_positive_tests(path) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 73d82e8762..b2d956032d 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -261,49 +261,3 @@ mio::IOResult generate_extrapolated_data(std::vector n return mio::success(); } - -/* -int main(int argc, char** argv) -{ - - mio::set_log_level(mio::LogLevel::warn); - mio::mpi::init(); - - std::string data_dir; - mio::Date start_date = mio::Date(2023, 6, 1); - double num_days_sim = 90.0; - - if (argc == 1) { - data_dir = "../../data"; - } - else if (argc == 2) { - data_dir = argv[1]; - } - else if (argc == 6) { - data_dir = argv[1]; - start_date = mio::Date(std::atoi(argv[2]), std::atoi(argv[3]), std::atoi(argv[4])); - num_days_sim = std::atoi(argv[5]); - } - else { - mio::mpi::finalize(); - return 0; - } - - //mio::thread_local_rng().seed( - // {114381446, 2427727386, 806223567, 832414962, 4121923627, 1581162203}); //set seeds, e.g., for debugging - mio::thread_local_rng().synchronize(); - if (mio::mpi::is_root()) { - printf("Seeds: "); - for (auto s : mio::thread_local_rng().get_seeds()) { - printf("%u, ", s); - } - printf("\n"); - } - - //create or load graph - auto create_extrapolated_data = get_graph(start_date, num_days_sim, data_dir); - - mio::mpi::finalize(); - return 0; -} -*/ \ No newline at end of file diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6ea0f5fa53..564979ba61 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -530,14 +530,14 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, split_line(line, &row); line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); uint32_t person_id = row[index["puid"]]; + bool has_home_trip = true; if (person_id != last_person_id) { number_of_persons_read_in++; last_person_id = person_id; if (number_of_persons_read_in > max_number_persons) { break; } - - bool has_home_trip = row[index["has_home_trip"]]; + has_home_trip = row[index["has_home_trip"]]; } uint32_t age = row[index["age"]]; @@ -552,7 +552,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (it_person == persons.end()) { auto home = locations.find(home_id)->second; auto& person = world.add_person(home, determine_age_group(age)); - person.set_mask_preferences({0.0, 0.5, 0.5, 0.5, 0.5, 0.5}); + person.set_mask_preferences({0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.2, 0.2}); person.set_assigned_location(home); person.set_assigned_location(hospital); person.set_assigned_location(icu); @@ -567,8 +567,8 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, mio::abm::TimePoint(0) + mio::abm::minutes(trip_start), target_location)); if (!has_home_trip) { trip_vec.push_back(mio::abm::Trip(it_person->second.get_person_id(), - mio::abm::TimePoint(0) + mio::abm::hours(17), locations.find(home_id)->second)); - has_home_trip = true; + mio::abm::TimePoint(0) + mio::abm::hours(17), + locations.find(home_id)->second)); } } world.get_trip_list().add_several_trips(trip_vec); @@ -626,7 +626,7 @@ void set_parameters(mio::abm::Parameters& params) //Set testing parameters auto pcr_test_values = mio::abm::TestParameters{0.9, 0.99}; - auto antigen_test_values = mio::abm::TestParameters{0.8, 0.95}; + auto antigen_test_values = mio::abm::TestParameters{0.69, 0.95}; auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; @@ -898,34 +898,34 @@ void set_local_parameters(mio::abm::World& world) switch (loc.get_type()) { case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; - loc.get_infection_parameters().get().array() *= 1; - loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 1.5; loc.get_infection_parameters().get().array() *= 1; break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; - loc.get_infection_parameters().get().array() *= 5; - loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 7.5; loc.get_infection_parameters().get().array() *= 1; break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; - loc.get_infection_parameters().get().array() *= 5; - loc.get_infection_parameters().get().array() *= 0.8; - loc.get_infection_parameters().get().array() *= 0.33; // 1/3 + loc.get_infection_parameters().get().array() *= 7.5; + loc.get_infection_parameters().get().array() *= 0.4; // 2/5z break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; - loc.get_infection_parameters().get().array() *= 30; - loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 15; loc.get_infection_parameters().get().array() *= 4; break; - case mio::abm::LocationType::BasicsShop: + case mio::abm::LocationType::BasicsShop: loc.get_infection_parameters().get() = contacts_other; - loc.get_infection_parameters().get().array() *= 30; - loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 15; loc.get_infection_parameters().get().array() *= 0.14; // 1/7 break; + case mio::abm::LocationType::Event: + loc.get_infection_parameters().get() = contacts_other; + loc.get_infection_parameters().get().array() *= 4; + loc.get_infection_parameters().get().array() *= 4; // 1/7 + break; default: loc.get_infection_parameters().get() = contacts_other; break; @@ -1051,6 +1051,58 @@ std::vector> distribute_grid_search(int rank, int num_procs, return grid_search_rank; } +void create_easter_social_event(mio::abm::World& world) +{ + // int number_of_persons_per_easter_event = 6; + // int actual_number_of_persons = 0; + // auto event = world.add_location(mio::abm::LocationType::Event); + + // for (auto& p : world.get_persons()) { + // if (actual_number_of_persons >= number_of_persons_per_easter_event) { + // actual_number_of_persons = 0; + // event = world.add_location(mio::abm::LocationType::Event); + // } + // p.set_goes_to_easter(true); + // p.set_assigned_location(event); + // actual_number_of_persons++; + // } + // we take 50% of each age group and move them to the social event location in a random fashion with 1 person per age group and 2 of the age group 15-34 + std::vector> person_per_age_group; + person_per_age_group.resize(num_age_groupss); + + for (size_t i = 0; i < world.get_persons().size(); i++) { + auto& p = world.get_persons()[i]; + person_per_age_group[determine_age_group_from_rki(p.get_age())].push_back(i); + } + + //shuffle this vector + std::random_device rd; + std::mt19937 g(rd()); + for (size_t i = 0; i < person_per_age_group.size(); i++) { + std::shuffle(person_per_age_group[i].begin(), person_per_age_group[i].end(), g); + } + int number_of_persons = (int)(0.3 * world.get_persons().size()); + int number_of_social_events = number_of_persons / (num_age_groupss + 1); + + for (auto i = 0; i < number_of_social_events; i++) { + auto easter_event = world.add_location(mio::abm::LocationType::Event); + for (size_t j = 0; j < num_age_groupss; j++) { + if (person_per_age_group[j].empty()) { + continue; + } + world.get_persons()[person_per_age_group[j].back()].set_assigned_location(easter_event); + world.get_persons()[person_per_age_group[j].back()].set_goes_to_easter(true); + person_per_age_group[j].pop_back(); + + if (j == 2) { + world.get_persons()[person_per_age_group[j].back()].set_assigned_location(easter_event); + world.get_persons()[person_per_age_group[j].back()].set_goes_to_easter(true); + person_per_age_group[j].pop_back(); + } + } + } +} + /** * Create a sampled simulation with start time t0. * @param t0 The start time of the Simulation. @@ -1070,6 +1122,9 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con world.use_migration_rules(false); restart_timer(timer, "time taken for braunschweig trip input"); + create_easter_social_event(world); + restart_timer(timer, "time taken for setting up easter social ebent"); + // Assign an infection state to each person. assign_infection_state(world, t0); restart_timer(timer, "time taken for assigning infection state"); @@ -1734,7 +1789,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } restart_timer(timer, "till advance 14"); - double normal_infection_viral_shed = 3.5; + double normal_infection_viral_shed = 4.2; sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); @@ -1752,30 +1807,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } - restart_timer(timer, "till advance 30 (eastern starts)"); + restart_timer(timer, "till advance 31 (march ends)"); sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - - restart_timer(timer, "till advance 37 (eastern ends)"); double seasonality_april = 0.9; sim.get_world().parameters.get() = normal_infection_viral_shed * seasonality_april; - double eastern_bonus = 5; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::Home || - location.get_type() == mio::abm::LocationType::SocialEvent) { - location.get_infection_parameters().get().array() *= eastern_bonus; - } - } - sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::Home || - location.get_type() == mio::abm::LocationType::SocialEvent) { - location.get_infection_parameters().get().array() /= eastern_bonus; - } - } restart_timer(timer, "till advance 42"); sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, @@ -1813,7 +1851,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { - location.get_infection_parameters().get().array() *= 0.5; + location.get_infection_parameters().get().array() *= 0.35; location.set_capacity(15, 0); } } @@ -1829,7 +1867,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::cout << "day 90 finished" << std::endl; } else { - sim.advance(mio::abm::TimePoint(mio::abm::days(max_num_days).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); } ////Advance till here @@ -1928,9 +1966,9 @@ int main(int argc, char** argv) #endif // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; - std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; + // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); From 3de2dc23c81fd855df3755e61ed524e423be2e0d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 29 Jul 2024 00:33:30 +0200 Subject: [PATCH 211/488] add grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/migration_rules.cpp | 2 +- cpp/simulations/analyze_bs_run.py | 44 +- cpp/simulations/generate_graph_from_data.cpp | 17 +- cpp/simulations/paper_abm_bs_testing.cpp | 459 +++++++++++-------- 4 files changed, 316 insertions(+), 206 deletions(-) diff --git a/cpp/models/abm/migration_rules.cpp b/cpp/models/abm/migration_rules.cpp index 09bd322b6a..01125dc8a6 100644 --- a/cpp/models/abm/migration_rules.cpp +++ b/cpp/models/abm/migration_rules.cpp @@ -184,7 +184,7 @@ LocationType easter_party(Person::RandomNumberGenerator& /*rng*/, const Person& { auto current_loc = person.get_location().get_type(); //leave - if (person.get_goes_to_easter() && t.days() > 34.0 && t.days() < 36.0 && (t.hour_of_day() >= 12) && + if (person.get_goes_to_easter() && t.days() > 33.0 && t.days() < 36.0 && (t.hour_of_day() >= 12) && (t.hour_of_day() <= 22) && !person.is_in_quarantine(t, params)) { return LocationType::Event; } diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index f55fbcf26c..0deba820a3 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -256,7 +256,6 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): # fig.tight_layout() # otherwise the right y-label is slightly clipped plt.show() - def plot_dead(path): # we will have a seperate plot the cumulative infected individuals, cumulative symptomatic individuals and cumulative dead individual # we need to load the data @@ -271,17 +270,35 @@ def plot_dead(path): # we need the real data json file cases_all_state_repdate_ma7 df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../pydata/Germany/cases_all_county.json") + # read in rki data rki_sum + + f_real = h5py.File( + path + "/Results_rki.h5", 'r') + real_bs = f_real['3101'] + total_real = real_bs['Total'][()] + total_real = total_real[0:90] + y_real = total_real[:, 9] + + # we just need the columns cases and date - df_abb = df_abb[['Date', 'Deaths', 'ID_County']] # we need just the dates bewteen 2021-03-01 and 2021-06-01 - df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & - (df_abb['Date'] <= '2021-06-01')] + df_abb = df_abb[(df_abb['Date'] >= '2021-02-01') & + (df_abb['Date'] <= '2021-05-01')] # we just need the cases with id 3101 df_abb = df_abb[df_abb['ID_County'] == 3101] # we just take the first 90 days df_abb = df_abb[0:90] - y_real = df_abb['Deaths'].to_numpy() + # y_real = df_abb['Deaths'].to_numpy() + + # #smooth y_real with a gaussian filter + # y_real = gaussian_filter1d(y_real, sigma=1, mode='nearest') + # # floor it to make it an integer + # y_real = np.floor(y_real) + + # we want to offset every date by 28 day + df_abb['Date'] = df_abb['Date'] + pd.DateOffset(days=28) + # we calculate the RMSE @@ -304,10 +321,9 @@ def plot_dead(path): ax.legend(['Dead Simulated', 'Real dead']) plt.show() - def plot_icu(path): df_abb = pd.read_json(path+"/pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu = 0.3 + perc_of_critical_in_icu = 0.4 # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] @@ -355,7 +371,6 @@ def plot_icu(path): ax.legend(['Real in ICU, smoothed','Simulated in ICU, Perc of Critical:'+str(perc_of_critical_in_icu)]) plt.show() - def plot_tests(path): df_abb = pd.read_excel( @@ -477,7 +492,6 @@ def plot_tests(path): ax.legend(['Asymptomatic persons', 'Asymptomatic persons positive']) plt.show() - def calc_positive_tests_overall(infection_states, sensitivity, specificity, r_sns, lt_sympt): lt_asympt = lt_sympt/r_sns @@ -580,7 +594,7 @@ def infer_positive_tests(path): plt.ylabel('Number of positive tests') plt.legend(['Assumed positive from Symptomatic', 'Assumed positive from Asymptomatic', 'Assumed positive from all Persons', 'Real positive tests']) - + # we also write calculated best rmse, r_sns and lt_sympt into the title plt.title('Positive tests inferred from model and real positive tests, RMSE: '+str(float("{:.2f}".format(best_rmse)))+' r_sns: '+str(float("{:.2f}".format(best_r_sns)))+' lt_sympt: '+str(float("{:.3f}".format(best_lt_sympt)))) @@ -600,8 +614,8 @@ def infer_positive_tests(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - # plot_infectoin_states_results(path) - # plot_infections_loc_types_avarage(path) - # plot_icu(path+"/..") - # plot_dead(path) + plot_infectoin_states_results(path) + plot_infections_loc_types_avarage(path) + plot_icu(path+"/..") + plot_dead(path) infer_positive_tests(path) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index b2d956032d..4e304a9a4c 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -136,8 +136,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double maxRiskOfInfectionFromSymptomaticMax = 0.5; const double recoveredPerInfectedNoSymptomsMin[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; const double recoveredPerInfectedNoSymptomsMax[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; - const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.05, 0.08}; - const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.05, 0.08}; + const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.025, 0.04}; + const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.025, 0.04}; const double criticalPerSevereMin[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; const double criticalPerSevereMax[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; const double deathsPerCriticalMin[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; @@ -209,7 +209,8 @@ mio::IOResult set_contact_matrices(const fs::path& data_dir, mio::osecir:: * @returns created graph or any io errors that happen during reading of the files. */ mio::IOResult> get_graph(mio::Date start_date, const int num_days, - const fs::path& data_dir) + const fs::path& data_dir, double scaling_factor_ag4, + double scaling_factor_ag5, double sclaling_infected) { // global parameters @@ -227,10 +228,10 @@ mio::IOResult> get_graph(mio::Date start_date, c for (auto& node : nodes) { node.parameters = params; } - auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), 2.8); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 0.5); - scaling_factor_icu[4] = 25.0; - scaling_factor_icu[5] = 5.0; + auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 0.05); + scaling_factor_icu[4] = scaling_factor_ag4; + scaling_factor_icu[5] = scaling_factor_ag5; const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, @@ -256,7 +257,7 @@ mio::IOResult generate_extrapolated_data(std::vector n BOOST_OUTCOME_TRY(export_input_data_county_timeseries( nodes, data_dir.string(), node_ids, start_date, scaling_factor_infected, scaling_factor_icu, num_days, mio::path_join(data_dir.string(), "pydata/Germany", "county_divi_ma7.json"), - mio::path_join(data_dir.string(), "pydata/Germany", "cases_all_county_age_repdate_ma7.json"), + mio::path_join(data_dir.string(), "pydata/Germany", "cases_all_county_age_ma7.json"), mio::path_join(data_dir.string(), "pydata/Germany", "county_current_population.json"))); return mio::success(); diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 564979ba61..02119fd9f6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -91,10 +91,12 @@ void extrapolate_real_world_data(mio::osecir::Model& model, const std::string& i /** * Determine initial distribution of infection states. */ -void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date) +void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date, + double scaling_factor_ag4, double scaling_factor_ag5, + double sclaling_infected) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(date, 1, input_dir); + auto initial_graph = get_graph(date, 1, input_dir, scaling_factor_ag4, scaling_factor_ag5, sclaling_infected); const size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); @@ -644,8 +646,8 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.0237; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.0373; params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.0795; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.1664; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.2374; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.2; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.3; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.1; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.11; @@ -691,7 +693,7 @@ void set_parameters(mio::abm::Parameters& params) }; //Set other parameters - params.get() = 0.5; //all masks have a 0.66 protection factor for now + params.get() = 0.55; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -900,6 +902,7 @@ void set_local_parameters(mio::abm::World& world) loc.get_infection_parameters().get() = contacts_home; loc.get_infection_parameters().get().array() *= 1.5; loc.get_infection_parameters().get().array() *= 1; + loc.get_infection_parameters().get().array() *= 0.75; // 2/5z break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; @@ -909,17 +912,17 @@ void set_local_parameters(mio::abm::World& world) case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; loc.get_infection_parameters().get().array() *= 7.5; - loc.get_infection_parameters().get().array() *= 0.4; // 2/5z + loc.get_infection_parameters().get().array() *= 0.25; // 2/5z break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= 15; - loc.get_infection_parameters().get().array() *= 4; + loc.get_infection_parameters().get().array() *= 5; break; case mio::abm::LocationType::BasicsShop: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= 15; - loc.get_infection_parameters().get().array() *= 0.14; // 1/7 + loc.get_infection_parameters().get().array() *= 0.2; // 1/7 break; case mio::abm::LocationType::Event: loc.get_infection_parameters().get() = contacts_other; @@ -968,53 +971,50 @@ void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool socia } } -std::pair calculate_rmse_from_results(const fs::path& results_dir, int max_num_days) +double calculate_rmse_from_results(const fs::path& results_dir, std::vector> sim_inf_states, + int max_num_days) { - // We need to read in the results from the results directory - auto real_data = mio::read_result((results_dir / "Results_rki.h5").generic_string()).value()[0].get_totals(); - auto sim_data = mio::read_result((results_dir / "/infection_state_per_age_group/p50/Results.h5").generic_string()) - .value()[0] - .get_totals(); + auto real_data_dead = mio::read_result((results_dir / "Results_rki.h5").generic_string()).value()[0].get_totals(); // we change the format to two vectors of the same length, in this case for debugging reasons, we just use the first 3 // for the simulation data we need to take only the first of each day, so just every 24th element - std::vector> real_data_vec; + std::vector real_data_dead_vec; std::vector> sim_data_vec; for (int i = 0; i < max_num_days; i++) { - real_data_vec.push_back(std::make_pair(real_data[i]((size_t)mio::osecir::InfectionState::Dead), - real_data[i]((size_t)mio::osecir::InfectionState::Exposed))); - } - for (int i = 0; i < max_num_days * 24; i += 24) { - sim_data_vec.push_back(std::make_pair(sim_data[i]((size_t)mio::abm::InfectionState::Dead), - sim_data[i]((size_t)mio::abm::InfectionState::Exposed))); + real_data_dead_vec.push_back(real_data_dead[i]((size_t)mio::osecir::InfectionState::Dead)); + // we need to calc total number of dead people + double total_dead = 0; + for (size_t j = 0; j < num_age_groupss; j++) { + int index = (((size_t)(mio::abm::InfectionState::Count)) * (j) + (size_t)mio::abm::InfectionState::Dead); + total_dead = total_dead + (double)sim_inf_states[0][i * 24][index]; + } + sim_data_vec.push_back(std::make_pair(i, total_dead)); } // now we calculate the RMSE - double rmse_dead = 0; - double rmse_exposed = 0; - for (size_t i = 0; i < real_data_vec.size(); i++) { - rmse_dead += pow(real_data_vec[i].first - sim_data_vec[i].first, 2); - rmse_exposed += pow(real_data_vec[i].second - sim_data_vec[i].second, 2); + double rmse_dead = 0; + for (size_t i = 0; i < real_data_dead_vec.size(); i++) { + rmse_dead += pow(real_data_dead_vec[i] - sim_data_vec[i].second, 2); } - rmse_dead = sqrt(rmse_dead / real_data_vec.size()); - rmse_exposed = sqrt(rmse_exposed / real_data_vec.size()); + rmse_dead = sqrt(rmse_dead / real_data_dead_vec.size()); - return std::make_pair(rmse_dead, rmse_exposed); + return rmse_dead; } /** * @brief Calculate a grid search for a given set of parameters. * @input std::vector where size is the amount of parameters, and the first entry is the min and the second is the max value */ -std::vector> grid_points(std::vector> parameters, int number_of_points) +std::vector> grid_points(std::vector> parameter_boundaries, + std::vector number_of_points) { std::vector> grid; - for (size_t i = 0; i < parameters.size(); i++) { + for (size_t i = 0; i < parameter_boundaries.size(); i++) { std::vector temp; - double step = (parameters[i].second - parameters[i].first) / (number_of_points - 1); - for (int j = 0; j < number_of_points + 1; j++) { - temp.push_back(parameters[i].first + j * step); + double step = (parameter_boundaries[i].second - parameter_boundaries[i].first) / (number_of_points.at(i) - 1); + for (int j = 0; j < number_of_points.at(i) - 1; j++) { + temp.push_back(parameter_boundaries[i].first + j * step); } grid.push_back(temp); } @@ -1027,7 +1027,10 @@ std::vector> grid_points(std::vector> distribute_grid_search(int rank, int num_procs, std::vector> grid) { //Calculate how many grid points there are, assuming that each parameter has the same amount of points - int number_of_points = (int)std::pow(grid[0].size(), grid.size()); + int number_of_points = 1; + for (size_t i = 0; i < grid.size(); i++) { + number_of_points *= grid[i].size(); + } //Calculate how many points each rank should calculate int points_per_rank = number_of_points / num_procs; //leftover points goes to the last rank @@ -1036,13 +1039,24 @@ std::vector> distribute_grid_search(int rank, int num_procs, } // we calculate every possible combination of the grid, independently of the rank std::vector> grid_search; - for (int i = 0; i < (int)grid.size(); i++) { + std::vector counter_per_dimension(grid.size(), 0); + for (int i = 0; i < number_of_points; i++) { std::vector temp; - for (int j = 0; j < (int)grid[i].size(); j++) { - temp.push_back(grid[i][j]); + for (size_t j = 0; j < grid.size(); j++) { + temp.push_back(grid[j][counter_per_dimension[j]]); } grid_search.push_back(temp); + // we increase the counter for the last dimension + counter_per_dimension.back()++; + // we increase the counter for the other dimensions if the last dimension has reached the end + for (int j = (int)grid.size() - 1; j >= 0; j--) { + if (counter_per_dimension[j] == (int)grid[j].size()) { + counter_per_dimension[j] = 0; + counter_per_dimension[j - 1]++; + } + } } + // we calculate the grid search for the rank std::vector> grid_search_rank; for (int i = 0; i < points_per_rank; i++) { @@ -1051,7 +1065,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, return grid_search_rank; } -void create_easter_social_event(mio::abm::World& world) +void create_easter_social_event(mio::abm::World& world, double perc_easter_event) { // int number_of_persons_per_easter_event = 6; // int actual_number_of_persons = 0; @@ -1081,7 +1095,7 @@ void create_easter_social_event(mio::abm::World& world) for (size_t i = 0; i < person_per_age_group.size(); i++) { std::shuffle(person_per_age_group[i].begin(), person_per_age_group[i].end(), g); } - int number_of_persons = (int)(0.3 * world.get_persons().size()); + int number_of_persons = (int)(perc_easter_event * world.get_persons().size()); int number_of_social_events = number_of_persons / (num_age_groupss + 1); for (auto i = 0; i < number_of_social_events; i++) { @@ -1108,7 +1122,7 @@ void create_easter_social_event(mio::abm::World& world) * @param t0 The start time of the Simulation. */ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, - int max_num_persons, mio::Date start_date_sim) + int max_num_persons, mio::Date start_date_sim, double perc_easter_event) { //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -1122,7 +1136,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con world.use_migration_rules(false); restart_timer(timer, "time taken for braunschweig trip input"); - create_easter_social_event(world); + create_easter_social_event(world, perc_easter_event); restart_timer(timer, "time taken for setting up easter social ebent"); // Assign an infection state to each person. @@ -1258,88 +1272,132 @@ T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) } return gathered_ensemble_vec; } -#endif -std::vector distribute_runs(size_t num_runs, int num_procs) +void get_grid_search_results_and_write_them_to_file( + int rank, int num_procs, const fs::path& result_dir, + std::vector, double>> grid_my_rank_with_rmse) { - //evenly distribute runs - //lower processes do one more run if runs are not evenly distributable - auto num_runs_local = num_runs / num_procs; //integer division! - auto remainder = num_runs % num_procs; + // we just send every grid point and the corresponding rmse to rank 0 who writes it to a file + auto gathered_grid_vector_with_rmse = std::vector, double>>{}; - std::vector run_distribution(num_procs); - std::fill(run_distribution.begin(), run_distribution.begin() + remainder, num_runs_local + 1); - std::fill(run_distribution.begin() + remainder, run_distribution.end(), num_runs_local); + if (rank == 0) { + std::copy(grid_my_rank_with_rmse.begin(), grid_my_rank_with_rmse.end(), + std::back_inserter(gathered_grid_vector_with_rmse)); - return run_distribution; -} + for (int src_rank = 1; src_rank < num_procs; ++src_rank) { + int bytes_size; + MPI_Recv(&bytes_size, 1, MPI_INT, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); + mio::ByteStream bytes(bytes_size); + MPI_Recv(bytes.data(), bytes.data_size(), MPI_BYTE, src_rank, 0, mio::mpi::get_world(), MPI_STATUS_IGNORE); -mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, - std::vector grid_params, bool save_single_runs = true) -{ - mio::Date start_date{2021, 3, 1}; - int max_num_days = 90; - auto max_num_persons = std::numeric_limits::max(); + auto src_grid_results = mio::deserialize_binary(bytes, mio::Tag{}); + std::copy(src_grid_results.value().begin(), src_grid_results.value().end(), + std::back_inserter(gathered_grid_vector_with_rmse)); + } + } + else { + auto bytes_grid = mio::serialize_binary(grid_my_rank_with_rmse); + auto bytes_size = int(bytes_grid.data_size()); + MPI_Send(&bytes_size, 1, MPI_INT, 0, 0, mio::mpi::get_world()); + MPI_Send(bytes_grid.data(), bytes_grid.data_size(), MPI_BYTE, 0, 0, mio::mpi::get_world()); + } - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation + // write the gathered grid search results to a file + if (rank == 0) { + std::ofstream file((result_dir / "grid_search_results.txt").string()); + if (!file.is_open()) { + mio::log_error("Error opening file for writing grid search results."); + } + for (size_t i = 0; i < gathered_grid_vector_with_rmse.size(); i++) { + file << "Grid point: "; + for (size_t j = 0; j < gathered_grid_vector_with_rmse[i].first.size(); j++) { + file << gathered_grid_vector_with_rmse[i].first.at(j) << " "; + } + file << "RMSE: " << gathered_grid_vector_with_rmse[i].second << std::endl; + } + file.close(); + } +} - //ENSEMBLE RESULTS - auto ensemble_infection_per_loc_type = - std::vector>>{}; // Vector of infection per location type results - ensemble_infection_per_loc_type.reserve(size_t(num_runs)); - auto ensemble_infection_state_per_age_group = - std::vector>>{}; // Vector of infection state per age group results - ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); - auto ensemble_params = std::vector>{}; // Vector of all worlds - ensemble_params.reserve(size_t(num_runs)); - restart_timer(timer, "time for initial setup"); +mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::path& result_dir, int num_runs, + std::vector> grid_points) +{ + int num_procs, rank; +#ifdef MEMILIO_ENABLE_MPI + MPI_Comm_size(mio::mpi::get_world(), &num_procs); + MPI_Comm_rank(mio::mpi::get_world(), &rank); +#else + num_procs = 1; + rank = 0; +#endif + mio::unused(num_runs); + + // define parameters for grid search + + // Distribute the grid search over the MPI ranks + auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); + + // Run the grid search + std::vector rmse_results_per_grid_point; + + for (size_t i = 0; i < grid_search_rank.size(); i++) { + auto params = grid_search_rank[i]; + + // grid search for parameters: + // 1: Viral Shed + // 2: Seasonality April + // 3: Seasonality May + // 4: Perc Easter Event + // 6: Dark Figure + // 7.: Contact rate forst ssocial ebents closure + // 8.: Contact intensity for social events + // 9.: Contact rate for home + auto viral_shedding_rate = params[0]; + auto seasonality_april = params[1]; + auto seasonality_may = params[2]; + auto perc_easter_event = params[3]; + auto dark_figure = params[4]; + auto contact_rate_ssc = params[5]; + + auto icu_start_scalability_4 = 7.0; + auto icu_start_scalability_5 = 5.0; + + mio::Date start_date{2021, 3, 1}; + int max_num_days = 1; + auto max_num_persons = std::numeric_limits::max(); + + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation + + // Determine inital infection state distribution + restart_timer(timer, "time for initial setup"); + determine_initial_infection_states_world(input_dir, start_date, icu_start_scalability_4, + icu_start_scalability_5, dark_figure); + restart_timer(timer, "time for determine_initial_infection_states_world"); + prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); + restart_timer(timer, "time for vaccinaiton state"); + + // Loop over a number of runs + auto world = mio::abm::World(num_age_groupss); - // Determine inital infection state distribution - determine_initial_infection_states_world(input_dir, start_date); - restart_timer(timer, "time for determine_initial_infection_states_world"); - // Prepare vaccination state - prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), - (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - restart_timer(timer, "time for vaccination state"); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); - // Loop over a number of runs - for (size_t run_idx = 0; run_idx < num_runs; run_idx++) { - auto world = mio::abm::World(num_age_groupss); - create_sampled_world(world, input_dir, t0, max_num_persons, start_date); restart_timer(timer, "time taken for create sampled world"); - auto sim = mio::abm::Simulation(t0, std::move(world)); - // Setup parameters for the simulation - sim.get_world().parameters.get() = grid_params[0]; - sim.get_world() - .parameters.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = - grid_params[1]; - sim.get_world().parameters.get() = grid_params[2]; - //Logger mio::History historyInfectionPerLocationType{ Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyCumulativeDetectedInfections{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; - const auto location_it = sim.get_world().get_locations(); + // / NPIS// - //Spontanaeus testing at home - // auto testing_min_time_home = mio::abm::days(7); - // auto probability_home = 0.05; - // auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(0).seconds()); - // auto end_date_test_home = mio::abm::TimePoint(tmax); - // auto test_type_home = mio::abm::TestType::Antigen; // Antigen test - // auto test_parameters_home = - // sim.get_world().parameters.get()[test_type_home]; // Test parameters - // auto testing_criteria_home = mio::abm::TestingCriteria(); - // auto testing_scheme_home = - // mio::abm::TestingScheme(testing_criteria_home, testing_min_time_home, start_date_test_home, - // end_date_test_home, test_parameters_home, probability_home); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_home); + const auto location_it = sim.get_world().get_locations(); // 1. testing schemes in schools auto testing_min_time_school = mio::abm::days(7); @@ -1429,16 +1487,17 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // // 4. Dampings for schools and Basic shops for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.6); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.0); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), - 0.6); // from 2021-04-12 till 2021-05-30 (end) + 0.5); // from 2021-04-12 till 2021-05-30 } if (location.get_type() == mio::abm::LocationType::BasicsShop) { location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 } if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.65); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 + location.get_infection_parameters().get().array() *= 0.75; } } @@ -1446,7 +1505,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // first we need two lists, one for 50% of random social event locations and the other list for the other 50% // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] - // ----> Divide Social Event locations into a 50/50 split. First 50% get the restrictive capacity + // ----> Divide Social Event locations into a 50/50 split. First 50% gƒet the restrictive capacity std::vector social_event_location_ids_small; std::vector social_event_location_ids_big; for (auto& location : location_it) { @@ -1456,61 +1515,67 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa } //take 50% of social event locations std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); - auto num_social_event_locations_small = (int)(0.75 * social_event_location_ids_small.size()); - social_event_location_ids_big.insert( - social_event_location_ids_big.end(), social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_small); + auto num_social_event_locations_big = (int)(0.25 * social_event_location_ids_small.size()); + social_event_location_ids_big.insert(social_event_location_ids_big.end(), + social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_big); social_event_location_ids_small.erase(social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + - num_social_event_locations_small); + social_event_location_ids_small.begin() + num_social_event_locations_big); // add capacity limits on day one for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(50, 0); + location.set_capacity(10, 0); } if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(5, 0); + location.set_capacity(0, 0); } } restart_timer(timer, "till advance 14"); - sim.get_world().parameters.get() = 5.5; - sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, + sim.get_world().parameters.get() = viral_shedding_rate; + sim.advance(mio::abm::TimePoint(mio::abm::days(1).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + mio::unused(seasonality_april, seasonality_may, contact_rate_ssc); std::cout << "day 14 finished" << std::endl; // small social events to capacity 5 for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(20, 0); + location.set_capacity(5, 0); + location.get_infection_parameters().get().array() *= contact_rate_ssc; + } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.get_infection_parameters().get().array() *= contact_rate_ssc; } } - restart_timer(timer, "till advance 30 (eastern starts)"); - sim.get_world().parameters.get() = 2.5; - sim.advance(mio::abm::TimePoint(mio::abm::days(30).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); - - restart_timer(timer, "till advance 37 (eastern ends)"); - sim.get_world().parameters.get() = 3.5; - sim.advance(mio::abm::TimePoint(mio::abm::days(37).seconds()), historyInfectionStatePerAgeGroup, + restart_timer(timer, "till advance 31 (march ends)"); + sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + sim.get_world().parameters.get() = + viral_shedding_rate * seasonality_april; restart_timer(timer, "till advance 42"); - sim.get_world().parameters.get() = 2.5; sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - std::cout << "day 42 finished" << std::endl; // date 2021-04-12 + std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::School) { location.set_npi_active(false); } } + + restart_timer(timer, "till advance 60"); + sim.advance(mio::abm::TimePoint(mio::abm::days(62).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 62 finished (date 2021-05-01)" << std::endl; + sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; + restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); @@ -1519,15 +1584,17 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa for (auto& location : location_it) { if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); + location.set_capacity(2, 0); + location.get_infection_parameters().get().array() *= 0.5; } //50% of big social events get reopened and capacity will be limited to xx - int number_of_big_social_events = (int)(0.5 * social_event_location_ids_big.size()); + int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { - location.set_capacity(10, 0); + location.get_infection_parameters().get().array() *= 0.35; + location.set_capacity(15, 0); } } } @@ -1537,7 +1604,6 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa location.set_npi_active(true); } } - sim.get_world().parameters.get() = 2.0; restart_timer(timer, "till advance tmax"); sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 90 finished" << std::endl; @@ -1551,28 +1617,40 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; // Push result of the simulation back to the result vector - ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); - ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); - ensemble_params.emplace_back(std::vector{sim.get_world()}); - std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; - printf("Saving results ... "); + auto rmse = calculate_rmse_from_results(result_dir, temp_sim_infection_state_per_age_group, max_num_days); + rmse_results_per_grid_point.push_back(rmse); } - BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, - result_dir / "infection_state_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, - result_dir / "infection_per_location_type/", save_single_runs)); - restart_timer(timer, "time taken for data gathering and saving results"); - - auto rmse = calculate_rmse_from_results(result_dir, max_num_days); - std::cout << "RMSE Dead: " << rmse.first << " RMSE Exposed: " << rmse.second << std::endl; - restart_timer(timer, "time taken for calculating RMSE"); + // make the gathered results available to all ranks + std::vector, double>> my_results; + for (size_t i = 0; i < grid_search_rank.size(); i++) { + my_results.push_back(std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); + } +#ifdef MEMILIO_ENABLE_MPI + get_grid_search_results_and_write_them_to_file(rank, num_procs, result_dir, my_results); +#endif printf("done.\n"); return mio::success(); } +#endif + +std::vector distribute_runs(size_t num_runs, int num_procs) +{ + //evenly distribute runs + //lower processes do one more run if runs are not evenly distributable + auto num_runs_local = num_runs / num_procs; //integer division! + auto remainder = num_runs % num_procs; + + std::vector run_distribution(num_procs); + std::fill(run_distribution.begin(), run_distribution.begin() + remainder, num_runs_local + 1); + std::fill(run_distribution.begin() + remainder, run_distribution.end(), num_runs_local); + + return run_distribution; +} + mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, bool save_single_runs = true) { @@ -1589,6 +1667,15 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; + auto viral_shedding_rate = 5.5; + auto seasonality_april = 0.9; + auto seasonality_may = 0.6; + auto perc_easter_event = 0.5; + auto dark_figure = 3.2; + auto contact_rate_ssc = 0.33; + auto icu_start_scalability_4 = 7.0; + auto icu_start_scalability_5 = 5.0; + mio::Date start_date{2021, 3, 1}; int max_num_days = 90; auto max_num_persons = 400000; @@ -1624,7 +1711,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date); + determine_initial_infection_states_world(input_dir, start_date, icu_start_scalability_4, icu_start_scalability_5, + dark_figure); restart_timer(timer, "time for determine_initial_infection_states_world"); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); @@ -1633,7 +1721,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { auto world = mio::abm::World(num_age_groupss); - create_sampled_world(world, input_dir, t0, max_num_persons, start_date); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -1741,7 +1829,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), + 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -1758,7 +1847,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // first we need two lists, one for 50% of random social event locations and the other list for the other 50% // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] - // ----> Divide Social Event locations into a 50/50 split. First 50% get the restrictive capacity + // ----> Divide Social Event locations into a 50/50 split. First 50% gƒet the restrictive capacity std::vector social_event_location_ids_small; std::vector social_event_location_ids_big; for (auto& location : location_it) { @@ -1789,8 +1878,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } restart_timer(timer, "till advance 14"); - double normal_infection_viral_shed = 4.2; - sim.get_world().parameters.get() = normal_infection_viral_shed; + sim.get_world().parameters.get() = viral_shedding_rate; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 14 finished" << std::endl; @@ -1800,22 +1888,20 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), location.get_index()) != social_event_location_ids_small.end()) { location.set_capacity(5, 0); - location.get_infection_parameters().get().array() *= 0.75; + location.get_infection_parameters().get().array() *= contact_rate_ssc; } if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.get_infection_parameters().get().array() *= 0.75; + location.get_infection_parameters().get().array() *= contact_rate_ssc; } } restart_timer(timer, "till advance 31 (march ends)"); sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - double seasonality_april = 0.9; sim.get_world().parameters.get() = - normal_infection_viral_shed * seasonality_april; + viral_shedding_rate * seasonality_april; restart_timer(timer, "till advance 42"); - sim.get_world().parameters.get() = normal_infection_viral_shed; sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 @@ -1826,13 +1912,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } - restart_timer(timer, "till advance 60"); + restart_timer(timer, "till advance 62"); sim.advance(mio::abm::TimePoint(mio::abm::days(62).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 62 finished (date 2021-05-01)" << std::endl; - double seasonality_may = 0.65; sim.get_world().parameters.get() = - normal_infection_viral_shed * seasonality_may; + viral_shedding_rate * seasonality_may; restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, @@ -1916,11 +2001,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s #endif restart_timer(timer, "time taken for data gathering and saving results"); - if (rank == 0) { - auto rmse = calculate_rmse_from_results(result_dir, max_num_days); - std::cout << "RMSE Dead: " << rmse.first << " RMSE Exposed: " << rmse.second << std::endl; - restart_timer(timer, "time taken for calculating RMSE"); - } printf("done.\n"); return mio::success(); @@ -1973,6 +2053,7 @@ int main(int argc, char** argv) std::string result_dir = input_dir + "/results_" + currentDateTime(); size_t num_runs; + bool run_grid_search = false; if (argc == 2) { num_runs = atoi(argv[1]); @@ -1981,20 +2062,19 @@ int main(int argc, char** argv) } else if (argc == 3) { - num_runs = atoi(argv[1]); - result_dir = argv[2]; - printf("Running with number of runs = %d\n", (int)num_runs); - printf("Saving results to \"%s\".\n", result_dir.c_str()); + num_runs = atoi(argv[1]); + run_grid_search = (bool)argv[2]; + + if (run_grid_search) { + printf("running with grid search\n"); + printf("Running with number of runs = 1\n"); + } + else { + printf("running without grid search\n"); + printf("Running with number of runs = %d\n", (int)num_runs); + } } else { - printf("Usage:\n"); - printf("abm_example \n"); - printf("\tRun the simulation for time(s).\n"); - printf("\tStore the results in the current directory.\n"); - printf("abm_braunschweig \n"); - printf("\tRun the simulation for time(s).\n"); - printf("\tStore the results in .\n"); - num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); @@ -2009,10 +2089,25 @@ int main(int argc, char** argv) return created.error().code().value(); } timer = TIME_NOW; - // grid search - // std::vector> grid = {{4.0, 6.0}, {0.6, 0.8}, {0.5, 0.9}, {0.7, 0.5}}; - auto result = run(input_dir, result_dir, num_runs); + if (run_grid_search) { + // grid search for parameters: + // 1: Viral Shed + // 2: Seasonality April + // 3: Seasonality May + // 4: Perc Easter Event + // 6: Dark Figure + // 7.: Contact rate forst ssocial ebents closure + std::vector> grid_boundaries = {{4.0, 6.0}, {0.8, 0.95}, {0.5, 0.9}, + {0.2, 0.7}, {1.5, 5.0}, {0.1, 0.5}}; + + std::vector points_per_dim = {2, 2, 2, 3, 3, 3}; + auto grid = grid_points(grid_boundaries, points_per_dim); + auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); + } + else { + auto result = run(input_dir, result_dir, num_runs); + } // copy results into a fixed name folder to have easier access std::string last_run_dir = input_dir + "/results_last_run"; From 4ecd9c589d979bab0ecc79413836524dcf9a4246 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 29 Jul 2024 00:36:37 +0200 Subject: [PATCH 212/488] for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 02119fd9f6..15f5341eab 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2045,8 +2045,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2101,7 +2101,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{4.0, 6.0}, {0.8, 0.95}, {0.5, 0.9}, {0.2, 0.7}, {1.5, 5.0}, {0.1, 0.5}}; - std::vector points_per_dim = {2, 2, 2, 3, 3, 3}; + std::vector points_per_dim = {4, 4, 4, 4, 4, 4}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From 1b8591ddd1368f69443d2eba191a699231e54eec Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:02:10 +0200 Subject: [PATCH 213/488] more improvements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/ode_secir/parameters_io.cpp | 4 +- cpp/simulations/analyze_bs_run.py | 138 +++++------ cpp/simulations/generate_graph_from_data.cpp | 23 +- cpp/simulations/paper_abm_bs_testing.cpp | 245 ++++++++++++------- 4 files changed, 227 insertions(+), 183 deletions(-) diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index 44073b410c..5df16c934f 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -125,6 +125,7 @@ IOResult read_confirmed_cases_data( auto& t_InfectedSymptoms = vt_InfectedSymptoms[region_idx]; auto& t_InfectedSevere = vt_InfectedSevere[region_idx]; auto& t_InfectedCritical = vt_InfectedCritical[region_idx]; + mio::unused(t_InfectedCritical); auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx]; auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx]; @@ -169,8 +170,7 @@ IOResult read_confirmed_cases_data( 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])) { + if (date_df == offset_date_by_days(date, -19)) { num_death[age] += region_entry.num_deaths; if (read_icu) { num_icu[age] -= mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * region_entry.num_confirmed; diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 0deba820a3..42ecd523cf 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -48,7 +48,6 @@ def plot_infections_loc_types_avarage(path): plot_infection_per_location_type_mean( time, total_50, total_25, total_75) - def plot_infection_per_location_type_mean(x, y50, y25, y75): plt.figure('Infection_location_types') @@ -90,7 +89,6 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): plt.ylabel('Number of individuals') plt.show() - def plot_infectoin_states_results(path): # 50-percentile f_p50 = h5py.File( @@ -110,16 +108,9 @@ def plot_infectoin_states_results(path): time = p50_bs['Time'][()] - # real world - f_real = h5py.File( - path + "/Results_rki.h5", 'r') - real_bs = f_real['3101'] - total_real = real_bs['Total'][()] - plot_infection_states_individual( - time, p50_bs, p25_bs, p75_bs, real_bs) - plot_infection_states(time, total_50, total_25, total_75, total_real) - + time, p50_bs, p25_bs, p75_bs) + plot_infection_states(time, total_50, total_25, total_75) def plot_infection_states(x, y50, y25, y75, y_real=None): plt.figure('Infection_states') @@ -155,11 +146,8 @@ def plot_infection_states(x, y50, y25, y75, y_real=None): plt.ylabel('Number of individuals') plt.show() +def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs): -def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): - - y_real_total = real_bs['Total'][()] - x_real = np.linspace(0, y_real_total.shape[0]-1, y_real_total.shape[0]) age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] @@ -173,7 +161,7 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): y50 = p50_bs[j][()] y25 = p25_bs[j][()] y75 = p75_bs[j][()] - y_real = np.floor(real_bs[j][()]) + # infeced no symptoms ax_infected_no_symptoms = ax[0, count] @@ -231,15 +219,13 @@ def plot_infection_states_individual(x, p50_bs, p25_bs, p75_bs, real_bs): ax_dead = ax[4, count] ax_dead.set_xlabel('time (days)') ax_dead.plot(x, y50[:, [7]], color=color_plot[count], label='y50') - ax_dead.plot(x_real, y_real[:, [9]], '.', - color=color_plot[count], label='y_real') ax_dead.fill_between(x, y50[:, 7], y25[:, 7], alpha=0.5, color=color_plot[count]) ax_dead.fill_between(x, y50[:, 7], y75[:, 7], alpha=0.5, color=color_plot[count]) ax_dead.tick_params(axis='y') ax_dead.title.set_text('#Dead, Age{}'.format(j)) - ax_dead.legend(['Simulation', 'Real']) + ax_dead.legend(['Simulation']) # Recovered ax_dead = ax[5, count] @@ -262,68 +248,73 @@ def plot_dead(path): f_p50 = h5py.File( path+"/infection_state_per_age_group/p50/Results.h5", 'r') p50_bs = f_p50['0'] - total_50 = p50_bs['Total'][()] - # we need just every 24th value - total_50 = total_50[::24] - # we just take the first 90 days - total_50 = total_50[0:90] + + age_group_access = ['Group1', 'Group2', 'Group3', + 'Group4', 'Group5', 'Group6', 'Total'] # we need the real data json file cases_all_state_repdate_ma7 df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county.json") - # read in rki data rki_sum - - f_real = h5py.File( - path + "/Results_rki.h5", 'r') - real_bs = f_real['3101'] - total_real = real_bs['Total'][()] - total_real = total_real[0:90] - y_real = total_real[:, 9] - + path+"/../pydata/Germany/cases_all_county_age_ma7.json") # we just need the columns cases and date + # we need to offset the dates by 19 day + df_abb['Date'] = df_abb['Date'] + pd.DateOffset(days=19) # we need just the dates bewteen 2021-03-01 and 2021-06-01 - df_abb = df_abb[(df_abb['Date'] >= '2021-02-01') & - (df_abb['Date'] <= '2021-05-01')] + df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & + (df_abb['Date'] <= '2021-06-01')] # we just need the cases with id 3101 df_abb = df_abb[df_abb['ID_County'] == 3101] - # we just take the first 90 days - df_abb = df_abb[0:90] - # y_real = df_abb['Deaths'].to_numpy() + df_abb['Deaths'] = np.floor(df_abb[['Deaths']].to_numpy()) - # #smooth y_real with a gaussian filter - # y_real = gaussian_filter1d(y_real, sigma=1, mode='nearest') - # # floor it to make it an integer - # y_real = np.floor(y_real) + # we need the amount of dead persons for each age group: These are A00-A04, A05-A14, A15-A34, A35-A59, A60-A79, A80+ + age_groups = ['A00-A04', 'A05-A14', 'A15-A34', 'A35-A59', 'A60-A79', 'A80+'] + # we need to sum up the amount of dead persons for each age group - # we want to offset every date by 28 day - df_abb['Date'] = df_abb['Date'] + pd.DateOffset(days=28) + # we want the deaths for the age groups + df_abb = df_abb[['Date', 'Deaths', 'Age_RKI']] + # we want a plot with 2 rows. Second row has a plot with each age group and the simulated and real dead persons + # First row has the cumulative dead persons + fig = plt.figure('Dead') + fig.set_figwidth(20) + fig.set_figheight(9) + gs = fig.add_gridspec(2,6) + # we need the cumulative dead persons + ax = fig.add_subplot(gs[0, :]) + df_total_dead = df_abb.groupby('Date').sum()[0:90] + y_real = df_total_dead['Deaths'].to_numpy() - # we calculate the RMSE - rmse_dead = np.sqrt(((y_real- total_50[:, 7])**2).mean()) - - # we plot this - fig, ax = plt.subplots(1, 1, constrained_layout=True) - fig.set_figwidth(20) - fig.set_figheight(9) - # we plot the tests positive and the real cases - start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') - ax.plot(df_abb['Date'], total_50[:, 7], color='tab:red') - ax.plot(df_abb['Date'], y_real, color='tab:blue') - # we also write the rmse + rmse_dead = np.sqrt(((y_real- p50_bs['Total'][()][:, 7][::24][0:90])**2).mean()) + # we need to plot the cumulative dead persons from the real world and from the simulation + ax.plot(df_total_dead.index, y_real, color='tab:blue') + ax.plot(df_total_dead.index, p50_bs['Total'][()][:, 7][::24][0:90], color='tab:red') ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) ax.set_xlabel('Date') - ax.set_ylabel('Number of dead') - ax.title.set_text('Cumulative Dead') - ax.legend(['Dead Simulated', 'Real dead']) + ax.set_label('Number of dead') + ax.set_title('Cumulative Dead') + ax.legend(['Real dead', 'Simulated dead']) + + # now for each age group + for i, age_group in zip(range(6), age_group_access): + ax = fig.add_subplot(gs[1, i]) + # we need the amount of dead persons for each age group + df_abb_age_group = df_abb[df_abb['Age_RKI'] == age_groups[i]][0:90] + y_real = np.floor(df_abb_age_group['Deaths'].to_numpy()) + # we need to plot the dead persons from the real world and from the simulation + ax.plot(df_abb_age_group['Date'], y_real, color='tab:blue') + ax.plot(df_abb_age_group['Date'], p50_bs[age_group_access[i]][()][:, 7][::24][0:90], color='tab:red') + ax.set_title('Dead, Age{}'.format(i)) + ax.set_xlabel('Date') + ax.set_xticks(df_abb_age_group['Date'][::50]) + ax.legend(['Real dead, Age{}'.format(i), 'Simulated dead, Age{}'.format(i)]) + plt.show() - + def plot_icu(path): df_abb = pd.read_json(path+"/pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu = 0.4 + perc_of_critical_in_icu = 0.5 # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] @@ -343,12 +334,12 @@ def plot_icu(path): # we just take the first 90 days total_50 = total_50[0:90] - ICU_Simulation = total_50[:, 5]*perc_of_critical_in_icu - ICU_Real = df_abb['ICU'][0:90] + ICU_Simulation = np.floor(total_50[:, 5]*perc_of_critical_in_icu) + ICU_Real = np.floor(df_abb['ICU'][0:90]) #smooth the data - ICU_Real = gaussian_filter1d(ICU_Real, sigma=1, mode='nearest') - ICU_Simulation = gaussian_filter1d(ICU_Simulation, sigma=1, mode='nearest') + # ICU_Real = gaussian_filter1d(ICU_Real, sigma=1, mode='nearest') + # ICU_Simulation = gaussian_filter1d(ICU_Simulation, sigma=1, mode='nearest') @@ -516,19 +507,12 @@ def infer_positive_tests(path): total_50 = p50_bs['Total'][()] total_50 = total_50[::24] total_50 = total_50[0:90] + time = p50_bs['Time'][()] time = time[::24] time = time[0:90] - # # we need the real positive tests - # # real world - # f_real = h5py.File( - # path + "/Results_rki.h5", 'r') - # real_bs = f_real['3101'] - # total_real = real_bs['Total'][()] - # total_real = total_real[0:90] - # we need the real data from the json file cases_all_county_age_repdate_ma7.json df_abb = pd.read_json( path+"/../pydata/Germany/cases_infected_county_repdate_ma7.json") @@ -537,8 +521,6 @@ def infer_positive_tests(path): # we need just the dates bewteen 2021-03-01 and 2021-06-01 df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] - # we just need the cases with id 3101 - df_abb = df_abb[df_abb['ID_County'] == 3101] # we just take the first 90 days df_abb = df_abb[0:90] # we need the amount of new positive tests each day insetad of cumulative @@ -615,7 +597,7 @@ def infer_positive_tests(path): n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) - plot_infections_loc_types_avarage(path) + # plot_infections_loc_types_avarage(path) plot_icu(path+"/..") plot_dead(path) - infer_positive_tests(path) + # infer_positive_tests(path) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 4e304a9a4c..180f75d112 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -134,14 +134,14 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.5, 0.45, 0.4, 0.35, 0.175, 0.05}; - const double severePerInfectedSymptomsMin[] = {0.03, 0.03, 0.04, 0.17, 0.025, 0.04}; - const double severePerInfectedSymptomsMax[] = {0.03, 0.03, 0.04, 0.17, 0.025, 0.04}; - const double criticalPerSevereMin[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; - const double criticalPerSevereMax[] = {0.10, 0.11, 0.12, 0.14, 0.33, 0.8}; - const double deathsPerCriticalMin[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; - const double deathsPerCriticalMax[] = {0.12, 0.13, 0.15, 0.29, 0.40, 0.48}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; + const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.20}; + const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.18, 0.25}; + const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; + const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; + const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; + const double deathsPerCriticalMax[] = {0.10, 0.10, 0.18, 0.18, 0.50, 0.7}; array_assign_uniform_distribution(params.get(), transmissionProbabilityOnContactMin, transmissionProbabilityOnContactMax); @@ -209,8 +209,7 @@ mio::IOResult set_contact_matrices(const fs::path& data_dir, mio::osecir:: * @returns created graph or any io errors that happen during reading of the files. */ mio::IOResult> get_graph(mio::Date start_date, const int num_days, - const fs::path& data_dir, double scaling_factor_ag4, - double scaling_factor_ag5, double sclaling_infected) + const fs::path& data_dir, double sclaling_infected) { // global parameters @@ -229,9 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 0.05); - scaling_factor_icu[4] = scaling_factor_ag4; - scaling_factor_icu[5] = scaling_factor_ag5; + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.0); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 15f5341eab..4f1e414fe2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -79,29 +79,17 @@ mio::CustomIndexArray initia std::map>> vacc_map; -/** - * Create extrapolation of real world data to compare with. -*/ -void extrapolate_real_world_data(mio::osecir::Model& model, const std::string& input_dir, const mio::Date date, - int num_days) -{ - auto test = generate_extrapolated_data({model}, {3101}, date, num_days, input_dir); -} - /** * Determine initial distribution of infection states. */ void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date, - double scaling_factor_ag4, double scaling_factor_ag5, double sclaling_infected) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(date, 1, input_dir, scaling_factor_ag4, scaling_factor_ag5, sclaling_infected); + auto initial_graph = get_graph(date, 1, input_dir, sclaling_infected); const size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); - - // extrapolate_real_world_data(braunschweig_node, input_dir.string(), date, 90); // 90 days } /** @@ -342,6 +330,7 @@ int longLatToInt(const std::string& input) double y = std::stod(input) * 1e+5; //we want the 5 numbers after digit return (int)y; } + void split_line(std::string string, std::vector* row) { std::vector strings; @@ -646,8 +635,8 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.0237; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.0373; params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.0795; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.2; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.3; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.1666; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.2374; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.1; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.11; @@ -971,35 +960,86 @@ void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool socia } } -double calculate_rmse_from_results(const fs::path& results_dir, std::vector> sim_inf_states, - int max_num_days) +std::vector read_in_icu(std::vector divi_data, mio::Date start_date, int max_num_days) { - // We need to read in the results from the results directory - auto real_data_dead = mio::read_result((results_dir / "Results_rki.h5").generic_string()).value()[0].get_totals(); + std::vector icu_data; + for (auto& entry : divi_data) { + if (entry.county_id->get() == 3101) { + if (entry.date >= start_date && entry.date < mio::offset_date_by_days(start_date, max_num_days)) { + icu_data.push_back(entry.num_icu); + } + } + } + return icu_data; +} - // we change the format to two vectors of the same length, in this case for debugging reasons, we just use the first 3 - // for the simulation data we need to take only the first of each day, so just every 24th element - std::vector real_data_dead_vec; - std::vector> sim_data_vec; +std::vector read_in_deaths(std::vector rki_data, mio::Date start_date, + int max_num_days) +{ + std::vector> death_data_age{num_age_groupss}; + auto date_need = mio::offset_date_by_days(start_date, -19); + for (auto& entry : rki_data) { + if (entry.county_id->get() == 3101) { + if (entry.date >= date_need && entry.date < mio::offset_date_by_days(date_need, max_num_days)) { + int age_group = entry.age_group.get(); + death_data_age.at(age_group).push_back(entry.num_deaths); + } + } + } + std::vector death_data; for (int i = 0; i < max_num_days; i++) { - real_data_dead_vec.push_back(real_data_dead[i]((size_t)mio::osecir::InfectionState::Dead)); - // we need to calc total number of dead people - double total_dead = 0; - for (size_t j = 0; j < num_age_groupss; j++) { - int index = (((size_t)(mio::abm::InfectionState::Count)) * (j) + (size_t)mio::abm::InfectionState::Dead); - total_dead = total_dead + (double)sim_inf_states[0][i * 24][index]; + int sum = 0; + for (size_t j = 0; j < death_data_age.size(); j++) { + sum += death_data_age[j][i]; + } + death_data.push_back(sum); + } + + return death_data; +} + +double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries sim_inf_states, + int max_num_days, mio::Date start_date) +{ + // We need to read in the results from the results directory + auto real_data_dead_path = + mio::path_join((data_dir / "pydata" / "Germany").string(), "cases_all_county_age_ma7.json"); + auto real_data_icu_path = mio::path_join((data_dir / "pydata" / "Germany").string(), "county_divi_ma7.json"); + auto divi_data = mio::read_divi_data(real_data_icu_path); + auto death_data = mio::read_confirmed_cases_data(real_data_dead_path); + // read in the real data + auto real_data_dead_vec = read_in_deaths(death_data.value(), start_date, max_num_days); + auto real_data_icu_vec = read_in_icu(divi_data.value(), start_date, max_num_days); + + // Simulated data + std::vector sim_data_vec_icu; + std::vector sim_data_vec_dead; + for (int i = 0; i < max_num_days; i++) { + int number_of_persons_in_icu = 0; + int number_of_persons_dead = 0; + for (size_t j = 0; j < (size_t)num_age_groupss; j++) { + auto index_icu = (((size_t)(mio::abm::InfectionState::Count)) * (j)) + + ((uint32_t)(mio::abm::InfectionState::InfectedCritical)); + auto index_dead = + (((size_t)(mio::abm::InfectionState::Count)) * (j)) + ((uint32_t)(mio::abm::InfectionState::Dead)); + number_of_persons_in_icu += sim_inf_states[i * 24][index_icu]; + number_of_persons_dead += sim_inf_states[i * 24][index_dead]; } - sim_data_vec.push_back(std::make_pair(i, total_dead)); + sim_data_vec_icu.push_back(number_of_persons_in_icu); + sim_data_vec_dead.push_back(number_of_persons_dead); } // now we calculate the RMSE double rmse_dead = 0; + double rmse_icu = 0; for (size_t i = 0; i < real_data_dead_vec.size(); i++) { - rmse_dead += pow(real_data_dead_vec[i] - sim_data_vec[i].second, 2); + rmse_dead += pow(real_data_dead_vec[i] - sim_data_vec_dead[i], 2); + rmse_icu += pow((int)(sim_data_vec_icu[i] * 0.5) - real_data_icu_vec[i], 2); } rmse_dead = sqrt(rmse_dead / real_data_dead_vec.size()); + rmse_icu = sqrt(rmse_icu / real_data_icu_vec.size()); - return rmse_dead; + return rmse_dead + rmse_icu; } /** @@ -1273,6 +1313,36 @@ T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) return gathered_ensemble_vec; } +void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, + std::pair, double> rmse) +{ + //make file if there is no file for my rank + + //file name is grid_search_results_"my_rank".txt + std::string filename = "grid_search_results_" + std::to_string(rank) + ".txt"; + // look if file exists in folder + bool file_exists = std::filesystem::exists(mio::path_join((result_dir / "grid_search").string(), filename)); + if (file_exists) { + // we open it and attach the new rmse double to the end + std::ofstream curr_file((result_dir / "/grid_search/" / filename).string(), std::ios::app); + // write the new rmse with parameters + curr_file << "Grid point: "; + for (size_t j = 0; j < rmse.first.size(); j++) { + curr_file << rmse.first.at(j) << " "; + } + curr_file << "RMSE: " << rmse.second << std::endl; + } + else { + // we create a new file and write the rmse double to it + std::ofstream curr_file((result_dir / "/grid_search/" / filename).string()); + curr_file << "Grid point: "; + for (size_t j = 0; j < rmse.first.size(); j++) { + curr_file << rmse.first.at(j) << " "; + } + curr_file << "RMSE: " << rmse.second << std::endl; + } +} + void get_grid_search_results_and_write_them_to_file( int rank, int num_procs, const fs::path& result_dir, std::vector, double>> grid_my_rank_with_rmse) @@ -1304,7 +1374,7 @@ void get_grid_search_results_and_write_them_to_file( // write the gathered grid search results to a file if (rank == 0) { - std::ofstream file((result_dir / "grid_search_results.txt").string()); + std::ofstream file((result_dir / "/grid_search/grid_search_results.txt").string()); if (!file.is_open()) { mio::log_error("Error opening file for writing grid search results."); } @@ -1337,9 +1407,16 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Distribute the grid search over the MPI ranks auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); + // short debug print to see if everything worked. Printing rank and amount of grid points as well as first point + std::cout << "Rank: " << rank << " has " << grid_search_rank.size() << " grid points" << std::endl; + std::cout << "First grid point: "; + for (size_t j = 0; j < grid_search_rank[0].size(); j++) { + std::cout << grid_search_rank[0].at(j) << " "; + } + std::cout << std::endl; + // Run the grid search std::vector rmse_results_per_grid_point; - for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -1358,12 +1435,10 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa auto perc_easter_event = params[3]; auto dark_figure = params[4]; auto contact_rate_ssc = params[5]; - - auto icu_start_scalability_4 = 7.0; - auto icu_start_scalability_5 = 5.0; + auto masks = params[6]; mio::Date start_date{2021, 3, 1}; - int max_num_days = 1; + int max_num_days = 90; auto max_num_persons = std::numeric_limits::max(); auto t0 = mio::abm::TimePoint(0); // Start time per simulation @@ -1371,8 +1446,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Determine inital infection state distribution restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date, icu_start_scalability_4, - icu_start_scalability_5, dark_figure); + determine_initial_infection_states_world(input_dir, start_date, dark_figure); restart_timer(timer, "time for determine_initial_infection_states_world"); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); @@ -1535,8 +1609,9 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa } restart_timer(timer, "till advance 14"); + sim.get_world().parameters.get() = masks; sim.get_world().parameters.get() = viral_shedding_rate; - sim.advance(mio::abm::TimePoint(mio::abm::days(1).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); mio::unused(seasonality_april, seasonality_may, contact_rate_ssc); std::cout << "day 14 finished" << std::endl; @@ -1570,14 +1645,14 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa } } - restart_timer(timer, "till advance 60"); - sim.advance(mio::abm::TimePoint(mio::abm::days(62).seconds()), historyInfectionStatePerAgeGroup, + restart_timer(timer, "till advance 61"); + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - std::cout << "day 62 finished (date 2021-05-01)" << std::endl; + std::cout << "day 61 finished (date 2021-05-01)" << std::endl; sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; restart_timer(timer, "till advance 72"); - sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(70).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; @@ -1616,10 +1691,13 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - // Push result of the simulation back to the result vector - auto rmse = calculate_rmse_from_results(result_dir, temp_sim_infection_state_per_age_group, max_num_days); + auto rmse = + calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], max_num_days, start_date); rmse_results_per_grid_point.push_back(rmse); + + write_grid_search_prematurely_to_file(rank, result_dir, + std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); } // make the gathered results available to all ranks @@ -1667,14 +1745,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 5.5; - auto seasonality_april = 0.9; - auto seasonality_may = 0.6; - auto perc_easter_event = 0.5; - auto dark_figure = 3.2; - auto contact_rate_ssc = 0.33; - auto icu_start_scalability_4 = 7.0; - auto icu_start_scalability_5 = 5.0; + auto viral_shedding_rate = 6.5; + auto seasonality_april = 0.9; + auto seasonality_may = 0.6; + auto perc_easter_event = 0.5; + auto dark_figure = 3.2; + auto contact_rate_ssc = 0.33; + auto masks = 0.5; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -1711,8 +1788,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date, icu_start_scalability_4, icu_start_scalability_5, - dark_figure); + determine_initial_infection_states_world(input_dir, start_date, dark_figure); restart_timer(timer, "time for determine_initial_infection_states_world"); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); @@ -1879,6 +1955,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "till advance 14"); sim.get_world().parameters.get() = viral_shedding_rate; + sim.get_world().parameters.get() = masks; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 14 finished" << std::endl; @@ -1913,14 +1990,14 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } restart_timer(timer, "till advance 62"); - sim.advance(mio::abm::TimePoint(mio::abm::days(62).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 62 finished (date 2021-05-01)" << std::endl; sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; restart_timer(timer, "till advance 72"); - sim.advance(mio::abm::TimePoint(mio::abm::days(72).seconds()), historyInfectionStatePerAgeGroup, + sim.advance(mio::abm::TimePoint(mio::abm::days(71).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; @@ -2016,20 +2093,17 @@ const std::string currentDateTime() return timeString; } -mio::IOResult create_result_folders(std::string const& result_dir) +mio::IOResult create_result_folders(std::string const& result_dir, bool grid_search = false) { BOOST_OUTCOME_TRY(mio::create_directory(result_dir)); BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_location_type/")); BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_state_per_age_group/")); + if (grid_search) { + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/grid_search/")); + } return mio::success(); } -void copy_precomputed_results(std::string const& from_dir, std::string const& to_dir) -{ - fs::copy(from_dir + "/Results_rki.h5", to_dir, fs::copy_options::overwrite_existing); - fs::copy(from_dir + "/Results_rki_sum.h5", to_dir, fs::copy_options::overwrite_existing); -} - mio::IOResult copy_result_folder(std::string const& from_dir, std::string const& to_dir) { BOOST_OUTCOME_TRY(mio::create_directory(to_dir)); @@ -2045,34 +2119,27 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); size_t num_runs; - bool run_grid_search = false; + bool run_grid_search = true; if (argc == 2) { - num_runs = atoi(argv[1]); + num_runs = std::stoi(argv[1]); + run_grid_search = false; printf("Running with number of runs = %d.\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); } - else if (argc == 3) { - num_runs = atoi(argv[1]); - run_grid_search = (bool)argv[2]; - - if (run_grid_search) { - printf("running with grid search\n"); - printf("Running with number of runs = 1\n"); - } - else { - printf("running without grid search\n"); - printf("Running with number of runs = %d\n", (int)num_runs); - } + num_runs = 1; + run_grid_search = true; + printf("running with grid search\n"); + printf("Running with number of runs = 1\n"); } else { num_runs = 1; @@ -2080,11 +2147,8 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } - auto created = create_result_folders(result_dir); - if (created) { - copy_precomputed_results(precomputed_dir, result_dir); - } - else { + auto created = create_result_folders(result_dir, run_grid_search); + if (!created) { std::cout << created.error().formatted_message(); return created.error().code().value(); } @@ -2098,10 +2162,11 @@ int main(int argc, char** argv) // 4: Perc Easter Event // 6: Dark Figure // 7.: Contact rate forst ssocial ebents closure - std::vector> grid_boundaries = {{4.0, 6.0}, {0.8, 0.95}, {0.5, 0.9}, - {0.2, 0.7}, {1.5, 5.0}, {0.1, 0.5}}; + // 8.: Masks + std::vector> grid_boundaries = {{4.0, 6.0}, {0.85, 0.95}, {0.5, 0.7}, {0.4, 0.5}, + {2.0, 5.0}, {0.3, 0.6}, {0.4, 0.6}}; - std::vector points_per_dim = {4, 4, 4, 4, 4, 4}; + std::vector points_per_dim = {5, 2, 2, 2, 2, 2, 2}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From 4b7756c2a521ba2063fa74e1aea9f857abe87c51 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:05:30 +0200 Subject: [PATCH 214/488] change for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 27 ++++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4f1e414fe2..7143b9cec9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -82,11 +82,10 @@ std::map>> vacc_map; /** * Determine initial distribution of infection states. */ -void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date, - double sclaling_infected) +void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date, double sclaling_infected) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(date, 1, input_dir, sclaling_infected); + auto initial_graph = get_graph(date, 1, input_dir, sclaling_infected); const size_t braunschweig_id = 16; // Braunschweig has ID 16 auto braunschweig_node = initial_graph.value()[braunschweig_id]; initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); @@ -1321,7 +1320,7 @@ void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, //file name is grid_search_results_"my_rank".txt std::string filename = "grid_search_results_" + std::to_string(rank) + ".txt"; // look if file exists in folder - bool file_exists = std::filesystem::exists(mio::path_join((result_dir / "grid_search").string(), filename)); + bool file_exists = boost::filesystem::exists(mio::path_join((result_dir / "grid_search").string(), filename)); if (file_exists) { // we open it and attach the new rmse double to the end std::ofstream curr_file((result_dir / "/grid_search/" / filename).string(), std::ios::app); @@ -1745,13 +1744,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 6.5; - auto seasonality_april = 0.9; - auto seasonality_may = 0.6; - auto perc_easter_event = 0.5; - auto dark_figure = 3.2; - auto contact_rate_ssc = 0.33; - auto masks = 0.5; + auto viral_shedding_rate = 5.0; + auto seasonality_april = 0.85; + auto seasonality_may = 0.5; + auto perc_easter_event = 0.4; + auto dark_figure = 2.0; + auto contact_rate_ssc = 0.3; + auto masks = 0.4; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2119,15 +2118,15 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); size_t num_runs; - bool run_grid_search = true; + bool run_grid_search = false; if (argc == 2) { num_runs = std::stoi(argv[1]); From 01bd8d0d0e58d1bf613268f990366d37d29f95be Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:47:38 +0200 Subject: [PATCH 215/488] some changes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 6 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 42ecd523cf..577f948436 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -534,7 +534,7 @@ def infer_positive_tests(path): best_r_sns = 0 best_lt_sympt = 0 for r_sns in np.linspace(1, 100, 100): - for lt_sympt in np.linspace(0.005, 0.1, 100): + for lt_sympt in np.linspace(0.005, 0.3, 500): total_positive_tests, inferred_positive_tests_sympt, inferred_positive_tests_asympt = calc_positive_tests_overall(total_50, sensitivity, specificity, r_sns, lt_sympt) rmse = np.sqrt(((df_abb['Confirmed'] - total_positive_tests)**2).mean()) if rmse < best_rmse: @@ -598,6 +598,6 @@ def infer_positive_tests(path): if os.path.isfile(os.path.join(path, entry))]) plot_infectoin_states_results(path) # plot_infections_loc_types_avarage(path) - plot_icu(path+"/..") - plot_dead(path) + # plot_icu(path+"/..") + # plot_dead(path) # infer_positive_tests(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7143b9cec9..d1a9d2cd35 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -626,29 +626,29 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.5; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.55; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.6; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.7; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.69; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.825; params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.9; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.0180; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.0237; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.0373; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.0795; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.1666; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.07; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.17; params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.2374; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.1; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.11; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.12; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.14; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.13; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.33; params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.62; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.12; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.13; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.15; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.29; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.4; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.28; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.43; params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.48; // Set infection parameters @@ -2118,8 +2118,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2162,10 +2162,10 @@ int main(int argc, char** argv) // 6: Dark Figure // 7.: Contact rate forst ssocial ebents closure // 8.: Masks - std::vector> grid_boundaries = {{4.0, 6.0}, {0.85, 0.95}, {0.5, 0.7}, {0.4, 0.5}, - {2.0, 5.0}, {0.3, 0.6}, {0.4, 0.6}}; + std::vector> grid_boundaries = {{4.0, 7.0}, {0.8, 0.95}, {0.5, 0.7}, {0.3, 0.6}, + {1.0, 5.0}, {0.2, 0.6}, {0.3, 0.5}}; - std::vector points_per_dim = {5, 2, 2, 2, 2, 2, 2}; + std::vector points_per_dim = {10, 4, 4, 4, 10, 7, 4}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From 2d0b9674d605907e1b8c0949f083ca09e45745d5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:30:09 +0200 Subject: [PATCH 216/488] slightly enhance parameters Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/generate_graph_from_data.cpp | 6 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 180f75d112..d1c734b51e 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -136,8 +136,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double maxRiskOfInfectionFromSymptomaticMax = 0.5; const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; - const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.15, 0.20}; - const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.18, 0.25}; + const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.1, 0.1}; + const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.1, 0.1}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.0); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.5); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d1a9d2cd35..ee19a03c9a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -890,7 +890,7 @@ void set_local_parameters(mio::abm::World& world) loc.get_infection_parameters().get() = contacts_home; loc.get_infection_parameters().get().array() *= 1.5; loc.get_infection_parameters().get().array() *= 1; - loc.get_infection_parameters().get().array() *= 0.75; // 2/5z + loc.get_infection_parameters().get().array() *= 0.66; // 2/5z break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; @@ -900,7 +900,7 @@ void set_local_parameters(mio::abm::World& world) case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; loc.get_infection_parameters().get().array() *= 7.5; - loc.get_infection_parameters().get().array() *= 0.25; // 2/5z + loc.get_infection_parameters().get().array() *= 0.3; // 2/5z break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; From 8b1ffff46d76096a9f0523e05eeb96fc3ea5aaea Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 31 Jul 2024 16:31:22 +0200 Subject: [PATCH 217/488] path for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ee19a03c9a..3c7ab9cfe9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2118,8 +2118,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From 4f13da57173a49a57e56bfc02f19043f9435ece7 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:15:39 +0200 Subject: [PATCH 218/488] Introduce new loggers for testing and reproduction number --- cpp/models/abm/infection.cpp | 5 +- cpp/simulations/analyze_bs_run.py | 5 +- cpp/simulations/paper_abm_bs_testing.cpp | 135 +++++++++++++++++++++-- 3 files changed, 133 insertions(+), 12 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 22be615ec4..a24da71c82 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -47,9 +47,8 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age vl_params.viral_load_incline.get_distribution_instance()(rng, vl_params.viral_load_incline.params); m_viral_load.decline = vl_params.viral_load_decline.get_distribution_instance()(rng, vl_params.viral_load_decline.params); - m_viral_load.end_date = - m_viral_load.start_date + - days(int(m_viral_load.peak / m_viral_load.incline - m_viral_load.peak / m_viral_load.decline)); + m_viral_load.end_date = m_viral_load.start_date + + days(m_viral_load.peak / m_viral_load.incline - m_viral_load.peak / m_viral_load.decline); auto inf_params = params.get()[{virus, age}]; m_log_norm_alpha = diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 577f948436..b62bdcd51e 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -89,7 +89,8 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): plt.ylabel('Number of individuals') plt.show() -def plot_infectoin_states_results(path): + +def plot_infection_states_results(path): # 50-percentile f_p50 = h5py.File( path+"/infection_state_per_age_group/p50/Results.h5", 'r') @@ -596,7 +597,7 @@ def infer_positive_tests(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infectoin_states_results(path) + plot_infection_states_results(path) # plot_infections_loc_types_avarage(path) # plot_icu(path+"/..") # plot_dead(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3c7ab9cfe9..c89e53ad18 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1201,8 +1201,8 @@ struct LogInfectionStatePerAgeGroup : mio::LogAlways { Eigen::VectorXd sum = Eigen::VectorXd::Zero( Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())); - auto curr_time = sim.get_time(); - const auto persons = sim.get_world().get_persons(); + const auto curr_time = sim.get_time(); + const auto persons = sim.get_world().get_persons(); // PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < persons.size(); ++i) { @@ -1251,6 +1251,72 @@ struct LogInfectionPerLocationTypePerAgeGroup : mio::LogAlways { } }; +struct LogTestPerLocationTypePerAgeGroup : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the number of Person%s that have been tested since the last time step. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the number of Person%s that have been tested. + */ + static Type log(const mio::abm::Simulation& sim) + { + + Eigen::VectorXd sum = Eigen::VectorXd::Zero( + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())); + const auto curr_time = sim.get_time(); + const auto prev_time = sim.get_prev_time(); + const auto persons = sim.get_world().get_persons(); + + // PRAGMA_OMP(parallel for) + for (auto i = size_t(0); i < persons.size(); ++i) { + auto& p = persons[i]; + if (p.get_should_be_logged()) { + // PRAGMA_OMP(atomic) + if ((p.get_time_of_last_test() > prev_time)) { + auto index = (((size_t)(mio::abm::LocationType::Count)) * ((uint32_t)p.get_age().get())) + + ((uint32_t)p.get_location().get_type()); + sum[index] += 1; + } + } + } + return std::make_pair(curr_time, sum); + } +}; + +struct LogPositveTestPerLocationTypePerAgeGroup : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the number of Person%s that have been tested positive since the last time step. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the number of Person%s that have been tested positive. + */ + static Type log(const mio::abm::Simulation& sim) + { + + Eigen::VectorXd sum = Eigen::VectorXd::Zero( + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())); + const auto curr_time = sim.get_time(); + const auto prev_time = sim.get_prev_time(); + const auto persons = sim.get_world().get_persons(); + + // PRAGMA_OMP(parallel for) + for (auto i = size_t(0); i < persons.size(); ++i) { + auto& p = persons[i]; + if (p.get_should_be_logged()) { + // PRAGMA_OMP(atomic) + // careful: this check assumes a persons goes into quarantine when a test is positive and that the duration of quarantine is >0 + if (p.get_time_of_last_test() > prev_time && + p.is_in_quarantine(curr_time, sim.get_world().parameters)) { + auto index = (((size_t)(mio::abm::LocationType::Count)) * ((uint32_t)p.get_age().get())) + + ((uint32_t)p.get_location().get_type()); + sum[index] += 1; + } + } + } + return std::make_pair(curr_time, sum); + } +}; + struct LogCumulativeDetectedInfections : mio::LogAlways { using Type = std::pair; /** @@ -1261,9 +1327,9 @@ struct LogCumulativeDetectedInfections : mio::LogAlways { static Type log(const mio::abm::Simulation& sim) { - Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); - auto curr_time = sim.get_time(); - const auto persons = sim.get_world().get_persons(); + Eigen::VectorXd sum = Eigen::VectorXd::Zero(Eigen::Index(sim.get_world().parameters.get_num_groups())); + const auto curr_time = sim.get_time(); + const auto persons = sim.get_world().get_persons(); // PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < persons.size(); ++i) { @@ -1280,6 +1346,61 @@ struct LogCumulativeDetectedInfections : mio::LogAlways { } }; +struct LogEstimatedReproductionNumber : mio::LogAlways { + using Type = std::pair; + /** + * @brief Log the TimeSeries of the estimated reproduction number. + * @param[in] sim The simulation of the abm. + * @return A pair of the TimePoint and the TimeSeries of the estimated reproduction number. + */ + static Type log(const mio::abm::Simulation& sim) + { + // time period to take into account for estimating the reproduction number + // longer periods lead to more averaged results + mio::abm::TimeSpan time_frame = mio::abm::days(1); + const auto t = sim.get_time(); + const auto persons = sim.get_world().get_persons(); + const auto virus = mio::abm::VirusVariant::Alpha; + + // PRAGMA_OMP(parallel for) + int number_newly_infected = 0; + int number_infectious = 0; + for (auto i = size_t(0); i < persons.size(); ++i) { + auto& p = persons[i]; + if (p.get_should_be_logged()) { + // PRAGMA_OMP(atomic) + if (p.is_infected(t) && !p.is_infected(t - time_frame)) { + number_newly_infected += 1; + } + // count infectious people at the midpoint of the time period as an estimation + if (p.is_infected(t - time_frame / 2)) { + if (p.get_infection().get_viral_shed(t - time_frame / 2) != 0) { + number_infectious += 1; + } + } + } + } + // if the infection dies out, the reproduction number has no meaningful value + if (number_infectious == 0) { + return std::make_pair(t, 0); + } + + // assume equal parameters for each age + auto vl_params = sim.get_world().parameters.get()[{virus, age_group_0_to_4}]; + + // Assume uniform distribution of parameters. Taking mean value of uniform distribution. Factor 1/2 cancels in the division. + double average_infectious_period = + (vl_params.viral_load_peak.params.a() + vl_params.viral_load_peak.params.b()) / + (vl_params.viral_load_incline.params.a() + vl_params.viral_load_incline.params.b()) - + (vl_params.viral_load_peak.params.a() + vl_params.viral_load_peak.params.b()) / + (vl_params.viral_load_decline.params.a() + vl_params.viral_load_decline.params.b()); + + double estimation = + (number_newly_infected * average_infectious_period) / (number_infectious * time_frame.days()); + return std::make_pair(t, estimation); + } +}; + #ifdef MEMILIO_ENABLE_MPI template T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) @@ -2118,9 +2239,9 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); From c451fbfec1a585139e188d1b800774d8153b9280 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:23:29 +0200 Subject: [PATCH 219/488] Further included new loggers --- cpp/simulations/paper_abm_bs_testing.cpp | 144 +++++++++++++++++------ 1 file changed, 111 insertions(+), 33 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c89e53ad18..a176ee00b2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1283,7 +1283,7 @@ struct LogTestPerLocationTypePerAgeGroup : mio::LogAlways { } }; -struct LogPositveTestPerLocationTypePerAgeGroup : mio::LogAlways { +struct LogPositiveTestPerLocationTypePerAgeGroup : mio::LogAlways { using Type = std::pair; /** * @brief Log the TimeSeries of the number of Person%s that have been tested positive since the last time step. @@ -1347,7 +1347,7 @@ struct LogCumulativeDetectedInfections : mio::LogAlways { }; struct LogEstimatedReproductionNumber : mio::LogAlways { - using Type = std::pair; + using Type = std::pair; /** * @brief Log the TimeSeries of the estimated reproduction number. * @param[in] sim The simulation of the abm. @@ -1355,6 +1355,8 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { */ static Type log(const mio::abm::Simulation& sim) { + Eigen::VectorXd estimation = Eigen::VectorXd::Zero(Eigen::Index(1)); + // time period to take into account for estimating the reproduction number // longer periods lead to more averaged results mio::abm::TimeSpan time_frame = mio::abm::days(1); @@ -1382,7 +1384,7 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { } // if the infection dies out, the reproduction number has no meaningful value if (number_infectious == 0) { - return std::make_pair(t, 0); + return std::make_pair(t, estimation); } // assume equal parameters for each age @@ -1395,8 +1397,7 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { (vl_params.viral_load_peak.params.a() + vl_params.viral_load_peak.params.b()) / (vl_params.viral_load_decline.params.a() + vl_params.viral_load_decline.params.b()); - double estimation = - (number_newly_infected * average_infectious_period) / (number_infectious * time_frame.days()); + estimation[0] += (number_newly_infected * average_infectious_period) / (number_infectious * time_frame.days()); return std::make_pair(t, estimation); } }; @@ -1876,23 +1877,35 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; int max_num_days = 90; auto max_num_persons = 400000; - bool npis_on = true; + bool npis_on = false; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation - auto ensemble_infection_per_loc_type = - std::vector>>{}; // Vector of infection per location type results - ensemble_infection_per_loc_type.reserve(size_t(num_runs)); + auto ensemble_infection_per_loc_type_per_age_group = std::vector< + std::vector>>{}; // Vector of infection per location type per age group results + ensemble_infection_per_loc_type_per_age_group.reserve(size_t(num_runs)); auto ensemble_infection_state_per_age_group = std::vector>>{}; // Vector of infection state per age group results ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); + auto ensemble_test_per_loc_type_per_age_group = std::vector< + std::vector>>{}; // Vector of tests per location type per age group results + ensemble_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + + auto ensemble_positive_test_per_loc_type_per_age_group = std::vector< + std::vector>>{}; // Vector of positive tests per location type per age group results + ensemble_positive_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + auto ensemble_cumulative_detected_infections = std::vector>>{}; // Vector of cumulative detected infections ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); + auto ensemble_estimated_reproduction_number = + std::vector>>{}; // Vector of estimated reproduction number + ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); + auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); @@ -1924,12 +1937,20 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s //Logger mio::History - historyInfectionPerLocationType{ + historyInfectionPerLocationTypePerAgeGroup{ Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyTestPerLocationTypePerAgeGroup{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyPositiveTestPerLocationTypePerAgeGroup{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyCumulativeDetectedInfections{ Eigen::Index(sim.get_world().parameters.get_num_groups())}; + mio::History historyEstimatedReproductionNumber{ + Eigen::Index(1)}; // / NPIS// if (npis_on) { @@ -2076,8 +2097,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "till advance 14"); sim.get_world().parameters.get() = viral_shedding_rate; sim.get_world().parameters.get() = masks; - sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionPerLocationTypePerAgeGroup, + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, + historyEstimatedReproductionNumber); std::cout << "day 14 finished" << std::endl; // small social events to capacity 5 @@ -2093,14 +2116,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } restart_timer(timer, "till advance 31 (march ends)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionPerLocationTypePerAgeGroup, + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, + historyEstimatedReproductionNumber); sim.get_world().parameters.get() = viral_shedding_rate * seasonality_april; restart_timer(timer, "till advance 42"); - sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionPerLocationTypePerAgeGroup, + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, + historyEstimatedReproductionNumber); std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 for (auto& location : location_it) { @@ -2110,15 +2137,19 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } restart_timer(timer, "till advance 62"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationTypePerAgeGroup, + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, + historyEstimatedReproductionNumber); std::cout << "day 62 finished (date 2021-05-01)" << std::endl; sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; restart_timer(timer, "till advance 72"); - sim.advance(mio::abm::TimePoint(mio::abm::days(71).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + sim.advance(mio::abm::TimePoint(mio::abm::days(71).seconds()), historyInfectionPerLocationTypePerAgeGroup, + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, + historyEstimatedReproductionNumber); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; for (auto& location : location_it) { @@ -2145,24 +2176,41 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + sim.advance(tmax, historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, + historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, + historyCumulativeDetectedInfections, historyEstimatedReproductionNumber); std::cout << "day 90 finished" << std::endl; } else { - sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionPerLocationTypePerAgeGroup, + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, + historyEstimatedReproductionNumber); } ////Advance till here // Stop the clock after sim.advance and calculate the duration restart_timer(timer, "time taken for simulation end"); // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_infection_per_loc_tpye = - std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_per_loc_type_per_age_group = + std::vector>{std::get<0>(historyInfectionPerLocationTypePerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + auto temp_sim_test_per_loc_type_per_age_group = + std::vector>{std::get<0>(historyTestPerLocationTypePerAgeGroup.get_log())}; + auto temp_sim_positive_test_per_loc_type_per_age_group = std::vector>{ + std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; + auto temp_sim_cumulative_detected_infections_per_age_group = + std::vector>{std::get<0>(historyCumulativeDetectedInfections.get_log())}; + auto temp_sim_estimated_reproduction_number = + std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; // Push result of the simulation back to the result vector - ensemble_infection_per_loc_type.emplace_back(temp_sim_infection_per_loc_tpye); + ensemble_infection_per_loc_type_per_age_group.emplace_back(temp_sim_infection_per_loc_type_per_age_group); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); + ensemble_test_per_loc_type_per_age_group.emplace_back(temp_sim_test_per_loc_type_per_age_group); + ensemble_positive_test_per_loc_type_per_age_group.emplace_back( + temp_sim_positive_test_per_loc_type_per_age_group); + ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); + ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; @@ -2179,22 +2227,47 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s #ifdef MEMILIO_ENABLE_MPI //gather results + auto final_ensemble_infection_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type_per_age_group); auto final_ensemble_infection_state_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); - auto final_ensemble_infection_per_loc_type = - gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type); + auto final_ensemble_test_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_test_per_loc_type_per_age_group); + auto final_ensemble_positive_test_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); + auto final_ensemble_cumulative_detected_infections = + gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); + auto final_ensemble_estimated_reproduction_number = + gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); if (rank == 0) { + BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "infection_per_location_type_per_age_group/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type, ensemble_params, {0}, - result_dir / "infection_per_location_type/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "test_per_location_type_per_age_group/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "positive_test_per_location_type_per_age_group/", + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, + result_dir / "cumulative_detected_infections/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, + result_dir / "estimated_reproduction_number/", save_single_runs)); } #else + BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, + result_dir / "infection_per_location_type_per_age_group/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, - result_dir / "infection_per_location_type/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "test_per_location_type_per_age_group/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "positive_test_per_location_type_per_age_group/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_cumulative_detected_infections, ensemble_params, {0}, + result_dir / "cumulative_detected_infections/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_estimated_reproduction_number, ensemble_params, {0}, + result_dir / "estimated_reproduction_number/", save_single_runs)); #endif restart_timer(timer, "time taken for data gathering and saving results"); @@ -2216,8 +2289,13 @@ const std::string currentDateTime() mio::IOResult create_result_folders(std::string const& result_dir, bool grid_search = false) { BOOST_OUTCOME_TRY(mio::create_directory(result_dir)); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_location_type/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_location_type_per_age_group/")); BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_state_per_age_group/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/test_per_location_type_per_age_group/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/positive_test_per_location_type_per_age_group/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/cumulative_detected_infections/")); + BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/estimated_reproduction_number/")); + if (grid_search) { BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/grid_search/")); } From e7fc7b28e2a05e38e9e46237caddb98c5013ae9a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:26:10 +0200 Subject: [PATCH 220/488] quick fix for cluster to run only on omp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 599 +++++++++++------------ 1 file changed, 297 insertions(+), 302 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a176ee00b2..e1dfcfb546 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1434,36 +1434,6 @@ T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) return gathered_ensemble_vec; } -void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, - std::pair, double> rmse) -{ - //make file if there is no file for my rank - - //file name is grid_search_results_"my_rank".txt - std::string filename = "grid_search_results_" + std::to_string(rank) + ".txt"; - // look if file exists in folder - bool file_exists = boost::filesystem::exists(mio::path_join((result_dir / "grid_search").string(), filename)); - if (file_exists) { - // we open it and attach the new rmse double to the end - std::ofstream curr_file((result_dir / "/grid_search/" / filename).string(), std::ios::app); - // write the new rmse with parameters - curr_file << "Grid point: "; - for (size_t j = 0; j < rmse.first.size(); j++) { - curr_file << rmse.first.at(j) << " "; - } - curr_file << "RMSE: " << rmse.second << std::endl; - } - else { - // we create a new file and write the rmse double to it - std::ofstream curr_file((result_dir / "/grid_search/" / filename).string()); - curr_file << "Grid point: "; - for (size_t j = 0; j < rmse.first.size(); j++) { - curr_file << rmse.first.at(j) << " "; - } - curr_file << "RMSE: " << rmse.second << std::endl; - } -} - void get_grid_search_results_and_write_them_to_file( int rank, int num_procs, const fs::path& result_dir, std::vector, double>> grid_my_rank_with_rmse) @@ -1510,6 +1480,38 @@ void get_grid_search_results_and_write_them_to_file( } } +#endif + +void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, + std::pair, double> rmse) +{ + //make file if there is no file for my rank + + //file name is grid_search_results_"my_rank".txt + std::string filename = "grid_search_results_" + std::to_string(rank) + ".txt"; + // look if file exists in folder + bool file_exists = boost::filesystem::exists(mio::path_join((result_dir / "grid_search").string(), filename)); + if (file_exists) { + // we open it and attach the new rmse double to the end + std::ofstream curr_file((result_dir / "/grid_search/" / filename).string(), std::ios::app); + // write the new rmse with parameters + curr_file << "Grid point: "; + for (size_t j = 0; j < rmse.first.size(); j++) { + curr_file << rmse.first.at(j) << " "; + } + curr_file << "RMSE: " << rmse.second << std::endl; + } + else { + // we create a new file and write the rmse double to it + std::ofstream curr_file((result_dir / "/grid_search/" / filename).string()); + curr_file << "Grid point: "; + for (size_t j = 0; j < rmse.first.size(); j++) { + curr_file << rmse.first.at(j) << " "; + } + curr_file << "RMSE: " << rmse.second << std::endl; + } +} + mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::path& result_dir, int num_runs, std::vector> grid_points) { @@ -1538,304 +1540,299 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Run the grid search std::vector rmse_results_per_grid_point; - for (size_t i = 0; i < grid_search_rank.size(); i++) { - auto params = grid_search_rank[i]; - - // grid search for parameters: - // 1: Viral Shed - // 2: Seasonality April - // 3: Seasonality May - // 4: Perc Easter Event - // 6: Dark Figure - // 7.: Contact rate forst ssocial ebents closure - // 8.: Contact intensity for social events - // 9.: Contact rate for home - auto viral_shedding_rate = params[0]; - auto seasonality_april = params[1]; - auto seasonality_may = params[2]; - auto perc_easter_event = params[3]; - auto dark_figure = params[4]; - auto contact_rate_ssc = params[5]; - auto masks = params[6]; - - mio::Date start_date{2021, 3, 1}; - int max_num_days = 90; - auto max_num_persons = std::numeric_limits::max(); - - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation - - // Determine inital infection state distribution - restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date, dark_figure); - restart_timer(timer, "time for determine_initial_infection_states_world"); - prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), - (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - restart_timer(timer, "time for vaccinaiton state"); - - // Loop over a number of runs - auto world = mio::abm::World(num_age_groupss); - - create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); + rmse_results_per_grid_point.reserve(grid_search_rank.size()); + +PRAGMA_OMP(parallel for) +for (size_t i = 0; i < grid_search_rank.size(); i++) { + auto params = grid_search_rank[i]; + + // grid search for parameters: + // 1: Viral Shed + // 2: Seasonality April + // 3: Seasonality May + // 4: Perc Easter Event + // 6: Dark Figure + // 7.: Contact rate forst ssocial ebents closure + // 8.: Contact intensity for social events + // 9.: Contact rate for home + auto viral_shedding_rate = params[0]; + auto seasonality_april = params[1]; + auto seasonality_may = params[2]; + auto perc_easter_event = params[3]; + auto dark_figure = params[4]; + auto contact_rate_ssc = params[5]; + auto masks = params[6]; - restart_timer(timer, "time taken for create sampled world"); - auto sim = mio::abm::Simulation(t0, std::move(world)); + mio::Date start_date{2021, 3, 1}; + int max_num_days = 90; + auto max_num_persons = std::numeric_limits::max(); - //Logger - mio::History - historyInfectionPerLocationType{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History historyInfectionStatePerAgeGroup{ - Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - mio::History historyCumulativeDetectedInfections{ - Eigen::Index(sim.get_world().parameters.get_num_groups())}; + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation - // / NPIS// + // Determine inital infection state distribution + restart_timer(timer, "time for initial setup"); + determine_initial_infection_states_world(input_dir, start_date, dark_figure); + restart_timer(timer, "time for determine_initial_infection_states_world"); + prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); + restart_timer(timer, "time for vaccinaiton state"); - const auto location_it = sim.get_world().get_locations(); - - // 1. testing schemes in schools - auto testing_min_time_school = mio::abm::days(7); - auto probability_school = 1.0; - auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 - auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 - auto test_type_school = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = - sim.get_world().parameters.get()[test_type_school]; // Test parameters - auto testing_criteria_school = mio::abm::TestingCriteria(); - auto testing_scheme_school = - mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, - end_date_test_school, test_parameters, probability_school); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - testing_scheme_school); - - // 2. testing schemes in work places for 35% of random workplaces - std::vector work_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::Work) { - work_location_ids.push_back(location.get_index()); - } + // Loop over a number of runs + auto world = mio::abm::World(num_age_groupss); + + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); + + restart_timer(timer, "time taken for create sampled world"); + auto sim = mio::abm::Simulation(t0, std::move(world)); + + //Logger + mio::History historyInfectionPerLocationType{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyInfectionStatePerAgeGroup{ + Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyCumulativeDetectedInfections{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; + + // / NPIS// + + const auto location_it = sim.get_world().get_locations(); + + // 1. testing schemes in schools + auto testing_min_time_school = mio::abm::days(7); + auto probability_school = 1.0; + auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 + auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 + auto test_type_school = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters = sim.get_world().parameters.get()[test_type_school]; // Test parameters + auto testing_criteria_school = mio::abm::TestingCriteria(); + auto testing_scheme_school = + mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, + end_date_test_school, test_parameters, probability_school); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); + + // 2. testing schemes in work places for 35% of random workplaces + std::vector work_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::Work) { + work_location_ids.push_back(location.get_index()); } - //take 35% of work locations - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); - auto num_work_locations = (int)(0.35 * work_location_ids.size()); - std::vector work_location_ids_35(work_location_ids.begin(), - work_location_ids.begin() + num_work_locations); - auto testing_min_time_work = mio::abm::days(1); - auto probability_work = 1.0; - auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); - auto end_date_test_work = mio::abm::TimePoint(tmax); - auto test_type_work = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_work = - sim.get_world().parameters.get()[test_type_work]; // Test parameters - auto testing_criteria_work = mio::abm::TestingCriteria(); - auto testing_scheme_work = - mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, - end_date_test_work, test_parameters_work, probability_work); - for (auto& location_id : work_location_ids_35) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); + } + //take 35% of work locations + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); + auto num_work_locations = (int)(0.35 * work_location_ids.size()); + std::vector work_location_ids_35(work_location_ids.begin(), + work_location_ids.begin() + num_work_locations); + auto testing_min_time_work = mio::abm::days(1); + auto probability_work = 1.0; + auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); + auto end_date_test_work = mio::abm::TimePoint(tmax); + auto test_type_work = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_work = sim.get_world().parameters.get()[test_type_work]; // Test parameters + auto testing_criteria_work = mio::abm::TestingCriteria(); + auto testing_scheme_work = + mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, end_date_test_work, + test_parameters_work, probability_work); + for (auto& location_id : work_location_ids_35) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); + } + + // 2.5 plus testing schemes at 20 % of basics shops + std::vector basics_shop_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + basics_shop_location_ids.push_back(location.get_index()); } - - // 2.5 plus testing schemes at 20 % of basics shops - std::vector basics_shop_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - basics_shop_location_ids.push_back(location.get_index()); - } + } + //take 20% of basics shop locations + std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); + auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); + std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), + basics_shop_location_ids.begin() + num_basics_shop_locations); + auto testing_min_time_basics_shop = mio::abm::days(2); + auto probability_basics_shop = 1.0; + auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); + auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); + auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_basics_shop = + sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters + auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); + auto testing_scheme_basics_shop = + mio::abm::TestingScheme(testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, + end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); + for (auto& location_id : basics_shop_location_ids_20) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); + } + + // 3. Mask schemes for all locations + // First set all locations to have mask usage, we need ffp2 masks + for (auto& location : location_it) { + location.set_required_mask(mio::abm::MaskType::FFP2); + if (location.get_type() == mio::abm::LocationType::Home) { + location.set_npi_active(false); } - //take 20% of basics shop locations - std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); - auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); - std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), - basics_shop_location_ids.begin() + num_basics_shop_locations); - auto testing_min_time_basics_shop = mio::abm::days(2); - auto probability_basics_shop = 1.0; - auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); - auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); - auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_basics_shop = - sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters - auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); - auto testing_scheme_basics_shop = mio::abm::TestingScheme( - testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, - end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); - for (auto& location_id : basics_shop_location_ids_20) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); + else { + location.set_npi_active(true); } + } - // 3. Mask schemes for all locations - // First set all locations to have mask usage, we need ffp2 masks - for (auto& location : location_it) { - location.set_required_mask(mio::abm::MaskType::FFP2); - if (location.get_type() == mio::abm::LocationType::Home) { - location.set_npi_active(false); - } - else { - location.set_npi_active(true); - } + // // 4. Dampings for schools and Basic shops + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::School) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), + 0.5); // from 2021-04-12 till 2021-05-30 } - - // // 4. Dampings for schools and Basic shops - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), - 0.5); // from 2021-04-12 till 2021-05-30 - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 - } - if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 - location.get_infection_parameters().get().array() *= 0.75; - } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 + location.get_infection_parameters().get().array() *= 0.75; } + } - // 5. add capacity limits to some locations - // first we need two lists, one for 50% of random social event locations and the other list for the other 50% - // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ - // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] - // ----> Divide Social Event locations into a 50/50 split. First 50% gƒet the restrictive capacity - std::vector social_event_location_ids_small; - std::vector social_event_location_ids_big; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::SocialEvent) { - social_event_location_ids_small.push_back(location.get_index()); - } + // 5. add capacity limits to some locations + // first we need two lists, one for 50% of random social event locations and the other list for the other 50% + // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ + // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] + // ----> Divide Social Event locations into a 50/50 split. First 50% gƒet the restrictive capacity + std::vector social_event_location_ids_small; + std::vector social_event_location_ids_big; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::SocialEvent) { + social_event_location_ids_small.push_back(location.get_index()); } - //take 50% of social event locations - std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); - auto num_social_event_locations_big = (int)(0.25 * social_event_location_ids_small.size()); - social_event_location_ids_big.insert(social_event_location_ids_big.end(), - social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_big); - social_event_location_ids_small.erase(social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_big); - - // add capacity limits on day one - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); - } - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(0, 0); - } + } + //take 50% of social event locations + std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); + auto num_social_event_locations_big = (int)(0.25 * social_event_location_ids_small.size()); + social_event_location_ids_big.insert(social_event_location_ids_big.end(), social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_big); + social_event_location_ids_small.erase(social_event_location_ids_small.begin(), + social_event_location_ids_small.begin() + num_social_event_locations_big); + + // add capacity limits on day one + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(10, 0); } + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + location.set_capacity(0, 0); + } + } - restart_timer(timer, "till advance 14"); - sim.get_world().parameters.get() = masks; - sim.get_world().parameters.get() = viral_shedding_rate; - sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); - mio::unused(seasonality_april, seasonality_may, contact_rate_ssc); - std::cout << "day 14 finished" << std::endl; - - // small social events to capacity 5 - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(5, 0); - location.get_infection_parameters().get().array() *= contact_rate_ssc; - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.get_infection_parameters().get().array() *= contact_rate_ssc; - } + restart_timer(timer, "till advance 14"); + sim.get_world().parameters.get() = masks; + sim.get_world().parameters.get() = viral_shedding_rate; + sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + mio::unused(seasonality_april, seasonality_may, contact_rate_ssc); + std::cout << "day 14 finished" << std::endl; + + // small social events to capacity 5 + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(5, 0); + location.get_infection_parameters().get().array() *= contact_rate_ssc; } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.get_infection_parameters().get().array() *= contact_rate_ssc; + } + } - restart_timer(timer, "till advance 31 (march ends)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); - sim.get_world().parameters.get() = - viral_shedding_rate * seasonality_april; + restart_timer(timer, "till advance 31 (march ends)"); + sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + sim.get_world().parameters.get() = viral_shedding_rate * seasonality_april; - restart_timer(timer, "till advance 42"); - sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); - std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 + restart_timer(timer, "till advance 42"); + sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(false); - } + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School) { + location.set_npi_active(false); } + } - restart_timer(timer, "till advance 61"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); - std::cout << "day 61 finished (date 2021-05-01)" << std::endl; - sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; - - restart_timer(timer, "till advance 72"); - sim.advance(mio::abm::TimePoint(mio::abm::days(70).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); - std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(2, 0); - location.get_infection_parameters().get().array() *= 0.5; - } - //50% of big social events get reopened and capacity will be limited to xx - int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - number_of_big_social_events--; - if (number_of_big_social_events >= 0) { - location.get_infection_parameters().get().array() *= 0.35; - location.set_capacity(15, 0); - } - } + restart_timer(timer, "till advance 61"); + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 61 finished (date 2021-05-01)" << std::endl; + sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; + + restart_timer(timer, "till advance 72"); + sim.advance(mio::abm::TimePoint(mio::abm::days(70).seconds()), historyInfectionStatePerAgeGroup, + historyInfectionPerLocationType); + std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + + for (auto& location : location_it) { + if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), + location.get_index()) != social_event_location_ids_small.end()) { + location.set_capacity(2, 0); + location.get_infection_parameters().get().array() *= 0.5; } - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School && - location.get_type() != mio::abm::LocationType::Home) { - location.set_npi_active(true); + //50% of big social events get reopened and capacity will be limited to xx + int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); + if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), + location.get_index()) != social_event_location_ids_big.end()) { + number_of_big_social_events--; + if (number_of_big_social_events >= 0) { + location.get_infection_parameters().get().array() *= 0.35; + location.set_capacity(15, 0); } } - restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - std::cout << "day 90 finished" << std::endl; - - ////Advance till here - // Stop the clock after sim.advance and calculate the duration - restart_timer(timer, "time taken for simulation end"); - // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_infection_per_loc_tpye = - std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; - auto temp_sim_infection_state_per_age_group = - std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - - auto rmse = - calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], max_num_days, start_date); - rmse_results_per_grid_point.push_back(rmse); - - write_grid_search_prematurely_to_file(rank, result_dir, - std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); } - - // make the gathered results available to all ranks - std::vector, double>> my_results; - for (size_t i = 0; i < grid_search_rank.size(); i++) { - my_results.push_back(std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::School && + location.get_type() != mio::abm::LocationType::Home) { + location.set_npi_active(true); + } } + restart_timer(timer, "till advance tmax"); + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + std::cout << "day 90 finished" << std::endl; + + ////Advance till here + // Stop the clock after sim.advance and calculate the duration + restart_timer(timer, "time taken for simulation end"); + // TODO: update result of the simulation to be a vector of location result. + auto temp_sim_infection_per_loc_tpye = + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_state_per_age_group = + std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + + auto rmse = + calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], max_num_days, start_date); + rmse_results_per_grid_point.at(i) = rmse; + + write_grid_search_prematurely_to_file(rank, result_dir, + std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); +} + +// make the gathered results available to all ranks +std::vector, double>> my_results; +for (size_t i = 0; i < grid_search_rank.size(); i++) { + my_results.push_back(std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); +} #ifdef MEMILIO_ENABLE_MPI - get_grid_search_results_and_write_them_to_file(rank, num_procs, result_dir, my_results); +get_grid_search_results_and_write_them_to_file(rank, num_procs, result_dir, my_results); #endif - printf("done.\n"); - return mio::success(); +printf("done.\n"); +return mio::success(); } -#endif - std::vector distribute_runs(size_t num_runs, int num_procs) { //evenly distribute runs @@ -2256,8 +2253,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } #else - BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type, ensemble_params, {0}, - result_dir / "infection_per_location_type_per_age_group/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, @@ -2318,8 +2313,8 @@ int main(int argc, char** argv) #endif // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; - std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; std::string result_dir = input_dir + "/results_" + currentDateTime(); @@ -2364,7 +2359,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{4.0, 7.0}, {0.8, 0.95}, {0.5, 0.7}, {0.3, 0.6}, {1.0, 5.0}, {0.2, 0.6}, {0.3, 0.5}}; - std::vector points_per_dim = {10, 4, 4, 4, 10, 7, 4}; + std::vector points_per_dim = {2, 2, 2, 2, 2, 2, 4}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From eed23592dc80d0b4c1487f53eab8b27627befb5f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:34:31 +0200 Subject: [PATCH 221/488] qucik bugfix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e1dfcfb546..1570c7d149 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1540,7 +1540,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Run the grid search std::vector rmse_results_per_grid_point; - rmse_results_per_grid_point.reserve(grid_search_rank.size()); + rmse_results_per_grid_point.resize(grid_search_rank.size()); PRAGMA_OMP(parallel for) for (size_t i = 0; i < grid_search_rank.size(); i++) { @@ -2312,8 +2312,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From a5db3e9410bc008496d0f03b99c27e45a762cf0e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:38:40 +0200 Subject: [PATCH 222/488] cout for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1570c7d149..47dd7cfb52 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2361,7 +2361,8 @@ int main(int argc, char** argv) std::vector points_per_dim = {2, 2, 2, 2, 2, 2, 4}; auto grid = grid_points(grid_boundaries, points_per_dim); - auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); + std::cout << "Grid size: " << grid.size() << std::endl; + auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } else { auto result = run(input_dir, result_dir, num_runs); From a0c90871558a806934e53049a38f645546e257a3 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:41:09 +0200 Subject: [PATCH 223/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 47dd7cfb52..aa5c9acfae 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1527,6 +1527,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // define parameters for grid search + std::cout << "Test" << std::endl; // Distribute the grid search over the MPI ranks auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); From c0beb2116d2a50fd7e94aa8a17d4b4a49bde39c6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:42:32 +0200 Subject: [PATCH 224/488] test2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index aa5c9acfae..b7659ca087 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1529,7 +1529,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::cout << "Test" << std::endl; // Distribute the grid search over the MPI ranks - auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); + // auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); // short debug print to see if everything worked. Printing rank and amount of grid points as well as first point std::cout << "Rank: " << rank << " has " << grid_search_rank.size() << " grid points" << std::endl; From 4decaf82903c103c206fe22816936b5a3dc965e1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:43:35 +0200 Subject: [PATCH 225/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b7659ca087..ddcf84f1f6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1076,6 +1076,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, if (rank == num_procs - 1) { points_per_rank = number_of_points - points_per_rank * (num_procs - 1); } + std::cout << "Test2" << std::endl; // we calculate every possible combination of the grid, independently of the rank std::vector> grid_search; std::vector counter_per_dimension(grid.size(), 0); @@ -1529,7 +1530,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::cout << "Test" << std::endl; // Distribute the grid search over the MPI ranks - // auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); + auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); // short debug print to see if everything worked. Printing rank and amount of grid points as well as first point std::cout << "Rank: " << rank << " has " << grid_search_rank.size() << " grid points" << std::endl; From be55832d3a94eec0ce1d0b872c7e3214b2e55f13 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:43:41 +0200 Subject: [PATCH 226/488] teest Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ddcf84f1f6..0c89beb17c 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1076,7 +1076,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, if (rank == num_procs - 1) { points_per_rank = number_of_points - points_per_rank * (num_procs - 1); } - std::cout << "Test2" << std::endl; + std::cout << "Test2" << std::endl; // we calculate every possible combination of the grid, independently of the rank std::vector> grid_search; std::vector counter_per_dimension(grid.size(), 0); @@ -1096,7 +1096,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, } } } - + std::cout << "Test3" << std::endl; // we calculate the grid search for the rank std::vector> grid_search_rank; for (int i = 0; i < points_per_rank; i++) { From 3d517c21c399092d287f17d348b8552118b83571 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:47:27 +0200 Subject: [PATCH 227/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 0c89beb17c..ac5bac4c21 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1076,7 +1076,6 @@ std::vector> distribute_grid_search(int rank, int num_procs, if (rank == num_procs - 1) { points_per_rank = number_of_points - points_per_rank * (num_procs - 1); } - std::cout << "Test2" << std::endl; // we calculate every possible combination of the grid, independently of the rank std::vector> grid_search; std::vector counter_per_dimension(grid.size(), 0); @@ -1096,12 +1095,13 @@ std::vector> distribute_grid_search(int rank, int num_procs, } } } - std::cout << "Test3" << std::endl; + std::cout << "Befor distribution: " << grid_search.size() << std::endl; // we calculate the grid search for the rank std::vector> grid_search_rank; for (int i = 0; i < points_per_rank; i++) { grid_search_rank.push_back(grid_search[i + rank * points_per_rank]); } + std::cout << "After distribution: " << grid_search_rank.size() << std::endl; return grid_search_rank; } @@ -1527,8 +1527,6 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa mio::unused(num_runs); // define parameters for grid search - - std::cout << "Test" << std::endl; // Distribute the grid search over the MPI ranks auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); From eb7322881765531d04e627441bf657c674ed5f4c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:49:42 +0200 Subject: [PATCH 228/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ac5bac4c21..b429354136 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1095,14 +1095,14 @@ std::vector> distribute_grid_search(int rank, int num_procs, } } } - std::cout << "Befor distribution: " << grid_search.size() << std::endl; + // we calculate the grid search for the rank - std::vector> grid_search_rank; + std::vector> grid_search_ranks; for (int i = 0; i < points_per_rank; i++) { - grid_search_rank.push_back(grid_search[i + rank * points_per_rank]); + grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); } - std::cout << "After distribution: " << grid_search_rank.size() << std::endl; - return grid_search_rank; + + return grid_search_ranks; } void create_easter_social_event(mio::abm::World& world, double perc_easter_event) From d376fcd1470f6b1e37b7c7670a2d84e788234596 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:51:43 +0200 Subject: [PATCH 229/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b429354136..4d8f42487f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1095,12 +1095,13 @@ std::vector> distribute_grid_search(int rank, int num_procs, } } } - + std::cout << "Test2" << std::endl; // we calculate the grid search for the rank std::vector> grid_search_ranks; for (int i = 0; i < points_per_rank; i++) { grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); } + std::cout << "Test3" << std::endl; return grid_search_ranks; } @@ -1528,8 +1529,9 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // define parameters for grid search // Distribute the grid search over the MPI ranks + std::cout << "Test1" << std::endl; auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); - + std::cout << "Test4" << std::endl; // short debug print to see if everything worked. Printing rank and amount of grid points as well as first point std::cout << "Rank: " << rank << " has " << grid_search_rank.size() << " grid points" << std::endl; std::cout << "First grid point: "; From ab12ca8a4755bffd236f586abd6875295facfaa4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:55:48 +0200 Subject: [PATCH 230/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4d8f42487f..531a961b76 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1068,7 +1068,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, //Calculate how many grid points there are, assuming that each parameter has the same amount of points int number_of_points = 1; for (size_t i = 0; i < grid.size(); i++) { - number_of_points *= grid[i].size(); + number_of_points = number_of_points * grid[i].size(); } //Calculate how many points each rank should calculate int points_per_rank = number_of_points / num_procs; @@ -1077,7 +1077,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, points_per_rank = number_of_points - points_per_rank * (num_procs - 1); } // we calculate every possible combination of the grid, independently of the rank - std::vector> grid_search; + std::vector> grid_search{}; std::vector counter_per_dimension(grid.size(), 0); for (int i = 0; i < number_of_points; i++) { std::vector temp; @@ -1095,13 +1095,11 @@ std::vector> distribute_grid_search(int rank, int num_procs, } } } - std::cout << "Test2" << std::endl; // we calculate the grid search for the rank std::vector> grid_search_ranks; for (int i = 0; i < points_per_rank; i++) { grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); } - std::cout << "Test3" << std::endl; return grid_search_ranks; } @@ -1529,9 +1527,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // define parameters for grid search // Distribute the grid search over the MPI ranks - std::cout << "Test1" << std::endl; auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); - std::cout << "Test4" << std::endl; // short debug print to see if everything worked. Printing rank and amount of grid points as well as first point std::cout << "Rank: " << rank << " has " << grid_search_rank.size() << " grid points" << std::endl; std::cout << "First grid point: "; From 72be63f96a8e495a16b9e6c7e7b5a21e51d933c3 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:57:54 +0200 Subject: [PATCH 231/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 42 ++++++++++++------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 531a961b76..911f6b6e8e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1077,29 +1077,29 @@ std::vector> distribute_grid_search(int rank, int num_procs, points_per_rank = number_of_points - points_per_rank * (num_procs - 1); } // we calculate every possible combination of the grid, independently of the rank - std::vector> grid_search{}; - std::vector counter_per_dimension(grid.size(), 0); - for (int i = 0; i < number_of_points; i++) { - std::vector temp; - for (size_t j = 0; j < grid.size(); j++) { - temp.push_back(grid[j][counter_per_dimension[j]]); - } - grid_search.push_back(temp); - // we increase the counter for the last dimension - counter_per_dimension.back()++; - // we increase the counter for the other dimensions if the last dimension has reached the end - for (int j = (int)grid.size() - 1; j >= 0; j--) { - if (counter_per_dimension[j] == (int)grid[j].size()) { - counter_per_dimension[j] = 0; - counter_per_dimension[j - 1]++; - } - } - } + // std::vector> grid_search{}; + // std::vector counter_per_dimension(grid.size(), 0); + // for (int i = 0; i < number_of_points; i++) { + // std::vector temp; + // for (size_t j = 0; j < grid.size(); j++) { + // temp.push_back(grid[j][counter_per_dimension[j]]); + // } + // grid_search.push_back(temp); + // // we increase the counter for the last dimension + // counter_per_dimension.back()++; + // // we increase the counter for the other dimensions if the last dimension has reached the end + // for (int j = (int)grid.size() - 1; j >= 0; j--) { + // if (counter_per_dimension[j] == (int)grid[j].size()) { + // counter_per_dimension[j] = 0; + // counter_per_dimension[j - 1]++; + // } + // } + // } // we calculate the grid search for the rank std::vector> grid_search_ranks; - for (int i = 0; i < points_per_rank; i++) { - grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); - } + // for (int i = 0; i < points_per_rank; i++) { + // grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); + // } return grid_search_ranks; } From aabb66356985aedd4b3e638546a3439ed9cbe889 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 14:59:58 +0200 Subject: [PATCH 232/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 911f6b6e8e..faf33b6661 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1077,24 +1077,24 @@ std::vector> distribute_grid_search(int rank, int num_procs, points_per_rank = number_of_points - points_per_rank * (num_procs - 1); } // we calculate every possible combination of the grid, independently of the rank - // std::vector> grid_search{}; - // std::vector counter_per_dimension(grid.size(), 0); - // for (int i = 0; i < number_of_points; i++) { - // std::vector temp; - // for (size_t j = 0; j < grid.size(); j++) { - // temp.push_back(grid[j][counter_per_dimension[j]]); - // } - // grid_search.push_back(temp); - // // we increase the counter for the last dimension - // counter_per_dimension.back()++; - // // we increase the counter for the other dimensions if the last dimension has reached the end - // for (int j = (int)grid.size() - 1; j >= 0; j--) { - // if (counter_per_dimension[j] == (int)grid[j].size()) { - // counter_per_dimension[j] = 0; - // counter_per_dimension[j - 1]++; - // } - // } - // } + std::vector> grid_search{}; + std::vector counter_per_dimension(grid.size(), 0); + for (int i = 0; i < number_of_points; i++) { + std::vector temp; + for (size_t j = 0; j < grid.size(); j++) { + temp.push_back(grid[j][counter_per_dimension[j]]); + } + grid_search.push_back(temp); + // we increase the counter for the last dimension + counter_per_dimension.back()++; + // we increase the counter for the other dimensions if the last dimension has reached the end + for (int j = (int)grid.size() - 1; j >= 0; j--) { + if (counter_per_dimension[j] == (int)grid[j].size()) { + counter_per_dimension[j] = 0; + counter_per_dimension[j - 1]++; + } + } + } // we calculate the grid search for the rank std::vector> grid_search_ranks; // for (int i = 0; i < points_per_rank; i++) { From d5d3e9fabca7991fbd480c6a7645e38f1da6e855 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:01:34 +0200 Subject: [PATCH 233/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index faf33b6661..bd8d75ebeb 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1088,18 +1088,18 @@ std::vector> distribute_grid_search(int rank, int num_procs, // we increase the counter for the last dimension counter_per_dimension.back()++; // we increase the counter for the other dimensions if the last dimension has reached the end - for (int j = (int)grid.size() - 1; j >= 0; j--) { - if (counter_per_dimension[j] == (int)grid[j].size()) { - counter_per_dimension[j] = 0; - counter_per_dimension[j - 1]++; - } - } + // for (int j = (int)grid.size() - 1; j >= 0; j--) { + // if (counter_per_dimension[j] == (int)grid[j].size()) { + // counter_per_dimension[j] = 0; + // counter_per_dimension[j - 1]++; + // } + // } } // we calculate the grid search for the rank std::vector> grid_search_ranks; - // for (int i = 0; i < points_per_rank; i++) { - // grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); - // } + for (int i = 0; i < points_per_rank; i++) { + grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); + } return grid_search_ranks; } From b85b6f1a1fa7fe2b5232cf3ad8deed22de6b8560 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:03:11 +0200 Subject: [PATCH 234/488] bug found Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bd8d75ebeb..3eb527aa23 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1088,12 +1088,12 @@ std::vector> distribute_grid_search(int rank, int num_procs, // we increase the counter for the last dimension counter_per_dimension.back()++; // we increase the counter for the other dimensions if the last dimension has reached the end - // for (int j = (int)grid.size() - 1; j >= 0; j--) { - // if (counter_per_dimension[j] == (int)grid[j].size()) { - // counter_per_dimension[j] = 0; - // counter_per_dimension[j - 1]++; - // } - // } + for (int k = (int)grid.size() - 1; k >= 0; k--) { + if (counter_per_dimension[k] == (int)grid[k].size()) { + counter_per_dimension[k] = 0; + counter_per_dimension[k - 1]++; + } + } } // we calculate the grid search for the rank std::vector> grid_search_ranks; From 7f0a5eb081dd917e3595f0629cd5757ae808f9fe Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:07:53 +0200 Subject: [PATCH 235/488] bug foound Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3eb527aa23..a4683a3495 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1089,7 +1089,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, counter_per_dimension.back()++; // we increase the counter for the other dimensions if the last dimension has reached the end for (int k = (int)grid.size() - 1; k >= 0; k--) { - if (counter_per_dimension[k] == (int)grid[k].size()) { + if (k > 0 && counter_per_dimension[k] == (int)grid[k].size()) { counter_per_dimension[k] = 0; counter_per_dimension[k - 1]++; } From ce2330772612419023ca840a334645c0d5ac9e80 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:10:36 +0200 Subject: [PATCH 236/488] buug Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a4683a3495..d015e7131c 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1088,8 +1088,8 @@ std::vector> distribute_grid_search(int rank, int num_procs, // we increase the counter for the last dimension counter_per_dimension.back()++; // we increase the counter for the other dimensions if the last dimension has reached the end - for (int k = (int)grid.size() - 1; k >= 0; k--) { - if (k > 0 && counter_per_dimension[k] == (int)grid[k].size()) { + for (int k = (int)grid.size(); k > 0; k--) { + if (counter_per_dimension[k] == (int)grid[k].size()) { counter_per_dimension[k] = 0; counter_per_dimension[k - 1]++; } @@ -2310,8 +2310,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From 72891b02e1daeb06bde97d78900e72eda43c20d5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:10:49 +0200 Subject: [PATCH 237/488] buug Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d015e7131c..566b63b9ec 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2310,8 +2310,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From ab208774252b01c7e9f1029fc2f3d7c6f848b1be Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:16:30 +0200 Subject: [PATCH 238/488] cluster grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 566b63b9ec..cb00e1f3a7 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2357,7 +2357,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{4.0, 7.0}, {0.8, 0.95}, {0.5, 0.7}, {0.3, 0.6}, {1.0, 5.0}, {0.2, 0.6}, {0.3, 0.5}}; - std::vector points_per_dim = {2, 2, 2, 2, 2, 2, 4}; + std::vector points_per_dim = {10, 4, 4, 4, 10, 7, 4}; auto grid = grid_points(grid_boundaries, points_per_dim); std::cout << "Grid size: " << grid.size() << std::endl; auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); From b9b3cf10c3b08c672c43294b703c14f1ecbc290b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:22:52 +0200 Subject: [PATCH 239/488] omp enhancement Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cb00e1f3a7..3342a445f9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1813,9 +1813,11 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], max_num_days, start_date); rmse_results_per_grid_point.at(i) = rmse; - - write_grid_search_prematurely_to_file(rank, result_dir, - std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); +#pragma omp critical + { + write_grid_search_prematurely_to_file(rank, result_dir, + std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); + } } // make the gathered results available to all ranks From ffff14a4b67069c21c90c168656dc5bc98d23f7c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 3 Aug 2024 15:37:56 +0200 Subject: [PATCH 240/488] short tesrt Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3342a445f9..997caeb29a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2359,7 +2359,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{4.0, 7.0}, {0.8, 0.95}, {0.5, 0.7}, {0.3, 0.6}, {1.0, 5.0}, {0.2, 0.6}, {0.3, 0.5}}; - std::vector points_per_dim = {10, 4, 4, 4, 10, 7, 4}; + std::vector points_per_dim = {5, 3, 3, 3, 7, 5, 3}; auto grid = grid_points(grid_boundaries, points_per_dim); std::cout << "Grid size: " << grid.size() << std::endl; auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); From 1b2c96b08f2680f82b212ef00db510e18d3b4908 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 4 Aug 2024 01:38:26 +0200 Subject: [PATCH 241/488] omp improvment Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 997caeb29a..5935eca7da 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1540,7 +1540,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); -PRAGMA_OMP(parallel for) +PRAGMA_OMP(parallel for num_threads(32)) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; From af9be819d91a7a6988313f48c56490f02fbcec72 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 4 Aug 2024 01:42:22 +0200 Subject: [PATCH 242/488] another improvement for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 48e53c2b90..3541b54e15 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for num_threads(4)) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for num_threads(4)) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,7 +168,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); - PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for num_threads(4)) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->adjust_contact_rates(parameters.get_num_groups()); diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5935eca7da..11131ac880 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1540,6 +1540,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); + omp_set_nested(1); PRAGMA_OMP(parallel for num_threads(32)) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; From 04d9b3edd65a82a87ddab196f28b0e67e8d7d26f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 4 Aug 2024 12:18:25 +0200 Subject: [PATCH 243/488] change some things Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 8 +- cpp/simulations/generate_graph_from_data.cpp | 4 +- cpp/simulations/paper_abm_bs_testing.cpp | 199 ++++++++++--------- 3 files changed, 107 insertions(+), 104 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index b62bdcd51e..c30d02c0f6 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -598,7 +598,7 @@ def infer_positive_tests(path): n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) plot_infection_states_results(path) - # plot_infections_loc_types_avarage(path) - # plot_icu(path+"/..") - # plot_dead(path) - # infer_positive_tests(path) + plot_infections_loc_types_avarage(path) + plot_icu(path+"/..") + plot_dead(path) + infer_positive_tests(path) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index d1c734b51e..b6cfd07903 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -136,8 +136,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double maxRiskOfInfectionFromSymptomaticMax = 0.5; const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; - const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.1, 0.1}; - const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.1, 0.1}; + const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.05, 0.01}; + const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.05, 0.01}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 11131ac880..07686b262d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -623,33 +623,33 @@ void set_parameters(mio::abm::Parameters& params) params.get()[mio::abm::TestType::Generic] = generic_test_values; // Set percentage parameters - params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.5; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.50; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.55; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.6; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.69; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.825; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.9; - - params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.0180; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.0237; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.0373; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.60; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.65; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.83; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.90; + + params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.02; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.03; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.04; params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.07; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.17; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.2374; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.24; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.1; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.11; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.12; params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.13; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.33; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.62; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.65; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.12; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.13; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.15; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.28; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.25; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.43; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.48; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.5; // Set infection parameters @@ -1476,6 +1476,23 @@ void get_grid_search_results_and_write_them_to_file( } file << "RMSE: " << gathered_grid_vector_with_rmse[i].second << std::endl; } + + // Sort the grid search results by RMSE in ascending order + std::sort(gathered_grid_vector_with_rmse.begin(), gathered_grid_vector_with_rmse.end(), + [](const auto& a, const auto& b) { + return a.second < b.second; + }); + + // Write the 5 best RMSE at the end of the file + file << std::endl << "Top 5 RMSE:" << std::endl; + for (size_t i = 0; i < std::min(5, gathered_grid_vector_with_rmse.size()); i++) { + file << "Grid point: "; + for (size_t j = 0; j < gathered_grid_vector_with_rmse[i].first.size(); j++) { + file << gathered_grid_vector_with_rmse[i].first.at(j) << " "; + } + file << "RMSE: " << gathered_grid_vector_with_rmse[i].second << std::endl; + } + file.close(); } } @@ -1541,7 +1558,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_nested(1); -PRAGMA_OMP(parallel for num_threads(32)) +PRAGMA_OMP(parallel for num_threads(64)) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -1864,18 +1881,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 5.0; - auto seasonality_april = 0.85; + auto viral_shedding_rate = 4.0; + auto seasonality_april = 0.8; auto seasonality_may = 0.5; - auto perc_easter_event = 0.4; - auto dark_figure = 2.0; - auto contact_rate_ssc = 0.3; - auto masks = 0.4; + auto perc_easter_event = 0.3; + auto dark_figure = 2.33; + auto contact_rate_ssc = 0.4; + auto masks = 0.3; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; auto max_num_persons = 400000; - bool npis_on = false; + bool npis_on = true; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation @@ -1888,21 +1905,21 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>>{}; // Vector of infection state per age group results ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); - auto ensemble_test_per_loc_type_per_age_group = std::vector< - std::vector>>{}; // Vector of tests per location type per age group results - ensemble_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + // auto ensemble_test_per_loc_type_per_age_group = std::vector< + // std::vector>>{}; // Vector of tests per location type per age group results + // ensemble_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); - auto ensemble_positive_test_per_loc_type_per_age_group = std::vector< - std::vector>>{}; // Vector of positive tests per location type per age group results - ensemble_positive_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + // auto ensemble_positive_test_per_loc_type_per_age_group = std::vector< + // std::vector>>{}; // Vector of positive tests per location type per age group results + // ensemble_positive_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); - auto ensemble_cumulative_detected_infections = - std::vector>>{}; // Vector of cumulative detected infections - ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); + // auto ensemble_cumulative_detected_infections = + // std::vector>>{}; // Vector of cumulative detected infections + // ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); - auto ensemble_estimated_reproduction_number = - std::vector>>{}; // Vector of estimated reproduction number - ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); + // auto ensemble_estimated_reproduction_number = + // std::vector>>{}; // Vector of estimated reproduction number + // ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); @@ -1939,16 +1956,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - mio::History - historyTestPerLocationTypePerAgeGroup{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History - historyPositiveTestPerLocationTypePerAgeGroup{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History historyCumulativeDetectedInfections{ - Eigen::Index(sim.get_world().parameters.get_num_groups())}; - mio::History historyEstimatedReproductionNumber{ - Eigen::Index(1)}; + // mio::History + // historyTestPerLocationTypePerAgeGroup{ + // Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + // mio::History + // historyPositiveTestPerLocationTypePerAgeGroup{ + // Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + // mio::History historyCumulativeDetectedInfections{ + // Eigen::Index(sim.get_world().parameters.get_num_groups())}; + // mio::History historyEstimatedReproductionNumber{ + // Eigen::Index(1)}; // / NPIS// if (npis_on) { @@ -2096,9 +2113,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.get_world().parameters.get() = viral_shedding_rate; sim.get_world().parameters.get() = masks; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, - historyEstimatedReproductionNumber); + historyInfectionStatePerAgeGroup); std::cout << "day 14 finished" << std::endl; // small social events to capacity 5 @@ -2115,17 +2130,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "till advance 31 (march ends)"); sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, - historyEstimatedReproductionNumber); + historyInfectionStatePerAgeGroup); sim.get_world().parameters.get() = viral_shedding_rate * seasonality_april; restart_timer(timer, "till advance 42"); sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, - historyEstimatedReproductionNumber); + historyInfectionStatePerAgeGroup); std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 for (auto& location : location_it) { @@ -2136,18 +2147,14 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "till advance 62"); sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, - historyEstimatedReproductionNumber); + historyInfectionStatePerAgeGroup); std::cout << "day 62 finished (date 2021-05-01)" << std::endl; sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(71).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, - historyEstimatedReproductionNumber); + historyInfectionStatePerAgeGroup); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; for (auto& location : location_it) { @@ -2174,16 +2181,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, - historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, - historyCumulativeDetectedInfections, historyEstimatedReproductionNumber); + sim.advance(tmax, historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup); std::cout << "day 90 finished" << std::endl; } else { sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfections, - historyEstimatedReproductionNumber); + historyInfectionStatePerAgeGroup); } ////Advance till here // Stop the clock after sim.advance and calculate the duration @@ -2193,22 +2196,22 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>{std::get<0>(historyInfectionPerLocationTypePerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - auto temp_sim_test_per_loc_type_per_age_group = - std::vector>{std::get<0>(historyTestPerLocationTypePerAgeGroup.get_log())}; - auto temp_sim_positive_test_per_loc_type_per_age_group = std::vector>{ - std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; - auto temp_sim_cumulative_detected_infections_per_age_group = - std::vector>{std::get<0>(historyCumulativeDetectedInfections.get_log())}; - auto temp_sim_estimated_reproduction_number = - std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; + // auto temp_sim_test_per_loc_type_per_age_group = + // std::vector>{std::get<0>(historyTestPerLocationTypePerAgeGroup.get_log())}; + // auto temp_sim_positive_test_per_loc_type_per_age_group = std::vector>{ + // std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; + // auto temp_sim_cumulative_detected_infections_per_age_group = + // std::vector>{std::get<0>(historyCumulativeDetectedInfections.get_log())}; + // auto temp_sim_estimated_reproduction_number = + // std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; // Push result of the simulation back to the result vector ensemble_infection_per_loc_type_per_age_group.emplace_back(temp_sim_infection_per_loc_type_per_age_group); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); - ensemble_test_per_loc_type_per_age_group.emplace_back(temp_sim_test_per_loc_type_per_age_group); - ensemble_positive_test_per_loc_type_per_age_group.emplace_back( - temp_sim_positive_test_per_loc_type_per_age_group); - ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); - ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); + // ensemble_test_per_loc_type_per_age_group.emplace_back(temp_sim_test_per_loc_type_per_age_group); + // ensemble_positive_test_per_loc_type_per_age_group.emplace_back( + // temp_sim_positive_test_per_loc_type_per_age_group); + // ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); + // ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; @@ -2229,28 +2232,28 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type_per_age_group); auto final_ensemble_infection_state_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); - auto final_ensemble_test_per_loc_type_per_age_group = - gather_results(rank, num_procs, num_runs, ensemble_test_per_loc_type_per_age_group); - auto final_ensemble_positive_test_per_loc_type_per_age_group = - gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); - auto final_ensemble_cumulative_detected_infections = - gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); - auto final_ensemble_estimated_reproduction_number = - gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); + // auto final_ensemble_test_per_loc_type_per_age_group = + // gather_results(rank, num_procs, num_runs, ensemble_test_per_loc_type_per_age_group); + // auto final_ensemble_positive_test_per_loc_type_per_age_group = + // gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); + // auto final_ensemble_cumulative_detected_infections = + // gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); + // auto final_ensemble_estimated_reproduction_number = + // gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); if (rank == 0) { BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type_per_age_group, ensemble_params, {0}, result_dir / "infection_per_location_type_per_age_group/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, - result_dir / "test_per_location_type_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, - result_dir / "positive_test_per_location_type_per_age_group/", - save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, - result_dir / "cumulative_detected_infections/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, - result_dir / "estimated_reproduction_number/", save_single_runs)); + // BOOST_OUTCOME_TRY(save_results(final_ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, + // result_dir / "test_per_location_type_per_age_group/", save_single_runs)); + // BOOST_OUTCOME_TRY(save_results(final_ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, + // result_dir / "positive_test_per_location_type_per_age_group/", + // save_single_runs)); + // BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, + // result_dir / "cumulative_detected_infections/", save_single_runs)); + // BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, + // result_dir / "estimated_reproduction_number/", save_single_runs)); } #else @@ -2354,13 +2357,13 @@ int main(int argc, char** argv) // 2: Seasonality April // 3: Seasonality May // 4: Perc Easter Event - // 6: Dark Figure - // 7.: Contact rate forst ssocial ebents closure - // 8.: Masks + // 5: Dark Figure + // 6.: Contact rate forst ssocial ebents closure + // 7.: Masks std::vector> grid_boundaries = {{4.0, 7.0}, {0.8, 0.95}, {0.5, 0.7}, {0.3, 0.6}, {1.0, 5.0}, {0.2, 0.6}, {0.3, 0.5}}; - std::vector points_per_dim = {5, 3, 3, 3, 7, 5, 3}; + std::vector points_per_dim = {8, 5, 5, 5, 8, 5, 5}; auto grid = grid_points(grid_boundaries, points_per_dim); std::cout << "Grid size: " << grid.size() << std::endl; auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); From 1f07c32cc30a5e23dd8187935f547cdb30804547 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:12:07 +0200 Subject: [PATCH 244/488] add pa function for person Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/person.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index c9f271a6b7..3be6e5a7fb 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -527,6 +527,11 @@ class Person m_goes_to_easter_event = goes_to_easter; } + bool was_person_ever_infected() const + { + return !m_infections.empty(); + } + private: observer_ptr m_location; ///< Current Location of the Person. std::vector m_assigned_locations; /**! Vector with the indices of the assigned Locations so that the From d35b7b958d48ef82069fd5ba15d5de2a26c498f9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 4 Aug 2024 19:13:04 +0200 Subject: [PATCH 245/488] some fixes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 138 ++++++++++++----------- 1 file changed, 74 insertions(+), 64 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 07686b262d..561e30dad3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1317,7 +1317,7 @@ struct LogPositiveTestPerLocationTypePerAgeGroup : mio::LogAlways { } }; -struct LogCumulativeDetectedInfections : mio::LogAlways { +struct LogCumulativeDetectedInfectionsPerAgeGroup : mio::LogAlways { using Type = std::pair; /** * @brief Log the TimeSeries of the number of Person%s in an #InfectionState. @@ -1336,7 +1336,7 @@ struct LogCumulativeDetectedInfections : mio::LogAlways { auto& p = persons[i]; if (p.get_should_be_logged()) { // PRAGMA_OMP(atomic) - if (p.get_infection().is_detected()) { + if (p.was_person_ever_infected() && p.get_infection().is_detected()) { uint32_t index = (uint32_t)p.get_age().get(); sum[index] += 1; } @@ -1607,8 +1607,6 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - mio::History historyCumulativeDetectedInfections{ - Eigen::Index(sim.get_world().parameters.get_num_groups())}; // / NPIS// @@ -1905,21 +1903,21 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>>{}; // Vector of infection state per age group results ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); - // auto ensemble_test_per_loc_type_per_age_group = std::vector< - // std::vector>>{}; // Vector of tests per location type per age group results - // ensemble_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + auto ensemble_test_per_loc_type_per_age_group = std::vector< + std::vector>>{}; // Vector of tests per location type per age group results + ensemble_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); - // auto ensemble_positive_test_per_loc_type_per_age_group = std::vector< - // std::vector>>{}; // Vector of positive tests per location type per age group results - // ensemble_positive_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + auto ensemble_positive_test_per_loc_type_per_age_group = std::vector< + std::vector>>{}; // Vector of positive tests per location type per age group results + ensemble_positive_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); - // auto ensemble_cumulative_detected_infections = - // std::vector>>{}; // Vector of cumulative detected infections - // ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); + auto ensemble_cumulative_detected_infections = + std::vector>>{}; // Vector of cumulative detected infections + ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); - // auto ensemble_estimated_reproduction_number = - // std::vector>>{}; // Vector of estimated reproduction number - // ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); + auto ensemble_estimated_reproduction_number = + std::vector>>{}; // Vector of estimated reproduction number + ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); @@ -1956,16 +1954,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - // mio::History - // historyTestPerLocationTypePerAgeGroup{ - // Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - // mio::History - // historyPositiveTestPerLocationTypePerAgeGroup{ - // Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - // mio::History historyCumulativeDetectedInfections{ - // Eigen::Index(sim.get_world().parameters.get_num_groups())}; - // mio::History historyEstimatedReproductionNumber{ - // Eigen::Index(1)}; + mio::History + historyTestPerLocationTypePerAgeGroup{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyPositiveTestPerLocationTypePerAgeGroup{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyCumulativeDetectedInfectionsPerAgeGroup{Eigen::Index(sim.get_world().parameters.get_num_groups())}; + mio::History historyEstimatedReproductionNumber{ + Eigen::Index(1)}; // / NPIS// if (npis_on) { @@ -2113,7 +2111,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.get_world().parameters.get() = viral_shedding_rate; sim.get_world().parameters.get() = masks; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup); + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, + historyEstimatedReproductionNumber); std::cout << "day 14 finished" << std::endl; // small social events to capacity 5 @@ -2130,13 +2130,17 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "till advance 31 (march ends)"); sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup); + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, + historyEstimatedReproductionNumber); sim.get_world().parameters.get() = viral_shedding_rate * seasonality_april; restart_timer(timer, "till advance 42"); sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup); + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, + historyEstimatedReproductionNumber); std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 for (auto& location : location_it) { @@ -2147,14 +2151,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "till advance 62"); sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup); + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, + historyEstimatedReproductionNumber); std::cout << "day 62 finished (date 2021-05-01)" << std::endl; sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(71).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup); + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, + historyEstimatedReproductionNumber); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; for (auto& location : location_it) { @@ -2181,7 +2189,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup); + sim.advance(tmax, historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, + historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, + historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); std::cout << "day 90 finished" << std::endl; } else { @@ -2196,22 +2206,22 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>{std::get<0>(historyInfectionPerLocationTypePerAgeGroup.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - // auto temp_sim_test_per_loc_type_per_age_group = - // std::vector>{std::get<0>(historyTestPerLocationTypePerAgeGroup.get_log())}; - // auto temp_sim_positive_test_per_loc_type_per_age_group = std::vector>{ - // std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; - // auto temp_sim_cumulative_detected_infections_per_age_group = - // std::vector>{std::get<0>(historyCumulativeDetectedInfections.get_log())}; - // auto temp_sim_estimated_reproduction_number = - // std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; + auto temp_sim_test_per_loc_type_per_age_group = + std::vector>{std::get<0>(historyTestPerLocationTypePerAgeGroup.get_log())}; + auto temp_sim_positive_test_per_loc_type_per_age_group = std::vector>{ + std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; + auto temp_sim_cumulative_detected_infections_per_age_group = std::vector>{ + std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; + auto temp_sim_estimated_reproduction_number = + std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; // Push result of the simulation back to the result vector ensemble_infection_per_loc_type_per_age_group.emplace_back(temp_sim_infection_per_loc_type_per_age_group); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); - // ensemble_test_per_loc_type_per_age_group.emplace_back(temp_sim_test_per_loc_type_per_age_group); - // ensemble_positive_test_per_loc_type_per_age_group.emplace_back( - // temp_sim_positive_test_per_loc_type_per_age_group); - // ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); - // ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); + ensemble_test_per_loc_type_per_age_group.emplace_back(temp_sim_test_per_loc_type_per_age_group); + ensemble_positive_test_per_loc_type_per_age_group.emplace_back( + temp_sim_positive_test_per_loc_type_per_age_group); + ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); + ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; @@ -2232,28 +2242,28 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type_per_age_group); auto final_ensemble_infection_state_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); - // auto final_ensemble_test_per_loc_type_per_age_group = - // gather_results(rank, num_procs, num_runs, ensemble_test_per_loc_type_per_age_group); - // auto final_ensemble_positive_test_per_loc_type_per_age_group = - // gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); - // auto final_ensemble_cumulative_detected_infections = - // gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); - // auto final_ensemble_estimated_reproduction_number = - // gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); + auto final_ensemble_test_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_test_per_loc_type_per_age_group); + auto final_ensemble_positive_test_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); + auto final_ensemble_cumulative_detected_infections = + gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); + auto final_ensemble_estimated_reproduction_number = + gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); if (rank == 0) { BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type_per_age_group, ensemble_params, {0}, result_dir / "infection_per_location_type_per_age_group/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group/", save_single_runs)); - // BOOST_OUTCOME_TRY(save_results(final_ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, - // result_dir / "test_per_location_type_per_age_group/", save_single_runs)); - // BOOST_OUTCOME_TRY(save_results(final_ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, - // result_dir / "positive_test_per_location_type_per_age_group/", - // save_single_runs)); - // BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, - // result_dir / "cumulative_detected_infections/", save_single_runs)); - // BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, - // result_dir / "estimated_reproduction_number/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "test_per_location_type_per_age_group/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "positive_test_per_location_type_per_age_group/", + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, + result_dir / "cumulative_detected_infections/", save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, + result_dir / "estimated_reproduction_number/", save_single_runs)); } #else @@ -2316,8 +2326,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From 107e8fad26ea85d9172d78a8653fe22d7be4da5a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:58:59 +0200 Subject: [PATCH 246/488] some improvements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 26 ++++++++------- cpp/simulations/find_best_rmse.py | 33 ++++++++++++++++++++ cpp/simulations/generate_graph_from_data.cpp | 2 +- 3 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 cpp/simulations/find_best_rmse.py diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index c30d02c0f6..43b149b8a7 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -27,19 +27,19 @@ def plot_infections_loc_types_avarage(path): # 50-percentile f_p50 = h5py.File( - path+"/infection_per_location_type/p50/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] # 25-percentile f_p25 = h5py.File( - path+"/infection_per_location_type/p25/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/p25/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # 75-percentile f_p75 = h5py.File( - path + "/infection_per_location_type/p75/Results.h5", 'r') + path + "/infection_per_location_type_per_age_group/p75/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] @@ -314,8 +314,8 @@ def plot_dead(path): plt.show() def plot_icu(path): - df_abb = pd.read_json(path+"/pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu = 0.5 + df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") + perc_of_critical_in_icu = 0.45 # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] @@ -327,7 +327,7 @@ def plot_icu(path): # we plot this against this the Amount of persons in the ICU from our model f_p50 = h5py.File( - path+"/results_last_run/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/infection_state_per_age_group/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] # we need just every 24th value @@ -585,10 +585,12 @@ def infer_positive_tests(path): plt.show() +def plot_estimated_reproduction_number(path): + if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-06135830" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" @@ -597,8 +599,8 @@ def infer_positive_tests(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infection_states_results(path) - plot_infections_loc_types_avarage(path) - plot_icu(path+"/..") - plot_dead(path) - infer_positive_tests(path) + # plot_infection_states_results(path) + # plot_infections_loc_types_avarage(path) + # plot_icu(path) + # plot_dead(path) + # infer_positive_tests(path) diff --git a/cpp/simulations/find_best_rmse.py b/cpp/simulations/find_best_rmse.py new file mode 100644 index 0000000000..88f865a2e4 --- /dev/null +++ b/cpp/simulations/find_best_rmse.py @@ -0,0 +1,33 @@ +import os +# Define the folder path +folder_path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/2/grid_search/grid_search" + +# Initialize a list to store the RMSE values and parameters +rmse_values = [] +parameters = [] + +# Iterate over each file in the folder +for filename in os.listdir(folder_path): + if filename.endswith(".txt"): + file_path = os.path.join(folder_path, filename) + with open(file_path, "r") as file: + # Read all lines in the file + lines = file.readlines() + for line in lines: + # Check if the line contains the RMSE value + if "RMSE:" in line: + # Extract the RMSE value + rmse = float(line.split("RMSE:")[1].strip()) + rmse_values.append(rmse) + # Extract the parameters + parameters.append(line.split("RMSE:")[0].strip()) + +# Sort the RMSE values in ascending order +sorted_indices = sorted(range(len(rmse_values)), key=lambda k: rmse_values[k]) +rmse_values = [rmse_values[i] for i in sorted_indices] +parameters = [parameters[i] for i in sorted_indices] + +# Print the 5 best RMSE values and parameters +print("Top 5 RMSE values and parameters:") +for i in range(20): + print(f"Parameters: {parameters[i]}, RMSE: {rmse_values[i]}") \ No newline at end of file diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index b6cfd07903..3c07ba5119 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.5); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.3); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, From 41b405b50f4a982187db37fe75a1279b6a194282 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 6 Aug 2024 18:00:17 +0200 Subject: [PATCH 247/488] cluster ready Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 43 ++++++++++++++++++------ 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 561e30dad3..61f22340d2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -542,7 +542,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (it_person == persons.end()) { auto home = locations.find(home_id)->second; auto& person = world.add_person(home, determine_age_group(age)); - person.set_mask_preferences({0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.2, 0.2}); + person.set_mask_preferences({0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25}); person.set_assigned_location(home); person.set_assigned_location(hospital); person.set_assigned_location(icu); @@ -1033,7 +1033,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries> grid_points(std::vector> grid_points(const std::vector& parameter_points, + const std::vector& number_of_points) +{ + std::vector> grid; + for (size_t i = 0; i < parameter_points.size(); i++) { + std::vector temp; + double min_value = parameter_points[i] * 0.8; + double max_value = parameter_points[i] * 1.2; + double step = (max_value - min_value) / (number_of_points.at(i) - 1); + for (int j = 0; j < number_of_points.at(i) - 1; j++) { + temp.push_back(min_value + j * step); + } + grid.push_back(temp); + } + return grid; +} + /** * @brief Distribute the grid search over the MPI ranks. */ @@ -1557,11 +1578,13 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); - omp_set_nested(1); + omp_set_max_active_levels(2); PRAGMA_OMP(parallel for num_threads(64)) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; + printf("I am Thread %d\n", omp_get_thread_num()); + // grid search for parameters: // 1: Viral Shed // 2: Seasonality April @@ -2326,8 +2349,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2370,13 +2393,13 @@ int main(int argc, char** argv) // 5: Dark Figure // 6.: Contact rate forst ssocial ebents closure // 7.: Masks - std::vector> grid_boundaries = {{4.0, 7.0}, {0.8, 0.95}, {0.5, 0.7}, {0.3, 0.6}, - {1.0, 5.0}, {0.2, 0.6}, {0.3, 0.5}}; + std::vector> grid_boundaries = {{3.0, 8.0}, {0.6, 0.95}, {0.4, 0.8}, {0.2, 0.6}, + {1.0, 5.0}, {0.2, 0.6}, {0.2, 0.6}}; - std::vector points_per_dim = {8, 5, 5, 5, 8, 5, 5}; + // std::vector points_per_dim = {6, 5, 5, 5, 6, 5, 5}; + std::vector points_per_dim = {3, 3, 3, 3, 3, 3, 3}; auto grid = grid_points(grid_boundaries, points_per_dim); - std::cout << "Grid size: " << grid.size() << std::endl; - auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); + auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } else { auto result = run(input_dir, result_dir, num_runs); From ae61b520d3e7df9afbf77e10d68f7b221294925a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 6 Aug 2024 21:17:41 +0200 Subject: [PATCH 248/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/memilio/io/result_io.h | 6 +++++- cpp/simulations/paper_abm_bs_testing.cpp | 20 +++++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/cpp/memilio/io/result_io.h b/cpp/memilio/io/result_io.h index 8de5ec6461..0d995b27aa 100644 --- a/cpp/memilio/io/result_io.h +++ b/cpp/memilio/io/result_io.h @@ -135,11 +135,15 @@ IOResult save_result_with_params(const std::vector>& re template IOResult save_results(const std::vector>>& ensemble_results, const std::vector>& ensemble_params, const std::vector& county_ids, - const fs::path& result_dir, bool save_single_runs = true, bool save_percentiles = true) + const fs::path& result_dir, bool save_single_runs = true, bool save_percentiles = true, + bool just_one_ag = false) { //save results and sum of results over nodes auto ensemble_result_sum = sum_nodes(ensemble_results); auto num_groups = (int)(size_t)ensemble_params[0][0].parameters.get_num_groups(); + if (just_one_ag) { + num_groups = 1; + } if (save_single_runs) { for (size_t i = 0; i < ensemble_result_sum.size(); ++i) { BOOST_OUTCOME_TRY(save_result(ensemble_result_sum[i], {0}, num_groups, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 61f22340d2..6df89d59d4 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -649,7 +649,7 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.15; params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.25; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.43; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.5; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.50; // Set infection parameters @@ -1293,7 +1293,7 @@ struct LogTestPerLocationTypePerAgeGroup : mio::LogAlways { auto& p = persons[i]; if (p.get_should_be_logged()) { // PRAGMA_OMP(atomic) - if ((p.get_time_of_last_test() > prev_time)) { + if ((p.get_time_of_last_test() == prev_time)) { auto index = (((size_t)(mio::abm::LocationType::Count)) * ((uint32_t)p.get_age().get())) + ((uint32_t)p.get_location().get_type()); sum[index] += 1; @@ -1326,7 +1326,7 @@ struct LogPositiveTestPerLocationTypePerAgeGroup : mio::LogAlways { if (p.get_should_be_logged()) { // PRAGMA_OMP(atomic) // careful: this check assumes a persons goes into quarantine when a test is positive and that the duration of quarantine is >0 - if (p.get_time_of_last_test() > prev_time && + if (p.get_time_of_last_test() == prev_time && p.is_in_quarantine(curr_time, sim.get_world().parameters)) { auto index = (((size_t)(mio::abm::LocationType::Count)) * ((uint32_t)p.get_age().get())) + ((uint32_t)p.get_location().get_type()); @@ -1945,16 +1945,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); - int tid = -1; -#pragma omp parallel private(tid) // Start of parallel region: forks threads - { - tid = omp_get_thread_num(); // default is number of CPUs on machine - printf("Hello World from thread = %d and rank = %d\n", tid, rank); - if (tid == 0) { - printf("Number of threads = %d\n", omp_get_num_threads()); - } - } // ** end of the the parallel: joins threads - // Determine inital infection state distribution restart_timer(timer, "time for initial setup"); determine_initial_infection_states_world(input_dir, start_date, dark_figure); @@ -2286,7 +2276,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, result_dir / "cumulative_detected_infections/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, - result_dir / "estimated_reproduction_number/", save_single_runs)); + result_dir / "estimated_reproduction_number/", save_single_runs, true, true)); } #else @@ -2299,7 +2289,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s BOOST_OUTCOME_TRY(save_results(ensemble_cumulative_detected_infections, ensemble_params, {0}, result_dir / "cumulative_detected_infections/", save_single_runs)); BOOST_OUTCOME_TRY(save_results(ensemble_estimated_reproduction_number, ensemble_params, {0}, - result_dir / "estimated_reproduction_number/", save_single_runs)); + result_dir / "estimated_reproduction_number/", save_single_runs, 1)); #endif restart_timer(timer, "time taken for data gathering and saving results"); From 9b2c3e17a41b05cec9a27274e0cac6fa020d6869 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 6 Aug 2024 21:56:26 +0200 Subject: [PATCH 249/488] grid search cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 108 ++++++++++++++++++++++- cpp/simulations/paper_abm_bs_testing.cpp | 8 +- 2 files changed, 111 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 43b149b8a7..fccc42f28a 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -586,11 +586,114 @@ def infer_positive_tests(path): plt.show() def plot_estimated_reproduction_number(path): + f_p50 = h5py.File( + path+"/estimated_reproduction_number/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + total_50 = total_50[::24] + total_50 = total_50[0:90].flatten() + # we smooth this with a gaussian filter + total_50 = gaussian_filter1d(total_50, sigma=1, mode='nearest') + time = p50_bs['Time'][()] + time = time[::24] + time = time[0:90] + + # we plot this + # we plot the tests positive and the real cases + plt.plot(time, total_50, color='tab:red') + plt.xlabel('time (days)') + plt.ylabel('Estimated reproduction number') + plt.title('Estimated reproduction number') + plt.show() + +def plot_cumulative_detected_infections(path): + f_p50 = h5py.File( + path+"/cumulative_detected_infections/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + total_50 = total_50[::24] + total_50 = total_50[0:90].flatten() + # we smooth this with a gaussian filter + total_50 = gaussian_filter1d(total_50, sigma=1, mode='nearest') + time = p50_bs['Time'][()] + time = time[::24] + time = time[0:90] + + # we also plot the amount of new detected infections with diff + total_50_diff = np.diff(total_50) + + + # we plot this + # we plot the tests positive and the real cases + plt.plot(time, total_50, color='tab:red') + plt.xlabel('time (days)') + plt.ylabel('Cumulative Amount of detected infections') + plt.title('Cumulative detected infections') + # also plot the new detected infections with the same color but dashed + plt.plot(time[1:], total_50_diff, color='tab:red', linestyle='dashed') + plt.show() + +def plot_positive_and_done_test(path): + f_p50_positive = h5py.File( + path+"/test_per_location_type_per_age_group/p50/Results.h5", 'r') + p50_bs_positive = f_p50_positive['0'] + total_50_positive = p50_bs_positive['Total'][()] + + f_p50_done = h5py.File( + path+"/test_per_location_type_per_age_group/p50/Results.h5", 'r') + p50_bs_done = f_p50_done['0'] + total_50_done = p50_bs_done['Total'][()] + + time = p50_bs_positive['Time'][()] + time = time[::24] + time = time[0:90] + + + # weas one entry is one hour we take the sum every 24 entries to get the daily amount, we do this with cumsum + total_50_positive = np.cumsum(total_50_positive, axis=0) + total_50_positive = total_50_positive[::24] + total_50_positive = total_50_positive[0:90] # we still need to take the difference to get the daily amount + total_50_positive = np.diff(total_50_positive, axis=0).flatten() + # we smooth this with a gaussian filter + total_50_positive = gaussian_filter1d(total_50_positive, sigma=1, mode='nearest') + + #same for the done tests + total_50_done = np.cumsum(total_50_done, axis=0) + total_50_done = total_50_done[::24] + total_50_done = total_50_done[0:90] # we still need to take the difference to get the daily amount + total_50_done = np.diff(total_50_done, axis=0).flatten() + # we smooth this with a gaussian filter + total_50_done = gaussian_filter1d(total_50_done, sigma=1, mode='nearest') + + # we plot this + # we plot the tests positive and the real cases + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + plt.gcf().autofmt_xdate() + + plt.plot(xx, total_50_positive, color='tab:red') + plt.plot(xx, total_50_done, color='tab:blue') + plt.xlabel('time (days)') + plt.ylabel('Number of tests') + plt.legend(['Positive tests', 'Done tests']) + plt.title('Positive and done tests') + plt.show() + + + + + + + + + + if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-06135830" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" @@ -604,3 +707,6 @@ def plot_estimated_reproduction_number(path): # plot_icu(path) # plot_dead(path) # infer_positive_tests(path) + # plot_estimated_reproduction_number(path) + # plot_cumulative_detected_infections(path) + plot_positive_and_done_test(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6df89d59d4..cb83554a51 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2386,10 +2386,10 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{3.0, 8.0}, {0.6, 0.95}, {0.4, 0.8}, {0.2, 0.6}, {1.0, 5.0}, {0.2, 0.6}, {0.2, 0.6}}; - // std::vector points_per_dim = {6, 5, 5, 5, 6, 5, 5}; - std::vector points_per_dim = {3, 3, 3, 3, 3, 3, 3}; - auto grid = grid_points(grid_boundaries, points_per_dim); - auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); + std::vector points_per_dim = {6, 5, 5, 5, 6, 5, 5}; + // std::vector points_per_dim = {3, 3, 3, 3, 3, 3, 3}; + auto grid = grid_points(grid_boundaries, points_per_dim); + auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } else { auto result = run(input_dir, result_dir, num_runs); From 7f70ee82913eb24548904d83dbae29f14d33a796 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 6 Aug 2024 22:17:51 +0200 Subject: [PATCH 250/488] plots done Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index fccc42f28a..9858a9f0be 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -635,7 +635,7 @@ def plot_cumulative_detected_infections(path): def plot_positive_and_done_test(path): f_p50_positive = h5py.File( - path+"/test_per_location_type_per_age_group/p50/Results.h5", 'r') + path+"/positive_test_per_location_type_per_age_group/p50/Results.h5", 'r') p50_bs_positive = f_p50_positive['0'] total_50_positive = p50_bs_positive['Total'][()] @@ -650,17 +650,20 @@ def plot_positive_and_done_test(path): # weas one entry is one hour we take the sum every 24 entries to get the daily amount, we do this with cumsum + # first we need to sum up over all age groups + total_50_positive = np.sum(total_50_positive, axis=1) total_50_positive = np.cumsum(total_50_positive, axis=0) total_50_positive = total_50_positive[::24] - total_50_positive = total_50_positive[0:90] # we still need to take the difference to get the daily amount + total_50_positive = total_50_positive[0:91] # we still need to take the difference to get the daily amount total_50_positive = np.diff(total_50_positive, axis=0).flatten() # we smooth this with a gaussian filter total_50_positive = gaussian_filter1d(total_50_positive, sigma=1, mode='nearest') #same for the done tests + total_50_done = np.sum(total_50_done, axis=1) total_50_done = np.cumsum(total_50_done, axis=0) total_50_done = total_50_done[::24] - total_50_done = total_50_done[0:90] # we still need to take the difference to get the daily amount + total_50_done = total_50_done[0:91] # we still need to take the difference to get the daily amount total_50_done = np.diff(total_50_done, axis=0).flatten() # we smooth this with a gaussian filter total_50_done = gaussian_filter1d(total_50_done, sigma=1, mode='nearest') @@ -683,14 +686,6 @@ def plot_positive_and_done_test(path): - - - - - - - - if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run_last_run" path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" From 3be08295fcbf5b68fd8ddf710b76d5a4df288fc1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 6 Aug 2024 23:03:28 +0200 Subject: [PATCH 251/488] add quarantine factor, change some params Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 13 +++++--- cpp/simulations/analyze_bs_run.py | 34 +++++++++++++-------- cpp/simulations/paper_abm_bs_testing.cpp | 39 ++++++++++++++++-------- 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 629c281422..6c1b98890d 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -175,14 +175,19 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou cell.m_cached_exposure_rate_air.array().setZero(); for (auto&& p : cell.m_persons) { if (p->is_infected(t)) { - auto& inf = p->get_infection(); - auto virus = inf.get_virus_variant(); - auto age = p->get_age(); + auto& inf = p->get_infection(); + auto virus = inf.get_virus_variant(); + auto age = p->get_age(); + double quarantine_factor = 1.0; + if (p->is_in_quarantine(t_middlepoint, params)) { + quarantine_factor = 0.5; + } /* average infectivity over the time step * to second order accuracy using midpoint rule */ cell.m_cached_exposure_rate_contacts[{virus, age}] += - params.get()[{virus}] * inf.get_viral_shed(t_middlepoint); + params.get()[{virus}] * inf.get_viral_shed(t_middlepoint) * + quarantine_factor; cell.m_cached_exposure_rate_air[{virus}] += inf.get_viral_shed(t_middlepoint); // TODO: Adapt function/factor for air transmission. } diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 9858a9f0be..d29d69f68e 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -89,7 +89,6 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): plt.ylabel('Number of individuals') plt.show() - def plot_infection_states_results(path): # 50-percentile f_p50 = h5py.File( @@ -534,8 +533,8 @@ def infer_positive_tests(path): best_rmse = 1000000000 best_r_sns = 0 best_lt_sympt = 0 - for r_sns in np.linspace(1, 100, 100): - for lt_sympt in np.linspace(0.005, 0.3, 500): + for r_sns in np.linspace(1, 50, 100): + for lt_sympt in np.linspace(0.005, 0.1, 500): total_positive_tests, inferred_positive_tests_sympt, inferred_positive_tests_asympt = calc_positive_tests_overall(total_50, sensitivity, specificity, r_sns, lt_sympt) rmse = np.sqrt(((df_abb['Confirmed'] - total_positive_tests)**2).mean()) if rmse < best_rmse: @@ -552,8 +551,19 @@ def infer_positive_tests(path): # we save the assumed tests done - # assumed__amount_of_test = (total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)+( - # total_50[:, 0]*lt_asympt)+(total_50[:, 1]+total_50[:, 2])*lt_asympt + assumed__amount_of_test = (total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)+( + total_50[:, 0]*(best_lt_sympt/best_r_sns))+(total_50[:, 1]+total_50[:, 2])*(best_lt_sympt/best_r_sns) + + #plot the assumed tests done + fig, ax = plt.subplots(1, 1, constrained_layout=True) + fig.set_figwidth(20) + fig.set_figheight(9) + ax.plot(time, assumed__amount_of_test, color='tab:red') + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of tests') + ax.title.set_text('Assumed amount of tests done') + ax.legend(['Assumed amount of tests done']) + plt.show() @@ -697,11 +707,11 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - # plot_infection_states_results(path) - # plot_infections_loc_types_avarage(path) - # plot_icu(path) - # plot_dead(path) - # infer_positive_tests(path) - # plot_estimated_reproduction_number(path) - # plot_cumulative_detected_infections(path) + plot_infection_states_results(path) + plot_infections_loc_types_avarage(path) + plot_icu(path) + plot_dead(path) + infer_positive_tests(path) + plot_estimated_reproduction_number(path) + plot_cumulative_detected_infections(path) plot_positive_and_done_test(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cb83554a51..7045846153 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1902,13 +1902,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 4.0; - auto seasonality_april = 0.8; - auto seasonality_may = 0.5; - auto perc_easter_event = 0.3; - auto dark_figure = 2.33; - auto contact_rate_ssc = 0.4; - auto masks = 0.3; + auto viral_shedding_rate = 5.5; + auto seasonality_april = 0.775; + auto seasonality_may = 0.6; + auto perc_easter_event = 0.4; + auto dark_figure = 3.0; + auto contact_rate_ssc = 0.2; + auto masks = 0.4; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -1983,9 +1983,24 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto location_it = sim.get_world().get_locations(); + // random testing at home + auto testing_min_time_home = mio::abm::days(7); + auto probability_home = 0.01; + auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(1).seconds()); // 2021-04-12 + auto end_date_test_home = mio::abm::TimePoint(tmax); // 2021-05-30 + auto test_type_home = mio::abm::TestType::Antigen; // Antigen test + auto test_parameters_home = + sim.get_world().parameters.get()[test_type_home]; // Test parameters + auto testing_criteria_home = mio::abm::TestingCriteria(); + auto testing_scheme_home = + mio::abm::TestingScheme(testing_criteria_home, testing_min_time_home, start_date_test_home, + end_date_test_home, test_parameters_home, probability_home); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, + testing_scheme_home); + // 1. testing schemes in schools auto testing_min_time_school = mio::abm::days(7); - auto probability_school = 1.0; + auto probability_school = 0.1; auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 auto test_type_school = mio::abm::TestType::Antigen; // Antigen test @@ -2013,7 +2028,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector work_location_ids_35(work_location_ids.begin(), work_location_ids.begin() + num_work_locations); auto testing_min_time_work = mio::abm::days(1); - auto probability_work = 1.0; + auto probability_work = 0.05; auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); auto end_date_test_work = mio::abm::TimePoint(tmax); auto test_type_work = mio::abm::TestType::Antigen; // Antigen test @@ -2041,7 +2056,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector basics_shop_location_ids_20( basics_shop_location_ids.begin(), basics_shop_location_ids.begin() + num_basics_shop_locations); auto testing_min_time_basics_shop = mio::abm::days(2); - auto probability_basics_shop = 1.0; + auto probability_basics_shop = 0.01; auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test @@ -2339,8 +2354,8 @@ int main(int argc, char** argv) mio::mpi::init(); #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From e1e838a5ed62ec197f41b0861b8a3ec5e72a302e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:48:31 +0200 Subject: [PATCH 252/488] minor improvements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/generate_graph_from_data.cpp | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 47 +++++++++++++++----- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 3c07ba5119..ee34c80342 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.3); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.4); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7045846153..7572f7e779 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1035,8 +1035,8 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries copy_result_folder(std::string const& from_dir, std::string int main(int argc, char** argv) { + mio::set_log_level(mio::LogLevel::err); auto start = std::chrono::system_clock::now(); + + int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI mio::mpi::init(); + MPI_Comm_size(mio::mpi::get_world(), &num_procs); + MPI_Comm_rank(mio::mpi::get_world(), &rank); +#else + num_procs = 1; + rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; - std::string result_dir = input_dir + "/results_" + currentDateTime(); + +#ifdef MEMILIO_ENABLE_MPI + // we need to send every rank the same folder + std::string result_dir; + if (rank == 0) + result_dir = input_dir + "/results_" + currentDateTime(); + int line_size = result_dir.size(); + MPI_Bcast(&line_size, 1, MPI_INT, 0, MPI_COMM_WORLD); + if (rank != 0) + result_dir.resize(line_size); + MPI_Bcast(const_cast(result_dir.data()), line_size, MPI_CHAR, 0, MPI_COMM_WORLD); +#else + std::string result_dir = input_dir + "/results_" + currentDateTime(); +#endif size_t num_runs; bool run_grid_search = false; @@ -2381,11 +2402,12 @@ int main(int argc, char** argv) printf("Running with number of runs = %d.\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); } - - auto created = create_result_folders(result_dir, run_grid_search); - if (!created) { - std::cout << created.error().formatted_message(); - return created.error().code().value(); + if (rank == 0) { + auto created = create_result_folders(result_dir, run_grid_search); + if (!created) { + std::cout << created.error().formatted_message(); + return created.error().code().value(); + } } timer = TIME_NOW; @@ -2401,7 +2423,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{3.0, 8.0}, {0.6, 0.95}, {0.4, 0.8}, {0.2, 0.6}, {1.0, 5.0}, {0.2, 0.6}, {0.2, 0.6}}; - std::vector points_per_dim = {6, 5, 5, 5, 6, 5, 5}; + std::vector points_per_dim = {5, 5, 5, 5, 5, 5, 5}; // std::vector points_per_dim = {3, 3, 3, 3, 3, 3, 3}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); @@ -2412,7 +2434,8 @@ int main(int argc, char** argv) // copy results into a fixed name folder to have easier access std::string last_run_dir = input_dir + "/results_last_run"; - auto copied = copy_result_folder(result_dir, last_run_dir); + if (rank == 0) + auto copied = copy_result_folder(result_dir, last_run_dir); mio::mpi::finalize(); From 220e78faa63a09a838af1cd2a985015f19690682 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 7 Aug 2024 10:53:49 +0200 Subject: [PATCH 253/488] some fixes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 1 - cpp/simulations/paper_abm_bs_testing.cpp | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index bccbd4144e..e285b08c27 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,6 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { - std::cout << "Updating testing schemes at time " << t.days() << std::endl; #pragma omp parallel for for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7572f7e779..a61869bc85 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1771,7 +1771,6 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { sim.get_world().parameters.get() = viral_shedding_rate; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); - mio::unused(seasonality_april, seasonality_may, contact_rate_ssc); std::cout << "day 14 finished" << std::endl; // small social events to capacity 5 @@ -1986,7 +1985,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // random testing at home auto testing_min_time_home = mio::abm::days(7); auto probability_home = 0.01; - auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(1).seconds()); // 2021-04-12 + auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 auto end_date_test_home = mio::abm::TimePoint(tmax); // 2021-05-30 auto test_type_home = mio::abm::TestType::Antigen; // Antigen test auto test_parameters_home = From 857f677ad1b69ee1798d87b9b0afb5a4eb6b2e9a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:01:45 +0200 Subject: [PATCH 254/488] fix some bugs and add some plots and refactor some things --- cpp/models/abm/person.cpp | 2 + cpp/models/abm/person.h | 7 +- cpp/models/abm/testing_strategy.cpp | 29 +- cpp/simulations/analyze_bs_run.py | 34 +- cpp/simulations/generate_graph_from_data.cpp | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 477 +++++++++++-------- 6 files changed, 329 insertions(+), 222 deletions(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index 04c786efd5..f39d83aca1 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -205,6 +205,7 @@ bool Person::get_tested(RandomNumberGenerator& rng, TimePoint t, const TestParam if (random < params.sensitivity) { m_quarantine_start = t; m_infections.back().set_detected(); + m_tested_positive = true; return true; } // false negative @@ -220,6 +221,7 @@ bool Person::get_tested(RandomNumberGenerator& rng, TimePoint t, const TestParam // false positive else { m_quarantine_start = t; + m_tested_positive = true; return true; } } diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index 3be6e5a7fb..d3ed51095e 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -527,9 +527,9 @@ class Person m_goes_to_easter_event = goes_to_easter; } - bool was_person_ever_infected() const + bool was_person_tested_positive() const { - return !m_infections.empty(); + return m_tested_positive; } private: @@ -547,7 +547,8 @@ class Person double m_random_goto_school_hour; ///< Value to determine at what time the Person goes to school. TimePoint m_time_of_last_test; ///< TimePoint of the last negative test. Mask m_mask; ///< The Mask of the Person. - bool m_wears_mask = false; ///< Whether the Person currently wears a Mask. + bool m_wears_mask = false; ///< Whether the Person currently wears a Mask. + bool m_tested_positive = false; std::vector m_mask_compliance; ///< Vector of Mask compliance values for all #LocationType%s. uint32_t m_person_id; ///< Id of the Person. std::vector m_cells; ///< Vector with all Cell%s the Person visits at its current Location. diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index e285b08c27..a7e9ae34bd 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -83,7 +83,7 @@ bool TestingScheme::operator==(const TestingScheme& other) const bool TestingScheme::is_active(const TimePoint t) const { - return (m_start_date <= t && t <= m_end_date); + return (m_start_date <= t && t < m_end_date); } bool TestingScheme::run_scheme(Person::RandomNumberGenerator& rng, Person& person, TimePoint t) const @@ -92,11 +92,11 @@ bool TestingScheme::run_scheme(Person::RandomNumberGenerator& rng, Person& perso if (m_testing_criteria.evaluate(person, t)) { double random = UniformDistribution::get_instance()(rng); if (random < m_probability) { - return !person.get_tested(rng, t, m_test_parameters); + return person.get_tested(rng, t, m_test_parameters); } } } - return true; + return false; } TestingStrategy::TestingStrategy( @@ -174,14 +174,24 @@ void TestingStrategy::update_location_testing_schemes( auto& location = locations[i]; auto loc_id = location.get_index(); auto& schemes = m_location_to_schemes_map; + m_testing_schemes_per_location[i].clear(); - auto iter_schemes = std::find_if(schemes.begin(), schemes.end(), [loc_id, &location](auto& p) { - return p.first.index == loc_id || - (p.first.index == INVALID_LOCATION_INDEX && p.first.type == location.get_type()); + auto iter_schemes_loc_type = std::find_if(schemes.begin(), schemes.end(), [&location](auto& p) { + return (p.first.index == INVALID_LOCATION_INDEX && p.first.type == location.get_type()); }); - if (iter_schemes != schemes.end()) { - m_testing_schemes_per_location[i].clear(); - for (auto&& scheme : iter_schemes->second) { + if (iter_schemes_loc_type != schemes.end()) { + for (auto&& scheme : iter_schemes_loc_type->second) { + if (scheme.is_active(t)) { + m_testing_schemes_per_location[i].push_back(scheme); + } + } + } + + auto iter_schemes_loc_id = std::find_if(schemes.begin(), schemes.end(), [loc_id](auto& p) { + return (p.first.index == loc_id); + }); + if (iter_schemes_loc_id != schemes.end()) { + for (auto&& scheme : iter_schemes_loc_id->second) { if (scheme.is_active(t)) { m_testing_schemes_per_location[i].push_back(scheme); } @@ -190,6 +200,5 @@ void TestingStrategy::update_location_testing_schemes( } } } - } // namespace abm } // namespace mio diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index d29d69f68e..23925a4158 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -527,7 +527,7 @@ def infer_positive_tests(path): df_abb['Confirmed'] = df_abb['Confirmed'].diff() sensitivity = 0.69 - specificity = 0.95 + specificity = 0.99 # we need to derive the lowest rmse for the real positive tests and the inferred positive tests we use a grid search # we need to find the best r_sns and lt_sympt best_rmse = 1000000000 @@ -617,30 +617,54 @@ def plot_estimated_reproduction_number(path): plt.show() def plot_cumulative_detected_infections(path): + + df_abb = pd.read_json( + path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + # we need the + df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] + df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] + df_abb = df_abb[df_abb['ID_County'] == 3101] + df_substract = np.floor(df_abb['Confirmed'][0:1]) + df_abb = np.floor(df_abb['Confirmed'][0:90]) + df_abb = df_abb - df_substract.values[0] + + + f_p50 = h5py.File( path+"/cumulative_detected_infections/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] total_50 = total_50[::24] - total_50 = total_50[0:90].flatten() + total_50 = np.floor(total_50[0:90].flatten()) # we smooth this with a gaussian filter - total_50 = gaussian_filter1d(total_50, sigma=1, mode='nearest') + time = p50_bs['Time'][()] time = time[::24] time = time[0:90] # we also plot the amount of new detected infections with diff total_50_diff = np.diff(total_50) + df_abb_diff = np.diff(df_abb) + # again the rmse + rmse_detected = np.sqrt(((df_abb - total_50)**2).mean()) + total_50 = gaussian_filter1d(total_50, sigma=1, mode='nearest') + # we plot this # we plot the tests positive and the real cases plt.plot(time, total_50, color='tab:red') + plt.plot(time, df_abb, color='tab:blue') plt.xlabel('time (days)') plt.ylabel('Cumulative Amount of detected infections') plt.title('Cumulative detected infections') # also plot the new detected infections with the same color but dashed plt.plot(time[1:], total_50_diff, color='tab:red', linestyle='dashed') + plt.plot(time[1:], df_abb_diff, color='tab:blue', linestyle='dashed') + plt.legend(['Simulated detected infections', 'Real detected infections', 'Simulated new detected infections', 'Real new detected infections']) + #rmse + plt.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_detected))), horizontalalignment='center', + verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) plt.show() def plot_positive_and_done_test(path): @@ -683,6 +707,8 @@ def plot_positive_and_done_test(path): start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') xx = [start_date + pd.Timedelta(days=int(i)) for i in range(90)] xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] + plt.gca().set_xticks(time[::5]) + plt.gca().set_xticklabels(xx[::5]) plt.gcf().autofmt_xdate() plt.plot(xx, total_50_positive, color='tab:red') @@ -697,7 +723,7 @@ def plot_positive_and_done_test(path): if __name__ == "__main__": - # path = "/Users/david/Documents/HZI/memilio/data/results_last_run_last_run" + # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index ee34c80342..b6cfd07903 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.4); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.5); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a61869bc85..a921259c0f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -616,7 +616,7 @@ void set_parameters(mio::abm::Parameters& params) //Set testing parameters auto pcr_test_values = mio::abm::TestParameters{0.9, 0.99}; - auto antigen_test_values = mio::abm::TestParameters{0.69, 0.95}; + auto antigen_test_values = mio::abm::TestParameters{0.69, 0.99}; auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; @@ -895,7 +895,7 @@ void set_local_parameters(mio::abm::World& world) case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; loc.get_infection_parameters().get().array() *= 7.5; - loc.get_infection_parameters().get().array() *= 1; + loc.get_infection_parameters().get().array() *= 0.5; break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; @@ -997,25 +997,60 @@ std::vector read_in_deaths(std::vector rki_da return death_data; } +std::vector read_in_detected(std::vector rki_data, mio::Date start_date, + int max_num_days) +{ + std::vector> conf_data_age{num_age_groupss}; + for (auto& entry : rki_data) { + if (entry.county_id->get() == 3101) { + if (entry.date >= start_date && entry.date < mio::offset_date_by_days(start_date, max_num_days)) { + auto age_group = entry.age_group.get(); + conf_data_age.at(age_group).push_back(entry.num_confirmed); + } + } + } + double sum_day_minus_one = 0; + for (size_t j = 0; j < conf_data_age.size(); j++) { + sum_day_minus_one += conf_data_age[j][0]; + } + + std::vector conf_data; + for (int i = 0; i < max_num_days; i++) { + double sum = 0; + for (size_t j = 0; j < conf_data_age.size(); j++) { + sum += conf_data_age[j][i]; + } + conf_data.push_back((int)(sum - sum_day_minus_one)); + } + + return conf_data; +} + double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries sim_inf_states, - int max_num_days, mio::Date start_date) + mio::TimeSeries sim_det, int max_num_days, mio::Date start_date) { // We need to read in the results from the results directory auto real_data_dead_path = mio::path_join((data_dir / "pydata" / "Germany").string(), "cases_all_county_age_ma7.json"); auto real_data_icu_path = mio::path_join((data_dir / "pydata" / "Germany").string(), "county_divi_ma7.json"); - auto divi_data = mio::read_divi_data(real_data_icu_path); - auto death_data = mio::read_confirmed_cases_data(real_data_dead_path); + auto real_detected_path = + mio::path_join((data_dir / "pydata" / "Germany").string(), "cases_all_county_age_repdate_ma7.json"); + auto divi_data = mio::read_divi_data(real_data_icu_path); + auto death_data = mio::read_confirmed_cases_data(real_data_dead_path); + auto detected_data = mio::read_confirmed_cases_data(real_detected_path); // read in the real data auto real_data_dead_vec = read_in_deaths(death_data.value(), start_date, max_num_days); auto real_data_icu_vec = read_in_icu(divi_data.value(), start_date, max_num_days); + auto real_data_conf_vec = read_in_detected(detected_data.value(), start_date, max_num_days); // Simulated data std::vector sim_data_vec_icu; std::vector sim_data_vec_dead; + std::vector sim_data_vec_conf; for (int i = 0; i < max_num_days; i++) { int number_of_persons_in_icu = 0; int number_of_persons_dead = 0; + int number_of_det = 0; for (size_t j = 0; j < (size_t)num_age_groupss; j++) { auto index_icu = (((size_t)(mio::abm::InfectionState::Count)) * (j)) + ((uint32_t)(mio::abm::InfectionState::InfectedCritical)); @@ -1023,7 +1058,9 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries()[antigen_test]; // Test parameters + auto testing_min_time = mio::abm::days(3); + auto vector_sympt_states = std::vector{mio::abm::InfectionState::InfectedSymptoms}; + auto vector_asympt_states = + std::vector{mio::abm::InfectionState::InfectedNoSymptoms, + mio::abm::InfectionState::Exposed, mio::abm::InfectionState::Susceptible}; + const auto location_it = sim.get_world().get_locations(); + + // We go through each location type and add the testing strategies + + // Schools + // asymptomatic + auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 + auto end_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-05-30 + auto testing_criteria_school = mio::abm::TestingCriteria({}, vector_asympt_states); + auto testing_scheme_school = + mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date_test_school, end_date_test_school, + antigen_test_parameters, testing_probability_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); + + //symptomatic + auto testing_criteria_school_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); + auto testing_scheme_school_sympt = + mio::abm::TestingScheme(testing_criteria_school_sympt, testing_min_time, start_date_test_school, + end_date_test_school, antigen_test_parameters, testing_probability_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_school_sympt); + + //have to test + auto testing_criteria_school_have_to_test = mio::abm::TestingCriteria(); + auto testing_scheme_school_have_to_test = + mio::abm::TestingScheme(testing_criteria_school_have_to_test, testing_min_time, end_date_test_school, tmax, + antigen_test_parameters, perc_have_to_test); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_school_have_to_test); + + // Work + // asymptomatic + auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 + auto end_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); // 2021-05-30 + auto testing_criteria_work = mio::abm::TestingCriteria({}, vector_asympt_states); + auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date_test_work, + tmax, antigen_test_parameters, testing_probability_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); + + //symptomatic + auto testing_criteria_work_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); + auto testing_scheme_work_sympt = + mio::abm::TestingScheme(testing_criteria_work_sympt, testing_min_time, start_date_test_work, tmax, + antigen_test_parameters, testing_probability_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work_sympt); + + // have to test in 35 % of workplaces + std::vector work_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::Work) { + work_location_ids.push_back(location.get_index()); + } + } + std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); + auto num_work_locations = (int)(work_location_ids.size()); + std::vector work_location_ids_35(work_location_ids.begin(), + work_location_ids.begin() + num_work_locations); + auto testing_criteria_work_have_to_test = mio::abm::TestingCriteria(); + auto testing_scheme_work_have_to_test = + mio::abm::TestingScheme(testing_criteria_work_have_to_test, testing_min_time, end_date_test_work, tmax, + antigen_test_parameters, perc_have_to_test); + for (auto& location_id : work_location_ids_35) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work_have_to_test); + } + + //basic shops: + std::vector basics_shop_location_ids; + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + basics_shop_location_ids.push_back(location.get_index()); + } + } + std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); + auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); + std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), + basics_shop_location_ids.begin() + num_basics_shop_locations); + + // asymptomatic + auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 + auto end_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); // 2021-05-30 + auto testing_criteria_basics_shop = mio::abm::TestingCriteria({}, vector_asympt_states); + auto testing_scheme_basics_shop = + mio::abm::TestingScheme(testing_criteria_basics_shop, testing_min_time, start_date_test_basics_shop, tmax, + antigen_test_parameters, testing_probability_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_basics_shop); + + //symptomatic + auto testing_criteria_basics_shop_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); + auto testing_scheme_basics_shop_sympt = + mio::abm::TestingScheme(testing_criteria_basics_shop_sympt, testing_min_time, start_date_test_basics_shop, tmax, + antigen_test_parameters, testing_probability_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_basics_shop_sympt); + + // have to test + auto testing_criteria_basics_shop_have_to_test = mio::abm::TestingCriteria(); + auto testing_scheme_basics_shop_have_to_test = + mio::abm::TestingScheme(testing_criteria_basics_shop_have_to_test, testing_min_time, end_date_test_basics_shop, + tmax, antigen_test_parameters, perc_have_to_test); + for (auto& location_id : basics_shop_location_ids_20) { + sim.get_world().get_testing_strategy().add_testing_scheme( + mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, + testing_scheme_basics_shop_have_to_test); + } + + // social events + // asymptomatic + auto start_date_test_social_event = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 + auto end_date_test_social_event = tmax; // 2021-05-30 + auto testing_criteria_social_event = mio::abm::TestingCriteria({}, vector_asympt_states); + auto testing_scheme_social_event = + mio::abm::TestingScheme(testing_criteria_social_event, testing_min_time, start_date_test_social_event, + end_date_test_social_event, antigen_test_parameters, testing_probability_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, + testing_scheme_social_event); + + //symptomatic + auto testing_criteria_social_event_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); + auto testing_scheme_social_event_sympt = + mio::abm::TestingScheme(testing_criteria_social_event_sympt, testing_min_time, start_date_test_social_event, + end_date_test_social_event, antigen_test_parameters, testing_probability_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, + testing_scheme_social_event_sympt); + + // easter event + // asymptomatic + auto start_date_test_easter_event = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 + auto end_date_test_easter_event = tmax; + auto testing_criteria_easter_event = mio::abm::TestingCriteria({}, vector_asympt_states); + auto testing_scheme_easter_event = + mio::abm::TestingScheme(testing_criteria_easter_event, testing_min_time, start_date_test_easter_event, + end_date_test_easter_event, antigen_test_parameters, testing_probability_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, + testing_scheme_easter_event); + + //symptomatic + auto testing_criteria_easter_event_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); + auto testing_scheme_easter_event_sympt = + mio::abm::TestingScheme(testing_criteria_easter_event_sympt, testing_min_time, start_date_test_easter_event, + end_date_test_easter_event, antigen_test_parameters, testing_probability_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, + testing_scheme_easter_event_sympt); +} + void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, std::pair, double> rmse) { @@ -1582,25 +1784,26 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa PRAGMA_OMP(parallel for num_threads(64)) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; + std::random_device rd; + std::mt19937 g(rd()); printf("I am Thread %d\n", omp_get_thread_num()); // grid search for parameters: // 1: Viral Shed - // 2: Seasonality April - // 3: Seasonality May - // 4: Perc Easter Event - // 6: Dark Figure - // 7.: Contact rate forst ssocial ebents closure - // 8.: Contact intensity for social events - // 9.: Contact rate for home - auto viral_shedding_rate = params[0]; - auto seasonality_april = params[1]; - auto seasonality_may = params[2]; - auto perc_easter_event = params[3]; - auto dark_figure = params[4]; - auto contact_rate_ssc = params[5]; - auto masks = params[6]; + // 2: Dark figure + // 3: testing prob symptomatic + // 4: perc have to test if npi active + auto viral_shedding_rate = params[0]; + auto seasonality_april = 0.8; + auto seasonality_may = 0.5; + auto perc_easter_event = 0.35; + auto dark_figure = params[1]; + auto contact_rate_ssc = 0.2; + auto masks = 0.4; + const double testing_probability_sympt = params[2]; + const double ratio_asympt_to_sympt = 20.0; + const double perc_have_to_test = params[3]; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -1630,80 +1833,17 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; mio::History historyInfectionStatePerAgeGroup{ Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyCumulativeDetectedInfectionsPerAgeGroup{Eigen::Index(sim.get_world().parameters.get_num_groups())}; // / NPIS// const auto location_it = sim.get_world().get_locations(); - // 1. testing schemes in schools - auto testing_min_time_school = mio::abm::days(7); - auto probability_school = 1.0; - auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 - auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 - auto test_type_school = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = sim.get_world().parameters.get()[test_type_school]; // Test parameters - auto testing_criteria_school = mio::abm::TestingCriteria(); - auto testing_scheme_school = - mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, - end_date_test_school, test_parameters, probability_school); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); - - // 2. testing schemes in work places for 35% of random workplaces - std::vector work_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::Work) { - work_location_ids.push_back(location.get_index()); - } - } - //take 35% of work locations - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); - auto num_work_locations = (int)(0.35 * work_location_ids.size()); - std::vector work_location_ids_35(work_location_ids.begin(), - work_location_ids.begin() + num_work_locations); - auto testing_min_time_work = mio::abm::days(1); - auto probability_work = 1.0; - auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); - auto end_date_test_work = mio::abm::TimePoint(tmax); - auto test_type_work = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_work = sim.get_world().parameters.get()[test_type_work]; // Test parameters - auto testing_criteria_work = mio::abm::TestingCriteria(); - auto testing_scheme_work = - mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, end_date_test_work, - test_parameters_work, probability_work); - for (auto& location_id : work_location_ids_35) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); - } + // 1. Add testing strategies - // 2.5 plus testing schemes at 20 % of basics shops - std::vector basics_shop_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - basics_shop_location_ids.push_back(location.get_index()); - } - } - //take 20% of basics shop locations - std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); - auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); - std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), - basics_shop_location_ids.begin() + num_basics_shop_locations); - auto testing_min_time_basics_shop = mio::abm::days(2); - auto probability_basics_shop = 1.0; - auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); - auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); - auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_basics_shop = - sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters - auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); - auto testing_scheme_basics_shop = - mio::abm::TestingScheme(testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, - end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); - for (auto& location_id : basics_shop_location_ids_20) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); - } + add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt, + perc_have_to_test); // 3. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks @@ -1770,7 +1910,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { sim.get_world().parameters.get() = masks; sim.get_world().parameters.get() = viral_shedding_rate; sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); std::cout << "day 14 finished" << std::endl; // small social events to capacity 5 @@ -1787,12 +1927,12 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { restart_timer(timer, "till advance 31 (march ends)"); sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); sim.get_world().parameters.get() = viral_shedding_rate * seasonality_april; restart_timer(timer, "till advance 42"); sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 for (auto& location : location_it) { @@ -1803,13 +1943,13 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { restart_timer(timer, "till advance 61"); sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); std::cout << "day 61 finished (date 2021-05-01)" << std::endl; sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; restart_timer(timer, "till advance 72"); sim.advance(mio::abm::TimePoint(mio::abm::days(70).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType); + historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); std::cout << "day 72 finished (date 2021-05-10)" << std::endl; for (auto& location : location_it) { @@ -1836,7 +1976,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { } } restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType); + sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + historyCumulativeDetectedInfectionsPerAgeGroup); std::cout << "day 90 finished" << std::endl; ////Advance till here @@ -1847,9 +1988,12 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; auto temp_sim_infection_state_per_age_group = std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + auto temp_sim_cumulative_detected_infections_per_age_group = + std::vector>{std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; auto rmse = - calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], max_num_days, start_date); + calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], + temp_sim_cumulative_detected_infections_per_age_group[0], max_num_days, start_date); rmse_results_per_grid_point.at(i) = rmse; #pragma omp critical { @@ -1901,13 +2045,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 5.5; - auto seasonality_april = 0.775; - auto seasonality_may = 0.6; - auto perc_easter_event = 0.4; - auto dark_figure = 3.0; - auto contact_rate_ssc = 0.2; - auto masks = 0.4; + auto viral_shedding_rate = 5.5; + auto seasonality_april = 0.775; + auto seasonality_may = 0.5; + auto perc_easter_event = 0.4; + auto dark_figure = 3.0; + auto contact_rate_ssc = 0.2; + auto masks = 0.4; + const double testing_probability_sympt = 0.05; + const double ratio_asympt_to_sympt = 20.0; + const double perc_have_to_test = 0.04; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -1953,6 +2100,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "time for vaccinaiton state"); // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { + + std::random_device rd; + std::mt19937 g(rd()); + auto world = mio::abm::World(num_age_groupss); create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); @@ -1982,93 +2133,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto location_it = sim.get_world().get_locations(); - // random testing at home - auto testing_min_time_home = mio::abm::days(7); - auto probability_home = 0.01; - auto start_date_test_home = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto end_date_test_home = mio::abm::TimePoint(tmax); // 2021-05-30 - auto test_type_home = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_home = - sim.get_world().parameters.get()[test_type_home]; // Test parameters - auto testing_criteria_home = mio::abm::TestingCriteria(); - auto testing_scheme_home = - mio::abm::TestingScheme(testing_criteria_home, testing_min_time_home, start_date_test_home, - end_date_test_home, test_parameters_home, probability_home); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, - testing_scheme_home); - - // 1. testing schemes in schools - auto testing_min_time_school = mio::abm::days(7); - auto probability_school = 0.1; - auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-04-12 - auto end_date_test_school = mio::abm::TimePoint(tmax); // 2021-05-30 - auto test_type_school = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = - sim.get_world().parameters.get()[test_type_school]; // Test parameters - auto testing_criteria_school = mio::abm::TestingCriteria(); - auto testing_scheme_school = - mio::abm::TestingScheme(testing_criteria_school, testing_min_time_school, start_date_test_school, - end_date_test_school, test_parameters, probability_school); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - testing_scheme_school); - - // 2. testing schemes in work places for 35% of random workplaces - std::vector work_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::Work) { - work_location_ids.push_back(location.get_index()); - } - } - //take 35% of work locations - std::random_device rd; - std::mt19937 g(rd()); - std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); - auto num_work_locations = (int)(0.35 * work_location_ids.size()); - std::vector work_location_ids_35(work_location_ids.begin(), - work_location_ids.begin() + num_work_locations); - auto testing_min_time_work = mio::abm::days(1); - auto probability_work = 0.05; - auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); - auto end_date_test_work = mio::abm::TimePoint(tmax); - auto test_type_work = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_work = - sim.get_world().parameters.get()[test_type_work]; // Test parameters - auto testing_criteria_work = mio::abm::TestingCriteria(); - auto testing_scheme_work = - mio::abm::TestingScheme(testing_criteria_work, testing_min_time_work, start_date_test_work, - end_date_test_work, test_parameters_work, probability_work); - for (auto& location_id : work_location_ids_35) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work); - } - - // 2.5 plus testing schemes at 20 % of basics shops - std::vector basics_shop_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - basics_shop_location_ids.push_back(location.get_index()); - } - } - //take 20% of basics shop locations - std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); - auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); - std::vector basics_shop_location_ids_20( - basics_shop_location_ids.begin(), basics_shop_location_ids.begin() + num_basics_shop_locations); - auto testing_min_time_basics_shop = mio::abm::days(2); - auto probability_basics_shop = 0.01; - auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); - auto end_date_test_basics_shop = mio::abm::TimePoint(tmax); - auto test_type_basics_shop = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters_basics_shop = - sim.get_world().parameters.get()[test_type_basics_shop]; // Test parameters - auto testing_criteria_basics_shop = mio::abm::TestingCriteria(); - auto testing_scheme_basics_shop = mio::abm::TestingScheme( - testing_criteria_basics_shop, testing_min_time_basics_shop, start_date_test_basics_shop, - end_date_test_basics_shop, test_parameters_basics_shop, probability_basics_shop); - for (auto& location_id : basics_shop_location_ids_20) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, testing_scheme_basics_shop); - } + add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt, + perc_have_to_test); // 3. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks @@ -2112,7 +2178,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s social_event_location_ids_small.push_back(location.get_index()); } } - //take 50% of social event locations + //take 25% of social event locations std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); auto num_social_event_locations_big = (int)(0.25 * social_event_location_ids_small.size()); social_event_location_ids_big.insert( @@ -2252,6 +2318,12 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; + //calculate RMSE + auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], + temp_sim_cumulative_detected_infections_per_age_group[0], max_num_days, + start_date); + std::cout << "RMSE: " << rmse << std::endl; + //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); //for now this doesnt work, but we can still save the results of the last world since the //parameters are the same for each run @@ -2361,8 +2433,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2413,17 +2485,14 @@ int main(int argc, char** argv) if (run_grid_search) { // grid search for parameters: // 1: Viral Shed - // 2: Seasonality April - // 3: Seasonality May - // 4: Perc Easter Event - // 5: Dark Figure - // 6.: Contact rate forst ssocial ebents closure - // 7.: Masks - std::vector> grid_boundaries = {{3.0, 8.0}, {0.6, 0.95}, {0.4, 0.8}, {0.2, 0.6}, - {1.0, 5.0}, {0.2, 0.6}, {0.2, 0.6}}; - - std::vector points_per_dim = {5, 5, 5, 5, 5, 5, 5}; - // std::vector points_per_dim = {3, 3, 3, 3, 3, 3, 3}; + // 2: Dark figure + // 3: testing prob symptomatic + // 4: perc have to test if npi active + + std::vector> grid_boundaries = {{5.5, 8.0}, {3.0, 6.0}, {0.05, 0.1}, {0.01, 0.05}}; + + std::vector points_per_dim = {2, 2, 2, 5}; + // std::vector points_per_dim = {9, 9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From 2326811c5095b6c1ddcadbe610fe4b2860eb134f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 7 Aug 2024 22:44:39 +0200 Subject: [PATCH 255/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a921259c0f..41b375d993 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2433,8 +2433,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2489,12 +2489,12 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{5.5, 8.0}, {3.0, 6.0}, {0.05, 0.1}, {0.01, 0.05}}; + std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.01, 0.035}}; - std::vector points_per_dim = {2, 2, 2, 5}; - // std::vector points_per_dim = {9, 9, 9, 9}; - auto grid = grid_points(grid_boundaries, points_per_dim); - auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); + // std::vector points_per_dim = {2, 2, 2, 5}; + std::vector points_per_dim = {9, 9, 9, 9}; + auto grid = grid_points(grid_boundaries, points_per_dim); + auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } else { auto result = run(input_dir, result_dir, num_runs); From fe742f01cbe45eb0b3fc33952730397f9598feea Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:22:47 +0200 Subject: [PATCH 256/488] Update logger for reproduction number --- cpp/models/abm/infection.cpp | 38 ++++++++++++++++++++++++ cpp/models/abm/infection.h | 14 ++++++++- cpp/models/abm/simulation.h | 8 +++++ cpp/simulations/paper_abm_bs_testing.cpp | 31 ++++++++----------- 4 files changed, 71 insertions(+), 20 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index a24da71c82..37a9182914 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -82,6 +82,44 @@ ScalarType Infection::get_viral_shed(TimePoint t) const return m_individual_virus_shed_factor / (1 + exp(-(m_log_norm_alpha + m_log_norm_beta * get_viral_load(t)))); } +ScalarType Infection::get_viral_shed_integral() const +{ + ScalarType integral = std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak)) / + (m_log_norm_beta * m_viral_load.incline); // Integral from start to peak + integral -= std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak)) / + (m_log_norm_beta * m_viral_load.decline); // Integral from peak to end + + return integral; +} + +ScalarType Infection::get_viral_shed_integral(TimePoint a, TimePoint b) const +{ + // Time period before peak + if (b.days() <= m_viral_load.start_date.days() + m_viral_load.peak / m_viral_load.incline) { + ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b))) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)))) / + (m_log_norm_beta * m_viral_load.incline); + return integral; + } + + // Time period after peak + if (a.days() >= m_viral_load.start_date.days() + m_viral_load.peak / m_viral_load.incline) { + ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b))) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)))) / + (m_log_norm_beta * m_viral_load.decline); + return integral; + } + + // Time period includes peak + ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak)) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)))) / + (m_log_norm_beta * m_viral_load.incline); + integral += (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b))) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak))) / + (m_log_norm_beta * m_viral_load.decline); + return integral; +} + VirusVariant Infection::get_virus_variant() const { return m_virus_variant; diff --git a/cpp/models/abm/infection.h b/cpp/models/abm/infection.h index 273ca95ecf..ad48d3e9cb 100644 --- a/cpp/models/abm/infection.h +++ b/cpp/models/abm/infection.h @@ -90,7 +90,19 @@ class Infection ScalarType get_viral_shed(TimePoint t) const; /** - * @brief: Get VirusVariant. + * @brief Get total viral shed. + */ + ScalarType get_viral_shed_integral() const; + + /** + * @brief Get viral shed between two TimePoints. + * @param[in] a Left limit of the time period. + * @param[in] b Right limit of the time period. + */ + ScalarType get_viral_shed_integral(TimePoint a, TimePoint b) const; + + /** + * @brief Get VirusVariant. * @return VirusVariant of the Infection. */ VirusVariant get_virus_variant() const; diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index 0a0cd97491..47abe1b48f 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -83,6 +83,14 @@ class Simulation std::cout << "Time spent on logging: " << sum << std::endl; } + /** + * @brief Get the time step of the Simulation. + */ + TimeSpan get_dt() const + { + return m_dt; + } + /** * @brief Get the current time of the Simulation. */ diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 41b375d993..217b929715 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1412,6 +1412,7 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { using Type = std::pair; /** * @brief Log the TimeSeries of the estimated reproduction number. + * We use the formula from https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3816335/ * @param[in] sim The simulation of the abm. * @return A pair of the TimePoint and the TimeSeries of the estimated reproduction number. */ @@ -1421,14 +1422,15 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { // time period to take into account for estimating the reproduction number // longer periods lead to more averaged results - mio::abm::TimeSpan time_frame = mio::abm::days(1); + mio::abm::TimeSpan time_frame = sim.get_dt(); const auto t = sim.get_time(); const auto persons = sim.get_world().get_persons(); const auto virus = mio::abm::VirusVariant::Alpha; // PRAGMA_OMP(parallel for) int number_newly_infected = 0; - int number_infectious = 0; + double infection_incidence = 0; + double total_integral_buffer = 0; for (auto i = size_t(0); i < persons.size(); ++i) { auto& p = persons[i]; if (p.get_should_be_logged()) { @@ -1436,30 +1438,21 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { if (p.is_infected(t) && !p.is_infected(t - time_frame)) { number_newly_infected += 1; } - // count infectious people at the midpoint of the time period as an estimation - if (p.is_infected(t - time_frame / 2)) { - if (p.get_infection().get_viral_shed(t - time_frame / 2) != 0) { - number_infectious += 1; - } + // sum the total infection incidence from all infected people in the desired time frame + if (p.is_infected(t) || p.is_infected(t - time_frame)) { + // this is the integral of the viral shed between t-time_frame and t + // divided by the total integral to normalize it to a density function + infection_incidence += p.get_infection().get_viral_shed_integral(t - time_frame, t) / + p.get_infection().get_viral_shed_integral(); } } } // if the infection dies out, the reproduction number has no meaningful value - if (number_infectious == 0) { + if (infection_incidence == 0) { return std::make_pair(t, estimation); } - // assume equal parameters for each age - auto vl_params = sim.get_world().parameters.get()[{virus, age_group_0_to_4}]; - - // Assume uniform distribution of parameters. Taking mean value of uniform distribution. Factor 1/2 cancels in the division. - double average_infectious_period = - (vl_params.viral_load_peak.params.a() + vl_params.viral_load_peak.params.b()) / - (vl_params.viral_load_incline.params.a() + vl_params.viral_load_incline.params.b()) - - (vl_params.viral_load_peak.params.a() + vl_params.viral_load_peak.params.b()) / - (vl_params.viral_load_decline.params.a() + vl_params.viral_load_decline.params.b()); - - estimation[0] += (number_newly_infected * average_infectious_period) / (number_infectious * time_frame.days()); + estimation[0] = number_newly_infected / infection_incidence; return std::make_pair(t, estimation); } }; From 47bbdb491e96fd3480cfd61673854b3dbc6e566a Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:42:15 +0200 Subject: [PATCH 257/488] Remove unused variables --- cpp/simulations/paper_abm_bs_testing.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 217b929715..ee6c05b2d6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1425,12 +1425,10 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { mio::abm::TimeSpan time_frame = sim.get_dt(); const auto t = sim.get_time(); const auto persons = sim.get_world().get_persons(); - const auto virus = mio::abm::VirusVariant::Alpha; // PRAGMA_OMP(parallel for) int number_newly_infected = 0; - double infection_incidence = 0; - double total_integral_buffer = 0; + double infection_incidence = 0; for (auto i = size_t(0); i < persons.size(); ++i) { auto& p = persons[i]; if (p.get_should_be_logged()) { From 31fad055aa5224b3d9f379d6c885c5bf7a1fa6ea Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 8 Aug 2024 12:37:15 +0200 Subject: [PATCH 258/488] Small error in integral formula --- cpp/models/abm/infection.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 37a9182914..e5c874c063 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -84,9 +84,9 @@ ScalarType Infection::get_viral_shed(TimePoint t) const ScalarType Infection::get_viral_shed_integral() const { - ScalarType integral = std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak)) / + ScalarType integral = std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak) + 1) / (m_log_norm_beta * m_viral_load.incline); // Integral from start to peak - integral -= std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak)) / + integral -= std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak) + 1) / (m_log_norm_beta * m_viral_load.decline); // Integral from peak to end return integral; @@ -96,26 +96,26 @@ ScalarType Infection::get_viral_shed_integral(TimePoint a, TimePoint b) const { // Time period before peak if (b.days() <= m_viral_load.start_date.days() + m_viral_load.peak / m_viral_load.incline) { - ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b))) - - std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)))) / + ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b)) + 1) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)) + 1)) / (m_log_norm_beta * m_viral_load.incline); return integral; } // Time period after peak if (a.days() >= m_viral_load.start_date.days() + m_viral_load.peak / m_viral_load.incline) { - ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b))) - - std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)))) / + ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b)) + 1) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a))) + 1) / (m_log_norm_beta * m_viral_load.decline); return integral; } // Time period includes peak - ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak)) - - std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)))) / + ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak) + 1) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)) + 1)) / (m_log_norm_beta * m_viral_load.incline); - integral += (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b))) - - std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak))) / + integral += (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b)) + 1) - + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak) + 1)) / (m_log_norm_beta * m_viral_load.decline); return integral; } From 85fa8eee99bf6f9b04fc950788b0569e78dd7bcd Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:04:31 +0200 Subject: [PATCH 259/488] analyzer update Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 38 ++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 23925a4158..21c85b748f 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -285,7 +285,7 @@ def plot_dead(path): y_real = df_total_dead['Deaths'].to_numpy() # we calculate the RMSE - rmse_dead = np.sqrt(((y_real- p50_bs['Total'][()][:, 7][::24][0:90])**2).mean()) + rmse_dead = (((y_real- p50_bs['Total'][()][:, 7][::24][0:90])**2).mean()) # we need to plot the cumulative dead persons from the real world and from the simulation ax.plot(df_total_dead.index, y_real, color='tab:blue') ax.plot(df_total_dead.index, p50_bs['Total'][()][:, 7][::24][0:90], color='tab:red') @@ -344,7 +344,7 @@ def plot_icu(path): # we calculate the RMSE - rmse_ICU = np.sqrt(((ICU_Real - ICU_Simulation)**2).mean()) + rmse_ICU = ((ICU_Real - ICU_Simulation)**2).mean() # plot the ICU beds and the ICU beds taken fig, ax = plt.subplots(1, 1, constrained_layout=True) @@ -647,10 +647,11 @@ def plot_cumulative_detected_infections(path): df_abb_diff = np.diff(df_abb) - # again the rmse - rmse_detected = np.sqrt(((df_abb - total_50)**2).mean()) - total_50 = gaussian_filter1d(total_50, sigma=1, mode='nearest') + # again the rmse + rmse_detected = ((df_abb - total_50)**2).mean()*(0.01*0.01) + total_50_diff = gaussian_filter1d(total_50_diff.flatten(), sigma=2, mode='nearest') + total_50 = gaussian_filter1d(total_50.flatten(), sigma=2, mode='nearest') # we plot this # we plot the tests positive and the real cases plt.plot(time, total_50, color='tab:red') @@ -658,15 +659,26 @@ def plot_cumulative_detected_infections(path): plt.xlabel('time (days)') plt.ylabel('Cumulative Amount of detected infections') plt.title('Cumulative detected infections') - # also plot the new detected infections with the same color but dashed - plt.plot(time[1:], total_50_diff, color='tab:red', linestyle='dashed') - plt.plot(time[1:], df_abb_diff, color='tab:blue', linestyle='dashed') - plt.legend(['Simulated detected infections', 'Real detected infections', 'Simulated new detected infections', 'Real new detected infections']) + plt.legend(['Simulated detected infections', 'Real detected infections']) #rmse plt.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_detected))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) plt.show() + + # also the amount of new detected infections + fig, ax = plt.subplots(1, 1, constrained_layout=True) + fig.set_figwidth(20) + fig.set_figheight(9) + # we plot the tests positive and the real cases + ax.plot(time[0:89], total_50_diff, color='tab:red') + ax.plot(time[0:89], df_abb_diff, color='tab:blue') + ax.set_xlabel('time (days)') + ax.set_ylabel('Number of new detected infections') + ax.title.set_text('New detected infections') + ax.legend(['Simulated new detected infections', 'Real new detected infections']) + plt.show() + def plot_positive_and_done_test(path): f_p50_positive = h5py.File( path+"/positive_test_per_location_type_per_age_group/p50/Results.h5", 'r') @@ -733,11 +745,11 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infection_states_results(path) - plot_infections_loc_types_avarage(path) + # plot_infection_states_results(path) + # plot_infections_loc_types_avarage(path) plot_icu(path) plot_dead(path) - infer_positive_tests(path) - plot_estimated_reproduction_number(path) + # infer_positive_tests(path) + # plot_estimated_reproduction_number(path) plot_cumulative_detected_infections(path) plot_positive_and_done_test(path) From efde6c12c78b797be436037c74e358415a29a563 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:06:08 +0200 Subject: [PATCH 260/488] paper update Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 36 ++++++++++++------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ee6c05b2d6..39d2e221ef 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -615,8 +615,8 @@ void set_parameters(mio::abm::Parameters& params) TimeInfectedCriticalToRecovered_my_sigma.second}; //Set testing parameters - auto pcr_test_values = mio::abm::TestParameters{0.9, 0.99}; - auto antigen_test_values = mio::abm::TestParameters{0.69, 0.99}; + auto pcr_test_values = mio::abm::TestParameters{0.9, 0.995}; + auto antigen_test_values = mio::abm::TestParameters{0.69, 0.993}; auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; @@ -932,7 +932,7 @@ void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool socia if (symptomatic) { std::cout << "Adding symptomatic testing strategy" << std::endl; auto testing_min_time_symptomatic = mio::abm::days(7); - auto probability_symptomatic = 1.0; + auto probability_symptomatic = 0.1; auto start_date_test_symptomatic = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 auto end_date_test_symptomatic = mio::abm::TimePoint(mio::abm::days(90).seconds()); // 2021-05-30 auto test_type_symptomatic = mio::abm::TestType::Antigen; // Antigen test @@ -1422,12 +1422,12 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { // time period to take into account for estimating the reproduction number // longer periods lead to more averaged results - mio::abm::TimeSpan time_frame = sim.get_dt(); + mio::abm::TimeSpan time_frame = mio::abm::days(7); const auto t = sim.get_time(); const auto persons = sim.get_world().get_persons(); // PRAGMA_OMP(parallel for) - int number_newly_infected = 0; + int number_newly_infected = 0; double infection_incidence = 0; for (auto i = size_t(0); i < persons.size(); ++i) { auto& p = persons[i]; @@ -1537,8 +1537,8 @@ void get_grid_search_results_and_write_them_to_file( }); // Write the 5 best RMSE at the end of the file - file << std::endl << "Top 5 RMSE:" << std::endl; - for (size_t i = 0; i < std::min(5, gathered_grid_vector_with_rmse.size()); i++) { + file << std::endl << "Top 20 RMSE:" << std::endl; + for (size_t i = 0; i < std::min(20, gathered_grid_vector_with_rmse.size()); i++) { file << "Grid point: "; for (size_t j = 0; j < gathered_grid_vector_with_rmse[i].first.size(); j++) { file << gathered_grid_vector_with_rmse[i].first.at(j) << " "; @@ -1577,15 +1577,15 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 auto end_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-05-30 auto testing_criteria_school = mio::abm::TestingCriteria({}, vector_asympt_states); auto testing_scheme_school = - mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date_test_school, end_date_test_school, + mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date_test_school, tmax, antigen_test_parameters, testing_probability_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); //symptomatic auto testing_criteria_school_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); auto testing_scheme_school_sympt = - mio::abm::TestingScheme(testing_criteria_school_sympt, testing_min_time, start_date_test_school, - end_date_test_school, antigen_test_parameters, testing_probability_sympt); + mio::abm::TestingScheme(testing_criteria_school_sympt, testing_min_time, start_date_test_school, tmax, + antigen_test_parameters, testing_probability_sympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school_sympt); @@ -2037,15 +2037,15 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; auto viral_shedding_rate = 5.5; - auto seasonality_april = 0.775; - auto seasonality_may = 0.5; + auto seasonality_april = 0.75; + auto seasonality_may = 0.4; auto perc_easter_event = 0.4; - auto dark_figure = 3.0; - auto contact_rate_ssc = 0.2; + auto dark_figure = 2.0; + auto contact_rate_ssc = 0.4; auto masks = 0.4; const double testing_probability_sympt = 0.05; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.04; + const double perc_have_to_test = 0.005; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2424,8 +2424,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2480,7 +2480,7 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.01, 0.035}}; + std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; // std::vector points_per_dim = {2, 2, 2, 5}; std::vector points_per_dim = {9, 9, 9, 9}; From 9fc270ff75b2069617ee684427f576acb3af2461 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:12:06 +0200 Subject: [PATCH 261/488] cluster update Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 39d2e221ef..7dec46e305 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1786,15 +1786,15 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { // 3: testing prob symptomatic // 4: perc have to test if npi active auto viral_shedding_rate = params[0]; - auto seasonality_april = 0.8; - auto seasonality_may = 0.5; - auto perc_easter_event = 0.35; + auto seasonality_april = 0.75; + auto seasonality_may = 0.4; + auto perc_easter_event = 0.4; auto dark_figure = params[1]; - auto contact_rate_ssc = 0.2; + auto contact_rate_ssc = 0.4; auto masks = 0.4; const double testing_probability_sympt = params[2]; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = params[3]; + const double perc_have_to_test = 0.005; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2424,8 +2424,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2480,10 +2480,10 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; - + // std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; + std::vector grid_boundaries = {5.5, 2.0, 0.05}; // std::vector points_per_dim = {2, 2, 2, 5}; - std::vector points_per_dim = {9, 9, 9, 9}; + std::vector points_per_dim = {8, 8, 8}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From 01ae8a609ab37e595ebfb9a20d311a7e7cfaa6c6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 14:16:27 +0200 Subject: [PATCH 262/488] cluster update Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7dec46e305..7ff3874f1a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2045,7 +2045,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto masks = 0.4; const double testing_probability_sympt = 0.05; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.005; + const double perc_have_to_test = 0.0035; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2483,7 +2483,7 @@ int main(int argc, char** argv) // std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; std::vector grid_boundaries = {5.5, 2.0, 0.05}; // std::vector points_per_dim = {2, 2, 2, 5}; - std::vector points_per_dim = {8, 8, 8}; + std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From 483a148d4c6f7bda38721b99bf0ddb3995fb4c4d Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:10:25 +0200 Subject: [PATCH 263/488] Bracket mistake fix --- cpp/models/abm/infection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index e5c874c063..7040b180db 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -105,7 +105,7 @@ ScalarType Infection::get_viral_shed_integral(TimePoint a, TimePoint b) const // Time period after peak if (a.days() >= m_viral_load.start_date.days() + m_viral_load.peak / m_viral_load.incline) { ScalarType integral = (std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(b)) + 1) - - std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a))) + 1) / + std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * get_viral_load(a)) + 1)) / (m_log_norm_beta * m_viral_load.decline); return integral; } From abd3eb9f0f6c6d85e936089ace9140a5ecd48f27 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:12:29 +0200 Subject: [PATCH 264/488] add 25 and 75 percentil Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 58 +++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 21c85b748f..d6b245606f 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -249,6 +249,15 @@ def plot_dead(path): path+"/infection_state_per_age_group/p50/Results.h5", 'r') p50_bs = f_p50['0'] + # do the same for 25 and 75 percentile + f_p25 = h5py.File( + path+"/infection_state_per_age_group/p25/Results.h5", 'r') + p25_bs = f_p25['0'] + + f_p75 = h5py.File( + path+"/infection_state_per_age_group/p75/Results.h5", 'r') + p75_bs = f_p75['0'] + age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] @@ -287,8 +296,10 @@ def plot_dead(path): # we calculate the RMSE rmse_dead = (((y_real- p50_bs['Total'][()][:, 7][::24][0:90])**2).mean()) # we need to plot the cumulative dead persons from the real world and from the simulation - ax.plot(df_total_dead.index, y_real, color='tab:blue') - ax.plot(df_total_dead.index, p50_bs['Total'][()][:, 7][::24][0:90], color='tab:red') + ax.plot(df_total_dead.index, y_real, color='tab:red') + ax.plot(df_total_dead.index, p50_bs['Total'][()][:, 7][::24][0:90], color='tab:blue') + ax.fill_between(df_total_dead.index, p75_bs['Total'][()][:, 7][::24][0:90], p25_bs['Total'][()][:, 7][::24][0:90], + alpha=0.5, color='tab:blue') ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) ax.set_xlabel('Date') @@ -303,8 +314,8 @@ def plot_dead(path): df_abb_age_group = df_abb[df_abb['Age_RKI'] == age_groups[i]][0:90] y_real = np.floor(df_abb_age_group['Deaths'].to_numpy()) # we need to plot the dead persons from the real world and from the simulation - ax.plot(df_abb_age_group['Date'], y_real, color='tab:blue') - ax.plot(df_abb_age_group['Date'], p50_bs[age_group_access[i]][()][:, 7][::24][0:90], color='tab:red') + ax.plot(df_abb_age_group['Date'], y_real, color='tab:red') + ax.plot(df_abb_age_group['Date'], p50_bs[age_group_access[i]][()][:, 7][::24][0:90], color='tab:blue') ax.set_title('Dead, Age{}'.format(i)) ax.set_xlabel('Date') ax.set_xticks(df_abb_age_group['Date'][::50]) @@ -334,7 +345,30 @@ def plot_icu(path): # we just take the first 90 days total_50 = total_50[0:90] + # we plot this against this the Amount of persons in the ICU from our model + f_p75 = h5py.File( + path+"/infection_state_per_age_group/p75/Results.h5", 'r') + p75_bs = f_p75['0'] + total_75 = p75_bs['Total'][()] + # we need just every 24th value + total_75 = total_75[::24] + # we just take the first 90 days + total_75 = total_75[0:90] + + # same with 25 percentile + f_p25 = h5py.File( + path+"/infection_state_per_age_group/p25/Results.h5", 'r') + p25_bs = f_p25['0'] + total_25 = p25_bs['Total'][()] + # we need just every 24th value + total_25 = total_25[::24] + # we just take the first 90 days + total_25 = total_25[0:90] + + ICU_Simulation = np.floor(total_50[:, 5]*perc_of_critical_in_icu) + ICU_Simulation75 = np.floor(total_75[:, 5]*perc_of_critical_in_icu) + ICU_Simulation25 = np.floor(total_25[:, 5]*perc_of_critical_in_icu) ICU_Real = np.floor(df_abb['ICU'][0:90]) #smooth the data @@ -351,8 +385,11 @@ def plot_icu(path): fig.set_figwidth(20) fig.set_figheight(9) # we plot the ICU_low and the ICU_high - ax.plot(df_abb['Date'][0:90], ICU_Real, color='tab:blue') - ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:red') + ax.plot(df_abb['Date'][0:90], ICU_Real, color='tab:red') + ax.fill_between(df_abb['Date'][0:90],ICU_Simulation75, ICU_Simulation25, + alpha=0.5, color='tab:blue') + ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:blue') + # we also write the rmse ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) @@ -733,7 +770,6 @@ def plot_positive_and_done_test(path): - if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" @@ -745,11 +781,11 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - # plot_infection_states_results(path) - # plot_infections_loc_types_avarage(path) + plot_infection_states_results(path) + plot_infections_loc_types_avarage(path) plot_icu(path) plot_dead(path) - # infer_positive_tests(path) - # plot_estimated_reproduction_number(path) + infer_positive_tests(path) + plot_estimated_reproduction_number(path) plot_cumulative_detected_infections(path) plot_positive_and_done_test(path) From ce4677277a3fec5796e1b85a1a89d1361cb3842f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:27:25 +0200 Subject: [PATCH 265/488] cluster run Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/migration_rules.cpp | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/models/abm/migration_rules.cpp b/cpp/models/abm/migration_rules.cpp index 01125dc8a6..3e713e4ac7 100644 --- a/cpp/models/abm/migration_rules.cpp +++ b/cpp/models/abm/migration_rules.cpp @@ -184,7 +184,7 @@ LocationType easter_party(Person::RandomNumberGenerator& /*rng*/, const Person& { auto current_loc = person.get_location().get_type(); //leave - if (person.get_goes_to_easter() && t.days() > 33.0 && t.days() < 36.0 && (t.hour_of_day() >= 12) && + if (person.get_goes_to_easter() && t.days() > 33.0 && t.days() < 37.0 && (t.hour_of_day() >= 12) && (t.hour_of_day() <= 22) && !person.is_in_quarantine(t, params)) { return LocationType::Event; } diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7ff3874f1a..01f2abe38e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1792,7 +1792,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { auto dark_figure = params[1]; auto contact_rate_ssc = 0.4; auto masks = 0.4; - const double testing_probability_sympt = params[2]; + const double testing_probability_sympt = 0.055; const double ratio_asympt_to_sympt = 20.0; const double perc_have_to_test = 0.005; @@ -2036,14 +2036,14 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 5.5; - auto seasonality_april = 0.75; + auto viral_shedding_rate = 5.225; + auto seasonality_april = 0.7; auto seasonality_may = 0.4; auto perc_easter_event = 0.4; auto dark_figure = 2.0; auto contact_rate_ssc = 0.4; auto masks = 0.4; - const double testing_probability_sympt = 0.05; + const double testing_probability_sympt = 0.055; const double ratio_asympt_to_sympt = 20.0; const double perc_have_to_test = 0.0035; @@ -2481,7 +2481,7 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; - std::vector grid_boundaries = {5.5, 2.0, 0.05}; + std::vector grid_boundaries = {5.5, 2.0}; // std::vector points_per_dim = {2, 2, 2, 5}; std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); From 0039281f54a9eea4ee56aa971ddb79d90d931f47 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:54:44 +0200 Subject: [PATCH 266/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 01f2abe38e..e09729514e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1422,7 +1422,7 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { // time period to take into account for estimating the reproduction number // longer periods lead to more averaged results - mio::abm::TimeSpan time_frame = mio::abm::days(7); + mio::abm::TimeSpan time_frame = sim.get_dt(); const auto t = sim.get_time(); const auto persons = sim.get_world().get_persons(); @@ -1786,15 +1786,15 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { // 3: testing prob symptomatic // 4: perc have to test if npi active auto viral_shedding_rate = params[0]; - auto seasonality_april = 0.75; + auto seasonality_april = params[2]; auto seasonality_may = 0.4; auto perc_easter_event = 0.4; - auto dark_figure = params[1]; - auto contact_rate_ssc = 0.4; + auto dark_figure = 2.0; + auto contact_rate_ssc = 0.33; auto masks = 0.4; - const double testing_probability_sympt = 0.055; + const double testing_probability_sympt = 0.0055; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.005; + const double perc_have_to_test = params[1]; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2036,16 +2036,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 5.225; + auto viral_shedding_rate = 5.5; auto seasonality_april = 0.7; auto seasonality_may = 0.4; auto perc_easter_event = 0.4; auto dark_figure = 2.0; auto contact_rate_ssc = 0.4; auto masks = 0.4; - const double testing_probability_sympt = 0.055; + const double testing_probability_sympt = 0.06; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.0035; + const double perc_have_to_test = 0.004; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2481,7 +2481,7 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; - std::vector grid_boundaries = {5.5, 2.0}; + std::vector grid_boundaries = {5.5, 0.004, 0.75}; // std::vector points_per_dim = {2, 2, 2, 5}; std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); From 94b7e71e639d580b763ec20cbfc2a8ff60f684b6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 17:43:10 +0200 Subject: [PATCH 267/488] push for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/generate_graph_from_data.cpp | 4 +-- cpp/simulations/paper_abm_bs_testing.cpp | 33 ++++++++++---------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index b6cfd07903..d1e3c65140 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -136,8 +136,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double maxRiskOfInfectionFromSymptomaticMax = 0.5; const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; - const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.049, 0.05, 0.01}; - const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.074, 0.05, 0.01}; + const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.02, 0.02, 0.01}; + const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.02, 0.02, 0.01}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e09729514e..ba497ccb26 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1786,15 +1786,15 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { // 3: testing prob symptomatic // 4: perc have to test if npi active auto viral_shedding_rate = params[0]; - auto seasonality_april = params[2]; - auto seasonality_may = 0.4; + auto seasonality_april = params[1]; + auto seasonality_may = params[1] * 0.5; auto perc_easter_event = 0.4; - auto dark_figure = 2.0; + auto dark_figure = 2.1; auto contact_rate_ssc = 0.33; auto masks = 0.4; - const double testing_probability_sympt = 0.0055; + const double testing_probability_sympt = params[2]; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = params[1]; + const double perc_have_to_test = 0.003; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -1861,7 +1861,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { } if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 - location.get_infection_parameters().get().array() *= 0.75; + location.get_infection_parameters().get().array() *= (0.75 * 0.75); } } @@ -1955,7 +1955,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { - location.get_infection_parameters().get().array() *= 0.35; + location.get_infection_parameters().get().array() *= contact_rate_ssc; + ; location.set_capacity(15, 0); } } @@ -2036,16 +2037,16 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 5.5; - auto seasonality_april = 0.7; - auto seasonality_may = 0.4; + auto viral_shedding_rate = 5.8; + auto seasonality_april = 0.66; + auto seasonality_may = 0.33; auto perc_easter_event = 0.4; auto dark_figure = 2.0; - auto contact_rate_ssc = 0.4; + auto contact_rate_ssc = 0.33; auto masks = 0.4; - const double testing_probability_sympt = 0.06; + const double testing_probability_sympt = 0.07; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.004; + const double perc_have_to_test = 0.003; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2153,7 +2154,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 - location.get_infection_parameters().get().array() *= 0.7; + location.get_infection_parameters().get().array() *= (0.75 * 0.75); } } @@ -2261,7 +2262,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.get_index()) != social_event_location_ids_big.end()) { number_of_big_social_events--; if (number_of_big_social_events >= 0) { - location.get_infection_parameters().get().array() *= 0.35; + location.get_infection_parameters().get().array() *= contact_rate_ssc; location.set_capacity(15, 0); } } @@ -2481,7 +2482,7 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; - std::vector grid_boundaries = {5.5, 0.004, 0.75}; + std::vector grid_boundaries = {5.5, 0.66, 0.07}; // std::vector points_per_dim = {2, 2, 2, 5}; std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); From ff4d03ecb029ba125665855b396e9d459581252c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 18:22:44 +0200 Subject: [PATCH 268/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 26 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index d6b245606f..6b025a6a1a 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -325,7 +325,7 @@ def plot_dead(path): def plot_icu(path): df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu = 0.45 + perc_of_critical_in_icu = 0.47 # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ba497ccb26..9d572efc78 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1788,13 +1788,13 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { auto viral_shedding_rate = params[0]; auto seasonality_april = params[1]; auto seasonality_may = params[1] * 0.5; - auto perc_easter_event = 0.4; - auto dark_figure = 2.1; - auto contact_rate_ssc = 0.33; + auto perc_easter_event = 0.6; + auto dark_figure = params[2]; + auto contact_rate_ssc = 0.45; auto masks = 0.4; - const double testing_probability_sympt = params[2]; + const double testing_probability_sympt = 0.08; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.003; + const double perc_have_to_test = 0.0033; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2038,15 +2038,15 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; auto viral_shedding_rate = 5.8; - auto seasonality_april = 0.66; - auto seasonality_may = 0.33; - auto perc_easter_event = 0.4; - auto dark_figure = 2.0; - auto contact_rate_ssc = 0.33; + auto seasonality_april = 0.6; + auto seasonality_may = 0.3; + auto perc_easter_event = 0.6; + auto dark_figure = 2.2; + auto contact_rate_ssc = 0.45; auto masks = 0.4; - const double testing_probability_sympt = 0.07; + const double testing_probability_sympt = 0.08; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.003; + const double perc_have_to_test = 0.0033; mio::Date start_date{2021, 3, 1}; int max_num_days = 90; @@ -2482,7 +2482,7 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; - std::vector grid_boundaries = {5.5, 0.66, 0.07}; + std::vector grid_boundaries = {5.8, 0.6, 2.2}; // std::vector points_per_dim = {2, 2, 2, 5}; std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); From ff1b33ee574f4406c4eabbd0cba696dae3dae7a7 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 8 Aug 2024 22:28:20 +0200 Subject: [PATCH 269/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- cpp/simulations/generate_graph_from_data.cpp | 4 ++-- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 3541b54e15..48e53c2b90 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for num_threads(4)) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for num_threads(4)) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,7 +168,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); - PRAGMA_OMP(parallel for num_threads(4)) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->adjust_contact_rates(parameters.get_num_groups()); diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index d1e3c65140..0244bb8e7f 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -134,8 +134,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.5, 0.5, 0.5}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.5, 0.5, 0.5}; const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.02, 0.02, 0.01}; const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.02, 0.02, 0.01}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9d572efc78..c28fa89095 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2037,11 +2037,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 5.8; - auto seasonality_april = 0.6; - auto seasonality_may = 0.3; + auto viral_shedding_rate = 6.09; + auto seasonality_april = 0.57; + auto seasonality_may = 0.5 * seasonality_april; auto perc_easter_event = 0.6; - auto dark_figure = 2.2; + auto dark_figure = 2.1; auto contact_rate_ssc = 0.45; auto masks = 0.4; const double testing_probability_sympt = 0.08; From bd5e097561e1f23e470abe7728fd304dc422058c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 10 Aug 2024 15:03:42 +0200 Subject: [PATCH 270/488] trash abm make new, make better, rinse repeat Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/infection.cpp | 3 +- cpp/models/abm/migration_rules.cpp | 2 +- cpp/simulations/analyze_bs_run.py | 13 +- cpp/simulations/paper_abm_bs_testing.cpp | 542 +++++++++-------------- 4 files changed, 213 insertions(+), 347 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 7040b180db..0fb0caca50 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -38,8 +38,7 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age auto vl_params = params.get()[{virus, age}]; ScalarType high_viral_load_factor = 1; if (latest_exposure.first != ExposureType::NoProtection) { - high_viral_load_factor -= - params.get()(init_date.days() - latest_exposure.second.days()); + high_viral_load_factor -= 0; } m_viral_load.peak = vl_params.viral_load_peak.get_distribution_instance()(rng, vl_params.viral_load_peak.params) * high_viral_load_factor; diff --git a/cpp/models/abm/migration_rules.cpp b/cpp/models/abm/migration_rules.cpp index 3e713e4ac7..fc0793acd9 100644 --- a/cpp/models/abm/migration_rules.cpp +++ b/cpp/models/abm/migration_rules.cpp @@ -184,7 +184,7 @@ LocationType easter_party(Person::RandomNumberGenerator& /*rng*/, const Person& { auto current_loc = person.get_location().get_type(); //leave - if (person.get_goes_to_easter() && t.days() > 33.0 && t.days() < 37.0 && (t.hour_of_day() >= 12) && + if (person.get_goes_to_easter() && t.days() > 35.0 && t.days() < 37.0 && (t.hour_of_day() >= 12) && (t.hour_of_day() <= 22) && !person.is_in_quarantine(t, params)) { return LocationType::Event; } diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 6b025a6a1a..233e0d276d 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -552,16 +552,19 @@ def infer_positive_tests(path): # we need the real data from the json file cases_all_county_age_repdate_ma7.json df_abb = pd.read_json( - path+"/../pydata/Germany/cases_infected_county_repdate_ma7.json") + path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") # we just need the columns cases and date df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] # we need just the dates bewteen 2021-03-01 and 2021-06-01 - df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & + df_abb = df_abb[(df_abb['Date'] >= '2021-02-28') & (df_abb['Date'] <= '2021-06-01')] # we just take the first 90 days - df_abb = df_abb[0:90] + df_abb= df_abb[df_abb['ID_County'] == 3101] + df_abb = df_abb[0:91] + # we need the amount of new positive tests each day insetad of cumulative df_abb['Confirmed'] = df_abb['Confirmed'].diff() + df_abb['Confirmed'] = df_abb['Confirmed'] sensitivity = 0.69 specificity = 0.99 @@ -573,7 +576,7 @@ def infer_positive_tests(path): for r_sns in np.linspace(1, 50, 100): for lt_sympt in np.linspace(0.005, 0.1, 500): total_positive_tests, inferred_positive_tests_sympt, inferred_positive_tests_asympt = calc_positive_tests_overall(total_50, sensitivity, specificity, r_sns, lt_sympt) - rmse = np.sqrt(((df_abb['Confirmed'] - total_positive_tests)**2).mean()) + rmse = np.sqrt(((df_abb['Confirmed'][1:91] - total_positive_tests)**2).mean()) if rmse < best_rmse: best_rmse = rmse best_r_sns = r_sns @@ -619,7 +622,7 @@ def infer_positive_tests(path): plt.plot(xx, inferred_positive_tests_sympt, color='tab:red') plt.plot(xx, inferred_positive_tests_asympt, color='tab:blue') plt.plot(xx, total_positive_tests, color='tab:green') - plt.plot(xx, df_abb['Confirmed'], color='tab:orange') + plt.plot(xx, df_abb['Confirmed'][1:91], color='tab:orange') plt.xlabel('time (days)') plt.ylabel('Number of positive tests') plt.legend(['Assumed positive from Symptomatic', 'Assumed positive from Asymptomatic', diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c28fa89095..fc3ee70b88 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -286,24 +286,24 @@ void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_begin vaccinated_persons[age].push_back(id_rnd); } } - for (uint32_t i = 0; i < vacc_entry.second[age].second; ++i) { - if (vaccinated_persons[age].size() == 0) { - // mio::log_error("Not enough vaccinated people to vacc 2nd time! "); - } - else { - // select random already vaccinated person and assign Vaccination - uint32_t id_rnd = vaccinated_persons[age][mio::UniformIntDistribution::get_instance()( - world.get_rng(), 0U, vaccinated_persons[age].size() - 1)]; - mio::abm::Person& person = world.get_person(id_rnd); - auto timePoint = mio::abm::TimePoint( - mio::get_offset_in_days(vacc_entry.first, simulation_beginning) * 24 * 60 * 60); - person.add_new_vaccination( - mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, timePoint)); - vaccinated_persons[age].erase( - std::remove(vaccinated_persons[age].begin(), vaccinated_persons[age].end(), id_rnd), - vaccinated_persons[age].end()); - } - } + // for (uint32_t i = 0; i < vacc_entry.second[age].second; ++i) { + // if (vaccinated_persons[age].size() == 0) { + // // mio::log_error("Not enough vaccinated people to vacc 2nd time! "); + // } + // else { + // // select random already vaccinated person and assign Vaccination + // uint32_t id_rnd = vaccinated_persons[age][mio::UniformIntDistribution::get_instance()( + // world.get_rng(), 0U, vaccinated_persons[age].size() - 1)]; + // mio::abm::Person& person = world.get_person(id_rnd); + // auto timePoint = mio::abm::TimePoint( + // mio::get_offset_in_days(vacc_entry.first, simulation_beginning) * 24 * 60 * 60); + // person.add_new_vaccination( + // mio::abm::Vaccination(mio::abm::ExposureType::GenericVaccine, timePoint)); + // vaccinated_persons[age].erase( + // std::remove(vaccinated_persons[age].begin(), vaccinated_persons[age].end(), id_rnd), + // vaccinated_persons[age].end()); + // } + // } } } } @@ -616,7 +616,7 @@ void set_parameters(mio::abm::Parameters& params) //Set testing parameters auto pcr_test_values = mio::abm::TestParameters{0.9, 0.995}; - auto antigen_test_values = mio::abm::TestParameters{0.69, 0.993}; + auto antigen_test_values = mio::abm::TestParameters{0.71, 0.996}; auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; @@ -626,7 +626,7 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.50; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.55; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.60; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.65; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.70; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.83; params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.90; @@ -640,48 +640,31 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.1; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.11; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.12; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.13; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.14; params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.33; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.65; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.62; params.get()[{mio::abm::VirusVariant::Alpha, age_group_0_to_4}] = 0.12; params.get()[{mio::abm::VirusVariant::Alpha, age_group_5_to_14}] = 0.13; params.get()[{mio::abm::VirusVariant::Alpha, age_group_15_to_34}] = 0.15; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.25; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.43; - params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.50; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_35_to_59}] = 0.26; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_60_to_79}] = 0.40; + params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.48; // Set infection parameters - // params.get()[{mio::abm::VirusVariant::Alpha}] = 3.5; - - // Set protection level from high viral load. Information based on: https://doi.org/10.1093/cid/ciaa886 - params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.00863}, {1, 0.00969}, {7, 0.0029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); + // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 + params.get() = [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set({{0, 0.0}, {30, 0.8}, {150, 0.7}}, days); }; // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 - params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.01967}, - {30, 0.01975}, - {60, 0.01977}, - {90, 0.01974}, - {120, 0.01963}, - {150, 0.01947}, - {180, 0.0193}, - {210, 0.01929}, - {240, 0.01923}, - {270, 0.01908}, - {300, 0.01893}, - {330, 0.01887}, - {360, 0.01887}, - {360, 0.015}}, - days); + params.get() = [](ScalarType days) -> ScalarType { + return mio::linear_interpolation_of_data_set( + {{0, 0.0}, {5, 1.0}, {30, 1.000}, {150, 0.7}}, days); }; //Set other parameters - params.get() = 0.55; //all masks have a 0.66 protection factor for now params.get() = 0.0; } @@ -880,45 +863,44 @@ void set_local_parameters(mio::abm::World& world) contacts_other[{age_group_80_plus, age_group_60_to_79}] = 0.2769; contacts_other[{age_group_80_plus, age_group_80_plus}] = 0.0180; + mio::CustomIndexArray contacts_random( + {mio::AgeGroup(n_age_groups), mio::AgeGroup(n_age_groups)}, 1.0); + for (auto& loc : world.get_locations()) { - // # we assume that a 20:4:4:1:1 ratio of contacts is made at home:school:work:SocialEv:basicshopping + // # we assume that a 20:5:3:1:1 ratio of contacts is made at home:school:work:SocialEv:basicshopping + // 16hours home 3h arbeiten 1h school 3h social und 1h basic shopping // First line: Sclaing according to which Timespan the contatcs have to be made // Second Line: Normalizing to 24 hours // Third Line: Scaling according intensity of contacts switch (loc.get_type()) { case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; - loc.get_infection_parameters().get().array() *= 1.5; - loc.get_infection_parameters().get().array() *= 1; - loc.get_infection_parameters().get().array() *= 0.66; // 2/5z + loc.get_infection_parameters().get().array() *= 1.6; break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; - loc.get_infection_parameters().get().array() *= 7.5; - loc.get_infection_parameters().get().array() *= 0.5; + loc.get_infection_parameters().get().array() *= 24.0; break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; - loc.get_infection_parameters().get().array() *= 7.5; - loc.get_infection_parameters().get().array() *= 0.3; // 2/5z + loc.get_infection_parameters().get().array() *= 6.0; break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; - loc.get_infection_parameters().get().array() *= 15; - loc.get_infection_parameters().get().array() *= 5; + loc.get_infection_parameters().get().array() *= 1.2; + loc.get_infection_parameters().get().array() *= 8.0; break; case mio::abm::LocationType::BasicsShop: loc.get_infection_parameters().get() = contacts_other; - loc.get_infection_parameters().get().array() *= 15; - loc.get_infection_parameters().get().array() *= 0.2; // 1/7 + loc.get_infection_parameters().get().array() *= 0.8; + loc.get_infection_parameters().get().array() *= 12.0; break; case mio::abm::LocationType::Event: - loc.get_infection_parameters().get() = contacts_other; - loc.get_infection_parameters().get().array() *= 4; - loc.get_infection_parameters().get().array() *= 4; // 1/7 + loc.get_infection_parameters().get() = contacts_home; + loc.get_infection_parameters().get().array() *= 32; break; default: - loc.get_infection_parameters().get() = contacts_other; + loc.get_infection_parameters().get() = contacts_random; break; } } @@ -1208,7 +1190,18 @@ void create_easter_social_event(mio::abm::World& world, double perc_easter_event world.get_persons()[person_per_age_group[j].back()].set_goes_to_easter(true); person_per_age_group[j].pop_back(); - if (j == 2) { + if (j == 4) { + if (person_per_age_group[j].empty()) { + continue; + } + world.get_persons()[person_per_age_group[j].back()].set_assigned_location(easter_event); + world.get_persons()[person_per_age_group[j].back()].set_goes_to_easter(true); + person_per_age_group[j].pop_back(); + } + if (j == 5) { + if (person_per_age_group[j].empty()) { + continue; + } world.get_persons()[person_per_age_group[j].back()].set_assigned_location(easter_event); world.get_persons()[person_per_age_group[j].back()].set_goes_to_easter(true); person_per_age_group[j].pop_back(); @@ -1224,6 +1217,7 @@ void create_easter_social_event(mio::abm::World& world, double perc_easter_event void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, int max_num_persons, mio::Date start_date_sim, double perc_easter_event) { + mio::unused(start_date_sim); //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world set_parameters(world.parameters); @@ -1553,10 +1547,8 @@ void get_grid_search_results_and_write_them_to_file( #endif void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 g, mio::abm::TimePoint tmax, - double testing_probability_sympt, double ratio_asympt_to_sympt, - double perc_have_to_test) + double testing_probability_sympt, double ratio_asympt_to_sympt) { - double testing_probability_asympt = testing_probability_sympt / ratio_asympt_to_sympt; auto antigen_test = mio::abm::TestType::Antigen; @@ -1574,7 +1566,6 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 // Schools // asymptomatic auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto end_date_test_school = mio::abm::TimePoint(mio::abm::days(42).seconds()); // 2021-05-30 auto testing_criteria_school = mio::abm::TestingCriteria({}, vector_asympt_states); auto testing_scheme_school = mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date_test_school, tmax, @@ -1589,18 +1580,17 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school_sympt); - //have to test - auto testing_criteria_school_have_to_test = mio::abm::TestingCriteria(); - auto testing_scheme_school_have_to_test = - mio::abm::TestingScheme(testing_criteria_school_have_to_test, testing_min_time, end_date_test_school, tmax, - antigen_test_parameters, perc_have_to_test); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - testing_scheme_school_have_to_test); + // //have to test + // auto testing_criteria_school_have_to_test = mio::abm::TestingCriteria(); + // auto testing_scheme_school_have_to_test = + // mio::abm::TestingScheme(testing_criteria_school_have_to_test, testing_min_time, end_date_test_school, tmax, + // antigen_test_parameters, perc_have_to_test); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + // testing_scheme_school_have_to_test); // Work // asymptomatic auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto end_date_test_work = mio::abm::TimePoint(mio::abm::days(72).seconds()); // 2021-05-30 auto testing_criteria_work = mio::abm::TestingCriteria({}, vector_asympt_states); auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date_test_work, tmax, antigen_test_parameters, testing_probability_asympt); @@ -1613,25 +1603,25 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 antigen_test_parameters, testing_probability_sympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work_sympt); - // have to test in 35 % of workplaces - std::vector work_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::Work) { - work_location_ids.push_back(location.get_index()); - } - } - std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); - auto num_work_locations = (int)(work_location_ids.size()); - std::vector work_location_ids_35(work_location_ids.begin(), - work_location_ids.begin() + num_work_locations); - auto testing_criteria_work_have_to_test = mio::abm::TestingCriteria(); - auto testing_scheme_work_have_to_test = - mio::abm::TestingScheme(testing_criteria_work_have_to_test, testing_min_time, end_date_test_work, tmax, - antigen_test_parameters, perc_have_to_test); - for (auto& location_id : work_location_ids_35) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work_have_to_test); - } + // // have to test in 35 % of workplaces + // std::vector work_location_ids; + // for (auto& location : location_it) { + // if (location.get_type() == mio::abm::LocationType::Work) { + // work_location_ids.push_back(location.get_index()); + // } + // } + // std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); + // auto num_work_locations = (int)(work_location_ids.size()); + // std::vector work_location_ids_35(work_location_ids.begin(), + // work_location_ids.begin() + num_work_locations); + // auto testing_criteria_work_have_to_test = mio::abm::TestingCriteria(); + // auto testing_scheme_work_have_to_test = + // mio::abm::TestingScheme(testing_criteria_work_have_to_test, testing_min_time, end_date_test_work, tmax, + // antigen_test_parameters, perc_have_to_test); + // for (auto& location_id : work_location_ids_35) { + // sim.get_world().get_testing_strategy().add_testing_scheme( + // mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work_have_to_test); + // } //basic shops: std::vector basics_shop_location_ids; @@ -1647,7 +1637,6 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 // asymptomatic auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto end_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(14).seconds()); // 2021-05-30 auto testing_criteria_basics_shop = mio::abm::TestingCriteria({}, vector_asympt_states); auto testing_scheme_basics_shop = mio::abm::TestingScheme(testing_criteria_basics_shop, testing_min_time, start_date_test_basics_shop, tmax, @@ -1663,16 +1652,16 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, testing_scheme_basics_shop_sympt); - // have to test - auto testing_criteria_basics_shop_have_to_test = mio::abm::TestingCriteria(); - auto testing_scheme_basics_shop_have_to_test = - mio::abm::TestingScheme(testing_criteria_basics_shop_have_to_test, testing_min_time, end_date_test_basics_shop, - tmax, antigen_test_parameters, perc_have_to_test); - for (auto& location_id : basics_shop_location_ids_20) { - sim.get_world().get_testing_strategy().add_testing_scheme( - mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, - testing_scheme_basics_shop_have_to_test); - } + // // have to test + // auto testing_criteria_basics_shop_have_to_test = mio::abm::TestingCriteria(); + // auto testing_scheme_basics_shop_have_to_test = + // mio::abm::TestingScheme(testing_criteria_basics_shop_have_to_test, testing_min_time, end_date_test_basics_shop, + // tmax, antigen_test_parameters, perc_have_to_test); + // for (auto& location_id : basics_shop_location_ids_20) { + // sim.get_world().get_testing_strategy().add_testing_scheme( + // mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, + // testing_scheme_basics_shop_have_to_test); + // } // social events // asymptomatic @@ -1786,19 +1775,21 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { // 3: testing prob symptomatic // 4: perc have to test if npi active auto viral_shedding_rate = params[0]; - auto seasonality_april = params[1]; - auto seasonality_may = params[1] * 0.5; - auto perc_easter_event = 0.6; - auto dark_figure = params[2]; - auto contact_rate_ssc = 0.45; - auto masks = 0.4; + auto perc_easter_event = 0.5; + auto dark_figure = params[1]; + auto contact_rate_ssc = params[2]; + auto masks = 0.45; const double testing_probability_sympt = 0.08; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.0033; + + auto seasonality_april = 0.95; + auto seasonality_may = 0.85; mio::Date start_date{2021, 3, 1}; - int max_num_days = 90; - auto max_num_persons = std::numeric_limits::max(); + int date_of_lockdown = 27; + int end_date_of_lockdown = 61; + int max_num_days = 90; + auto max_num_persons = 400000; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation @@ -1833,10 +1824,9 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { // 1. Add testing strategies - add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt, - perc_have_to_test); + add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt); - // 3. Mask schemes for all locations + // 2. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks for (auto& location : location_it) { location.set_required_mask(mio::abm::MaskType::FFP2); @@ -1848,129 +1838,69 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { } } - // // 4. Dampings for schools and Basic shops + // 3. Dampings everywhere except home for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.00); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), + location.get_infection_parameters().get().array() *= (0.5 * 0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.00); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + contact_rate_ssc); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 } - if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 - location.get_infection_parameters().get().array() *= (0.75 * 0.75); - } - } - - // 5. add capacity limits to some locations - // first we need two lists, one for 50% of random social event locations and the other list for the other 50% - // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ - // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] - // ----> Divide Social Event locations into a 50/50 split. First 50% gƒet the restrictive capacity - std::vector social_event_location_ids_small; - std::vector social_event_location_ids_big; - for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::SocialEvent) { - social_event_location_ids_small.push_back(location.get_index()); + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + contact_rate_ssc); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 } - } - //take 50% of social event locations - std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); - auto num_social_event_locations_big = (int)(0.25 * social_event_location_ids_small.size()); - social_event_location_ids_big.insert(social_event_location_ids_big.end(), social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_big); - social_event_location_ids_small.erase(social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_big); - - // add capacity limits on day one - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); - } - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(0, 0); + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.75 * 0.75); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + contact_rate_ssc); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.75); // from 2021-03-15 } } - restart_timer(timer, "till advance 14"); - sim.get_world().parameters.get() = masks; sim.get_world().parameters.get() = viral_shedding_rate; - sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); - std::cout << "day 14 finished" << std::endl; - - // small social events to capacity 5 - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(5, 0); - location.get_infection_parameters().get().array() *= contact_rate_ssc; - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.get_infection_parameters().get().array() *= contact_rate_ssc; - } - } + sim.get_world().parameters.get() = masks; - restart_timer(timer, "till advance 31 (march ends)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); + restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); + sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionPerLocationType, + historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); sim.get_world().parameters.get() = viral_shedding_rate * seasonality_april; - restart_timer(timer, "till advance 42"); - sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); - std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(false); + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= contact_rate_ssc; } } - restart_timer(timer, "till advance 61"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); - std::cout << "day 61 finished (date 2021-05-01)" << std::endl; - sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; - - restart_timer(timer, "till advance 72"); - sim.advance(mio::abm::TimePoint(mio::abm::days(70).seconds()), historyInfectionStatePerAgeGroup, - historyInfectionPerLocationType, historyCumulativeDetectedInfectionsPerAgeGroup); - std::cout << "day 72 finished (date 2021-05-10)" << std::endl; + restart_timer(timer, "till advance 62 & lockdown ends"); + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationType, + historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(2, 0); - location.get_infection_parameters().get().array() *= 0.5; - } - //50% of big social events get reopened and capacity will be limited to xx - int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - number_of_big_social_events--; - if (number_of_big_social_events >= 0) { - location.get_infection_parameters().get().array() *= contact_rate_ssc; - ; - location.set_capacity(15, 0); - } - } - } - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School && - location.get_type() != mio::abm::LocationType::Home) { - location.set_npi_active(true); + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= (1 / contact_rate_ssc); } } - restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionStatePerAgeGroup, historyInfectionPerLocationType, + sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; + restart_timer(timer, "till advance tmax "); + sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationType, historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); - std::cout << "day 90 finished" << std::endl; ////Advance till here // Stop the clock after sim.advance and calculate the duration @@ -2037,21 +1967,23 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 6.09; - auto seasonality_april = 0.57; - auto seasonality_may = 0.5 * seasonality_april; - auto perc_easter_event = 0.6; - auto dark_figure = 2.1; - auto contact_rate_ssc = 0.45; - auto masks = 0.4; + auto viral_shedding_rate = 2.5; + auto perc_easter_event = 0.55; + auto dark_figure = 2.5; + auto contact_rate_ssc = 0.6; + auto masks = 0.5; const double testing_probability_sympt = 0.08; const double ratio_asympt_to_sympt = 20.0; - const double perc_have_to_test = 0.0033; + + auto seasonality_april = 0.95; + auto seasonality_may = 0.85; mio::Date start_date{2021, 3, 1}; - int max_num_days = 90; - auto max_num_persons = 400000; - bool npis_on = true; + int date_of_lockdown = 27; + int end_date_of_lockdown = 60; + int max_num_days = 90; + auto max_num_persons = 400000; + bool npis_on = true; auto t0 = mio::abm::TimePoint(0); // Start time per simulation auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation @@ -2124,11 +2056,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (npis_on) { const auto location_it = sim.get_world().get_locations(); + //Testing strategies + add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt); - add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt, - perc_have_to_test); - - // 3. Mask schemes for all locations + // 2. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks for (auto& location : location_it) { location.set_required_mask(mio::abm::MaskType::FFP2); @@ -2140,144 +2071,77 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } - // // 4. Dampings for schools and Basic shops + // 3. Dampings everywhere except home for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), + location.get_infection_parameters().get().array() *= (0.5 * 0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), 0.00); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(42).seconds()), + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(14).seconds()), 0.8); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + contact_rate_ssc); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 } - if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-01 - location.get_infection_parameters().get().array() *= (0.75 * 0.75); - } - } - - // 5. add capacity limits to some locations - // first we need two lists, one for 50% of random social event locations and the other list for the other 50% - // 1. -> Restrict trips to a SocialEvent Location to maximum of 10 (,5,2) for the times ['2021-03-01 to 2021-03-14'], ['2021-03-15 to 2021-05-09'], ['2021-05-10 to 2021-05-30'], as this is the percentage outside this has to be randomly taken from an 50/50 split between inside and outside events, see https://de.statista.com/statistik/daten/studie/171168/umfrage/haeufig-betriebene-freizeitaktivitaeten/ - // 2. -> For the other 50%, we do : -> full closure for 70 days ['2021-03-01 to 2021-05-09'], partial closure (10%) for the remaining days ['2021-05-10 to 2021-05-31'] - // ----> Divide Social Event locations into a 50/50 split. First 50% gƒet the restrictive capacity - std::vector social_event_location_ids_small; - std::vector social_event_location_ids_big; - for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::SocialEvent) { - social_event_location_ids_small.push_back(location.get_index()); - } - } - //take 25% of social event locations - std::shuffle(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), g); - auto num_social_event_locations_big = (int)(0.25 * social_event_location_ids_small.size()); - social_event_location_ids_big.insert( - social_event_location_ids_big.end(), social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + num_social_event_locations_big); - social_event_location_ids_small.erase(social_event_location_ids_small.begin(), - social_event_location_ids_small.begin() + - num_social_event_locations_big); - - // add capacity limits on day one - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(10, 0); + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + contact_rate_ssc); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 } - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - location.set_capacity(0, 0); + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.75 * 0.75); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + contact_rate_ssc); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.75); // from 2021-03-15 } } - restart_timer(timer, "till advance 14"); sim.get_world().parameters.get() = viral_shedding_rate; sim.get_world().parameters.get() = masks; - sim.advance(mio::abm::TimePoint(mio::abm::days(14).seconds()), historyInfectionPerLocationTypePerAgeGroup, + + restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); + sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); - std::cout << "day 14 finished" << std::endl; + sim.get_world().parameters.get() = + viral_shedding_rate * seasonality_april; - // small social events to capacity 5 for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(5, 0); - location.get_infection_parameters().get().array() *= contact_rate_ssc; - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { + if (location.get_type() != mio::abm::LocationType::Home) { location.get_infection_parameters().get().array() *= contact_rate_ssc; } } - restart_timer(timer, "till advance 31 (march ends)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(31).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, - historyEstimatedReproductionNumber); - sim.get_world().parameters.get() = - viral_shedding_rate * seasonality_april; - - restart_timer(timer, "till advance 42"); - sim.advance(mio::abm::TimePoint(mio::abm::days(42).seconds()), historyInfectionPerLocationTypePerAgeGroup, + restart_timer(timer, "till advance 62 & lockdown ends"); + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); - std::cout << "day 42 finished" << std::endl; // 2date 2021-04-12 for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School) { - location.set_npi_active(false); + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= (1 / contact_rate_ssc); } } - - restart_timer(timer, "till advance 62"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, - historyEstimatedReproductionNumber); - std::cout << "day 62 finished (date 2021-05-01)" << std::endl; sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; - - restart_timer(timer, "till advance 72"); - sim.advance(mio::abm::TimePoint(mio::abm::days(71).seconds()), historyInfectionPerLocationTypePerAgeGroup, + restart_timer(timer, "till advance tmax "); + sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); - std::cout << "day 72 finished (date 2021-05-10)" << std::endl; - - for (auto& location : location_it) { - if (std::find(social_event_location_ids_small.begin(), social_event_location_ids_small.end(), - location.get_index()) != social_event_location_ids_small.end()) { - location.set_capacity(2, 0); - location.get_infection_parameters().get().array() *= 0.5; - } - //50% of big social events get reopened and capacity will be limited to xx - int number_of_big_social_events = (int)(0.9 * social_event_location_ids_big.size()); - if (std::find(social_event_location_ids_big.begin(), social_event_location_ids_big.end(), - location.get_index()) != social_event_location_ids_big.end()) { - number_of_big_social_events--; - if (number_of_big_social_events >= 0) { - location.get_infection_parameters().get().array() *= contact_rate_ssc; - location.set_capacity(15, 0); - } - } - } - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::School && - location.get_type() != mio::abm::LocationType::Home) { - location.set_npi_active(true); - } - } - restart_timer(timer, "till advance tmax"); - sim.advance(tmax, historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, - historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, - historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); - std::cout << "day 90 finished" << std::endl; } else { sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionPerLocationTypePerAgeGroup, @@ -2311,9 +2175,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; //calculate RMSE - auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], - temp_sim_cumulative_detected_infections_per_age_group[0], max_num_days, - start_date); + auto rmse = + calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], + temp_sim_cumulative_detected_infections_per_age_group[0], 20, start_date); std::cout << "RMSE: " << rmse << std::endl; //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); @@ -2425,8 +2289,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From 67ba95a00310b966a712eb787e7e282e2f07f6cd Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 10 Aug 2024 15:14:13 +0200 Subject: [PATCH 271/488] cluster params Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fc3ee70b88..574fd34305 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1053,14 +1053,14 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries> grid_boundaries = {{3.0, 8.0}, {1.0, 4.0}, {0.02, 0.1}, {0.005, 0.035}}; - std::vector grid_boundaries = {5.8, 0.6, 2.2}; + std::vector> grid_boundaries = {{1.5, 4.0}, {1.0, 4.0}, {0.2, 0.5}}; + // std::vector grid_boundaries = {1.5, 0.6, 2.2}; // std::vector points_per_dim = {2, 2, 2, 5}; std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); From 62008304c09a3eebc5c160014101c70a458746dc Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 12 Aug 2024 00:28:29 +0200 Subject: [PATCH 272/488] reweork simulation Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 32 ++- cpp/simulations/generate_graph_from_data.cpp | 4 +- cpp/simulations/paper_abm_bs_testing.cpp | 283 +++++++------------ 3 files changed, 131 insertions(+), 188 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 233e0d276d..23d1b82351 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -677,7 +677,23 @@ def plot_cumulative_detected_infections(path): total_50 = total_50[::24] total_50 = np.floor(total_50[0:90].flatten()) # we smooth this with a gaussian filter - + + f_p95 = h5py.File( + path+"/cumulative_detected_infections/p95/Results.h5", 'r') + p95_bs = f_p95['0'] + total_95 = p95_bs['Total'][()] + total_95 = total_95[::24] + total_95 = np.floor(total_95[0:90].flatten()) + + f_p05 = h5py.File( + path+"/cumulative_detected_infections/p95/Results.h5", 'r') + p05_bs = f_p05['0'] + total_05 = p05_bs['Total'][()] + total_05 = total_05[::24] + total_05 = np.floor(total_05[0:90].flatten()) + + + # we smooth this with a gaussian filter time = p50_bs['Time'][()] time = time[::24] time = time[0:90] @@ -694,8 +710,10 @@ def plot_cumulative_detected_infections(path): total_50 = gaussian_filter1d(total_50.flatten(), sigma=2, mode='nearest') # we plot this # we plot the tests positive and the real cases - plt.plot(time, total_50, color='tab:red') - plt.plot(time, df_abb, color='tab:blue') + plt.plot(time, total_50, color='tab:blue') + plt.plot(time, df_abb, color='tab:red') + plt.fill_between(time, total_95, total_05, + alpha=0.5, color='tab:blue') plt.xlabel('time (days)') plt.ylabel('Cumulative Amount of detected infections') plt.title('Cumulative detected infections') @@ -711,8 +729,8 @@ def plot_cumulative_detected_infections(path): fig.set_figwidth(20) fig.set_figheight(9) # we plot the tests positive and the real cases - ax.plot(time[0:89], total_50_diff, color='tab:red') - ax.plot(time[0:89], df_abb_diff, color='tab:blue') + ax.plot(time[0:89], total_50_diff, color='tab:blue') + ax.plot(time[0:89], df_abb_diff, color='tab:red') ax.set_xlabel('time (days)') ax.set_ylabel('Number of new detected infections') ax.title.set_text('New detected infections') @@ -763,8 +781,8 @@ def plot_positive_and_done_test(path): plt.gca().set_xticklabels(xx[::5]) plt.gcf().autofmt_xdate() - plt.plot(xx, total_50_positive, color='tab:red') - plt.plot(xx, total_50_done, color='tab:blue') + plt.plot(xx, total_50_positive, color='tab:green') + plt.plot(xx, total_50_done, color='tab:red') plt.xlabel('time (days)') plt.ylabel('Number of tests') plt.legend(['Positive tests', 'Done tests']) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 0244bb8e7f..d1e3c65140 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -134,8 +134,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double riskOfInfectionFromSymptomaticMax = 0.3; const double maxRiskOfInfectionFromSymptomaticMin = 0.3; const double maxRiskOfInfectionFromSymptomaticMax = 0.5; - const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.5, 0.5, 0.5}; - const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.5, 0.5, 0.5}; + const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; + const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.02, 0.02, 0.01}; const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.02, 0.02, 0.01}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 574fd34305..ab025e2eeb 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -542,7 +542,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, if (it_person == persons.end()) { auto home = locations.find(home_id)->second; auto& person = world.add_person(home, determine_age_group(age)); - person.set_mask_preferences({0.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 0.25}); + person.set_mask_preferences({0.0, -0.1, -0.1, -0.3, -0.2, -0.0, -0.0, -0.0, -0.0, -0.0, 0.0, -0.0}); person.set_assigned_location(home); person.set_assigned_location(hospital); person.set_assigned_location(icu); @@ -652,16 +652,15 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.48; // Set infection parameters - // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.0}, {30, 0.8}, {150, 0.7}}, days); + return mio::linear_interpolation_of_data_set({{0, 0.0}, {30, 0.0}, {150, 0.0}}, days); }; // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { return mio::linear_interpolation_of_data_set( - {{0, 0.0}, {5, 1.0}, {30, 1.000}, {150, 0.7}}, days); + {{0, 0.0}, {10, 0.6}, {30, 0.75}, {150, 0.2}}, days); }; //Set other parameters @@ -879,11 +878,11 @@ void set_local_parameters(mio::abm::World& world) break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; - loc.get_infection_parameters().get().array() *= 24.0; + loc.get_infection_parameters().get().array() *= 12.0; break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; - loc.get_infection_parameters().get().array() *= 6.0; + loc.get_infection_parameters().get().array() *= 8.0; break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; @@ -1060,7 +1059,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries()[antigen_test]; // Test parameters @@ -1567,147 +1572,56 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, std::mt19937 auto vector_asympt_states = std::vector{mio::abm::InfectionState::InfectedNoSymptoms, mio::abm::InfectionState::Exposed, mio::abm::InfectionState::Susceptible}; - const auto location_it = sim.get_world().get_locations(); + + auto testing_criteria_asympt = mio::abm::TestingCriteria({}, vector_asympt_states); + auto testing_criteria_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); // We go through each location type and add the testing strategies - // Schools - // asymptomatic - auto start_date_test_school = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto testing_criteria_school = mio::abm::TestingCriteria({}, vector_asympt_states); - auto testing_scheme_school = - mio::abm::TestingScheme(testing_criteria_school, testing_min_time, start_date_test_school, tmax, - antigen_test_parameters, testing_probability_asympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_school); - - //symptomatic - auto testing_criteria_school_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); - auto testing_scheme_school_sympt = - mio::abm::TestingScheme(testing_criteria_school_sympt, testing_min_time, start_date_test_school, tmax, - antigen_test_parameters, testing_probability_sympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - testing_scheme_school_sympt); - - // //have to test - // auto testing_criteria_school_have_to_test = mio::abm::TestingCriteria(); - // auto testing_scheme_school_have_to_test = - // mio::abm::TestingScheme(testing_criteria_school_have_to_test, testing_min_time, end_date_test_school, tmax, - // antigen_test_parameters, perc_have_to_test); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, - // testing_scheme_school_have_to_test); + auto testing_scheme_asympt = mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, start_date_test, + tmax, antigen_test_parameters, testing_probability_asympt); + auto testing_scheme_sympt = mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, start_date_test, tmax, + antigen_test_parameters, testing_probability_sympt); + // auto testing_scheme_asympt_al = + // mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, after_lockdown_date, end_date_test, + // antigen_test_parameters, ratio_after_lockdown * testing_probability_asympt); + // auto testing_scheme_sympt_al = + // mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, after_lockdown_date, end_date_test, + // antigen_test_parameters, ratio_after_lockdown * testing_probability_sympt); + + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt_al); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt_al); // Work - // asymptomatic - auto start_date_test_work = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto testing_criteria_work = mio::abm::TestingCriteria({}, vector_asympt_states); - auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, testing_min_time, start_date_test_work, - tmax, antigen_test_parameters, testing_probability_asympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); - - //symptomatic - auto testing_criteria_work_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); - auto testing_scheme_work_sympt = - mio::abm::TestingScheme(testing_criteria_work_sympt, testing_min_time, start_date_test_work, tmax, - antigen_test_parameters, testing_probability_sympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work_sympt); - - // // have to test in 35 % of workplaces - // std::vector work_location_ids; - // for (auto& location : location_it) { - // if (location.get_type() == mio::abm::LocationType::Work) { - // work_location_ids.push_back(location.get_index()); - // } - // } - // std::shuffle(work_location_ids.begin(), work_location_ids.end(), g); - // auto num_work_locations = (int)(work_location_ids.size()); - // std::vector work_location_ids_35(work_location_ids.begin(), - // work_location_ids.begin() + num_work_locations); - // auto testing_criteria_work_have_to_test = mio::abm::TestingCriteria(); - // auto testing_scheme_work_have_to_test = - // mio::abm::TestingScheme(testing_criteria_work_have_to_test, testing_min_time, end_date_test_work, tmax, - // antigen_test_parameters, perc_have_to_test); - // for (auto& location_id : work_location_ids_35) { - // sim.get_world().get_testing_strategy().add_testing_scheme( - // mio::abm::LocationId{location_id, mio::abm::LocationType::Work}, testing_scheme_work_have_to_test); - // } + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt_al); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt_al); //basic shops: - std::vector basics_shop_location_ids; - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - basics_shop_location_ids.push_back(location.get_index()); - } - } - std::shuffle(basics_shop_location_ids.begin(), basics_shop_location_ids.end(), g); - auto num_basics_shop_locations = (int)(0.2 * basics_shop_location_ids.size()); - std::vector basics_shop_location_ids_20(basics_shop_location_ids.begin(), - basics_shop_location_ids.begin() + num_basics_shop_locations); - - // asymptomatic - auto start_date_test_basics_shop = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto testing_criteria_basics_shop = mio::abm::TestingCriteria({}, vector_asympt_states); - auto testing_scheme_basics_shop = - mio::abm::TestingScheme(testing_criteria_basics_shop, testing_min_time, start_date_test_basics_shop, tmax, - antigen_test_parameters, testing_probability_asympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, - testing_scheme_basics_shop); - - //symptomatic - auto testing_criteria_basics_shop_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); - auto testing_scheme_basics_shop_sympt = - mio::abm::TestingScheme(testing_criteria_basics_shop_sympt, testing_min_time, start_date_test_basics_shop, tmax, - antigen_test_parameters, testing_probability_sympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, - testing_scheme_basics_shop_sympt); - - // // have to test - // auto testing_criteria_basics_shop_have_to_test = mio::abm::TestingCriteria(); - // auto testing_scheme_basics_shop_have_to_test = - // mio::abm::TestingScheme(testing_criteria_basics_shop_have_to_test, testing_min_time, end_date_test_basics_shop, - // tmax, antigen_test_parameters, perc_have_to_test); - // for (auto& location_id : basics_shop_location_ids_20) { - // sim.get_world().get_testing_strategy().add_testing_scheme( - // mio::abm::LocationId{location_id, mio::abm::LocationType::BasicsShop}, - // testing_scheme_basics_shop_have_to_test); - // } + testing_scheme_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, testing_scheme_sympt); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + // testing_scheme_asympt_al); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + // testing_scheme_sympt_al); // social events - // asymptomatic - auto start_date_test_social_event = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto end_date_test_social_event = tmax; // 2021-05-30 - auto testing_criteria_social_event = mio::abm::TestingCriteria({}, vector_asympt_states); - auto testing_scheme_social_event = - mio::abm::TestingScheme(testing_criteria_social_event, testing_min_time, start_date_test_social_event, - end_date_test_social_event, antigen_test_parameters, testing_probability_asympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, - testing_scheme_social_event); - - //symptomatic - auto testing_criteria_social_event_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); - auto testing_scheme_social_event_sympt = - mio::abm::TestingScheme(testing_criteria_social_event_sympt, testing_min_time, start_date_test_social_event, - end_date_test_social_event, antigen_test_parameters, testing_probability_sympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, - testing_scheme_social_event_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_sympt); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + // testing_scheme_asympt_al); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + // testing_scheme_sympt_al); // easter event - // asymptomatic - auto start_date_test_easter_event = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto end_date_test_easter_event = tmax; - auto testing_criteria_easter_event = mio::abm::TestingCriteria({}, vector_asympt_states); - auto testing_scheme_easter_event = - mio::abm::TestingScheme(testing_criteria_easter_event, testing_min_time, start_date_test_easter_event, - end_date_test_easter_event, antigen_test_parameters, testing_probability_asympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, - testing_scheme_easter_event); - - //symptomatic - auto testing_criteria_easter_event_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); - auto testing_scheme_easter_event_sympt = - mio::abm::TestingScheme(testing_criteria_easter_event_sympt, testing_min_time, start_date_test_easter_event, - end_date_test_easter_event, antigen_test_parameters, testing_probability_sympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, - testing_scheme_easter_event_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_asympt); } void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, @@ -1777,21 +1691,21 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { printf("I am Thread %d\n", omp_get_thread_num()); - // grid search for parameters: - // 1: Viral Shed - // 2: Dark figure - // 3: testing prob symptomatic - // 4: perc have to test if npi active - auto viral_shedding_rate = params[0]; - auto perc_easter_event = 0.55; - auto dark_figure = params[1]; - auto contact_rate_ssc = params[2]; - auto masks = 0.45; - const double testing_probability_sympt = 0.08; - const double ratio_asympt_to_sympt = 20.0; - - auto seasonality_april = 0.95; - auto seasonality_may = 0.85; + const double viral_shedding_rate = 1.9; + const double dark_figure = 4.0; + const double contact_red_lockdown = 0.70; + const double damping_community_lockdown = 0.58; + const double testing_probability_sympt = 0.028; + + const double after_lockdown_prob = 1.0; + + const auto seasonality_april = 0.95; + const auto seasonality_may = 0.85; + + const double masks = 0.55; + const double after_lockdown_contact_reduction = 0.8; + const double ratio_asympt_to_sympt = 20.0; + const double perc_easter_event = 0.5; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 27; @@ -1832,7 +1746,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { // 1. Add testing strategies - add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt); + add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, + after_lockdown_prob); // 2. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks @@ -1850,7 +1765,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.get_infection_parameters().get().array() *= (0.5 * 0.5); + location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), @@ -1860,7 +1775,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - contact_rate_ssc); // from 2021-03-15 + damping_community_lockdown); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.8); // from 2021-03-15 } @@ -1868,7 +1783,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - contact_rate_ssc); // from 2021-03-15 + damping_community_lockdown); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.8); // from 2021-03-15 } @@ -1876,7 +1791,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - contact_rate_ssc); // from 2021-03-15 + 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -1892,7 +1807,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= contact_rate_ssc; + location.get_infection_parameters().get().array() *= + contact_red_lockdown * contact_red_lockdown; } } @@ -1902,7 +1818,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= (1 / contact_rate_ssc); + location.get_infection_parameters().get().array() *= + (1 / (contact_red_lockdown * contact_red_lockdown)) * after_lockdown_contact_reduction; } } sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; @@ -1975,19 +1892,24 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - auto viral_shedding_rate = 2.5; - auto perc_easter_event = 0.55; - auto dark_figure = 2.5; - auto contact_rate_ssc = 0.6; - auto masks = 0.5; - const double testing_probability_sympt = 0.08; - const double ratio_asympt_to_sympt = 20.0; + const double viral_shedding_rate = 1.9; + const double dark_figure = 4.0; + const double contact_red_lockdown = 0.70; + const double damping_community_lockdown = 0.58; + const double testing_probability_sympt = 0.028; + + const double after_lockdown_prob = 1.0; - auto seasonality_april = 0.95; - auto seasonality_may = 0.85; + const auto seasonality_april = 0.95; + const auto seasonality_may = 0.85; + + const double masks = 0.55; + const double after_lockdown_contact_reduction = 0.8; + const double ratio_asympt_to_sympt = 20.0; + const double perc_easter_event = 0.5; mio::Date start_date{2021, 3, 1}; - int date_of_lockdown = 27; + int date_of_lockdown = 26; int end_date_of_lockdown = 60; int max_num_days = 90; auto max_num_persons = 400000; @@ -2065,7 +1987,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto location_it = sim.get_world().get_locations(); //Testing strategies - add_npi_testing_strategies_to_world(sim, g, tmax, testing_probability_sympt, ratio_asympt_to_sympt); + add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, + after_lockdown_prob); // 2. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks @@ -2083,7 +2006,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (location.get_type() == mio::abm::LocationType::School) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.get_infection_parameters().get().array() *= (0.5 * 0.5); + location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), @@ -2093,7 +2016,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - contact_rate_ssc); // from 2021-03-15 + damping_community_lockdown); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.8); // from 2021-03-15 } @@ -2101,7 +2024,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - contact_rate_ssc); // from 2021-03-15 + damping_community_lockdown); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.8); // from 2021-03-15 } @@ -2109,7 +2032,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - contact_rate_ssc); // from 2021-03-15 + 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2128,7 +2051,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= contact_rate_ssc; + location.get_infection_parameters().get().array() *= contact_red_lockdown; } } @@ -2140,7 +2063,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (auto& location : location_it) { if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= (1 / contact_rate_ssc); + location.get_infection_parameters().get().array() *= + ((1 / contact_red_lockdown) * after_lockdown_contact_reduction); } } sim.get_world().parameters.get() = @@ -2152,6 +2076,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s historyEstimatedReproductionNumber); } else { + sim.get_world().parameters.get() = viral_shedding_rate; sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup); } @@ -2297,8 +2222,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; From 465b31f0c4678fbf7a1df876ab8d4b9fcb5393eb Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 12 Aug 2024 00:36:05 +0200 Subject: [PATCH 273/488] p95/05 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 23d1b82351..2e2e0b3381 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -33,13 +33,13 @@ def plot_infections_loc_types_avarage(path): # 25-percentile f_p25 = h5py.File( - path+"/infection_per_location_type_per_age_group/p25/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/p05/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # 75-percentile f_p75 = h5py.File( - path + "/infection_per_location_type_per_age_group/p75/Results.h5", 'r') + path + "/infection_per_location_type_per_age_group/p95/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] @@ -97,12 +97,12 @@ def plot_infection_states_results(path): total_50 = p50_bs['Total'][()] # 25-percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/p25/Results.h5", 'r') + path+"/infection_state_per_age_group/p05/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # 75-percentile f_p75 = h5py.File( - path + "/infection_state_per_age_group/p75/Results.h5", 'r') + path + "/infection_state_per_age_group/p95/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] @@ -251,11 +251,11 @@ def plot_dead(path): # do the same for 25 and 75 percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/p25/Results.h5", 'r') + path+"/infection_state_per_age_group/p05/Results.h5", 'r') p25_bs = f_p25['0'] f_p75 = h5py.File( - path+"/infection_state_per_age_group/p75/Results.h5", 'r') + path+"/infection_state_per_age_group/p95/Results.h5", 'r') p75_bs = f_p75['0'] age_group_access = ['Group1', 'Group2', 'Group3', @@ -347,7 +347,7 @@ def plot_icu(path): # we plot this against this the Amount of persons in the ICU from our model f_p75 = h5py.File( - path+"/infection_state_per_age_group/p75/Results.h5", 'r') + path+"/infection_state_per_age_group/p95/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] # we need just every 24th value @@ -357,7 +357,7 @@ def plot_icu(path): # same with 25 percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/p25/Results.h5", 'r') + path+"/infection_state_per_age_group/p05/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # we need just every 24th value From 98a9670c63d880e86273d0cdd2c5ab573ea466c6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 12 Aug 2024 00:37:10 +0200 Subject: [PATCH 274/488] cluster runs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ab025e2eeb..1a5bc74611 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1691,9 +1691,9 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { printf("I am Thread %d\n", omp_get_thread_num()); - const double viral_shedding_rate = 1.9; - const double dark_figure = 4.0; - const double contact_red_lockdown = 0.70; + const double viral_shedding_rate = params[0]; + const double dark_figure = params[1]; + const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.58; const double testing_probability_sympt = 0.028; @@ -1904,7 +1904,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.8; + const double after_lockdown_contact_reduction = 0.7; const double ratio_asympt_to_sympt = 20.0; const double perc_easter_event = 0.5; @@ -2222,8 +2222,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; std::string precomputed_dir = input_dir + "/results"; @@ -2278,10 +2278,10 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{1.5, 4.0}, {1.0, 4.0}, {0.2, 0.5}}; - // std::vector grid_boundaries = {1.5, 0.6, 2.2}; + std::vector> grid_boundaries = {{1.5, 2.5}, {1.0, 6.0}, {0.2, 0.8}}; + // std::vector grid_boundaries = {1.9, 4.0, 0.7}; // std::vector points_per_dim = {2, 2, 2, 5}; - std::vector points_per_dim = {9, 9, 9}; + std::vector points_per_dim = {13, 13, 13}; auto grid = grid_points(grid_boundaries, points_per_dim); auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } From 76ad8e3085cca70202724c421bceae3b7ccc7166 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 12 Aug 2024 00:43:00 +0200 Subject: [PATCH 275/488] omp change Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 48e53c2b90..3541b54e15 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for num_threads(4)) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for num_threads(4)) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,7 +168,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); - PRAGMA_OMP(parallel for) + PRAGMA_OMP(parallel for num_threads(4)) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->adjust_contact_rates(parameters.get_num_groups()); From 854803c0a464a1a6d4d2ada6db1baf8d76c1798f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 12 Aug 2024 07:29:08 +0200 Subject: [PATCH 276/488] new guestimates Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1a5bc74611..cf93e611c7 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -896,7 +896,7 @@ void set_local_parameters(mio::abm::World& world) break; case mio::abm::LocationType::Event: loc.get_infection_parameters().get() = contacts_home; - loc.get_infection_parameters().get().array() *= 32; + loc.get_infection_parameters().get().array() *= 16; break; default: loc.get_infection_parameters().get() = contacts_random; @@ -1892,11 +1892,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - const double viral_shedding_rate = 1.9; - const double dark_figure = 4.0; - const double contact_red_lockdown = 0.70; + const double viral_shedding_rate = 1.88; + const double dark_figure = 4.1; + const double contact_red_lockdown = 0.67; const double damping_community_lockdown = 0.58; - const double testing_probability_sympt = 0.028; + const double testing_probability_sympt = 0.0285; const double after_lockdown_prob = 1.0; @@ -1906,7 +1906,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double masks = 0.55; const double after_lockdown_contact_reduction = 0.7; const double ratio_asympt_to_sympt = 20.0; - const double perc_easter_event = 0.5; + const double perc_easter_event = 0.55; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 26; @@ -2110,7 +2110,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s //calculate RMSE auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], - temp_sim_cumulative_detected_infections_per_age_group[0], 20, start_date); + temp_sim_cumulative_detected_infections_per_age_group[0], tmax, start_date); std::cout << "RMSE: " << rmse << std::endl; //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); From efdc6d5236f99a543dd2ad85d02580351651f885 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 14 Aug 2024 16:46:47 +0200 Subject: [PATCH 277/488] quick bugfix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/infection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 0fb0caca50..e33e6bbc22 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -340,7 +340,7 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}]; - if (p > (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { + if (p < (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; From 56dba366ed238ce42290fa0dbfcbf00ac479d126 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 15 Aug 2024 17:40:21 +0200 Subject: [PATCH 278/488] new par_varaition plots Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/parameter_varation.py | 132 ++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 cpp/simulations/parameter_varation.py diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py new file mode 100644 index 0000000000..959cc7ba0f --- /dev/null +++ b/cpp/simulations/parameter_varation.py @@ -0,0 +1,132 @@ +import sys +import argparse +import os +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import matplotlib +import matplotlib.colors as colors +import matplotlib.cm as cmx +import matplotlib.patches as mpatches +import matplotlib.lines as mlines +import h5py +from datetime import datetime +from matplotlib.dates import DateFormatter +from scipy.ndimage import gaussian_filter1d +from scipy.signal import savgol_filter + +def plot_of_cumuative_infections(path, index=0): + # plot cumulative infections + f_p50 = h5py.File( + path+"/infection_per_location_type_per_age_group/"+str(index)+"/p50/Results.h5", 'r') + p50_bs = f_p50['0'] + total_50 = p50_bs['Total'][()] + + time = p50_bs['Time'][()] + time = time[::24] + time = time[0:90] + + + states_plot = [0, 1, 2, 3, 4, 10] + np_y50_total = np.zeros(90) + for i in states_plot: + # we need to sum up every 24 hours + indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=24) + np_y50 = pd.DataFrame(total_50[:, i]).rolling(window=indexer, min_periods=1).sum().to_numpy() + np_y50=np_y50[0::24].flatten()[0:90] + np_y50_total += np_y50 + return np_y50_total + +def plot_number_of_tests(path, index): + f_p50_done = h5py.File( + path+"/test_per_location_type_per_age_group/"+str(index)+"/p50/Results.h5", 'r') + p50_bs_done = f_p50_done['0'] + total_50_done = p50_bs_done['Total'][()] + #same for the done tests + total_50_done = np.sum(total_50_done, axis=1) + total_50_done = np.cumsum(total_50_done, axis=0) + total_50_done = total_50_done[::24] + total_50_done = total_50_done[0:91] # we still need to take the difference to get the daily amount + total_50_done = np.diff(total_50_done, axis=0).flatten() + # we smooth this with a gaussian filter + total_50_done = gaussian_filter1d(total_50_done, sigma=1, mode='nearest') + return total_50_done + +def plot_positive_tests(path, index): + f_p50_done = h5py.File( + path+"/positive_test_per_location_type_per_age_group/"+str(index)+"/p50/Results.h5", 'r') + p50_bs_done = f_p50_done['0'] + total_50_done = p50_bs_done['Total'][()] + #same for the done tests + total_50_done = np.sum(total_50_done, axis=1) + total_50_done = np.cumsum(total_50_done, axis=0) + total_50_done = total_50_done[::24] + total_50_done = total_50_done[0:91] # we still need to take the difference to get the daily amount + total_50_done = np.diff(total_50_done, axis=0).flatten() + # we smooth this with a gaussian filter + total_50_done = gaussian_filter1d(total_50_done, sigma=1, mode='nearest') + return total_50_done + +if __name__ == "__main__": + + path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-15140128" + variable_1 = "test_likelihood_symptom" + variable_2 = "test_likelihood_asymptom" + values_1 = [0.01, 0.03, 0.05] + values_2 = [5, 10, 30] + + # we want to have a Grid Plot with the size of the values + # in each grid we plot a certain plot which we can define + # on the general structure of the plot we we write the values of the parameters + # we want to plot in the title of the plot + + fig = plt.figure('Parameter Variation', figsize=(1, 1)) + gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + fig.suptitle('Parameter Variation', fontsize=16) + fig.show() + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) + + ax = fig.add_subplot(gs[i, j]) + ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + + plot_data = plot_of_cumuative_infections(path_data, index) + ax.plot(plot_data, label='Cumulative Infections') + ax.legend() + plt.show() + fig = plt.figure('Parameter Variation', figsize=(1, 1)) + gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + fig.suptitle('Parameter Variation', fontsize=16) + fig.show() + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) + + ax = fig.add_subplot(gs[i, j]) + ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + + plot_data = plot_number_of_tests(path_data, index) + ax.plot(plot_data, label='Number of Tests') + ax.legend() + plt.show() + fig = plt.figure('Parameter Variation', figsize=(1, 1)) + gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + fig.suptitle('Parameter Variation', fontsize=16) + fig.show() + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) + + ax = fig.add_subplot(gs[i, j]) + ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + + plot_data = plot_positive_tests(path_data, index) + ax.plot(plot_data, label='Positive Tests') + ax.legend() + + plt.show() + + + + From 6d37816ea1709411266b0f5778bb528050e85783 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 15 Aug 2024 17:40:38 +0200 Subject: [PATCH 279/488] huge refactoring etc Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 42 +- cpp/simulations/generate_graph_from_data.cpp | 6 +- cpp/simulations/paper_abm_bs_testing.cpp | 743 +++++++++++-------- 3 files changed, 448 insertions(+), 343 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 2e2e0b3381..9270624c35 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -27,19 +27,19 @@ def plot_infections_loc_types_avarage(path): # 50-percentile f_p50 = h5py.File( - path+"/infection_per_location_type_per_age_group/p50/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] # 25-percentile f_p25 = h5py.File( - path+"/infection_per_location_type_per_age_group/p05/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/0/p05/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # 75-percentile f_p75 = h5py.File( - path + "/infection_per_location_type_per_age_group/p95/Results.h5", 'r') + path + "/infection_per_location_type_per_age_group/0/p95/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] @@ -92,17 +92,17 @@ def plot_infection_per_location_type_mean(x, y50, y25, y75): def plot_infection_states_results(path): # 50-percentile f_p50 = h5py.File( - path+"/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] # 25-percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/p05/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # 75-percentile f_p75 = h5py.File( - path + "/infection_state_per_age_group/p95/Results.h5", 'r') + path + "/infection_state_per_age_group/0/p95/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] @@ -246,16 +246,16 @@ def plot_dead(path): # we will have a seperate plot the cumulative infected individuals, cumulative symptomatic individuals and cumulative dead individual # we need to load the data f_p50 = h5py.File( - path+"/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] # do the same for 25 and 75 percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/p05/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') p25_bs = f_p25['0'] f_p75 = h5py.File( - path+"/infection_state_per_age_group/p95/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') p75_bs = f_p75['0'] age_group_access = ['Group1', 'Group2', 'Group3', @@ -325,7 +325,7 @@ def plot_dead(path): def plot_icu(path): df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu = 0.47 + perc_of_critical_in_icu = 0.42 # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] @@ -337,7 +337,7 @@ def plot_icu(path): # we plot this against this the Amount of persons in the ICU from our model f_p50 = h5py.File( - path+"/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] # we need just every 24th value @@ -347,7 +347,7 @@ def plot_icu(path): # we plot this against this the Amount of persons in the ICU from our model f_p75 = h5py.File( - path+"/infection_state_per_age_group/p95/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] # we need just every 24th value @@ -357,7 +357,7 @@ def plot_icu(path): # same with 25 percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/p05/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # we need just every 24th value @@ -436,7 +436,7 @@ def plot_tests(path): ratio_testing_symptomatic_vs_asymptomatic = 0.1 f_p50 = h5py.File( - path+"/results_last_run/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/results_last_run/infection_state_per_age_group/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] total_50 = total_50[::24] @@ -539,7 +539,7 @@ def infer_positive_tests(path): # we need every compartment of the model f_p50 = h5py.File( - path+"/infection_state_per_age_group/p50/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] total_50 = total_50[::24] @@ -637,7 +637,7 @@ def infer_positive_tests(path): def plot_estimated_reproduction_number(path): f_p50 = h5py.File( - path+"/estimated_reproduction_number/p50/Results.h5", 'r') + path+"/estimated_reproduction_number/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] total_50 = total_50[::24] @@ -671,7 +671,7 @@ def plot_cumulative_detected_infections(path): f_p50 = h5py.File( - path+"/cumulative_detected_infections/p50/Results.h5", 'r') + path+"/cumulative_detected_infections/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] total_50 = total_50[::24] @@ -679,14 +679,14 @@ def plot_cumulative_detected_infections(path): # we smooth this with a gaussian filter f_p95 = h5py.File( - path+"/cumulative_detected_infections/p95/Results.h5", 'r') + path+"/cumulative_detected_infections/0/p95/Results.h5", 'r') p95_bs = f_p95['0'] total_95 = p95_bs['Total'][()] total_95 = total_95[::24] total_95 = np.floor(total_95[0:90].flatten()) f_p05 = h5py.File( - path+"/cumulative_detected_infections/p95/Results.h5", 'r') + path+"/cumulative_detected_infections/0/p95/Results.h5", 'r') p05_bs = f_p05['0'] total_05 = p05_bs['Total'][()] total_05 = total_05[::24] @@ -739,12 +739,12 @@ def plot_cumulative_detected_infections(path): def plot_positive_and_done_test(path): f_p50_positive = h5py.File( - path+"/positive_test_per_location_type_per_age_group/p50/Results.h5", 'r') + path+"/positive_test_per_location_type_per_age_group/0/p50/Results.h5", 'r') p50_bs_positive = f_p50_positive['0'] total_50_positive = p50_bs_positive['Total'][()] f_p50_done = h5py.File( - path+"/test_per_location_type_per_age_group/p50/Results.h5", 'r') + path+"/test_per_location_type_per_age_group/0/p50/Results.h5", 'r') p50_bs_done = f_p50_done['0'] total_50_done = p50_bs_done['Total'][()] diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index d1e3c65140..fdf61f5511 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -136,8 +136,8 @@ mio::IOResult set_covid_parameters(mio::osecir::Parameters& params) const double maxRiskOfInfectionFromSymptomaticMax = 0.5; const double recoveredPerInfectedNoSymptomsMin[] = {0.2, 0.2, 0.15, 0.15, 0.15, 0.15}; const double recoveredPerInfectedNoSymptomsMax[] = {0.3, 0.3, 0.25, 0.25, 0.25, 0.25}; - const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.015, 0.02, 0.02, 0.01}; - const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.023, 0.02, 0.02, 0.01}; + const double severePerInfectedSymptomsMin[] = {0.006, 0.006, 0.01, 0.01, 0.01, 0.01}; + const double severePerInfectedSymptomsMax[] = {0.009, 0.009, 0.01, 0.01, 0.01, 0.01}; const double criticalPerSevereMin[] = {0.05, 0.05, 0.05, 0.10, 0.25, 0.35}; const double criticalPerSevereMax[] = {0.10, 0.10, 0.10, 0.20, 0.35, 0.45}; const double deathsPerCriticalMin[] = {0.00, 0.00, 0.10, 0.10, 0.30, 0.5}; @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.5); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.8); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cf93e611c7..ed667412bd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -616,7 +616,7 @@ void set_parameters(mio::abm::Parameters& params) //Set testing parameters auto pcr_test_values = mio::abm::TestParameters{0.9, 0.995}; - auto antigen_test_values = mio::abm::TestParameters{0.71, 0.996}; + auto antigen_test_values = mio::abm::TestParameters{0.71, 0.993}; auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; @@ -654,13 +654,13 @@ void set_parameters(mio::abm::Parameters& params) // Set infection parameters // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.0}, {30, 0.0}, {150, 0.0}}, days); + return mio::linear_interpolation_of_data_set({{0, 0.0}, {30, 0.3}, {150, 0.5}}, days); }; // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { return mio::linear_interpolation_of_data_set( - {{0, 0.0}, {10, 0.6}, {30, 0.75}, {150, 0.2}}, days); + {{0, 0.0}, {10, 0.6}, {30, 0.75}, {150, 0.5}}, days); }; //Set other parameters @@ -896,7 +896,7 @@ void set_local_parameters(mio::abm::World& world) break; case mio::abm::LocationType::Event: loc.get_infection_parameters().get() = contacts_home; - loc.get_infection_parameters().get().array() *= 16; + loc.get_infection_parameters().get().array() *= 32; break; default: loc.get_infection_parameters().get() = contacts_random; @@ -1102,6 +1102,34 @@ std::vector> grid_points(const std::vector& paramete return grid; } +std::vector> every_combination_of_parameters(std::vector> grid) +{ + // we get n parameters and several values for each parameter. We want to get all possible combinations of the parameters + std::vector> parameter_combinations; + std::vector counter_per_dimension(grid.size(), 0); + int number_of_points = 1; + for (size_t i = 0; i < grid.size(); i++) { + number_of_points = number_of_points * grid[i].size(); + } + for (int i = 0; i < number_of_points; i++) { + std::vector temp; + for (size_t j = 0; j < grid.size(); j++) { + temp.push_back(grid[j][counter_per_dimension[j]]); + } + parameter_combinations.push_back(temp); + // we increase the counter for the last dimension + counter_per_dimension.back()++; + // we increase the counter for the other dimensions if the last dimension has reached the end + for (int k = (int)grid.size(); k > 0; k--) { + if (counter_per_dimension[k] == (int)grid[k].size()) { + counter_per_dimension[k] = 0; + counter_per_dimension[k - 1]++; + } + } + } + return parameter_combinations; +} + /** * @brief Distribute the grid search over the MPI ranks. */ @@ -1555,15 +1583,14 @@ void get_grid_search_results_and_write_them_to_file( void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::TimePoint tmax, double testing_probability_sympt, double ratio_asympt_to_sympt, - double after_lockdown_prob) + double lockdown_prob, double after_lockdown_prob) { double testing_probability_asympt = testing_probability_sympt / ratio_asympt_to_sympt; - double ratio_after_lockdown = after_lockdown_prob; auto start_date_test = mio::abm::TimePoint(mio::abm::days(0).seconds()); + auto lockdown_start_date = mio::abm::TimePoint(mio::abm::days(30).seconds()); + auto lockdown_end_date = mio::abm::TimePoint(mio::abm::days(60).seconds()); auto end_date_test = tmax; - auto after_lockdown_date = mio::abm::TimePoint(mio::abm::days(30).seconds()); - mio::unused(ratio_after_lockdown, end_date_test, after_lockdown_date); auto antigen_test = mio::abm::TestType::Antigen; auto antigen_test_parameters = sim.get_world().parameters.get()[antigen_test]; // Test parameters @@ -1578,50 +1605,70 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti // We go through each location type and add the testing strategies - auto testing_scheme_asympt = mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, start_date_test, - tmax, antigen_test_parameters, testing_probability_asympt); - auto testing_scheme_sympt = mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, start_date_test, tmax, - antigen_test_parameters, testing_probability_sympt); - // auto testing_scheme_asympt_al = - // mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, after_lockdown_date, end_date_test, - // antigen_test_parameters, ratio_after_lockdown * testing_probability_asympt); - // auto testing_scheme_sympt_al = - // mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, after_lockdown_date, end_date_test, - // antigen_test_parameters, ratio_after_lockdown * testing_probability_sympt); + auto testing_scheme_asympt = + mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, start_date_test, lockdown_start_date, + antigen_test_parameters, testing_probability_asympt); + auto testing_scheme_sympt = + mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, start_date_test, lockdown_start_date, + antigen_test_parameters, testing_probability_sympt); + auto testing_scheme_asympt_wl = + mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, lockdown_start_date, lockdown_end_date, + antigen_test_parameters, lockdown_prob * testing_probability_asympt); + auto testing_scheme_sympt_wl = + mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, lockdown_start_date, lockdown_end_date, + antigen_test_parameters, lockdown_prob * testing_probability_sympt); + auto testing_scheme_asympt_al = + mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, lockdown_end_date, end_date_test, + antigen_test_parameters, after_lockdown_prob * testing_probability_asympt); + auto testing_scheme_sympt_al = + mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, lockdown_end_date, end_date_test, + antigen_test_parameters, after_lockdown_prob * testing_probability_sympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt_al); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt_al); // Work sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt_al); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt_al); //basic shops: sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, testing_scheme_sympt); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, - // testing_scheme_asympt_al); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, - // testing_scheme_sympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_asympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_sympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_asympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_sympt_al); // social events sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme_sympt); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, - // testing_scheme_asympt_al); - // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, - // testing_scheme_sympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_asympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_sympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_asympt_al); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_sympt_al); // easter event - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_sympt); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_asympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_asympt_wl); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_sympt_wl); } void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, @@ -1698,6 +1745,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const double testing_probability_sympt = 0.028; const double after_lockdown_prob = 1.0; + const auto while_lockdown_prob = 0.8; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; @@ -1747,7 +1795,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { // 1. Add testing strategies add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, - after_lockdown_prob); + while_lockdown_prob, after_lockdown_prob); // 2. Mask schemes for all locations // First set all locations to have mask usage, we need ffp2 masks @@ -1877,7 +1925,7 @@ std::vector distribute_runs(size_t num_runs, int num_procs) } mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, - bool save_single_runs = true) + std::vector> parameter_values, bool save_single_runs = true) { int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI @@ -1888,288 +1936,316 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s rank = 0; #endif - auto run_distribution = distribute_runs(num_runs, num_procs); - auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); - auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - - const double viral_shedding_rate = 1.88; - const double dark_figure = 4.1; - const double contact_red_lockdown = 0.67; - const double damping_community_lockdown = 0.58; - const double testing_probability_sympt = 0.0285; - - const double after_lockdown_prob = 1.0; - - const auto seasonality_april = 0.95; - const auto seasonality_may = 0.85; - - const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.7; - const double ratio_asympt_to_sympt = 20.0; - const double perc_easter_event = 0.55; - - mio::Date start_date{2021, 3, 1}; - int date_of_lockdown = 26; - int end_date_of_lockdown = 60; - int max_num_days = 90; - auto max_num_persons = 400000; - bool npis_on = true; - - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation - - auto ensemble_infection_per_loc_type_per_age_group = std::vector< - std::vector>>{}; // Vector of infection per location type per age group results - ensemble_infection_per_loc_type_per_age_group.reserve(size_t(num_runs)); - - auto ensemble_infection_state_per_age_group = - std::vector>>{}; // Vector of infection state per age group results - ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); - - auto ensemble_test_per_loc_type_per_age_group = std::vector< - std::vector>>{}; // Vector of tests per location type per age group results - ensemble_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); - - auto ensemble_positive_test_per_loc_type_per_age_group = std::vector< - std::vector>>{}; // Vector of positive tests per location type per age group results - ensemble_positive_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); - - auto ensemble_cumulative_detected_infections = - std::vector>>{}; // Vector of cumulative detected infections - ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); - - auto ensemble_estimated_reproduction_number = - std::vector>>{}; // Vector of estimated reproduction number - ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); - - auto ensemble_params = std::vector>{}; // Vector of all worlds - ensemble_params.reserve(size_t(num_runs)); - - // Determine inital infection state distribution - restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date, dark_figure); - restart_timer(timer, "time for determine_initial_infection_states_world"); - prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), - (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - restart_timer(timer, "time for vaccinaiton state"); - // Loop over a number of runs - for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { - - std::random_device rd; - std::mt19937 g(rd()); - - auto world = mio::abm::World(num_age_groupss); - - create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); - - restart_timer(timer, "time taken for create sampled world"); - auto sim = mio::abm::Simulation(t0, std::move(world)); - - //Logger - mio::History - historyInfectionPerLocationTypePerAgeGroup{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History historyInfectionStatePerAgeGroup{ - Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - mio::History - historyTestPerLocationTypePerAgeGroup{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History - historyPositiveTestPerLocationTypePerAgeGroup{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History - historyCumulativeDetectedInfectionsPerAgeGroup{Eigen::Index(sim.get_world().parameters.get_num_groups())}; - mio::History historyEstimatedReproductionNumber{ - Eigen::Index(1)}; - - // / NPIS// - if (npis_on) { - - const auto location_it = sim.get_world().get_locations(); - //Testing strategies - add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, - after_lockdown_prob); - - // 2. Mask schemes for all locations - // First set all locations to have mask usage, we need ffp2 masks - for (auto& location : location_it) { - location.set_required_mask(mio::abm::MaskType::FFP2); - if (location.get_type() == mio::abm::LocationType::Home) { - location.set_npi_active(false); + for (size_t par_i = 0; par_i < parameter_values.size(); par_i++) { + auto params = parameter_values[par_i]; + + auto run_distribution = distribute_runs(num_runs, num_procs); + auto start_run_idx = + std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); + auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; + + const double viral_shedding_rate = 2.08; + const double dark_figure = 3.3; + const double contact_red_lockdown = 0.65; + const double damping_community_lockdown = 0.5; + // const double testing_probability_sympt = 0.035; + const double testing_probability_sympt = params[0]; + + const double lockdown_test_prob = 1.2; + const double after_lockdown_test_prob = 0.6; + + const auto seasonality_april = 0.95; + const auto seasonality_may = 0.85; + + const double masks = 0.55; + const double after_lockdown_contact_reduction = 0.7; + // const double ratio_asympt_to_sympt = 20.0; + const double ratio_asympt_to_sympt = params[1]; + const double perc_easter_event = 0.58; + + mio::Date start_date{2021, 3, 1}; + int date_of_lockdown = 26; + int end_date_of_lockdown = 60; + int max_num_days = 90; + auto max_num_persons = 400000; + bool npis_on = true; + + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation + + auto ensemble_infection_per_loc_type_per_age_group = std::vector< + std::vector>>{}; // Vector of infection per location type per age group results + ensemble_infection_per_loc_type_per_age_group.reserve(size_t(num_runs)); + + auto ensemble_infection_state_per_age_group = + std::vector>>{}; // Vector of infection state per age group results + ensemble_infection_state_per_age_group.reserve(size_t(num_runs)); + + auto ensemble_test_per_loc_type_per_age_group = std::vector< + std::vector>>{}; // Vector of tests per location type per age group results + ensemble_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + + auto ensemble_positive_test_per_loc_type_per_age_group = std::vector>>{}; // Vector of positive tests per location type per age group results + ensemble_positive_test_per_loc_type_per_age_group.reserve(size_t(num_runs)); + + auto ensemble_cumulative_detected_infections = + std::vector>>{}; // Vector of cumulative detected infections + ensemble_cumulative_detected_infections.reserve(size_t(num_runs)); + + auto ensemble_estimated_reproduction_number = + std::vector>>{}; // Vector of estimated reproduction number + ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); + + auto ensemble_params = std::vector>{}; // Vector of all worlds + ensemble_params.reserve(size_t(num_runs)); + + // Determine inital infection state distribution + restart_timer(timer, "time for initial setup"); + determine_initial_infection_states_world(input_dir, start_date, dark_figure); + restart_timer(timer, "time for determine_initial_infection_states_world"); + prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); + restart_timer(timer, "time for vaccinaiton state"); + // Loop over a number of runs + for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { + + std::random_device rd; + std::mt19937 g(rd()); + + auto world = mio::abm::World(num_age_groupss); + + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); + + restart_timer(timer, "time taken for create sampled world"); + auto sim = mio::abm::Simulation(t0, std::move(world)); + + //Logger + mio::History + historyInfectionPerLocationTypePerAgeGroup{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyInfectionStatePerAgeGroup{ + Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyTestPerLocationTypePerAgeGroup{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyPositiveTestPerLocationTypePerAgeGroup{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyCumulativeDetectedInfectionsPerAgeGroup{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; + mio::History historyEstimatedReproductionNumber{ + Eigen::Index(1)}; + + // / NPIS// + if (npis_on) { + + const auto location_it = sim.get_world().get_locations(); + //Testing strategies + add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, + lockdown_test_prob, after_lockdown_test_prob); + + // 2. Mask schemes for all locations + // First set all locations to have mask usage, we need ffp2 masks + for (auto& location : location_it) { + location.set_required_mask(mio::abm::MaskType::FFP2); + if (location.get_type() == mio::abm::LocationType::Home) { + location.set_npi_active(false); + } + else { + location.set_npi_active(true); + } } - else { - location.set_npi_active(true); - } - } - // 3. Dampings everywhere except home - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.5); // from 2021-04-12 till 2021-05-30 - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - damping_community_lockdown); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.8); // from 2021-03-15 + // 3. Dampings everywhere except home + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::School) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 + location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.00); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.5); // from 2021-04-12 till 2021-05-30 + } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + damping_community_lockdown); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::SocialEvent) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + damping_community_lockdown); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.75 * 0.75); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.7); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.75); // from 2021-03-15 + } } - if (location.get_type() == mio::abm::LocationType::SocialEvent) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - damping_community_lockdown); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.8); // from 2021-03-15 - } - if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.75 * 0.75); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.75); // from 2021-03-15 - } - } - sim.get_world().parameters.get() = viral_shedding_rate; - sim.get_world().parameters.get() = masks; - - restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, - historyEstimatedReproductionNumber); - sim.get_world().parameters.get() = - viral_shedding_rate * seasonality_april; - - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= contact_red_lockdown; + sim.get_world().parameters.get() = viral_shedding_rate; + sim.get_world().parameters.get() = masks; + + restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); + sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), + historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, + historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, + historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); + sim.get_world().parameters.get() = + viral_shedding_rate * seasonality_april; + + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= + contact_red_lockdown; + } } - } - restart_timer(timer, "till advance 62 & lockdown ends"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, - historyEstimatedReproductionNumber); - - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= - ((1 / contact_red_lockdown) * after_lockdown_contact_reduction); + restart_timer(timer, "till advance 62 & lockdown ends"); + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), + historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, + historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, + historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); + + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= + ((1 / contact_red_lockdown) * after_lockdown_contact_reduction); + } } + sim.get_world().parameters.get() = + viral_shedding_rate * seasonality_may; + restart_timer(timer, "till advance tmax "); + sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationTypePerAgeGroup, + historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, + historyPositiveTestPerLocationTypePerAgeGroup, + historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); } - sim.get_world().parameters.get() = - viral_shedding_rate * seasonality_may; - restart_timer(timer, "till advance tmax "); - sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, - historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, - historyEstimatedReproductionNumber); - } - else { - sim.get_world().parameters.get() = viral_shedding_rate; - sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), historyInfectionPerLocationTypePerAgeGroup, - historyInfectionStatePerAgeGroup); - } - ////Advance till here - // Stop the clock after sim.advance and calculate the duration - restart_timer(timer, "time taken for simulation end"); - // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_infection_per_loc_type_per_age_group = - std::vector>{std::get<0>(historyInfectionPerLocationTypePerAgeGroup.get_log())}; - auto temp_sim_infection_state_per_age_group = - std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - auto temp_sim_test_per_loc_type_per_age_group = - std::vector>{std::get<0>(historyTestPerLocationTypePerAgeGroup.get_log())}; - auto temp_sim_positive_test_per_loc_type_per_age_group = std::vector>{ - std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; - auto temp_sim_cumulative_detected_infections_per_age_group = std::vector>{ - std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; - auto temp_sim_estimated_reproduction_number = - std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; - // Push result of the simulation back to the result vector - ensemble_infection_per_loc_type_per_age_group.emplace_back(temp_sim_infection_per_loc_type_per_age_group); - ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); - ensemble_test_per_loc_type_per_age_group.emplace_back(temp_sim_test_per_loc_type_per_age_group); - ensemble_positive_test_per_loc_type_per_age_group.emplace_back( - temp_sim_positive_test_per_loc_type_per_age_group); - ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); - ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); - - std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; - - //calculate RMSE - auto rmse = - calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], - temp_sim_cumulative_detected_infections_per_age_group[0], tmax, start_date); - std::cout << "RMSE: " << rmse << std::endl; - - //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); - //for now this doesnt work, but we can still save the results of the last world since the - //parameters are the same for each run - if (rank == 0 && run_idx == end_run_idx - 1) { - for (size_t i = 0; i < num_runs; i++) { - ensemble_params.emplace_back(std::vector{sim.get_world()}); + else { + sim.get_world().parameters.get() = viral_shedding_rate; + sim.advance(mio::abm::TimePoint(mio::abm::days(20).seconds()), + historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup); + } + ////Advance till here + // Stop the clock after sim.advance and calculate the duration + restart_timer(timer, "time taken for simulation end"); + // TODO: update result of the simulation to be a vector of location result. + auto temp_sim_infection_per_loc_type_per_age_group = std::vector>{ + std::get<0>(historyInfectionPerLocationTypePerAgeGroup.get_log())}; + auto temp_sim_infection_state_per_age_group = + std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + auto temp_sim_test_per_loc_type_per_age_group = + std::vector>{std::get<0>(historyTestPerLocationTypePerAgeGroup.get_log())}; + auto temp_sim_positive_test_per_loc_type_per_age_group = std::vector>{ + std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; + auto temp_sim_cumulative_detected_infections_per_age_group = std::vector>{ + std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; + auto temp_sim_estimated_reproduction_number = + std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; + // Push result of the simulation back to the result vector + ensemble_infection_per_loc_type_per_age_group.emplace_back(temp_sim_infection_per_loc_type_per_age_group); + ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); + ensemble_test_per_loc_type_per_age_group.emplace_back(temp_sim_test_per_loc_type_per_age_group); + ensemble_positive_test_per_loc_type_per_age_group.emplace_back( + temp_sim_positive_test_per_loc_type_per_age_group); + ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); + ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); + + std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; + + //calculate RMSE + // int number_of_days_for_rmse = 0; + // if (npis_on) { + // number_of_days_for_rmse = 90; + // } + // else { + // number_of_days_for_rmse = 20; + // } + // auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], + // temp_sim_cumulative_detected_infections_per_age_group[0], + // number_of_days_for_rmse, start_date); + // std::cout << "RMSE: " << rmse << std::endl; + + //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); + //for now this doesnt work, but we can still save the results of the last world since the + //parameters are the same for each run + if (rank == 0 && run_idx == end_run_idx - 1) { + for (size_t i = 0; i < num_runs; i++) { + ensemble_params.emplace_back(std::vector{sim.get_world()}); + } } } - } - printf("Saving results ... "); + printf("Saving results ... "); #ifdef MEMILIO_ENABLE_MPI - //gather results - auto final_ensemble_infection_per_loc_type_per_age_group = - gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type_per_age_group); - auto final_ensemble_infection_state_per_age_group = - gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); - auto final_ensemble_test_per_loc_type_per_age_group = - gather_results(rank, num_procs, num_runs, ensemble_test_per_loc_type_per_age_group); - auto final_ensemble_positive_test_per_loc_type_per_age_group = - gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); - auto final_ensemble_cumulative_detected_infections = - gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); - auto final_ensemble_estimated_reproduction_number = - gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); - if (rank == 0) { - BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_per_loc_type_per_age_group, ensemble_params, {0}, - result_dir / "infection_per_location_type_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, - result_dir / "infection_state_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, - result_dir / "test_per_location_type_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, - result_dir / "positive_test_per_location_type_per_age_group/", - save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, - result_dir / "cumulative_detected_infections/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, - result_dir / "estimated_reproduction_number/", save_single_runs, true, true)); - } + //gather results + auto final_ensemble_infection_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type_per_age_group); + auto final_ensemble_infection_state_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_infection_state_per_age_group); + auto final_ensemble_test_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_test_per_loc_type_per_age_group); + auto final_ensemble_positive_test_per_loc_type_per_age_group = + gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); + auto final_ensemble_cumulative_detected_infections = + gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); + auto final_ensemble_estimated_reproduction_number = + gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); + if (rank == 0) { + BOOST_OUTCOME_TRY(save_results( + final_ensemble_infection_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "infection_per_location_type_per_age_group" / std::to_string(par_i), save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_infection_state_per_age_group, ensemble_params, {0}, + result_dir / "infection_state_per_age_group" / std::to_string(par_i), + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "test_per_location_type_per_age_group" / std::to_string(par_i), + save_single_runs)); + BOOST_OUTCOME_TRY( + save_results(final_ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "positive_test_per_location_type_per_age_group" / std::to_string(par_i), + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, + result_dir / "cumulative_detected_infections" / std::to_string(par_i), + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, + result_dir / "estimated_reproduction_number" / std::to_string(par_i), + save_single_runs, true, true)); + } #else - BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, - result_dir / "infection_state_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, - result_dir / "test_per_location_type_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, - result_dir / "positive_test_per_location_type_per_age_group/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_cumulative_detected_infections, ensemble_params, {0}, - result_dir / "cumulative_detected_infections/", save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_estimated_reproduction_number, ensemble_params, {0}, - result_dir / "estimated_reproduction_number/", save_single_runs, 1)); + BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, + result_dir / "infection_state_per_age_group" / std::to_string(par_i), + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "test_per_location_type_per_age_group" / std::to_string(par_i), + save_single_runs)); + BOOST_OUTCOME_TRY(save_results( + ensemble_positive_test_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "positive_test_per_location_type_per_age_group" / std::to_string(par_i), save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_cumulative_detected_infections, ensemble_params, {0}, + result_dir / "cumulative_detected_infections" / std::to_string(par_i), + save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_estimated_reproduction_number, ensemble_params, {0}, + result_dir / "estimated_reproduction_number" / std::to_string(par_i), + save_single_runs, 1)); #endif - restart_timer(timer, "time taken for data gathering and saving results"); + restart_timer(timer, "time taken for data gathering and saving results"); - printf("done.\n"); + printf("done.\n"); + } return mio::success(); } @@ -2183,18 +2259,37 @@ const std::string currentDateTime() return timeString; } -mio::IOResult create_result_folders(std::string const& result_dir, bool grid_search = false) +mio::IOResult create_result_folders(std::string const& result_dir, int n_params = 0, bool grid_search = false) { + std::string inf_p_loc_t_p_ag = result_dir + "/infection_per_location_type_per_age_group/"; + std::string inf_state_p_ag = result_dir + "/infection_state_per_age_group/"; + std::string test_p_loc_t_p_ag = result_dir + "/test_per_location_type_per_age_group/"; + std::string pos_test_p_loc_t_p_ag = result_dir + "/positive_test_per_location_type_per_age_group/"; + std::string cum_det_inf = result_dir + "/cumulative_detected_infections/"; + std::string est_rep_num = result_dir + "/estimated_reproduction_number/"; + BOOST_OUTCOME_TRY(mio::create_directory(result_dir)); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_per_location_type_per_age_group/")); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/infection_state_per_age_group/")); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/test_per_location_type_per_age_group/")); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/positive_test_per_location_type_per_age_group/")); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/cumulative_detected_infections/")); - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/estimated_reproduction_number/")); + BOOST_OUTCOME_TRY(mio::create_directory(inf_p_loc_t_p_ag)); + BOOST_OUTCOME_TRY(mio::create_directory(inf_state_p_ag)); + BOOST_OUTCOME_TRY(mio::create_directory(test_p_loc_t_p_ag)); + BOOST_OUTCOME_TRY(mio::create_directory(pos_test_p_loc_t_p_ag)); + BOOST_OUTCOME_TRY(mio::create_directory(cum_det_inf)); + BOOST_OUTCOME_TRY(mio::create_directory(est_rep_num)); + if (n_params > 0) { + // we create n_param folders in each of the subfolders + for (int i = 0; i < n_params; i++) { + BOOST_OUTCOME_TRY(mio::create_directory(inf_p_loc_t_p_ag + "/" + std::to_string(i))); + BOOST_OUTCOME_TRY(mio::create_directory(inf_state_p_ag + "/" + std::to_string(i))); + BOOST_OUTCOME_TRY(mio::create_directory(test_p_loc_t_p_ag + "/" + std::to_string(i))); + BOOST_OUTCOME_TRY(mio::create_directory(pos_test_p_loc_t_p_ag + "/" + std::to_string(i))); + BOOST_OUTCOME_TRY(mio::create_directory(cum_det_inf + "/" + std::to_string(i))); + BOOST_OUTCOME_TRY(mio::create_directory(est_rep_num + "/" + std::to_string(i))); + } + } if (grid_search) { - BOOST_OUTCOME_TRY(mio::create_directory(result_dir + "/grid_search/")); + std::string grid_search_dir = result_dir + "/grid_search/"; + BOOST_OUTCOME_TRY(mio::create_directory(grid_search_dir)); } return mio::success(); } @@ -2222,11 +2317,10 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; - std::string precomputed_dir = input_dir + "/results"; #ifdef MEMILIO_ENABLE_MPI // we need to send every rank the same folder @@ -2262,13 +2356,7 @@ int main(int argc, char** argv) printf("Running with number of runs = %d.\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); } - if (rank == 0) { - auto created = create_result_folders(result_dir, run_grid_search); - if (!created) { - std::cout << created.error().formatted_message(); - return created.error().code().value(); - } - } + timer = TIME_NOW; if (run_grid_search) { @@ -2283,10 +2371,27 @@ int main(int argc, char** argv) // std::vector points_per_dim = {2, 2, 2, 5}; std::vector points_per_dim = {13, 13, 13}; auto grid = grid_points(grid_boundaries, points_per_dim); - auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); + if (rank == 0) { + auto created = create_result_folders(result_dir, 0, run_grid_search); + if (!created) { + std::cout << created.error().formatted_message(); + return created.error().code().value(); + } + } + auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } else { - auto result = run(input_dir, result_dir, num_runs); + std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; + // std::vector> parameters = {{0.01}, {5}}; + auto every_combination = every_combination_of_parameters(parameters); + if (rank == 0) { + auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); + if (!created) { + std::cout << created.error().formatted_message(); + return created.error().code().value(); + } + } + auto result = run(input_dir, result_dir, num_runs, every_combination); } // copy results into a fixed name folder to have easier access From 3463a4d540f141ea61327e573b78c9c827296b6f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 15 Aug 2024 17:48:39 +0200 Subject: [PATCH 280/488] scale y_axis Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/parameter_varation.py | 34 +++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index 959cc7ba0f..22cd8360ff 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -78,34 +78,51 @@ def plot_positive_tests(path, index): # we want to have a Grid Plot with the size of the values # in each grid we plot a certain plot which we can define # on the general structure of the plot we we write the values of the parameters - # we want to plot in the title of the plot + # we want to plot in the title of the plot + # they all should have the same y-axis, so we can compare them, the highest value should be the maximum of all plots fig = plt.figure('Parameter Variation', figsize=(1, 1)) gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) fig.suptitle('Parameter Variation', fontsize=16) fig.show() + highest_value = 0 + for i in range(len(values_1)): + for j in range(len(values_2)): + index = (i)*len(values_2)+(j) + plot_data = plot_of_cumuative_infections(path_data, index) + if np.max(plot_data) > highest_value: + highest_value = np.max(plot_data) + for i, value_1 in enumerate(values_1): for j, value_2 in enumerate(values_2): index = (i)*len(values_2)+(j) - ax = fig.add_subplot(gs[i, j]) ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - plot_data = plot_of_cumuative_infections(path_data, index) + ax.set_ylim(0, highest_value) ax.plot(plot_data, label='Cumulative Infections') ax.legend() plt.show() + + fig = plt.figure('Parameter Variation', figsize=(1, 1)) gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) fig.suptitle('Parameter Variation', fontsize=16) fig.show() + highest_value = 0 + for i in range(len(values_1)): + for j in range(len(values_2)): + index = (i)*len(values_2)+(j) + plot_data = plot_number_of_tests(path_data, index) + if np.max(plot_data) > highest_value: + highest_value = np.max(plot_data) for i, value_1 in enumerate(values_1): for j, value_2 in enumerate(values_2): index = (i)*len(values_2)+(j) ax = fig.add_subplot(gs[i, j]) ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - + ax.set_ylim(0, highest_value) plot_data = plot_number_of_tests(path_data, index) ax.plot(plot_data, label='Number of Tests') ax.legend() @@ -114,13 +131,20 @@ def plot_positive_tests(path, index): gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) fig.suptitle('Parameter Variation', fontsize=16) fig.show() + highest_value = 0 + for i in range(len(values_1)): + for j in range(len(values_2)): + index = (i)*len(values_2)+(j) + plot_data = plot_positive_tests(path_data, index) + if np.max(plot_data) > highest_value: + highest_value = np.max(plot_data) for i, value_1 in enumerate(values_1): for j, value_2 in enumerate(values_2): index = (i)*len(values_2)+(j) ax = fig.add_subplot(gs[i, j]) ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - + ax.set_ylim(0, highest_value) plot_data = plot_positive_tests(path_data, index) ax.plot(plot_data, label='Positive Tests') ax.legend() From a244820615e290c358e0ee2a63a5821ef8056b9d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:25:39 +0200 Subject: [PATCH 281/488] parameters settings --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ed667412bd..12b275fa15 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -654,13 +654,13 @@ void set_parameters(mio::abm::Parameters& params) // Set infection parameters // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.0}, {30, 0.3}, {150, 0.5}}, days); + return mio::linear_interpolation_of_data_set({{0, 0.8}, {150, 0.8}}, days); }; // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { return mio::linear_interpolation_of_data_set( - {{0, 0.0}, {10, 0.6}, {30, 0.75}, {150, 0.5}}, days); + {{0, 0.6}, {150, 0.6}}, days); }; //Set other parameters From f1db06a884f5dd8333606b7156e7957c3efbb08d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 18 Aug 2024 20:28:04 +0200 Subject: [PATCH 282/488] push grad_search enhancecments Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 232 ++++++++++++----------- 1 file changed, 118 insertions(+), 114 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 12b275fa15..d8c3cb41f9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1712,7 +1712,6 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa num_procs = 1; rank = 0; #endif - mio::unused(num_runs); // define parameters for grid search // Distribute the grid search over the MPI ranks @@ -1741,19 +1740,19 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.58; - const double testing_probability_sympt = 0.028; + const double damping_community_lockdown = 0.5; + const double testing_probability_sympt = 0.035; - const double after_lockdown_prob = 1.0; - const auto while_lockdown_prob = 0.8; + const double lockdown_test_prob = 1.2; + const auto after_lockdown_test_prob = 0.6; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.8; + const double after_lockdown_contact_reduction = 0.7; const double ratio_asympt_to_sympt = 20.0; - const double perc_easter_event = 0.5; + const double perc_easter_event = 0.55; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 27; @@ -1771,125 +1770,130 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); restart_timer(timer, "time for vaccinaiton state"); + for (int j = 0; j < num_runs; j++) { - // Loop over a number of runs - auto world = mio::abm::World(num_age_groupss); + // Loop over a number of runs + auto world = mio::abm::World(num_age_groupss); - create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); - restart_timer(timer, "time taken for create sampled world"); - auto sim = mio::abm::Simulation(t0, std::move(world)); + restart_timer(timer, "time taken for create sampled world"); + auto sim = mio::abm::Simulation(t0, std::move(world)); - //Logger - mio::History historyInfectionPerLocationType{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History historyInfectionStatePerAgeGroup{ - Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - mio::History - historyCumulativeDetectedInfectionsPerAgeGroup{Eigen::Index(sim.get_world().parameters.get_num_groups())}; + //Logger + mio::History + historyInfectionPerLocationType{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyInfectionStatePerAgeGroup{ + Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyCumulativeDetectedInfectionsPerAgeGroup{Eigen::Index(sim.get_world().parameters.get_num_groups())}; - // / NPIS// + // / NPIS// - const auto location_it = sim.get_world().get_locations(); + const auto location_it = sim.get_world().get_locations(); - // 1. Add testing strategies + // 1. Add testing strategies - add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, - while_lockdown_prob, after_lockdown_prob); + add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, + lockdown_test_prob, after_lockdown_test_prob); - // 2. Mask schemes for all locations - // First set all locations to have mask usage, we need ffp2 masks - for (auto& location : location_it) { - location.set_required_mask(mio::abm::MaskType::FFP2); - if (location.get_type() == mio::abm::LocationType::Home) { - location.set_npi_active(false); - } - else { - location.set_npi_active(true); + // 2. Mask schemes for all locations + // First set all locations to have mask usage, we need ffp2 masks + for (auto& location : location_it) { + location.set_required_mask(mio::abm::MaskType::FFP2); + if (location.get_type() == mio::abm::LocationType::Home) { + location.set_npi_active(false); + } + else { + location.set_npi_active(true); + } } - } - // 3. Dampings everywhere except home - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.5); // from 2021-04-12 till 2021-05-30 - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - damping_community_lockdown); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.8); // from 2021-03-15 - } - if (location.get_type() == mio::abm::LocationType::SocialEvent) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - damping_community_lockdown); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.8); // from 2021-03-15 - } - if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.75 * 0.75); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.75); // from 2021-03-15 + // 3. Dampings everywhere except home + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::School) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 + location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.00); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.5); // from 2021-04-12 till 2021-05-30 + } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + damping_community_lockdown); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::SocialEvent) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + damping_community_lockdown); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.75 * 0.75); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.7); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.75); // from 2021-03-15 + } } - } - sim.get_world().parameters.get() = viral_shedding_rate; - sim.get_world().parameters.get() = masks; + sim.get_world().parameters.get() = viral_shedding_rate; + sim.get_world().parameters.get() = masks; - restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionPerLocationType, - historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); - sim.get_world().parameters.get() = viral_shedding_rate * seasonality_april; + restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); + sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionPerLocationType, + historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); + sim.get_world().parameters.get() = + viral_shedding_rate * seasonality_april; - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= - contact_red_lockdown * contact_red_lockdown; + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= + contact_red_lockdown * contact_red_lockdown; + } } - } - restart_timer(timer, "till advance 62 & lockdown ends"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationType, - historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); + restart_timer(timer, "till advance 62 & lockdown ends"); + sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationType, + historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= - (1 / (contact_red_lockdown * contact_red_lockdown)) * after_lockdown_contact_reduction; + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= + (1 / (contact_red_lockdown * contact_red_lockdown)) * after_lockdown_contact_reduction; + } } - } - sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; - restart_timer(timer, "till advance tmax "); - sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationType, historyInfectionStatePerAgeGroup, - historyCumulativeDetectedInfectionsPerAgeGroup); - - ////Advance till here - // Stop the clock after sim.advance and calculate the duration - restart_timer(timer, "time taken for simulation end"); - // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_infection_per_loc_tpye = - std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; - auto temp_sim_infection_state_per_age_group = - std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - auto temp_sim_cumulative_detected_infections_per_age_group = - std::vector>{std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; - - auto rmse = - calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], - temp_sim_cumulative_detected_infections_per_age_group[0], max_num_days, start_date); - rmse_results_per_grid_point.at(i) = rmse; + sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; + restart_timer(timer, "till advance tmax "); + sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationType, + historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); + + ////Advance till here + // Stop the clock after sim.advance and calculate the duration + restart_timer(timer, "time taken for simulation end"); + // TODO: update result of the simulation to be a vector of location result. + auto temp_sim_infection_per_loc_tpye = + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_state_per_age_group = + std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + auto temp_sim_cumulative_detected_infections_per_age_group = std::vector>{ + std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; + + auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], + temp_sim_cumulative_detected_infections_per_age_group[0], max_num_days, + start_date); + rmse_results_per_grid_point.at(i) += rmse; + } + rmse_results_per_grid_point.at(i) /= num_runs; #pragma omp critical { write_grid_search_prematurely_to_file(rank, result_dir, @@ -1961,7 +1965,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double after_lockdown_contact_reduction = 0.7; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.58; + const double perc_easter_event = 0.55; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 26; @@ -2317,8 +2321,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2346,7 +2350,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 1; + num_runs = 5; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs = 1\n"); @@ -2366,10 +2370,10 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{1.5, 2.5}, {1.0, 6.0}, {0.2, 0.8}}; - // std::vector grid_boundaries = {1.9, 4.0, 0.7}; + // std::vector> grid_boundaries = {{1.5, 2.5}, {1.0, 6.0}, {0.2, 0.8}}; + std::vector grid_boundaries = {2.08, 3.3, 0.65}; // std::vector points_per_dim = {2, 2, 2, 5}; - std::vector points_per_dim = {13, 13, 13}; + std::vector points_per_dim = {7, 7, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From c4f980b72160a94d66b8b4847135b3d202aa78a5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 18 Aug 2024 20:36:31 +0200 Subject: [PATCH 283/488] just calc from dead Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d8c3cb41f9..064e78e4db 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -659,8 +659,7 @@ void set_parameters(mio::abm::Parameters& params) // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set( - {{0, 0.6}, {150, 0.6}}, days); + return mio::linear_interpolation_of_data_set({{0, 0.6}, {150, 0.6}}, days); }; //Set other parameters @@ -1059,7 +1058,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries Date: Sun, 18 Aug 2024 21:26:04 +0200 Subject: [PATCH 284/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 3 +- cpp/simulations/generate_graph_from_data.cpp | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 32 ++++++++++---------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 9270624c35..aca8f199c2 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -325,7 +325,7 @@ def plot_dead(path): def plot_icu(path): df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu = 0.42 + perc_of_critical_in_icu = 0.47 # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] @@ -345,6 +345,7 @@ def plot_icu(path): # we just take the first 90 days total_50 = total_50[0:90] + # we plot this against this the Amount of persons in the ICU from our model f_p75 = h5py.File( path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index fdf61f5511..37d11890c4 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.8); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.3); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 064e78e4db..26f9549edd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1058,7 +1058,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries run(const fs::path& input_dir, const fs::path& result_dir, s std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - const double viral_shedding_rate = 2.08; - const double dark_figure = 3.3; + const double viral_shedding_rate = 2.11; + const double dark_figure = 3.0; const double contact_red_lockdown = 0.65; const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.035; @@ -1961,7 +1961,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.7; + const double after_lockdown_contact_reduction = 0.6; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[1]; const double perc_easter_event = 0.55; @@ -2369,11 +2369,11 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = {{1.5, 2.5}, {1.0, 6.0}, {0.2, 0.8}}; - std::vector grid_boundaries = {2.08, 3.3, 0.65}; - // std::vector points_per_dim = {2, 2, 2, 5}; - std::vector points_per_dim = {7, 7, 7}; - auto grid = grid_points(grid_boundaries, points_per_dim); + std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; + // std::vector grid_boundaries = {2.08, 3.3, 0.65}; + std::vector points_per_dim = {11, 11, 7, 11}; + // std::vector points_per_dim = {7, 7, 7}; + auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); if (!created) { @@ -2384,9 +2384,9 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } else { - std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - // std::vector> parameters = {{0.01}, {5}}; - auto every_combination = every_combination_of_parameters(parameters); + // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; + std::vector> parameters = {{0.035}, {20}}; + auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); if (!created) { From a4dbc92cbb540396ef0244a3f66899be3e25c134 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 18 Aug 2024 23:46:53 +0200 Subject: [PATCH 285/488] bugfix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index aca8f199c2..b56eeca30b 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -687,7 +687,7 @@ def plot_cumulative_detected_infections(path): total_95 = np.floor(total_95[0:90].flatten()) f_p05 = h5py.File( - path+"/cumulative_detected_infections/0/p95/Results.h5", 'r') + path+"/cumulative_detected_infections/0/p05/Results.h5", 'r') p05_bs = f_p05['0'] total_05 = p05_bs['Total'][()] total_05 = total_05[::24] From acd892ebfc3f058a7bb4701182648f437947be61 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 18 Aug 2024 23:48:13 +0200 Subject: [PATCH 286/488] some param changes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 27 +++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 26f9549edd..cc21503577 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1751,7 +1751,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const double masks = 0.55; const double after_lockdown_contact_reduction = 0.6; const double ratio_asympt_to_sympt = 20.0; - const double perc_easter_event = 0.5; + const double perc_easter_event = 0.45; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 27; @@ -1947,12 +1947,15 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - const double viral_shedding_rate = 2.11; - const double dark_figure = 3.0; - const double contact_red_lockdown = 0.65; + // const double viral_shedding_rate = 2.11; + const double viral_shedding_rate = params[0]; + // const double dark_figure = 3.0; + const double dark_figure = params[1]; + // const double contact_red_lockdown = 0.65; + const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - // const double testing_probability_sympt = 0.035; - const double testing_probability_sympt = params[0]; + const double testing_probability_sympt = 0.035; + // const double testing_probability_sympt = params[0]; const double lockdown_test_prob = 1.2; const double after_lockdown_test_prob = 0.6; @@ -1962,9 +1965,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double masks = 0.55; const double after_lockdown_contact_reduction = 0.6; - // const double ratio_asympt_to_sympt = 20.0; - const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.55; + const double ratio_asympt_to_sympt = 20.0; + // const double ratio_asympt_to_sympt = params[1]; + const double perc_easter_event = 0.45; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 26; @@ -2320,8 +2323,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2385,7 +2388,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{0.035}, {20}}; + std::vector> parameters = {{2.21}, {3.3}, {0.52}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 87fd1e11e9936b97b175f794e2ef7ce20a6e4819 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 19 Aug 2024 22:39:27 +0200 Subject: [PATCH 287/488] link bs data Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/cleanup_data.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index c250ca151a..889be45751 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -422,7 +422,7 @@ def add_time_if_null(pd): pd['start_time'] = pd['start_time'].fillna("12:30") return pd - +# We use https://zenodo.org/records/13318436 as input data PATH = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/" # PATH = "/Users/david/Documents/HZI/memilio/data/mobility/" FILE = PATH + "braunschweig_result_ffa8.csv" diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cc21503577..e70169869e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -400,7 +400,8 @@ mio::AgeGroup determine_age_group(uint32_t age) void create_world_from_data(mio::abm::World& world, const std::string& filename, const int max_number_persons) { - // Open File + + // Open File; we use the cleaned up version of https://zenodo.org/records/13318436 const fs::path p = filename; if (!fs::exists(p)) { mio::log_error("Cannot read in data. File does not exist."); @@ -1954,7 +1955,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // const double contact_red_lockdown = 0.65; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.035; + const double testing_probability_sympt = 0.034; // const double testing_probability_sympt = params[0]; const double lockdown_test_prob = 1.2; @@ -2388,7 +2389,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.21}, {3.3}, {0.52}}; + std::vector> parameters = {{2.08}, {2.8}, {0.75}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From d7a164f256739e08727e7d9596f7b8546734a4a2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 19 Aug 2024 23:32:30 +0200 Subject: [PATCH 288/488] change setup markdown Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/setup.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/setup.md b/cpp/simulations/setup.md index 96125eaf3d..20dc743b80 100644 --- a/cpp/simulations/setup.md +++ b/cpp/simulations/setup.md @@ -1,13 +1,12 @@ # How to setup the paper simulation from brunswick -1. You need the file "braunschweig_result_ffa8.csv" downloadable a this URL: +1. You need the file "braunschweig_result_ffa8.csv" downloadable a this URL: 2. You need to save this file into the folder:"/memilio/data/mobility/braunschweig_result_ffa8.csv" 3. You need to run cleanup_data.py (install numpy and pandas beforehand) please change the folders 4. You need to download the simulation files. Please follow the installation instructions at "" 5. Run "python getSimulationData.py -s 2021-01-01 -e 2021-07-01 -m 7" +6. Run "python getSimulationData.py -s 2021-01-01 -e 2021-07-01 -m 7 --rep-date" 6. Copy the Germany folder into data/mobility/Germany -7. mkdir data/results -8. Put rki files in results 9. Change the folder in paper_abm_testing to your data folder. 10. cmake --build /Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/build --config Release --target paper_abm_bs_testing -j 6 -- 11. ./memilio/cpp/build/bin/paper_abm_bs_testing From 04598aa74c44cd03d11e1df332bbc56634c9bb72 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:50:25 +0200 Subject: [PATCH 289/488] change punctual grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e70169869e..9898e22683 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1091,8 +1091,8 @@ std::vector> grid_points(const std::vector& paramete std::vector> grid; for (size_t i = 0; i < parameter_points.size(); i++) { std::vector temp; - double min_value = parameter_points[i] * 0.8; - double max_value = parameter_points[i] * 1.2; + double min_value = parameter_points[i] * 0.95; + double max_value = parameter_points[i] * 1.05; double step = (max_value - min_value) / (number_of_points.at(i) - 1); for (int j = 0; j < number_of_points.at(i) - 1; j++) { temp.push_back(min_value + j * step); @@ -2389,7 +2389,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.08}, {2.8}, {0.75}}; + std::vector> parameters = {{2.35}, {2.8}, {0.675}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 3949c667814f16d5c1b1796956108da00fc7e072 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:51:08 +0200 Subject: [PATCH 290/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 9898e22683..982a440b46 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2324,8 +2324,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From 086616c01487af5ad919fc82e4bdd7c5efe3d381 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 12:52:02 +0200 Subject: [PATCH 291/488] cluuster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 982a440b46..f0537e8da6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2353,7 +2353,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 5; + num_runs = 11; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs = 1\n"); From 4d956aec715ef4b0a22d5e49f38b04490f3aab62 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:31:06 +0200 Subject: [PATCH 292/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 38 +++++++++++++----------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f0537e8da6..7836b3e10b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1939,7 +1939,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s num_procs = 1; rank = 0; #endif - + std::vector rmse_results_per_grid_point; + rmse_results_per_grid_point.resize(parameter_values.size()); for (size_t par_i = 0; par_i < parameter_values.size(); par_i++) { auto params = parameter_values[par_i]; @@ -1955,7 +1956,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // const double contact_red_lockdown = 0.65; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.034; + const double testing_probability_sympt = 0.038; // const double testing_probability_sympt = params[0]; const double lockdown_test_prob = 1.2; @@ -2171,18 +2172,19 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; - //calculate RMSE - // int number_of_days_for_rmse = 0; - // if (npis_on) { - // number_of_days_for_rmse = 90; - // } - // else { - // number_of_days_for_rmse = 20; - // } - // auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], - // temp_sim_cumulative_detected_infections_per_age_group[0], - // number_of_days_for_rmse, start_date); - // std::cout << "RMSE: " << rmse << std::endl; + // calculate RMSE + int number_of_days_for_rmse = 0; + if (npis_on) { + number_of_days_for_rmse = 90; + } + else { + number_of_days_for_rmse = 20; + } + auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], + temp_sim_cumulative_detected_infections_per_age_group[0], + number_of_days_for_rmse, start_date); + + rmse_results_per_grid_point.at(par_i) += rmse; //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); //for now this doesnt work, but we can still save the results of the last world since the @@ -2193,6 +2195,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } } + rmse_results_per_grid_point.at(par_i) /= num_runs; + std::cout << "RMSE: " << rmse_results_per_grid_point.at(par_i) << std::endl; printf("Saving results ... "); #ifdef MEMILIO_ENABLE_MPI @@ -2324,8 +2328,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2389,7 +2393,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.35}, {2.8}, {0.675}}; + std::vector> parameters = {{2.08}, {2.9}, {0.75}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 653c9ab32e41befa8877cf6c913bfa40b52158e1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:26:54 +0200 Subject: [PATCH 293/488] benchmark Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 13 +++++++++---- cpp/models/abm/world.cpp | 9 +++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index 9649ae8d62..f657d5a68b 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -36,7 +36,7 @@ mio::abm::Simulation make_simulation(size_t num_persons, std::initializer_list locs(num_locs); std::generate(locs.begin(), locs.end(), [&] { return world.add_location(loc_type); @@ -114,6 +114,7 @@ mio::abm::Simulation make_simulation(size_t num_persons, std::initializer_list( {{0, 0.863}, {1, 0.969}, {7, 0.029}, {10, 0.002}, {14, 0.0014}, {21, 0}}, days); }; + world.parameters.get() = 100; return mio::abm::Simulation(mio::abm::TimePoint(0), std::move(world)); } @@ -126,6 +127,7 @@ mio::abm::Simulation make_simulation(size_t num_persons, std::initializer_list seeds) { int tid = -1; + std::cout << "Number of persons = " << num_persons << "\n"; #pragma omp parallel private(tid) // Start of parallel region: forks threads { tid = omp_get_thread_num(); // default is number of CPUs on machine @@ -167,8 +169,11 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer //have to be adjusted to get the benchmark back to normal. //For small sizes (e.g. 10k) extreme cases are too likely, i.e. infections die out //or overwhelm everything, so we don't benchmark these. Results should be mostly transferrable. -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50k, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100k, 100000, {38462643u, 38327950u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_200k, 200000, {28841971u, 69399375u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_400k_pt, 400000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_800k_pt, 800000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_1600k_pt, 1600000, {14159265u, 35897932u}) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) + ->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 3541b54e15..0fb44332f3 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for num_threads(4)) + PRAGMA_OMP(parallel for ) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for num_threads(4)) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -131,7 +131,7 @@ void World::migration(TimePoint t, TimeSpan dt) // check if a person makes a trip size_t num_trips = m_trip_list.num_trips(); - if (num_trips != 0) { + if (!m_use_migration_rules && num_trips != 0) { while (m_trip_list.get_current_index() < num_trips && m_trip_list.get_next_trip_time().seconds() < (t + dt).time_since_midnight().seconds()) { auto& trip = m_trip_list.get_next_trip(); @@ -168,9 +168,10 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); - PRAGMA_OMP(parallel for num_threads(4)) + PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; + // mio::unused(location, dt); location->adjust_contact_rates(parameters.get_num_groups()); location->cache_exposure_rates(t, dt, parameters.get_num_groups(), parameters); } From dd2823af17cb7ffac570e6058bb31a2d06c0e9d9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:44:40 +0200 Subject: [PATCH 294/488] benchmarks Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index f657d5a68b..f86100c932 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -169,7 +169,10 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer //have to be adjusted to get the benchmark back to normal. //For small sizes (e.g. 10k) extreme cases are too likely, i.e. infections die out //or overwhelm everything, so we don't benchmark these. Results should be mostly transferrable. - +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_25k_pt, 25000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50k_pt, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100k_pt, 100000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_200k_pt, 200000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_400k_pt, 400000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_800k_pt, 800000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_1600k_pt, 1600000, {14159265u, 35897932u}) From 6bc3d5f1834b13504e943c3322b496cf05e15b55 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 19:45:28 +0200 Subject: [PATCH 295/488] 6.4mio Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index f86100c932..0d323c00af 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -179,4 +179,6 @@ BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_1600k_pt, 1600000, {14159265u, 35 ->Unit(benchmark::kMillisecond); BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_6400k_pt, 6400000, {14159265u, 35897932u}) + ->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); From 21579f18a473cd8999597b7cf048bd5f34e15358 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:11:12 +0200 Subject: [PATCH 296/488] scaling results Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 20 ++++---- cpp/simulations/scaling results.py | 76 ++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 cpp/simulations/scaling results.py diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index b56eeca30b..533f5c0dc0 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -263,7 +263,7 @@ def plot_dead(path): # we need the real data json file cases_all_state_repdate_ma7 df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_age_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_age_ma7.json") # we just need the columns cases and date # we need to offset the dates by 19 day @@ -324,7 +324,7 @@ def plot_dead(path): plt.show() def plot_icu(path): - df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") + df_abb = pd.read_json(path+"/../../../pydata/Germany/county_divi_ma7.json") perc_of_critical_in_icu = 0.47 # we just need the columns ICU_low and ICU_hig @@ -386,7 +386,7 @@ def plot_icu(path): fig.set_figwidth(20) fig.set_figheight(9) # we plot the ICU_low and the ICU_high - ax.plot(df_abb['Date'][0:90], ICU_Real, color='tab:red') + ax.plot(df_abb['Date'][0:90], ICU_Real,'x', color='tab:red') ax.fill_between(df_abb['Date'][0:90],ICU_Simulation75, ICU_Simulation25, alpha=0.5, color='tab:blue') ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:blue') @@ -553,7 +553,7 @@ def infer_positive_tests(path): # we need the real data from the json file cases_all_county_age_repdate_ma7.json df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") # we just need the columns cases and date df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] # we need just the dates bewteen 2021-03-01 and 2021-06-01 @@ -660,7 +660,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -712,7 +712,7 @@ def plot_cumulative_detected_infections(path): # we plot this # we plot the tests positive and the real cases plt.plot(time, total_50, color='tab:blue') - plt.plot(time, df_abb, color='tab:red') + plt.plot(time, df_abb, 'x', color='tab:red') plt.fill_between(time, total_95, total_05, alpha=0.5, color='tab:blue') plt.xlabel('time (days)') @@ -731,7 +731,9 @@ def plot_cumulative_detected_infections(path): fig.set_figheight(9) # we plot the tests positive and the real cases ax.plot(time[0:89], total_50_diff, color='tab:blue') - ax.plot(time[0:89], df_abb_diff, color='tab:red') + # we dont plot the real curve as a line but as x points and not every day but every 2nd day + ax.plot(time[0:89], df_abb_diff[0:89], 'x', color='tab:red') + ax.set_xlabel('time (days)') ax.set_ylabel('Number of new detected infections') ax.title.set_text('New detected infections') @@ -794,8 +796,8 @@ def plot_positive_and_done_test(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/1/results_last_run" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/5/results_2024-08-20135139" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): diff --git a/cpp/simulations/scaling results.py b/cpp/simulations/scaling results.py new file mode 100644 index 0000000000..7c476a0053 --- /dev/null +++ b/cpp/simulations/scaling results.py @@ -0,0 +1,76 @@ +import matplotlib.pyplot as plt + +# First plot: Runtime vs. Number of Processors on +# processors = [1, 2, 4, 8] # Number of processors +# runtime = [[0.6, 0.8, 1.1, 2.2], # 0.025 mio agents per processor +# [1.4, 1.8, 2.5, 4.5], # 0.05 mio agents per processor +# [3.3, 4.8, 6.4, 9.5]] # 0.1 mio agents per processor +processors = [1, 2, 4, 8, 16, 32] # Number of processors +runtime = [ [02.0, 02.9, 04.5, 05.3, 06.1, 08.2], # 0.025 mio agents per processor + [05.7, 06.2, 08.9, 10.0, 12.1, 16.7], # 0.05 mio agents per processor + [11.2, 12.5, 16.8, 19.0, 24.3, 32.1], # 0.1 mio agents per processor + [23.6, 24.9, 32.1, 37.5, 47.9, 63.4]] # 0.2 mio agents per processor + +plt.figure() +for i in range(len(runtime)): + plt.plot(processors, runtime[i], marker='o') +plt.legend(['0.025 mio agents per processor', '0.05 mio agents per processor', '0.1 mio agents per processor', '0.2 mio agents per processor']) +plt.xlabel('Number of Processors') +plt.ylabel('Runtime (seconds)') +plt.title('Runtime vs. Number of Processors for 0.025/0.05/0.1/0.2 mio Agents per Processor for 10 days') + +plt.grid(True) +plt.show() + +# Second plot: Speedup vs. Number of Processors +# time for 800k agents on x processors +processors = [1, 2, 4, 8, 16, 32] # Number of processors +time_800k = [95, 49, 32, 19, 12.1, 8.3] # Time in seconds +speedup = [time_800k[0] / t for t in time_800k] +ideal_speedup = [p for p in processors] + +plt.figure() +plt.plot(processors, speedup, marker='o') +plt.plot(processors, ideal_speedup, marker='o') +plt.xlabel('Number of Processors') +plt.ylabel('Speedup') +plt.title('Speedup vs. Number of Processors') +plt.legend(['Speedup', 'Ideal Speedup']) +plt.grid(True) +plt.show() + +# Third plot: CPU Time vs. Population Size on 8 processors +population_size = [25, 50, 100, 200, 400, 800, 1600, 3200,6400] # Population size in thousand +population_size = [p * 1000 for p in population_size] +cpu_time_real = [0.32,0.84,2.5,5.3,10.1,19.2,37.5,72.9,148] # CPU time in seconds +# we also need the avarage number of seconds per 1000 agents +cpu_time_per_1000 = [t / p for t, p in zip(cpu_time_real, population_size)] +avarage_cpu_time_per_1000 = sum(cpu_time_per_1000) / len(cpu_time_per_1000) +#calculate the CP time with the avarage for above population sizes +cpu_time_av = [p * avarage_cpu_time_per_1000 for p in population_size] + + +plt.figure() +#logarithmic scale +plt.yscale('log') +plt.xscale('log') +plt.plot(population_size, cpu_time_real, marker='o') +plt.plot(population_size, cpu_time_av, marker='x', alpha=0.5) +plt.legend(['Real CPU Time', 'Constant CPU time = '+str(avarage_cpu_time_per_1000)+' * Population Size']) +plt.xlabel('Population Size') +plt.ylabel('CPU Time (seconds)') +plt.title('CPU Time vs. Population Size in thousand') +plt.grid(True) +plt.show() + +# Fourth plot: Memory Usage vs. Population Size +population_size = [25, 50, 100, 200, 400, 800, 1600, 3200] # Population size in thousand +memory_usage = [10,22, 50, 111, 228,455,900,1777] # Memory usage in MB + +plt.figure() +plt.plot(population_size, memory_usage, marker='o') +plt.xlabel('Population Size') +plt.ylabel('Memory Usage (MB)') +plt.title('Memory Usage vs. Population Size') +plt.grid(True) +plt.show() \ No newline at end of file From b2c36252a71c42962cf74cfa2ce3e8cf94f03f3a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:37:29 +0200 Subject: [PATCH 297/488] cluster grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7836b3e10b..d3b04521a0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1729,7 +1729,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -PRAGMA_OMP(parallel for num_threads(64)) +PRAGMA_OMP(parallel for num_threads(128) schedule (dynamic, 4)) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; std::random_device rd; @@ -2328,8 +2328,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2377,11 +2377,11 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; - // std::vector grid_boundaries = {2.08, 3.3, 0.65}; - std::vector points_per_dim = {11, 11, 7, 11}; - // std::vector points_per_dim = {7, 7, 7}; - auto grid = grid_points(grid_boundaries, points_per_dim); + // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; + std::vector grid_boundaries = {2.1, 3.0, 0.68}; + // std::vector points_per_dim = {11, 11, 7, 11}; + std::vector points_per_dim = {7, 7, 7}; + auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); if (!created) { @@ -2393,7 +2393,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.08}, {2.9}, {0.75}}; + std::vector> parameters = {{2.21}, {2.9}, {0.675}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From b891bb8e923c5e9bdc5b17906a6cea3935e816b5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 22:46:08 +0200 Subject: [PATCH 298/488] quick update Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d3b04521a0..cd08bab38f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2378,7 +2378,7 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; - std::vector grid_boundaries = {2.1, 3.0, 0.68}; + std::vector grid_boundaries = {2.1, 2.6, 0.7}; // std::vector points_per_dim = {11, 11, 7, 11}; std::vector points_per_dim = {7, 7, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); From 31cdc27e9ecf4d58c634e659578ad2491ea20d47 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:25:19 +0200 Subject: [PATCH 299/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cd08bab38f..41483a7234 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2378,7 +2378,7 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; - std::vector grid_boundaries = {2.1, 2.6, 0.7}; + std::vector grid_boundaries = {2.2, 2.8, 0.7}; // std::vector points_per_dim = {11, 11, 7, 11}; std::vector points_per_dim = {7, 7, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); @@ -2393,7 +2393,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.21}, {2.9}, {0.675}}; + std::vector> parameters = {{2.3}, {3.2}, {0.65}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From e12e1368f365c592779cbcbafacd21709d666713 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:35:27 +0200 Subject: [PATCH 300/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 41483a7234..cc1cd29c3a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1059,7 +1059,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; - std::vector grid_boundaries = {2.2, 2.8, 0.7}; + std::vector grid_boundaries = {2.2, 2.8, 0.7, 0.03}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {7, 7, 7}; + std::vector points_per_dim = {7, 7, 7, 3}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 7f321da26364e8459c4f1f9dd298a3b4d2160da0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 00:17:16 +0200 Subject: [PATCH 301/488] lets see Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cc1cd29c3a..be86477f2a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1741,7 +1741,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = params[3]; + const double testing_probability_sympt = 0.033; const double lockdown_test_prob = 1.2; const auto after_lockdown_test_prob = 0.8; @@ -1750,7 +1750,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.6; + const double after_lockdown_contact_reduction = params[3]; const double ratio_asympt_to_sympt = 20.0; const double perc_easter_event = 0.45; @@ -1956,7 +1956,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // const double contact_red_lockdown = 0.65; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.038; + const double testing_probability_sympt = 0.033; // const double testing_probability_sympt = params[0]; const double lockdown_test_prob = 1.2; @@ -1969,7 +1969,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double after_lockdown_contact_reduction = 0.6; const double ratio_asympt_to_sympt = 20.0; // const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.45; + const double perc_easter_event = 0.4; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 26; @@ -2378,9 +2378,9 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; - std::vector grid_boundaries = {2.2, 2.8, 0.7, 0.03}; + std::vector grid_boundaries = {2.2, 2.8, 0.7, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {7, 7, 7, 3}; + std::vector points_per_dim = {7, 7, 7, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2393,7 +2393,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.3}, {3.2}, {0.65}}; + std::vector> parameters = {{2.2}, {3.0}, {0.6}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 52c1149ce2461173d46e393601b0aa10f9ed682e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 00:18:18 +0200 Subject: [PATCH 302/488] paaper Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index be86477f2a..3f68d57f5a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1059,7 +1059,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries Date: Wed, 21 Aug 2024 10:10:54 +0200 Subject: [PATCH 303/488] this the run? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3f68d57f5a..5152538919 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1729,7 +1729,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -PRAGMA_OMP(parallel for num_threads(128) schedule (dynamic, 4)) +PRAGMA_OMP(parallel for num_threads(128) ) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; std::random_device rd; @@ -1750,7 +1750,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = params[3]; + const double after_lockdown_contact_reduction = 0.52; const double ratio_asympt_to_sympt = 20.0; const double perc_easter_event = 0.45; @@ -1969,11 +1969,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double after_lockdown_contact_reduction = 0.6; const double ratio_asympt_to_sympt = 20.0; // const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.4; + const double perc_easter_event = 0.45; mio::Date start_date{2021, 3, 1}; - int date_of_lockdown = 26; - int end_date_of_lockdown = 60; + int date_of_lockdown = 27; + int end_date_of_lockdown = 61; int max_num_days = 90; auto max_num_persons = 400000; bool npis_on = true; @@ -2393,7 +2393,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.2}, {3.0}, {0.6}}; + std::vector> parameters = {{2.23}, {2.84}, {0.66}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From a9051a1db7b892ddbf763548676ad012f5c3c002 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 11:49:22 +0200 Subject: [PATCH 304/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5152538919..ad0438e7ff 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1969,7 +1969,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double after_lockdown_contact_reduction = 0.6; const double ratio_asympt_to_sympt = 20.0; // const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.45; + const double perc_easter_event = 0.33; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 27; @@ -2393,7 +2393,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.23}, {2.84}, {0.66}}; + std::vector> parameters = {{2.29}, {2.80}, {0.60}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 0e124a5a5768e7c8a0254962795e207ebee2b26b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:44:20 +0200 Subject: [PATCH 305/488] add scenario plotter and other improvements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 59 ++++++++++++++++---- cpp/simulations/generate_graph_from_data.cpp | 2 +- cpp/simulations/scaling results.py | 3 +- cpp/simulations/scenario_plots.py | 43 ++++++++++++++ 4 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 cpp/simulations/scenario_plots.py diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 533f5c0dc0..1d5820def5 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -251,19 +251,28 @@ def plot_dead(path): # do the same for 25 and 75 percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p25/Results.h5", 'r') p25_bs = f_p25['0'] f_p75 = h5py.File( - path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p75/Results.h5", 'r') p75_bs = f_p75['0'] + # do the same for 05 and 95 percentile + f_p05 = h5py.File( + path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') + p05_bs = f_p05['0'] + + f_p95 = h5py.File( + path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') + p95_bs = f_p95['0'] + age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] # we need the real data json file cases_all_state_repdate_ma7 df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_age_ma7.json") + path+"/../pydata/Germany/cases_all_county_age_ma7.json") # we just need the columns cases and date # we need to offset the dates by 19 day @@ -296,10 +305,12 @@ def plot_dead(path): # we calculate the RMSE rmse_dead = (((y_real- p50_bs['Total'][()][:, 7][::24][0:90])**2).mean()) # we need to plot the cumulative dead persons from the real world and from the simulation - ax.plot(df_total_dead.index, y_real, color='tab:red') + ax.plot(df_total_dead.index, y_real, 'v',color='tab:red') ax.plot(df_total_dead.index, p50_bs['Total'][()][:, 7][::24][0:90], color='tab:blue') ax.fill_between(df_total_dead.index, p75_bs['Total'][()][:, 7][::24][0:90], p25_bs['Total'][()][:, 7][::24][0:90], alpha=0.5, color='tab:blue') + ax.fill_between(df_total_dead.index, p95_bs['Total'][()][:, 7][::24][0:90], p05_bs['Total'][()][:, 7][::24][0:90], + alpha=0.25, color='tab:blue') ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_dead))), horizontalalignment='center', verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) ax.set_xlabel('Date') @@ -316,6 +327,8 @@ def plot_dead(path): # we need to plot the dead persons from the real world and from the simulation ax.plot(df_abb_age_group['Date'], y_real, color='tab:red') ax.plot(df_abb_age_group['Date'], p50_bs[age_group_access[i]][()][:, 7][::24][0:90], color='tab:blue') + ax.fill_between(df_abb_age_group['Date'], p75_bs[age_group_access[i]][()][:, 7][::24][0:90], p25_bs[age_group_access[i]][()][:, 7][::24][0:90], + alpha=0.5, color='tab:blue') ax.set_title('Dead, Age{}'.format(i)) ax.set_xlabel('Date') ax.set_xticks(df_abb_age_group['Date'][::50]) @@ -324,7 +337,7 @@ def plot_dead(path): plt.show() def plot_icu(path): - df_abb = pd.read_json(path+"/../../../pydata/Germany/county_divi_ma7.json") + df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") perc_of_critical_in_icu = 0.47 # we just need the columns ICU_low and ICU_hig @@ -348,7 +361,7 @@ def plot_icu(path): # we plot this against this the Amount of persons in the ICU from our model f_p75 = h5py.File( - path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p75/Results.h5", 'r') p75_bs = f_p75['0'] total_75 = p75_bs['Total'][()] # we need just every 24th value @@ -358,18 +371,40 @@ def plot_icu(path): # same with 25 percentile f_p25 = h5py.File( - path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') + path+"/infection_state_per_age_group/0/p25/Results.h5", 'r') p25_bs = f_p25['0'] total_25 = p25_bs['Total'][()] # we need just every 24th value total_25 = total_25[::24] # we just take the first 90 days total_25 = total_25[0:90] + + # same with 05 and 95 percentile + f_p05 = h5py.File( + path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') + p05_bs = f_p05['0'] + total_05 = p05_bs['Total'][()] + # we need just every 24th value + total_05 = total_05[::24] + # we just take the first 90 days + total_05 = total_05[0:90] + + f_p95 = h5py.File( + path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') + p95_bs = f_p95['0'] + total_95 = p95_bs['Total'][()] + # we need just every 24th value + total_95 = total_95[::24] + # we just take the first 90 days + total_95 = total_95[0:90] + ICU_Simulation = np.floor(total_50[:, 5]*perc_of_critical_in_icu) ICU_Simulation75 = np.floor(total_75[:, 5]*perc_of_critical_in_icu) ICU_Simulation25 = np.floor(total_25[:, 5]*perc_of_critical_in_icu) + ICU_Simulation05 = np.floor(total_05[:, 5]*perc_of_critical_in_icu) + ICU_Simulation95 = np.floor(total_95[:, 5]*perc_of_critical_in_icu) ICU_Real = np.floor(df_abb['ICU'][0:90]) #smooth the data @@ -389,6 +424,8 @@ def plot_icu(path): ax.plot(df_abb['Date'][0:90], ICU_Real,'x', color='tab:red') ax.fill_between(df_abb['Date'][0:90],ICU_Simulation75, ICU_Simulation25, alpha=0.5, color='tab:blue') + ax.fill_between(df_abb['Date'][0:90],ICU_Simulation05, ICU_Simulation95, + alpha=0.25, color='tab:blue') ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:blue') # we also write the rmse @@ -553,7 +590,7 @@ def infer_positive_tests(path): # we need the real data from the json file cases_all_county_age_repdate_ma7.json df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") # we just need the columns cases and date df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] # we need just the dates bewteen 2021-03-01 and 2021-06-01 @@ -660,7 +697,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -796,8 +833,8 @@ def plot_positive_and_done_test(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/5/results_2024-08-20135139" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index 37d11890c4..e743cf59d9 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.3); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 3.5); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, diff --git a/cpp/simulations/scaling results.py b/cpp/simulations/scaling results.py index 7c476a0053..e853ba04f4 100644 --- a/cpp/simulations/scaling results.py +++ b/cpp/simulations/scaling results.py @@ -34,7 +34,7 @@ plt.plot(processors, ideal_speedup, marker='o') plt.xlabel('Number of Processors') plt.ylabel('Speedup') -plt.title('Speedup vs. Number of Processors') +plt.title('Speedup vs. Number of Processors for 800k Agents') plt.legend(['Speedup', 'Ideal Speedup']) plt.grid(True) plt.show() @@ -65,6 +65,7 @@ # Fourth plot: Memory Usage vs. Population Size population_size = [25, 50, 100, 200, 400, 800, 1600, 3200] # Population size in thousand +population_size = [p * 1000 for p in population_size] memory_usage = [10,22, 50, 111, 228,455,900,1777] # Memory usage in MB plt.figure() diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py new file mode 100644 index 0000000000..04eb70e2d2 --- /dev/null +++ b/cpp/simulations/scenario_plots.py @@ -0,0 +1,43 @@ +import sys +import argparse +import os +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import matplotlib +import matplotlib.colors as colors +import matplotlib.cm as cmx +import matplotlib.patches as mpatches +import matplotlib.lines as mlines +import h5py +from datetime import datetime +from matplotlib.dates import DateFormatter +from scipy.ndimage import gaussian_filter1d +from scipy.signal import savgol_filter + +def plot_cumulative_infections(path, folder_normal, folder_high, folder_enough): + + # four plots with 3 lines for each scenario and another one for the real data + # we do one plot with 3 subplots first two plots in upper left and right are + # 1. daily new infections and 2. cumulative infections + # the third plot in the lower left is the number of tests per day + # the fourth plot in the lower right is the number of positive tests per day + + + + + + + +if __name__ == "__main__": + path_to_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/6/" + path_to_main_data = "results_2024-08-21084018" + path_to_high_testing_data = "results_2024-08-21084018" + path_to_enough_testing_data = "results_2024-08-21084018" + + if (len(sys.argv) > 1): + n_runs = sys.argv[1] + else: + n_runs = len([entry for entry in os.listdir(path) + if os.path.isfile(os.path.join(path, entry))]) + plot(path) From 4fd6c7a5c1a40e5cc65a0977847d18168f6a9198 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:01:37 +0200 Subject: [PATCH 306/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ad0438e7ff..cb6f9fa1b1 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1667,8 +1667,8 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti testing_scheme_sympt_al); // easter event - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_asympt_wl); - sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_sympt_wl); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_asympt_wl); + // sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Event, testing_scheme_sympt_wl); } void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, @@ -1729,7 +1729,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -PRAGMA_OMP(parallel for num_threads(128) ) +PRAGMA_OMP(parallel for num_threads(90) ) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; std::random_device rd; @@ -1750,9 +1750,9 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.52; + const double after_lockdown_contact_reduction = 0.55; const double ratio_asympt_to_sympt = 20.0; - const double perc_easter_event = 0.45; + const double perc_easter_event = 0.25; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 27; @@ -1966,10 +1966,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.6; + const double after_lockdown_contact_reduction = 0.55; const double ratio_asympt_to_sympt = 20.0; // const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.33; + const double perc_easter_event = 0.25; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 27; @@ -2357,7 +2357,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 11; + num_runs = 9; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs = 1\n"); @@ -2378,9 +2378,9 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; - std::vector grid_boundaries = {2.2, 2.8, 0.7, 0.55}; + std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {7, 7, 7, 7}; + std::vector points_per_dim = {7, 7, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2393,7 +2393,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.29}, {2.80}, {0.60}}; + std::vector> parameters = {{2.3}, {2.6}, {0.55}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 1b20e768ecb2c1fbbbec0688e7f143274d0705c8 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:32:37 +0200 Subject: [PATCH 307/488] benchmark_results again Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index 0d323c00af..8ec57ba5e9 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -169,16 +169,15 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer //have to be adjusted to get the benchmark back to normal. //For small sizes (e.g. 10k) extreme cases are too likely, i.e. infections die out //or overwhelm everything, so we don't benchmark these. Results should be mostly transferrable. -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_25k_pt, 25000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50k_pt, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100k_pt, 100000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_200k_pt, 200000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_400k_pt, 400000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_800k_pt, 800000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_1600k_pt, 1600000, {14159265u, 35897932u}) - ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) - ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_6400k_pt, 6400000, {14159265u, 35897932u}) - ->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_25k_pt, 25000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50k_pt, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100k_pt, 100000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_200k_pt, 200000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_400k_pt, 400000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_800k_pt, 800000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_1600k_pt, 1600000, {14159265u, 35897932u}) +// ->Unit(benchmark::kMillisecond); +// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) +// ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_5000k_pt, 500000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); From baf1288e16af453b2a543b909153ed29254eedaa Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:58:49 +0200 Subject: [PATCH 308/488] scenario plotter Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/scenario_plots.py | 178 ++++++++++++++++++++++++++++-- 1 file changed, 166 insertions(+), 12 deletions(-) diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index 04eb70e2d2..4979bfc70c 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -21,23 +21,177 @@ def plot_cumulative_infections(path, folder_normal, folder_high, folder_enough): # we do one plot with 3 subplots first two plots in upper left and right are # 1. daily new infections and 2. cumulative infections # the third plot in the lower left is the number of tests per day - # the fourth plot in the lower right is the number of positive tests per day + # the fourth plot in the lower right is the number of cumulative positive tests per day + # the x-axis is the time for a date + # load the data + locations = [0, 1, 2, 3, 4, 10] + legend_plot = ['Home', 'School', 'Work', + 'SocialEvent', 'BasicsShop','Event'] + # folders to iterate over + folders = [folder_normal, folder_high, folder_enough] + # for folder in [folder_normal, folder_high, folder_enough]: + # we plot both in separate plots + fig, axs = plt.subplots(2, 2, figsize=(19, 10)) + fig.suptitle('Infection and Tests during the first 90 days for normal and high testing scenarios') + inf_p50_normal = h5py.File( + path+folder_normal+"/infection_per_location_type_per_age_group/0/p50/Results.h5", 'r') + time = inf_p50_normal['0']['Time'][()] + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in time] + xx = [xx[i].strftime('%m-%d') for i in range(len(xx))] + xx = xx[1:][::24][:90] + for folder in folders: + inf_p50_normal = h5py.File( + path+folder+"/infection_per_location_type_per_age_group/0/p50/Results.h5", 'r') + inf_p75_normal = h5py.File( + path+folder+"/infection_per_location_type_per_age_group/0/p75/Results.h5", 'r') + inf_p25_normal = h5py.File( + path+folder+"/infection_per_location_type_per_age_group/0/p25/Results.h5", 'r') + p50_bs_normal = inf_p50_normal['0']['Total'][()] + p25_bs_normal = inf_p25_normal['0']['Total'][()] + p75_bs_normal = inf_p75_normal['0']['Total'][()] + + tests_p50_normal = h5py.File( + path+folder+"/test_per_location_type_per_age_group/0/p50/Results.h5", 'r') + tests_p25_normal = h5py.File( + path+folder+"/test_per_location_type_per_age_group/0/p25/Results.h5", 'r') + tests_p75_normal = h5py.File( + path+folder+"/test_per_location_type_per_age_group/0/p75/Results.h5", 'r') + p50_bs_tests_normal = tests_p50_normal['0']['Total'][()] + p25_bs_tests_normal = tests_p25_normal['0']['Total'][()] + p75_bs_tests_normal = tests_p75_normal['0']['Total'][()] + + + test_p_pos_p50_normal = h5py.File( + path+folder+"/positive_test_per_location_type_per_age_group/0/p50/Results.h5", 'r') + test_p_pos_p25_normal = h5py.File( + path+folder+"/positive_test_per_location_type_per_age_group/0/p25/Results.h5", 'r') + test_p_pos_p75_normal = h5py.File( + path+folder+"/positive_test_per_location_type_per_age_group/0/p75/Results.h5", 'r') + p50_bs_test_p_pos_normal = test_p_pos_p50_normal['0']['Total'][()] + p25_bs_test_p_pos_normal = test_p_pos_p25_normal['0']['Total'][()] + p75_bs_test_p_pos_normal = test_p_pos_p75_normal['0']['Total'][()] + + total_50_positive = np.sum(p50_bs_test_p_pos_normal, axis=1) + total_50_positive = np.cumsum(total_50_positive, axis=0) + total_50_positive = total_50_positive[::24] + total_50_positive = total_50_positive[0:91] # we still need to take the difference to get the daily amount + total_50_positive = np.diff(total_50_positive, axis=0).flatten() + total_50_positive = gaussian_filter1d(total_50_positive, sigma=1, mode='nearest') + + total_25_positive = np.sum(p25_bs_test_p_pos_normal, axis=1) + total_25_positive = np.cumsum(total_25_positive, axis=0) + total_25_positive = total_25_positive[::24] + total_25_positive = total_25_positive[0:91] # we still need to take the difference to get the daily amount + total_25_positive = np.diff(total_25_positive, axis=0).flatten() + total_25_positive = gaussian_filter1d(total_25_positive, sigma=1, mode='nearest') + + total_75_positive = np.sum(p75_bs_test_p_pos_normal, axis=1) + total_75_positive = np.cumsum(total_75_positive, axis=0) + total_75_positive = total_75_positive[::24] + total_75_positive = total_75_positive[0:91] # we still need to take the difference to get the daily amount + total_75_positive = np.diff(total_75_positive, axis=0).flatten() + total_75_positive = gaussian_filter1d(total_75_positive, sigma=1, mode='nearest') + + total_50_done = np.sum(p50_bs_tests_normal, axis=1) + total_50_done = np.cumsum(total_50_done, axis=0) + total_50_done = total_50_done[::24] + total_50_done = total_50_done[0:91] # we still need to take the difference to get the daily amount + total_50_done = np.diff(total_50_done, axis=0).flatten() + # we smooth this with a gaussian filter + total_50_done = gaussian_filter1d(total_50_done, sigma=2, mode='nearest') + + total_25_done = np.sum(p25_bs_tests_normal, axis=1) + total_25_done = np.cumsum(total_25_done, axis=0) + total_25_done = total_25_done[::24] + total_25_done = total_25_done[0:91] # we still need to take the difference to get the daily amount + total_25_done = np.diff(total_25_done, axis=0).flatten() + # we smooth this with a gaussian filter + total_25_done = gaussian_filter1d(total_25_done, sigma=2, mode='nearest') + + total_75_done = np.sum(p75_bs_tests_normal, axis=1) + total_75_done = np.cumsum(total_75_done, axis=0) + total_75_done = total_75_done[::24] + total_75_done = total_75_done[0:91] # we still need to take the difference to get the daily amount + total_75_done = np.diff(total_75_done, axis=0).flatten() + # we smooth this with a gaussian filter + total_75_done = gaussian_filter1d(total_75_done, sigma=2, mode='nearest') + + + p50_bs_normal_all_locations = np.zeros(len(p50_bs_normal)) + p25_bs_normal_all_locations = np.zeros(len(p25_bs_normal)) + p75_bs_normal_all_locations = np.zeros(len(p75_bs_normal)) + for location in locations: + p50_bs_normal_all_locations += p50_bs_normal[:, location] + p25_bs_normal_all_locations += p25_bs_normal[:, location] + p75_bs_normal_all_locations += p75_bs_normal[:, location] + + + cum_inf_normal_50 = np.cumsum(p50_bs_normal_all_locations) + cum_inf_normal_50 = cum_inf_normal_50[::24] + cum_inf_normal_50 = cum_inf_normal_50[:91] + new_inf_normal_50 = np.diff(cum_inf_normal_50) + + cum_inf_normal_25 = np.cumsum(p25_bs_normal_all_locations) + cum_inf_normal_25 = cum_inf_normal_25[::24] + cum_inf_normal_25 = cum_inf_normal_25[:91] + new_inf_normal_25 = np.diff(cum_inf_normal_25) + + cum_inf_normal_75 = np.cumsum(p75_bs_normal_all_locations) + cum_inf_normal_75 = cum_inf_normal_75[::24] + cum_inf_normal_75 = cum_inf_normal_75[:91] + new_inf_normal_75 = np.diff(cum_inf_normal_75) + + + # first plot + axs[0, 0].plot(xx, new_inf_normal_50, label='Normal') + axs[0, 0].fill_between(xx, new_inf_normal_25, new_inf_normal_75, alpha=0.5) + + + # second plot + axs[0, 1].plot(xx, cum_inf_normal_50[0:90], label='Normal') + axs[0, 1].fill_between(xx, cum_inf_normal_25[0:90], cum_inf_normal_75[0:90], alpha=0.5) + + # third plot + axs[1, 0].plot(xx, total_50_done, label='Normal') + axs[1, 0].fill_between(xx, total_25_done, total_75_done, alpha=0.5) + # make x axis start at 0 and end at maximum of the data + axs[1, 0].set_ylim([0, max(total_75_done)*1.5]) + + # fourth plot + axs[1, 1].plot(xx, total_50_positive, label='Normal') + axs[1, 1].fill_between(xx, total_25_positive, total_75_positive, alpha=0.5) + + + + axs[0, 0].set_title('Daily New Infections') + axs[0, 0].set_ylabel('Number of Infections') + axs[0, 0].set_xlabel('Date') + axs[0, 1].set_title('Cumulative Infections') + axs[0, 1].set_ylabel('Number of Infections') + axs[0, 1].set_xlabel('Date') + axs[1, 0].set_title('Daily Tests') + axs[1, 0].set_ylabel('Number of Tests') + axs[1, 0].set_xlabel('Date') + axs[1, 1].set_title('Daily Positive Tests') + axs[1, 1].set_ylabel('Number of Positive Tests') + axs[1, 1].set_xlabel('Date') + for ax in axs.flat: + ax.set_xticks(xx[::10]) + ax.set_xticklabels(xx[::10]) + ax.tick_params(axis='x', rotation=45) + plt.show() if __name__ == "__main__": - path_to_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/6/" - path_to_main_data = "results_2024-08-21084018" - path_to_high_testing_data = "results_2024-08-21084018" - path_to_enough_testing_data = "results_2024-08-21084018" - - if (len(sys.argv) > 1): - n_runs = sys.argv[1] - else: - n_runs = len([entry for entry in os.listdir(path) - if os.path.isfile(os.path.join(path, entry))]) - plot(path) + path_to_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" + path_to_main_data = "results_2024-08-20204040" + path_to_high_testing_data = "results_2024-08-21152952" + path_to_enough_testing_data = "results_2024-08-20215706" + + plot_cumulative_infections(path_to_data, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) From 2a72daa257afedd4c7b5cc15e5d16526f63bc6ab Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 20:00:04 +0200 Subject: [PATCH 309/488] icu oimprovement Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 1d5820def5..d42f3fcf58 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -339,6 +339,12 @@ def plot_dead(path): def plot_icu(path): df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") perc_of_critical_in_icu = 0.47 + perc_of_critical_in_icu_age = [0.56,0.56,0.56,0.57,0.55,0.47] + # perc_of_critical_in_icu_age =0.47 + + age_group_access = ['Group1', 'Group2', 'Group3', + 'Group4', 'Group5', 'Group6', 'Total'] + # we just need the columns ICU_low and ICU_hig df_abb = df_abb[['ID_County', 'ICU', 'Date']] @@ -353,10 +359,15 @@ def plot_icu(path): path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] + total_50_age = p50_bs[age_group_access[0]][()] + for i in range(6): + total_50_age += np.floor(p50_bs[age_group_access[i]][()]*perc_of_critical_in_icu_age[i]) # we need just every 24th value total_50 = total_50[::24] + total_50_age = total_50_age[::24] # we just take the first 90 days total_50 = total_50[0:90] + total_50_age = total_50_age[0:90] # we plot this against this the Amount of persons in the ICU from our model @@ -401,6 +412,7 @@ def plot_icu(path): ICU_Simulation = np.floor(total_50[:, 5]*perc_of_critical_in_icu) + ICU_Simulation_age = np.floor(total_50_age[:, 5]) ICU_Simulation75 = np.floor(total_75[:, 5]*perc_of_critical_in_icu) ICU_Simulation25 = np.floor(total_25[:, 5]*perc_of_critical_in_icu) ICU_Simulation05 = np.floor(total_05[:, 5]*perc_of_critical_in_icu) @@ -427,6 +439,7 @@ def plot_icu(path): ax.fill_between(df_abb['Date'][0:90],ICU_Simulation05, ICU_Simulation95, alpha=0.25, color='tab:blue') ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:blue') + ax.plot(df_abb['Date'][0:90], ICU_Simulation_age, color='tab:blue', linestyle='dashed') # we also write the rmse ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', @@ -810,7 +823,7 @@ def plot_positive_and_done_test(path): total_50_done = total_50_done[0:91] # we still need to take the difference to get the daily amount total_50_done = np.diff(total_50_done, axis=0).flatten() # we smooth this with a gaussian filter - total_50_done = gaussian_filter1d(total_50_done, sigma=1, mode='nearest') + total_50_done = gaussian_filter1d(total_50_done, sigma=2, mode='nearest') # we plot this # we plot the tests positive and the real cases @@ -846,7 +859,9 @@ def plot_positive_and_done_test(path): plot_infections_loc_types_avarage(path) plot_icu(path) plot_dead(path) - infer_positive_tests(path) - plot_estimated_reproduction_number(path) plot_cumulative_detected_infections(path) plot_positive_and_done_test(path) + + + # infer_positive_tests(path) + # plot_estimated_reproduction_number(path) From 66d9f17a0a8af9ffb4292173a2b4edb78bf16b44 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 20:00:39 +0200 Subject: [PATCH 310/488] further sim improvs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 54 ++++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cb6f9fa1b1..98bd0fa4e0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1588,6 +1588,7 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti double testing_probability_asympt = testing_probability_sympt / ratio_asympt_to_sympt; auto start_date_test = mio::abm::TimePoint(mio::abm::days(0).seconds()); auto lockdown_start_date = mio::abm::TimePoint(mio::abm::days(30).seconds()); + auto easter_end_date = mio::abm::TimePoint(mio::abm::days(37).seconds()); auto lockdown_end_date = mio::abm::TimePoint(mio::abm::days(60).seconds()); auto end_date_test = tmax; @@ -1611,11 +1612,17 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti auto testing_scheme_sympt = mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, start_date_test, lockdown_start_date, antigen_test_parameters, testing_probability_sympt); + auto testing_scheme_asympt_easter = + mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, lockdown_start_date, easter_end_date, + antigen_test_parameters, 0.66 * testing_probability_asympt); + auto testing_scheme_sympt_easter = + mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, lockdown_start_date, easter_end_date, + antigen_test_parameters, 0.66 * testing_probability_sympt); auto testing_scheme_asympt_wl = - mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, lockdown_start_date, lockdown_end_date, + mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, easter_end_date, lockdown_end_date, antigen_test_parameters, lockdown_prob * testing_probability_asympt); auto testing_scheme_sympt_wl = - mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, lockdown_start_date, lockdown_end_date, + mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, easter_end_date, lockdown_end_date, antigen_test_parameters, lockdown_prob * testing_probability_sympt); auto testing_scheme_asympt_al = mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, lockdown_end_date, end_date_test, @@ -1626,6 +1633,10 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_asympt_easter); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, + testing_scheme_sympt_easter); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt_wl); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_sympt_wl); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::School, testing_scheme_asympt_al); @@ -1634,6 +1645,10 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti // Work sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, + testing_scheme_asympt_easter); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, + testing_scheme_sympt_easter); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt_wl); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_sympt_wl); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_asympt_al); @@ -1643,6 +1658,10 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, testing_scheme_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_asympt_easter); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, + testing_scheme_sympt_easter); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, testing_scheme_asympt_wl); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::BasicsShop, @@ -1657,6 +1676,10 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti testing_scheme_asympt); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme_sympt); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_asympt_easter); + sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, + testing_scheme_sympt_easter); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme_asympt_wl); sim.get_world().get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, @@ -1741,10 +1764,10 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.033; + const double testing_probability_sympt = 0.036; - const double lockdown_test_prob = 1.2; - const auto after_lockdown_test_prob = 0.8; + const double lockdown_test_prob = 1.25; + const auto after_lockdown_test_prob = 0.75; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; @@ -1755,7 +1778,7 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const double perc_easter_event = 0.25; mio::Date start_date{2021, 3, 1}; - int date_of_lockdown = 27; + int date_of_lockdown = 29; int end_date_of_lockdown = 61; int max_num_days = 90; auto max_num_persons = 400000; @@ -1835,6 +1858,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { damping_community_lockdown); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.8); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(mio::abm::days(72).seconds()).seconds()), + 0.2); // from 2021-03-15 } if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 @@ -1956,11 +1981,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // const double contact_red_lockdown = 0.65; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.033; + const double testing_probability_sympt = 0.036; // const double testing_probability_sympt = params[0]; - const double lockdown_test_prob = 1.2; - const double after_lockdown_test_prob = 0.6; + const double lockdown_test_prob = 1.25; + const double after_lockdown_test_prob = 0.75; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; @@ -1969,10 +1994,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double after_lockdown_contact_reduction = 0.55; const double ratio_asympt_to_sympt = 20.0; // const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.25; + const double perc_easter_event = 0.2; mio::Date start_date{2021, 3, 1}; - int date_of_lockdown = 27; + int date_of_lockdown = 29; int end_date_of_lockdown = 61; int max_num_days = 90; auto max_num_persons = 400000; @@ -2091,6 +2116,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s damping_community_lockdown); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.8); // from 2021-03-15 + location.add_damping( + mio::abm::TimePoint(mio::abm::days(mio::abm::days(72).seconds()).seconds()), + 0.2); // from 2021-03-15 } if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 @@ -2328,8 +2356,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From c8fb8e323e8ba1f7dd27e16927b926738a47585e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 20:00:49 +0200 Subject: [PATCH 311/488] forgit this Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/generate_graph_from_data.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/generate_graph_from_data.cpp b/cpp/simulations/generate_graph_from_data.cpp index e743cf59d9..fdf61f5511 100644 --- a/cpp/simulations/generate_graph_from_data.cpp +++ b/cpp/simulations/generate_graph_from_data.cpp @@ -228,7 +228,7 @@ mio::IOResult> get_graph(mio::Date start_date, c node.parameters = params; } auto scaling_factor_infected = std::vector(size_t(params.get_num_groups()), sclaling_infected); - auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 3.5); + auto scaling_factor_icu = std::vector(size_t(params.get_num_groups()), 2.8); const auto& read_function_nodes = mio::osecir::read_input_data_county; BOOST_OUTCOME_TRY(read_function_nodes(nodes, start_date, node_ids, scaling_factor_infected, scaling_factor_icu, From be97f954e7c98320b13e709bcb807f300f3bb04e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 21:11:05 +0200 Subject: [PATCH 312/488] sc a par vari Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/parameter_varation.py | 143 +++++++++++++++----------- cpp/simulations/scenario_plots.py | 40 +++---- 2 files changed, 107 insertions(+), 76 deletions(-) diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index 22cd8360ff..345211f4c2 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -81,75 +81,102 @@ def plot_positive_tests(path, index): # we want to plot in the title of the plot # they all should have the same y-axis, so we can compare them, the highest value should be the maximum of all plots - fig = plt.figure('Parameter Variation', figsize=(1, 1)) - gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - fig.suptitle('Parameter Variation', fontsize=16) - fig.show() - highest_value = 0 - for i in range(len(values_1)): - for j in range(len(values_2)): - index = (i)*len(values_2)+(j) - plot_data = plot_of_cumuative_infections(path_data, index) - if np.max(plot_data) > highest_value: - highest_value = np.max(plot_data) + # fig = plt.figure('Parameter Variation', figsize=(1, 1)) + # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + # fig.suptitle('Parameter Variation', fontsize=16) + # fig.show() + # highest_value = 0 + # for i in range(len(values_1)): + # for j in range(len(values_2)): + # index = (i)*len(values_2)+(j) + # plot_data = plot_of_cumuative_infections(path_data, index) + # if np.max(plot_data) > highest_value: + # highest_value = np.max(plot_data) - for i, value_1 in enumerate(values_1): - for j, value_2 in enumerate(values_2): - index = (i)*len(values_2)+(j) - ax = fig.add_subplot(gs[i, j]) - ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - plot_data = plot_of_cumuative_infections(path_data, index) - ax.set_ylim(0, highest_value) - ax.plot(plot_data, label='Cumulative Infections') - ax.legend() - plt.show() + # for i, value_1 in enumerate(values_1): + # for j, value_2 in enumerate(values_2): + # index = (i)*len(values_2)+(j) + # ax = fig.add_subplot(gs[i, j]) + # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + # plot_data = plot_of_cumuative_infections(path_data, index) + # ax.set_ylim(0, highest_value) + # ax.plot(plot_data, label='Cumulative Infections') + # ax.legend() + # plt.show() - fig = plt.figure('Parameter Variation', figsize=(1, 1)) - gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - fig.suptitle('Parameter Variation', fontsize=16) - fig.show() - highest_value = 0 - for i in range(len(values_1)): - for j in range(len(values_2)): - index = (i)*len(values_2)+(j) - plot_data = plot_number_of_tests(path_data, index) - if np.max(plot_data) > highest_value: - highest_value = np.max(plot_data) - for i, value_1 in enumerate(values_1): - for j, value_2 in enumerate(values_2): - index = (i)*len(values_2)+(j) + # fig = plt.figure('Parameter Variation', figsize=(1, 1)) + # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + # fig.suptitle('Parameter Variation', fontsize=16) + # fig.show() + # highest_value = 0 + # for i in range(len(values_1)): + # for j in range(len(values_2)): + # index = (i)*len(values_2)+(j) + # plot_data = plot_number_of_tests(path_data, index) + # if np.max(plot_data) > highest_value: + # highest_value = np.max(plot_data) + # for i, value_1 in enumerate(values_1): + # for j, value_2 in enumerate(values_2): + # index = (i)*len(values_2)+(j) - ax = fig.add_subplot(gs[i, j]) - ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - ax.set_ylim(0, highest_value) - plot_data = plot_number_of_tests(path_data, index) - ax.plot(plot_data, label='Number of Tests') - ax.legend() - plt.show() - fig = plt.figure('Parameter Variation', figsize=(1, 1)) - gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + # ax = fig.add_subplot(gs[i, j]) + # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + # ax.set_ylim(0, highest_value) + # plot_data = plot_number_of_tests(path_data, index) + # ax.plot(plot_data, label='Number of Tests') + # ax.legend() + # plt.show() + # fig = plt.figure('Parameter Variation', figsize=(1, 1)) + # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + # fig.suptitle('Parameter Variation', fontsize=16) + # fig.show() + # highest_value = 0 + # for i in range(len(values_1)): + # for j in range(len(values_2)): + # index = (i)*len(values_2)+(j) + # plot_data = plot_positive_tests(path_data, index) + # if np.max(plot_data) > highest_value: + # highest_value = np.max(plot_data) + # for i, value_1 in enumerate(values_1): + # for j, value_2 in enumerate(values_2): + # index = (i)*len(values_2)+(j) + + # ax = fig.add_subplot(gs[i, j]) + # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + # ax.set_ylim(0, highest_value) + # plot_data = plot_positive_tests(path_data, index) + # ax.plot(plot_data, label='Positive Tests') + # ax.legend() + # plt.show() + + # we want to have four plots in one figure + # in each plot for each value of the parameter we want to plot a big square in a color which is defined by the value of the interesting value in that plot + # first plot that value is the maximum of the cumulative infections + # second plot that value is the maximum of the daily infections + # third plot that value is the maximum of persons dead + # fourth plot that value is the maximum of persons in the hospital + + fig, axs = plt.subplots(2, 2, figsize=(10, 10)) fig.suptitle('Parameter Variation', fontsize=16) fig.show() + # first plot is the maximum of the cumulative infections highest_value = 0 for i in range(len(values_1)): for j in range(len(values_2)): index = (i)*len(values_2)+(j) - plot_data = plot_positive_tests(path_data, index) - if np.max(plot_data) > highest_value: - highest_value = np.max(plot_data) - for i, value_1 in enumerate(values_1): - for j, value_2 in enumerate(values_2): - index = (i)*len(values_2)+(j) + plot_data = plot_of_cumuative_infections(path_data, index) + plot_data.max() + # plot the square + axs[0, 0].add_patch(mpatches.Rectangle((i, j), 1, 1, color=cmx.viridis(plot_data.max()/highest_value))) + - ax = fig.add_subplot(gs[i, j]) - ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - ax.set_ylim(0, highest_value) - plot_data = plot_positive_tests(path_data, index) - ax.plot(plot_data, label='Positive Tests') - ax.legend() - - plt.show() + + + + + + diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index 4979bfc70c..1dba7dca90 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -15,7 +15,7 @@ from scipy.ndimage import gaussian_filter1d from scipy.signal import savgol_filter -def plot_cumulative_infections(path, folder_normal, folder_high, folder_enough): +def plot_scenario(path, folder, folder_high, folder_enough): # four plots with 3 lines for each scenario and another one for the real data # we do one plot with 3 subplots first two plots in upper left and right are @@ -30,14 +30,14 @@ def plot_cumulative_infections(path, folder_normal, folder_high, folder_enough): 'SocialEvent', 'BasicsShop','Event'] # folders to iterate over - folders = [folder_normal, folder_high, folder_enough] + folders = [folder, folder_high, folder_enough] # for folder in [folder_normal, folder_high, folder_enough]: # we plot both in separate plots fig, axs = plt.subplots(2, 2, figsize=(19, 10)) fig.suptitle('Infection and Tests during the first 90 days for normal and high testing scenarios') inf_p50_normal = h5py.File( - path+folder_normal+"/infection_per_location_type_per_age_group/0/p50/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/"+folder+"/p50/Results.h5", 'r') time = inf_p50_normal['0']['Time'][()] start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') xx = [start_date + pd.Timedelta(days=int(i)) for i in time] @@ -46,32 +46,32 @@ def plot_cumulative_infections(path, folder_normal, folder_high, folder_enough): for folder in folders: inf_p50_normal = h5py.File( - path+folder+"/infection_per_location_type_per_age_group/0/p50/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/"+folder+"/p50/Results.h5", 'r') inf_p75_normal = h5py.File( - path+folder+"/infection_per_location_type_per_age_group/0/p75/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/"+folder+"/p75/Results.h5", 'r') inf_p25_normal = h5py.File( - path+folder+"/infection_per_location_type_per_age_group/0/p25/Results.h5", 'r') + path+"/infection_per_location_type_per_age_group/"+folder+"/p25/Results.h5", 'r') p50_bs_normal = inf_p50_normal['0']['Total'][()] p25_bs_normal = inf_p25_normal['0']['Total'][()] p75_bs_normal = inf_p75_normal['0']['Total'][()] tests_p50_normal = h5py.File( - path+folder+"/test_per_location_type_per_age_group/0/p50/Results.h5", 'r') + path+"/test_per_location_type_per_age_group/"+folder+"/p50/Results.h5", 'r') tests_p25_normal = h5py.File( - path+folder+"/test_per_location_type_per_age_group/0/p25/Results.h5", 'r') + path+"/test_per_location_type_per_age_group/"+folder+"/p25/Results.h5", 'r') tests_p75_normal = h5py.File( - path+folder+"/test_per_location_type_per_age_group/0/p75/Results.h5", 'r') + path+"/test_per_location_type_per_age_group/"+folder+"/p75/Results.h5", 'r') p50_bs_tests_normal = tests_p50_normal['0']['Total'][()] p25_bs_tests_normal = tests_p25_normal['0']['Total'][()] p75_bs_tests_normal = tests_p75_normal['0']['Total'][()] test_p_pos_p50_normal = h5py.File( - path+folder+"/positive_test_per_location_type_per_age_group/0/p50/Results.h5", 'r') + path+"/positive_test_per_location_type_per_age_group/"+folder+"/p50/Results.h5", 'r') test_p_pos_p25_normal = h5py.File( - path+folder+"/positive_test_per_location_type_per_age_group/0/p25/Results.h5", 'r') + path+"/positive_test_per_location_type_per_age_group/"+folder+"/p25/Results.h5", 'r') test_p_pos_p75_normal = h5py.File( - path+folder+"/positive_test_per_location_type_per_age_group/0/p75/Results.h5", 'r') + path+"/positive_test_per_location_type_per_age_group/"+folder+"/p75/Results.h5", 'r') p50_bs_test_p_pos_normal = test_p_pos_p50_normal['0']['Total'][()] p25_bs_test_p_pos_normal = test_p_pos_p25_normal['0']['Total'][()] p75_bs_test_p_pos_normal = test_p_pos_p75_normal['0']['Total'][()] @@ -189,9 +189,13 @@ def plot_cumulative_infections(path, folder_normal, folder_high, folder_enough): if __name__ == "__main__": - path_to_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" - path_to_main_data = "results_2024-08-20204040" - path_to_high_testing_data = "results_2024-08-21152952" - path_to_enough_testing_data = "results_2024-08-20215706" - - plot_cumulative_infections(path_to_data, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21181533" + path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" + path_to_scenario_3 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" + path_to_main_data = "0" + path_to_high_testing_data = "1" + path_to_enough_testing_data = "2" + + plot_scenario(path_to_scenario_1, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + # plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + # plot_scenario(path_to_scenario_3, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) From 5619748b8e0d50589e5069b66b83312e8c62ef2c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:17:01 +0200 Subject: [PATCH 313/488] scenario improv Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/scenario_plots.py | 50 +++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index 1dba7dca90..29d1450ab6 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -33,7 +33,7 @@ def plot_scenario(path, folder, folder_high, folder_enough): folders = [folder, folder_high, folder_enough] # for folder in [folder_normal, folder_high, folder_enough]: # we plot both in separate plots - fig, axs = plt.subplots(2, 2, figsize=(19, 10)) + fig, axs = plt.subplots(3, 2, figsize=(19, 10)) fig.suptitle('Infection and Tests during the first 90 days for normal and high testing scenarios') inf_p50_normal = h5py.File( @@ -76,6 +76,29 @@ def plot_scenario(path, folder, folder_high, folder_enough): p25_bs_test_p_pos_normal = test_p_pos_p25_normal['0']['Total'][()] p75_bs_test_p_pos_normal = test_p_pos_p75_normal['0']['Total'][()] + deaths_p50_normal = h5py.File( + path+"/infection_state_per_age_group/"+folder+"/p50/Results.h5", 'r') + deaths_p25_normal = h5py.File( + path+"/infection_state_per_age_group/"+folder+"/p25/Results.h5", 'r') + deaths_p75_normal = h5py.File( + path+"/infection_state_per_age_group/"+folder+"/p75/Results.h5", 'r') + p50_bs_deaths_normal = deaths_p50_normal['0']['Total'][()][:, 7][::24][0:90] + p25_bs_deaths_normal = deaths_p25_normal['0']['Total'][()][:, 7][::24][0:90] + p75_bs_deaths_normal = deaths_p75_normal['0']['Total'][()][:, 7][::24][0:90] + + reproduction_p50_normal = h5py.File( + path+"/estimated_reproduction_number/"+folder+"/p50/Results.h5", 'r') + reproduction_p25_normal = h5py.File( + path+"/estimated_reproduction_number/"+folder+"/p25/Results.h5", 'r') + reproduction_p75_normal = h5py.File( + path+"/estimated_reproduction_number/"+folder+"/p75/Results.h5", 'r') + p50_bs_reproduction_normal = reproduction_p50_normal['0']['Total'][()][::24][0:90].flatten() + p25_bs_reproduction_normal = reproduction_p25_normal['0']['Total'][()][::24][0:90].flatten() + p75_bs_reproduction_normal = reproduction_p75_normal['0']['Total'][()][::24][0:90].flatten() + + + + total_50_positive = np.sum(p50_bs_test_p_pos_normal, axis=1) total_50_positive = np.cumsum(total_50_positive, axis=0) total_50_positive = total_50_positive[::24] @@ -147,6 +170,7 @@ def plot_scenario(path, folder, folder_high, folder_enough): new_inf_normal_75 = np.diff(cum_inf_normal_75) + # first plot axs[0, 0].plot(xx, new_inf_normal_50, label='Normal') axs[0, 0].fill_between(xx, new_inf_normal_25, new_inf_normal_75, alpha=0.5) @@ -165,6 +189,17 @@ def plot_scenario(path, folder, folder_high, folder_enough): # fourth plot axs[1, 1].plot(xx, total_50_positive, label='Normal') axs[1, 1].fill_between(xx, total_25_positive, total_75_positive, alpha=0.5) + + # plot dead in last row + axs[2, 0].plot(xx, p50_bs_deaths_normal, label='Normal') + axs[2, 0].fill_between(xx, p25_bs_deaths_normal, p75_bs_deaths_normal, alpha=0.5) + + # plot reproduction number + axs[2, 1].plot(xx, p50_bs_reproduction_normal, label='Normal') + axs[2, 1].fill_between(xx, p25_bs_reproduction_normal, p75_bs_reproduction_normal, alpha=0.5) + axs[2, 1].set_ylim([0, max(p75_bs_reproduction_normal)*1.5]) + + @@ -180,6 +215,13 @@ def plot_scenario(path, folder, folder_high, folder_enough): axs[1, 1].set_title('Daily Positive Tests') axs[1, 1].set_ylabel('Number of Positive Tests') axs[1, 1].set_xlabel('Date') + axs[2, 0].set_title('Cumulative Deaths') + axs[2, 0].set_ylabel('Number of Deaths') + axs[2, 0].set_xlabel('Date') + axs[2, 1].set_title('Reproduction Number') + axs[2, 1].set_ylabel('Reproduction Number') + axs[2, 1].set_xlabel('Date') + for ax in axs.flat: ax.set_xticks(xx[::10]) ax.set_xticklabels(xx[::10]) @@ -188,14 +230,16 @@ def plot_scenario(path, folder, folder_high, folder_enough): + + if __name__ == "__main__": path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21181533" - path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" + path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21194839" path_to_scenario_3 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" path_to_main_data = "0" path_to_high_testing_data = "1" path_to_enough_testing_data = "2" plot_scenario(path_to_scenario_1, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) - # plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) # plot_scenario(path_to_scenario_3, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) From eedd8b6a155387e311851190654c3692a5fe964e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:17:27 +0200 Subject: [PATCH 314/488] scaling improv Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/scaling results.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/scaling results.py b/cpp/simulations/scaling results.py index e853ba04f4..2d9e78dab3 100644 --- a/cpp/simulations/scaling results.py +++ b/cpp/simulations/scaling results.py @@ -23,10 +23,11 @@ plt.show() # Second plot: Speedup vs. Number of Processors -# time for 800k agents on x processors +# time for 6400k agents on x processors processors = [1, 2, 4, 8, 16, 32] # Number of processors time_800k = [95, 49, 32, 19, 12.1, 8.3] # Time in seconds -speedup = [time_800k[0] / t for t in time_800k] +time_6400k = [741, 407, 220, 143, 93, 59] # Time in seconds +speedup = [time_6400k[0] / t for t in time_6400k] ideal_speedup = [p for p in processors] plt.figure() From 15a76d4953dfb565df037d45b751efae6db9f879 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:02:29 +0200 Subject: [PATCH 315/488] update parameters Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 2 +- cpp/models/abm/parameters.h | 26 ++++-- cpp/simulations/parameter_varation.py | 118 +++++++++++++++++++++++--- 3 files changed, 130 insertions(+), 16 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 6c1b98890d..6c07100b12 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -180,7 +180,7 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou auto age = p->get_age(); double quarantine_factor = 1.0; if (p->is_in_quarantine(t_middlepoint, params)) { - quarantine_factor = 0.5; + quarantine_factor = 1-params.get(); } /* average infectivity over the time step * to second order accuracy using midpoint rule diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index 61064c69d1..bc23f75d9f 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -348,6 +348,22 @@ struct InfectionRateFromViralShed { } }; +/** + * @brief Quarantine effectiveness + * + */ +struct QuarantineEffectiveness { + using Type = ScalarType; + static Type get_default(AgeGroup /*size*/) + { + return Type(0.5); + } + static std::string name() + { + return "QuarantineEffectiveness"; + } +}; + /** * @brief Aerosol transmission rates. */ @@ -650,11 +666,11 @@ using ParametersBase = TimeInfectedSevereToRecovered, TimeInfectedCriticalToDead, TimeInfectedCriticalToRecovered, SymptomsPerInfectedNoSymptoms, SeverePerInfectedSymptoms, CriticalPerInfectedSevere, DeathsPerInfectedCritical, ViralLoadDistributions, InfectivityDistributions, VirusShedFactor, - DetectInfection, MaskProtection, InfectionRateFromViralShed, AerosolTransmissionRates, LockdownDate, - QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum, - GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool, - AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor, - TestData>; + DetectInfection, MaskProtection, InfectionRateFromViralShed, AerosolTransmissionRates, + QuarantineEffectiveness, LockdownDate, QuarantineDuration, SocialEventRate, BasicShoppingRate, + WorkRatio, SchoolRatio, GotoWorkTimeMinimum, GotoWorkTimeMaximum, GotoSchoolTimeMinimum, + GotoSchoolTimeMaximum, AgeGroupGotoSchool, AgeGroupGotoWork, InfectionProtectionFactor, + SeverityProtectionFactor, HighViralLoadProtectionFactor, TestData>; /** * @brief Maximum number of Person%s an infectious Person can infect at the respective Location. diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index 345211f4c2..0836d5a27d 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -3,17 +3,20 @@ import os import pandas as pd import numpy as np +import matplotlib.patches as mpatches import matplotlib.pyplot as plt import matplotlib import matplotlib.colors as colors import matplotlib.cm as cmx import matplotlib.patches as mpatches import matplotlib.lines as mlines +import colormaps as cmaps import h5py from datetime import datetime from matplotlib.dates import DateFormatter from scipy.ndimage import gaussian_filter1d from scipy.signal import savgol_filter +import seaborn as sns def plot_of_cumuative_infections(path, index=0): # plot cumulative infections @@ -67,6 +70,32 @@ def plot_positive_tests(path, index): total_50_done = gaussian_filter1d(total_50_done, sigma=1, mode='nearest') return total_50_done +def get_maximum_dead(path, index): + deaths_p50_normal = h5py.File( + path+"/infection_state_per_age_group/"+str(index)+"/p50/Results.h5", 'r') + p50_bs_deaths_normal = deaths_p50_normal['0']['Total'][()][:, 7][::24][0:90] + return np.max(p50_bs_deaths_normal) + +def get_maximum_hospitalized(path, index): + hospitalized_p50_normal = h5py.File( + path+"/infection_state_per_age_group/"+str(index)+"/p50/Results.h5", 'r') + p50_bs_hospitalized_normal = hospitalized_p50_normal['0']['Total'][()][:, 5][::24][0:90] + return np.max(p50_bs_hospitalized_normal) + +def get_maximum_cum_infected(path, index): + infected_p50_normal = h5py.File( + path+"/infection_per_location_type_per_age_group/"+str(index)+"/p50/Results.h5", 'r') + locations = [0, 1, 2, 3, 4, 10] + p50_bs_infected_normal = infected_p50_normal['0']['Total'][()] + p50_bs_normal_all_locations = np.zeros(len(p50_bs_infected_normal)) + for location in locations: + p50_bs_normal_all_locations += p50_bs_infected_normal[:, location] + cum_inf_normal_50 = np.cumsum(p50_bs_normal_all_locations) + return np.max(cum_inf_normal_50) + + + + if __name__ == "__main__": path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-15140128" @@ -160,24 +189,93 @@ def plot_positive_tests(path, index): fig, axs = plt.subplots(2, 2, figsize=(10, 10)) fig.suptitle('Parameter Variation', fontsize=16) fig.show() - # first plot is the maximum of the cumulative infections - highest_value = 0 - for i in range(len(values_1)): - for j in range(len(values_2)): + + # first plot + value_for_values = np.zeros((len(values_1), len(values_2))) + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): index = (i)*len(values_2)+(j) - plot_data = plot_of_cumuative_infections(path_data, index) - plot_data.max() - # plot the square - axs[0, 0].add_patch(mpatches.Rectangle((i, j), 1, 1, color=cmx.viridis(plot_data.max()/highest_value))) + value_for_values[i, j] = get_maximum_cum_infected(path_data, index) + # permute the values, so that the plot is correct + value_for_values = np.flip(value_for_values, axis=1) + # we need a seaborn heatmap for the colorbar - + sns.heatmap(value_for_values, ax=axs[0, 0], cmap='viridis', cbar_kws={'label': 'Maximum Cumulative Infections'}, annot=True, fmt=".0f") + axs[0, 0].set_title('Maximum Cumulative Infections') + # x and y axis labels + axs[0, 0].set_xticklabels(values_2) + axs[0, 0].set_yticklabels(values_1) + axs[0, 0].set_xlabel(variable_2) + axs[0, 0].set_ylabel(variable_1) + + + + + + # second plot + value_for_values = np.zeros((len(values_1), len(values_2))) + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) + value_for_values[i, j] = get_maximum_dead(path_data, index) + # permute the values, so that the plot is correct + value_for_values = np.flip(value_for_values, axis=1) + # we need a seaborn heatmap for the colorbar + sns.heatmap(value_for_values, ax=axs[0, 1], cmap='viridis', cbar_kws={'label': 'Maximum Dead'}, annot=True, fmt=".0f") + axs[0, 1].set_title('Maximum Dead') + # x and y axis labels + axs[0, 1].set_xticklabels(values_2) + axs[0, 1].set_yticklabels(values_1) + axs[0, 1].set_xlabel(variable_2) + axs[0, 1].set_ylabel(variable_1) + # third plot + value_for_values = np.zeros((len(values_1), len(values_2))) + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) + value_for_values[i, j] = get_maximum_hospitalized(path_data, index) + # permute the values, so that the plot is correct + value_for_values = np.flip(value_for_values, axis=1) + # we need a seaborn heatmap for the colorbar + sns.heatmap(value_for_values, ax=axs[1, 0], cmap='viridis', cbar_kws={'label': 'Maximum Hospitalized'}, annot=True, fmt=".0f") + axs[1, 0].set_title('Maximum Hospitalized') + # x and y axis labels + axs[1, 0].set_xticklabels(values_2) + axs[1, 0].set_yticklabels(values_1) + axs[1, 0].set_xlabel(variable_2) + axs[1, 0].set_ylabel(variable_1) + # fourth plot + value_for_values = np.zeros((len(values_1), len(values_2))) + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) + value_for_values[i, j] = get_maximum_cum_infected(path_data, index) + # permute the values, so that the plot is correct + value_for_values = np.flip(value_for_values, axis=1) + # we need a seaborn heatmap for the colorbar + sns.heatmap(value_for_values, ax=axs[1, 1], cmap='viridis', cbar_kws={'label': 'Maximum Cumulative Infections'}, annot=True, fmt=".0f") + axs[1, 1].set_title('Maximum Cumulative Infections') + # x and y axis labels + axs[1, 1].set_xticklabels(values_2) + axs[1, 1].set_yticklabels(values_1) + axs[1, 1].set_xlabel(variable_2) + axs[1, 1].set_ylabel(variable_1) + plt.show() + + - + + + + + + + From 440203529983b4455303dcb3c2e45e5010ff464a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:17:13 +0200 Subject: [PATCH 316/488] paper improv Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 37 ++++++++++++++++-------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 98bd0fa4e0..f4c8cf2b05 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1776,6 +1776,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { const double after_lockdown_contact_reduction = 0.55; const double ratio_asympt_to_sympt = 20.0; const double perc_easter_event = 0.25; + const auto quarantine_duration = mio::abm::days(10); + const double quarantine_effectiveness = 0.5; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 29; @@ -1873,7 +1875,8 @@ for (size_t i = 0; i < grid_search_rank.size(); i++) { sim.get_world().parameters.get() = viral_shedding_rate; sim.get_world().parameters.get() = masks; - + sim.get_world().parameters.get() = quarantine_effectiveness; + sim.get_world().parameters.get() = quarantine_duration; restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionPerLocationType, historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); @@ -1969,20 +1972,23 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s for (size_t par_i = 0; par_i < parameter_values.size(); par_i++) { auto params = parameter_values[par_i]; + std::cout << "Parameter values: "; + for (size_t j = 0; j < params.size(); j++) { + std::cout << params.at(j) << " "; + } + std::cout << std::endl; + auto run_distribution = distribute_runs(num_runs, num_procs); auto start_run_idx = std::accumulate(run_distribution.begin(), run_distribution.begin() + size_t(rank), size_t(0)); auto end_run_idx = start_run_idx + run_distribution[size_t(rank)]; - // const double viral_shedding_rate = 2.11; - const double viral_shedding_rate = params[0]; - // const double dark_figure = 3.0; - const double dark_figure = params[1]; - // const double contact_red_lockdown = 0.65; + const double viral_shedding_rate = params[0]; + const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; const double testing_probability_sympt = 0.036; - // const double testing_probability_sympt = params[0]; + // const double testing_probability_sympt = params[3]; const double lockdown_test_prob = 1.25; const double after_lockdown_test_prob = 0.75; @@ -1993,8 +1999,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double masks = 0.55; const double after_lockdown_contact_reduction = 0.55; const double ratio_asympt_to_sympt = 20.0; - // const double ratio_asympt_to_sympt = params[1]; - const double perc_easter_event = 0.2; + // const double ratio_asympt_to_sympt = params[4]; + const double perc_easter_event = 0.2; + const auto quarantine_duration = mio::abm::days(10); + const double quarantine_effectiveness = 0.5; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 29; @@ -2132,6 +2140,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.get_world().parameters.get() = viral_shedding_rate; sim.get_world().parameters.get() = masks; + sim.get_world().parameters.get() = quarantine_effectiveness; + sim.get_world().parameters.get() = quarantine_duration; restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), @@ -2223,11 +2233,14 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } } - rmse_results_per_grid_point.at(par_i) /= num_runs; - std::cout << "RMSE: " << rmse_results_per_grid_point.at(par_i) << std::endl; - printf("Saving results ... "); #ifdef MEMILIO_ENABLE_MPI + // gather rmse with reduce sum + double rmse_sum = 0; + MPI_Reduce(&rmse_results_per_grid_point.at(0), &rmse_sum, 1, MPI_DOUBLE, MPI_SUM, 0, mio::mpi::get_world()); + if (rank == 0) { + std::cout << "RMSE sum: " << rmse_sum << std::endl; + } //gather results auto final_ensemble_infection_per_loc_type_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type_per_age_group); From 33caa44c8faf85a7e4b0484c15067bb5d0ad0231 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 22 Aug 2024 00:30:12 +0200 Subject: [PATCH 317/488] upload for cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f4c8cf2b05..4b4803e769 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2224,6 +2224,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s rmse_results_per_grid_point.at(par_i) += rmse; + std::cout << "RMSE: " << rmse << std::endl; + //HACK since // gather_results(rank, num_procs, num_runs, ensemble_params); //for now this doesnt work, but we can still save the results of the last world since the //parameters are the same for each run @@ -2235,12 +2237,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } #ifdef MEMILIO_ENABLE_MPI - // gather rmse with reduce sum - double rmse_sum = 0; - MPI_Reduce(&rmse_results_per_grid_point.at(0), &rmse_sum, 1, MPI_DOUBLE, MPI_SUM, 0, mio::mpi::get_world()); - if (rank == 0) { - std::cout << "RMSE sum: " << rmse_sum << std::endl; - } + //gather results auto final_ensemble_infection_per_loc_type_per_age_group = gather_results(rank, num_procs, num_runs, ensemble_infection_per_loc_type_per_age_group); @@ -2369,8 +2366,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From 8f713e598166b214920b0fa014fa7eab4ba0dab5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:19:53 +0200 Subject: [PATCH 318/488] location fix --- cpp/models/abm/location.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 6c1b98890d..178847eb59 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -116,10 +116,6 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time ScalarType mask_protection = person.get_mask_protective_factor(global_params); assert(person.get_cells().size() && "Person is in multiple cells. Interact logic is incorrect at the moment."); - if (person.get_infection_state(t) != InfectionState::Susceptible && m_id.type == LocationType::Event) { - std::cout << "Person is not susc at event" << std::endl; - } - for (auto cell_index : person.get_cells()) { // TODO: the logic here is incorrect in case a person is in multiple cells std::pair local_indiv_expected_trans[static_cast(VirusVariant::Count)]; From 8d463061f65282400fc54809d435656ed8dc629e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 22 Aug 2024 23:48:13 +0200 Subject: [PATCH 319/488] some plot improvs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/parameter_varation.py | 16 +++++----------- cpp/simulations/scaling results.py | 6 +++--- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index 0836d5a27d..b02ca69d92 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -104,6 +104,11 @@ def get_maximum_cum_infected(path, index): values_1 = [0.01, 0.03, 0.05] values_2 = [5, 10, 30] + path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21224000" + variable_1 = "quarantine lenth" + variable_2 = "quarantine efficiancy" + values_1 = [2, 4, 8, 16] + values_2 = [0.1, 0.25, 0.5, 1.0] # we want to have a Grid Plot with the size of the values # in each grid we plot a certain plot which we can define # on the general structure of the plot we we write the values of the parameters @@ -266,16 +271,5 @@ def get_maximum_cum_infected(path, index): plt.show() - - - - - - - - - - - diff --git a/cpp/simulations/scaling results.py b/cpp/simulations/scaling results.py index 2d9e78dab3..b7153a3493 100644 --- a/cpp/simulations/scaling results.py +++ b/cpp/simulations/scaling results.py @@ -14,10 +14,10 @@ plt.figure() for i in range(len(runtime)): plt.plot(processors, runtime[i], marker='o') -plt.legend(['0.025 mio agents per processor', '0.05 mio agents per processor', '0.1 mio agents per processor', '0.2 mio agents per processor']) +plt.legend(['25k agents per processor', '50k agents per processor', '100k agents per processor', '200k agents per processor']) plt.xlabel('Number of Processors') plt.ylabel('Runtime (seconds)') -plt.title('Runtime vs. Number of Processors for 0.025/0.05/0.1/0.2 mio Agents per Processor for 10 days') +plt.title('Runtime vs. Number of Processors for 25/50/100/200 k Agents per Processor for 10 days') plt.grid(True) plt.show() @@ -35,7 +35,7 @@ plt.plot(processors, ideal_speedup, marker='o') plt.xlabel('Number of Processors') plt.ylabel('Speedup') -plt.title('Speedup vs. Number of Processors for 800k Agents') +plt.title('Speedup vs. Number of Processors for 6.4mio Agents') plt.legend(['Speedup', 'Ideal Speedup']) plt.grid(True) plt.show() From 1517632a16a1960e6ad64bd0d7df2603e4e86e3c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 22 Aug 2024 23:49:01 +0200 Subject: [PATCH 320/488] analysze results imrpv Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 102 +++++++++++++----------------- 1 file changed, 45 insertions(+), 57 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index d42f3fcf58..95b8b4f7bd 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -272,7 +272,7 @@ def plot_dead(path): # we need the real data json file cases_all_state_repdate_ma7 df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_age_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_age_ma7.json") # we just need the columns cases and date # we need to offset the dates by 19 day @@ -337,9 +337,8 @@ def plot_dead(path): plt.show() def plot_icu(path): - df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu = 0.47 - perc_of_critical_in_icu_age = [0.56,0.56,0.56,0.57,0.55,0.47] + df_abb = pd.read_json(path+"/../../../pydata/Germany/county_divi_ma7.json") + perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.55,0.54,0.46] # perc_of_critical_in_icu_age =0.47 age_group_access = ['Group1', 'Group2', 'Group3', @@ -357,67 +356,57 @@ def plot_icu(path): # we plot this against this the Amount of persons in the ICU from our model f_p50 = h5py.File( path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') - p50_bs = f_p50['0'] - total_50 = p50_bs['Total'][()] - total_50_age = p50_bs[age_group_access[0]][()] + total_50 = f_p50['0']['Total'][()][::24][0:90] + + total_50_age = f_p50['0'][age_group_access[0]][()] for i in range(6): - total_50_age += np.floor(p50_bs[age_group_access[i]][()]*perc_of_critical_in_icu_age[i]) - # we need just every 24th value - total_50 = total_50[::24] - total_50_age = total_50_age[::24] - # we just take the first 90 days - total_50 = total_50[0:90] - total_50_age = total_50_age[0:90] + total_50_age += f_p50['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_50_age = total_50_age[::24][0:90] # we plot this against this the Amount of persons in the ICU from our model f_p75 = h5py.File( path+"/infection_state_per_age_group/0/p75/Results.h5", 'r') - p75_bs = f_p75['0'] - total_75 = p75_bs['Total'][()] - # we need just every 24th value - total_75 = total_75[::24] - # we just take the first 90 days - total_75 = total_75[0:90] + total_75 = f_p75['0']['Total'][()][::24][0:90] + total_75_age = f_p75['0'][age_group_access[0]][()] + for i in range(6): + total_75_age += f_p75['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_75_age = total_75_age[::24][0:90] # same with 25 percentile f_p25 = h5py.File( path+"/infection_state_per_age_group/0/p25/Results.h5", 'r') - p25_bs = f_p25['0'] - total_25 = p25_bs['Total'][()] - # we need just every 24th value - total_25 = total_25[::24] - # we just take the first 90 days - total_25 = total_25[0:90] + total_25 = f_p25['0']['Total'][()][::24][0:90] + total_25_age = f_p25['0'][age_group_access[0]][()] + for i in range(6): + total_25_age += f_p25['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_25_age = total_25_age[::24][0:90] # same with 05 and 95 percentile f_p05 = h5py.File( path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') - p05_bs = f_p05['0'] - total_05 = p05_bs['Total'][()] - # we need just every 24th value - total_05 = total_05[::24] - # we just take the first 90 days - total_05 = total_05[0:90] + total_05 = f_p05['0']['Total'][()][::24][0:90] + total_05_age = f_p05['0'][age_group_access[0]][()] + for i in range(6): + total_05_age += f_p05['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_05_age = total_05_age[::24][0:90] f_p95 = h5py.File( path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') - p95_bs = f_p95['0'] - total_95 = p95_bs['Total'][()] - # we need just every 24th value - total_95 = total_95[::24] - # we just take the first 90 days - total_95 = total_95[0:90] + total_95 = f_p95['0']['Total'][()][::24][0:90] + total_95_age = f_p95['0'][age_group_access[0]][()] + for i in range(6): + total_95_age += f_p95['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_95_age = total_95_age[::24][0:90] - ICU_Simulation = np.floor(total_50[:, 5]*perc_of_critical_in_icu) - ICU_Simulation_age = np.floor(total_50_age[:, 5]) - ICU_Simulation75 = np.floor(total_75[:, 5]*perc_of_critical_in_icu) - ICU_Simulation25 = np.floor(total_25[:, 5]*perc_of_critical_in_icu) - ICU_Simulation05 = np.floor(total_05[:, 5]*perc_of_critical_in_icu) - ICU_Simulation95 = np.floor(total_95[:, 5]*perc_of_critical_in_icu) - ICU_Real = np.floor(df_abb['ICU'][0:90]) + ICU_Simulation = np.floor(total_50_age[:, 5]) + ICU_Simulation75 = np.floor(total_75_age[:, 5]) + ICU_Simulation25 = np.floor(total_25_age[:, 5]) + ICU_Simulation05 = np.floor(total_05_age[:, 5]) + ICU_Simulation95 = np.floor(total_95_age[:, 5]) + ICU_Real = np.ceil(df_abb['ICU'][0:90]) #smooth the data # ICU_Real = gaussian_filter1d(ICU_Real, sigma=1, mode='nearest') @@ -439,7 +428,6 @@ def plot_icu(path): ax.fill_between(df_abb['Date'][0:90],ICU_Simulation05, ICU_Simulation95, alpha=0.25, color='tab:blue') ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:blue') - ax.plot(df_abb['Date'][0:90], ICU_Simulation_age, color='tab:blue', linestyle='dashed') # we also write the rmse ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', @@ -447,7 +435,7 @@ def plot_icu(path): ax.set_xlabel('Date') ax.set_ylabel('Number of persons in an ICU') ax.title.set_text('Simulated and real ICU beds occupied') - ax.legend(['Real in ICU, smoothed','Simulated in ICU, Perc of Critical:'+str(perc_of_critical_in_icu)]) + ax.legend(['Real in ICU, smoothed','Simulated in ICU']) plt.show() def plot_tests(path): @@ -603,7 +591,7 @@ def infer_positive_tests(path): # we need the real data from the json file cases_all_county_age_repdate_ma7.json df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") # we just need the columns cases and date df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] # we need just the dates bewteen 2021-03-01 and 2021-06-01 @@ -710,7 +698,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -756,7 +744,7 @@ def plot_cumulative_detected_infections(path): # again the rmse - rmse_detected = ((df_abb - total_50)**2).mean()*(0.01*0.01) + rmse_detected = ((df_abb - total_50)**2).mean()*(0.01*0.01*0.05) total_50_diff = gaussian_filter1d(total_50_diff.flatten(), sigma=2, mode='nearest') total_50 = gaussian_filter1d(total_50.flatten(), sigma=2, mode='nearest') # we plot this @@ -846,8 +834,8 @@ def plot_positive_and_done_test(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/7/results_2024-08-21223144" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): @@ -855,12 +843,12 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infection_states_results(path) - plot_infections_loc_types_avarage(path) + # plot_infection_states_results(path) + # plot_infections_loc_types_avarage(path) plot_icu(path) - plot_dead(path) - plot_cumulative_detected_infections(path) - plot_positive_and_done_test(path) + # plot_dead(path) + # plot_cumulative_detected_infections(path) + # plot_positive_and_done_test(path) # infer_positive_tests(path) From c01c89eeed8fbab5cd2ddc2084ccb44597a5f584 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 22 Aug 2024 23:49:49 +0200 Subject: [PATCH 321/488] paper params Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4b4803e769..fa812f5a60 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2000,9 +2000,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double after_lockdown_contact_reduction = 0.55; const double ratio_asympt_to_sympt = 20.0; // const double ratio_asympt_to_sympt = params[4]; - const double perc_easter_event = 0.2; - const auto quarantine_duration = mio::abm::days(10); - const double quarantine_effectiveness = 0.5; + const double perc_easter_event = 0.2; + // const auto quarantine_duration = mio::abm::days(10); + // const double quarantine_effectiveness = 0.5; + const auto quarantine_duration = mio::abm::days(params[3]); + const double quarantine_effectiveness = params[4]; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 29; @@ -2366,8 +2368,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2431,7 +2433,8 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; - std::vector> parameters = {{2.3}, {2.6}, {0.55}}; + // std::vector> parameters = {{2.3}, {2.6}, {0.55}, {2, 4, 8, 16}, {0.1, 0.25, 0.5, 1.0}}; + std::vector> parameters = {{2.3}, {2.6}, {0.55}, {16}, {1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From a6392e49168b7f0c825fe8d8eaea8b7721bdc301 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:16:56 +0200 Subject: [PATCH 322/488] perf improcv loc flag Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 5 +++-- cpp/models/abm/location.cpp | 3 ++- cpp/models/abm/location.h | 1 + cpp/models/abm/person.cpp | 3 ++- cpp/models/abm/world.cpp | 4 +++- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index 8ec57ba5e9..c5472f0f3b 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -143,7 +143,7 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer state.ResumeTiming(); //simulated time should be long enough to have full infection runs and migration to every location - auto final_time = sim.get_time() + mio::abm::days(10); + auto final_time = sim.get_time() + mio::abm::days(1); sim.advance(final_time); //debug output can be enabled to check for unexpected results (e.g. infections dieing out) @@ -179,5 +179,6 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer // ->Unit(benchmark::kMillisecond); // BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) // ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_5000k_pt, 500000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_5000k_pt, 2500000, {14159265u, 35897932u}) + ->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index 89fa97386f..b0e8a14fdc 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -171,12 +171,13 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou cell.m_cached_exposure_rate_air.array().setZero(); for (auto&& p : cell.m_persons) { if (p->is_infected(t)) { + location_contaminated = true; auto& inf = p->get_infection(); auto virus = inf.get_virus_variant(); auto age = p->get_age(); double quarantine_factor = 1.0; if (p->is_in_quarantine(t_middlepoint, params)) { - quarantine_factor = 1-params.get(); + quarantine_factor = 1 - params.get(); } /* average infectivity over the time step * to second order accuracy using midpoint rule diff --git a/cpp/models/abm/location.h b/cpp/models/abm/location.h index 706339a3f6..a18510c017 100644 --- a/cpp/models/abm/location.h +++ b/cpp/models/abm/location.h @@ -106,6 +106,7 @@ class Location */ Location(LocationId loc_id, size_t num_agegroups = 1, uint32_t num_cells = 1); + bool location_contaminated = false; /** * @brief Construct a Location with provided parameters. * @param[in] loc_type The #LocationType. diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index f39d83aca1..6e01971844 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -67,7 +67,8 @@ void Person::interact(RandomNumberGenerator& rng, TimePoint t, TimeSpan dt, cons // m_location->interact(rng, *this, t, dt, params); // } if (get_infection_state(t) == InfectionState::Susceptible) { // Susceptible or Recovered people can be (re)infected - m_location->interact(rng, *this, t, dt, params); + if (m_location->location_contaminated) + m_location->interact(rng, *this, t, dt, params); } m_time_at_location += dt; } diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 0fb44332f3..32a5d953a1 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -170,7 +170,9 @@ void World::begin_step(TimePoint t, TimeSpan dt) m_testing_strategy.update_location_testing_schemes(t, get_locations()); PRAGMA_OMP(parallel for) for (auto i = size_t(0); i < m_locations.size(); ++i) { - auto&& location = m_locations[i]; + + auto&& location = m_locations[i]; + location->location_contaminated = false; // mio::unused(location, dt); location->adjust_contact_rates(parameters.get_num_groups()); location->cache_exposure_rates(t, dt, parameters.get_num_groups(), parameters); From 2121e0f6ff7fd3877e5b487d2f54dcd95227704a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 00:40:48 +0200 Subject: [PATCH 323/488] plot enhancement Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 30 ++++++++++++------------ cpp/simulations/paper_abm_bs_testing.cpp | 22 ++++++++--------- cpp/simulations/parameter_varation.py | 2 ++ 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 95b8b4f7bd..e5392e848a 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -272,7 +272,7 @@ def plot_dead(path): # we need the real data json file cases_all_state_repdate_ma7 df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_age_ma7.json") + path+"/../pydata/Germany/cases_all_county_age_ma7.json") # we just need the columns cases and date # we need to offset the dates by 19 day @@ -337,7 +337,7 @@ def plot_dead(path): plt.show() def plot_icu(path): - df_abb = pd.read_json(path+"/../../../pydata/Germany/county_divi_ma7.json") + df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.55,0.54,0.46] # perc_of_critical_in_icu_age =0.47 @@ -591,7 +591,7 @@ def infer_positive_tests(path): # we need the real data from the json file cases_all_county_age_repdate_ma7.json df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") # we just need the columns cases and date df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] # we need just the dates bewteen 2021-03-01 and 2021-06-01 @@ -698,7 +698,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -746,6 +746,8 @@ def plot_cumulative_detected_infections(path): # again the rmse rmse_detected = ((df_abb - total_50)**2).mean()*(0.01*0.01*0.05) total_50_diff = gaussian_filter1d(total_50_diff.flatten(), sigma=2, mode='nearest') + total_05_diff = gaussian_filter1d(total_05.flatten(), sigma=2, mode='nearest') + total_95_diff = gaussian_filter1d(total_95.flatten(), sigma=2, mode='nearest') total_50 = gaussian_filter1d(total_50.flatten(), sigma=2, mode='nearest') # we plot this # we plot the tests positive and the real cases @@ -771,7 +773,8 @@ def plot_cumulative_detected_infections(path): ax.plot(time[0:89], total_50_diff, color='tab:blue') # we dont plot the real curve as a line but as x points and not every day but every 2nd day ax.plot(time[0:89], df_abb_diff[0:89], 'x', color='tab:red') - + ax.fill_between(time[0:89], total_95_diff[0:89], total_05_diff[0:89], + alpha=0.5, color='tab:blue') ax.set_xlabel('time (days)') ax.set_ylabel('Number of new detected infections') ax.title.set_text('New detected infections') @@ -789,10 +792,7 @@ def plot_positive_and_done_test(path): p50_bs_done = f_p50_done['0'] total_50_done = p50_bs_done['Total'][()] - time = p50_bs_positive['Time'][()] - time = time[::24] - time = time[0:90] - + time = p50_bs_positive['Time'][()][::24][0:90] # weas one entry is one hour we take the sum every 24 entries to get the daily amount, we do this with cumsum # first we need to sum up over all age groups @@ -834,8 +834,8 @@ def plot_positive_and_done_test(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/7/results_2024-08-21223144" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/128_runs/results_2024-08-21224038" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): @@ -843,11 +843,11 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - # plot_infection_states_results(path) - # plot_infections_loc_types_avarage(path) + plot_infection_states_results(path) + plot_infections_loc_types_avarage(path) plot_icu(path) - # plot_dead(path) - # plot_cumulative_detected_infections(path) + plot_dead(path) + plot_cumulative_detected_infections(path) # plot_positive_and_done_test(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fa812f5a60..70eade7bb2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1987,8 +1987,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.036; - // const double testing_probability_sympt = params[3]; + // const double testing_probability_sympt = 0.036; + const double testing_probability_sympt = params[3]; const double lockdown_test_prob = 1.25; const double after_lockdown_test_prob = 0.75; @@ -1998,13 +1998,13 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double masks = 0.55; const double after_lockdown_contact_reduction = 0.55; - const double ratio_asympt_to_sympt = 20.0; - // const double ratio_asympt_to_sympt = params[4]; - const double perc_easter_event = 0.2; + // const double ratio_asympt_to_sympt = 20.0; + const double ratio_asympt_to_sympt = params[4]; + const double perc_easter_event = 0.2; // const auto quarantine_duration = mio::abm::days(10); // const double quarantine_effectiveness = 0.5; - const auto quarantine_duration = mio::abm::days(params[3]); - const double quarantine_effectiveness = params[4]; + const auto quarantine_duration = mio::abm::days(params[5]); + const double quarantine_effectiveness = params[6]; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 29; @@ -2368,8 +2368,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2432,9 +2432,9 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); } else { - // std::vector> parameters = {{0.01, 0.03, 0.05}, {5, 10, 30}}; + // std::vector> parameters = {{2.26}, {2.64}, {0.56}}; // std::vector> parameters = {{2.3}, {2.6}, {0.55}, {2, 4, 8, 16}, {0.1, 0.25, 0.5, 1.0}}; - std::vector> parameters = {{2.3}, {2.6}, {0.55}, {16}, {1.0}}; + std::vector> parameters = {{2.26}, {2.64}, {0.56}, {0.036}, {20.0}, {16}, {1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index b02ca69d92..86c3112102 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -203,6 +203,7 @@ def get_maximum_cum_infected(path, index): value_for_values[i, j] = get_maximum_cum_infected(path_data, index) # permute the values, so that the plot is correct value_for_values = np.flip(value_for_values, axis=1) + value_for_values = np.flip(value_for_values, axis=0) # we need a seaborn heatmap for the colorbar sns.heatmap(value_for_values, ax=axs[0, 0], cmap='viridis', cbar_kws={'label': 'Maximum Cumulative Infections'}, annot=True, fmt=".0f") @@ -226,6 +227,7 @@ def get_maximum_cum_infected(path, index): value_for_values[i, j] = get_maximum_dead(path_data, index) # permute the values, so that the plot is correct value_for_values = np.flip(value_for_values, axis=1) + value_for_values = np.flip(value_for_values, axis=0) # we need a seaborn heatmap for the colorbar sns.heatmap(value_for_values, ax=axs[0, 1], cmap='viridis', cbar_kws={'label': 'Maximum Dead'}, annot=True, fmt=".0f") axs[0, 1].set_title('Maximum Dead') From 1d8ebd3bb62f82c67b0db1fafd1bd49b86e83c69 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 01:00:28 +0200 Subject: [PATCH 324/488] scenario 2 cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 70eade7bb2..87207cf3e3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1986,18 +1986,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; + const double damping_community_lockdown = 1.0; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.25; - const double after_lockdown_test_prob = 0.75; + const double lockdown_test_prob = 1.00; + const double after_lockdown_test_prob = 1.00; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.55; + const double after_lockdown_contact_reduction = 1.0; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2106,8 +2106,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::School) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 + // location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + // 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2133,8 +2133,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 + // location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + // 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2434,7 +2434,8 @@ int main(int argc, char** argv) else { // std::vector> parameters = {{2.26}, {2.64}, {0.56}}; // std::vector> parameters = {{2.3}, {2.6}, {0.55}, {2, 4, 8, 16}, {0.1, 0.25, 0.5, 1.0}}; - std::vector> parameters = {{2.26}, {2.64}, {0.56}, {0.036}, {20.0}, {16}, {1.0}}; + std::vector> parameters = {{2.26}, {2.64}, {0.56}, {0.036, 0.072, 0.108}, + {20.0}, {16}, {1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From d54e6c8c4fb6d4fc9503aff9cb21cd305ffdb644 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 01:01:15 +0200 Subject: [PATCH 325/488] redo Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 87207cf3e3..70eade7bb2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1986,18 +1986,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 1.0; + const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.00; - const double after_lockdown_test_prob = 1.00; + const double lockdown_test_prob = 1.25; + const double after_lockdown_test_prob = 0.75; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.55; - const double after_lockdown_contact_reduction = 1.0; + const double after_lockdown_contact_reduction = 0.55; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2106,8 +2106,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::School) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); - // location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - // 0.00); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2133,8 +2133,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); - // location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - // 0.7); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2434,8 +2434,7 @@ int main(int argc, char** argv) else { // std::vector> parameters = {{2.26}, {2.64}, {0.56}}; // std::vector> parameters = {{2.3}, {2.6}, {0.55}, {2, 4, 8, 16}, {0.1, 0.25, 0.5, 1.0}}; - std::vector> parameters = {{2.26}, {2.64}, {0.56}, {0.036, 0.072, 0.108}, - {20.0}, {16}, {1.0}}; + std::vector> parameters = {{2.26}, {2.64}, {0.56}, {0.036}, {20.0}, {16}, {1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 0c7872ed5cfc07f30a3acaee6695b23d1a53e1b4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 01:01:27 +0200 Subject: [PATCH 326/488] par var Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/parameter_varation.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index 86c3112102..a4f562c410 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -98,17 +98,25 @@ def get_maximum_cum_infected(path, index): if __name__ == "__main__": - path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-15140128" + # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-15140128" variable_1 = "test_likelihood_symptom" variable_2 = "test_likelihood_asymptom" - values_1 = [0.01, 0.03, 0.05] - values_2 = [5, 10, 30] + values_1 = [0.018,0.036,0.054,0.072,0.09] + values_2 = [40,30,20,10,1] path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21224000" variable_1 = "quarantine lenth" variable_2 = "quarantine efficiancy" - values_1 = [2, 4, 8, 16] - values_2 = [0.1, 0.25, 0.5, 1.0] + values_1 = [1,4,7,10,13,16] + values_2 = [0.0,0.25,0.5,0.75,1.0] + + path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21224000" + variable_1 = "test_likelihood_symptom" + variable_2 = "quarantine lenth" + values_1 = [0.018,0.036,0.054,0.072,0.09] + values_2 = [1,4,7,10,13,16] + + # we want to have a Grid Plot with the size of the values # in each grid we plot a certain plot which we can define # on the general structure of the plot we we write the values of the parameters From 441128ac3dacad77d4e6362e37fb6517878cb9b2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:30:39 +0200 Subject: [PATCH 327/488] short easter event diff --- cpp/models/abm/migration_rules.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/abm/migration_rules.cpp b/cpp/models/abm/migration_rules.cpp index fc0793acd9..04a698f8cf 100644 --- a/cpp/models/abm/migration_rules.cpp +++ b/cpp/models/abm/migration_rules.cpp @@ -185,7 +185,7 @@ LocationType easter_party(Person::RandomNumberGenerator& /*rng*/, const Person& auto current_loc = person.get_location().get_type(); //leave if (person.get_goes_to_easter() && t.days() > 35.0 && t.days() < 37.0 && (t.hour_of_day() >= 12) && - (t.hour_of_day() <= 22) && !person.is_in_quarantine(t, params)) { + (t.hour_of_day() <= 20) && !person.is_in_quarantine(t, params)) { return LocationType::Event; } From fa1652ea48ee218225d7f7e8ce05a148c8cc8154 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:31:08 +0200 Subject: [PATCH 328/488] mask improv Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/location.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/models/abm/location.cpp b/cpp/models/abm/location.cpp index b0e8a14fdc..3f40521961 100644 --- a/cpp/models/abm/location.cpp +++ b/cpp/models/abm/location.cpp @@ -121,12 +121,12 @@ void Location::interact(Person::RandomNumberGenerator& rng, Person& person, Time std::pair local_indiv_expected_trans[static_cast(VirusVariant::Count)]; for (uint32_t v = 0; v != static_cast(VirusVariant::Count); ++v) { VirusVariant virus = static_cast(v); - ScalarType local_indiv_expected_trans_v = + ScalarType exposed_viral_shed = (transmission_contacts_per_day(cell_index, virus, age_receiver, global_params.get_num_groups()) + transmission_air_per_day(cell_index, virus, global_params)) * (1 - mask_protection) * (1 - person.get_protection_factor(t, virus, global_params)); - - local_indiv_expected_trans[v] = std::make_pair(virus, local_indiv_expected_trans_v); + ScalarType infection_rate = global_params.get()[{virus}] * exposed_viral_shed; + local_indiv_expected_trans[v] = std::make_pair(virus, infection_rate); } VirusVariant virus = random_transition(rng, VirusVariant::Count, dt, @@ -183,8 +183,7 @@ void Location::cache_exposure_rates(TimePoint t, TimeSpan dt, size_t num_agegrou * to second order accuracy using midpoint rule */ cell.m_cached_exposure_rate_contacts[{virus, age}] += - params.get()[{virus}] * inf.get_viral_shed(t_middlepoint) * - quarantine_factor; + inf.get_viral_shed(t_middlepoint) * quarantine_factor * (1 - p->get_mask_protective_factor(params)); cell.m_cached_exposure_rate_air[{virus}] += inf.get_viral_shed(t_middlepoint); // TODO: Adapt function/factor for air transmission. } From baf98150c870d40d3e4ee72494f3c99ad4448653 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:13:48 +0200 Subject: [PATCH 329/488] dath date before 16 days Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/ode_secir/parameters_io.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index 5df16c934f..b179138211 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -170,7 +170,7 @@ IOResult read_confirmed_cases_data( 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, -19)) { + if (date_df == offset_date_by_days(date, -16)) { num_death[age] += region_entry.num_deaths; if (read_icu) { num_icu[age] -= mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * region_entry.num_confirmed; From 50ea98c2577931f7f40d1cd1302491830f288a73 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:14:57 +0200 Subject: [PATCH 330/488] some plot improvs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 76 ++++++++++++++++++------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index e5392e848a..98c6afe0a6 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -276,7 +276,7 @@ def plot_dead(path): # we just need the columns cases and date # we need to offset the dates by 19 day - df_abb['Date'] = df_abb['Date'] + pd.DateOffset(days=19) + df_abb['Date'] = df_abb['Date'] + pd.DateOffset(days=16) # we need just the dates bewteen 2021-03-01 and 2021-06-01 df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -337,9 +337,11 @@ def plot_dead(path): plt.show() def plot_icu(path): - df_abb = pd.read_json(path+"/../pydata/Germany/county_divi_ma7.json") - perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.55,0.54,0.46] - # perc_of_critical_in_icu_age =0.47 + + df_abb = pd.read_json(path+"/../pydata/Germany/county_divi.json") + + perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.56,0.54,0.46] + perc_of_critical_in_icu=0.55 age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] @@ -367,7 +369,7 @@ def plot_icu(path): # we plot this against this the Amount of persons in the ICU from our model f_p75 = h5py.File( path+"/infection_state_per_age_group/0/p75/Results.h5", 'r') - total_75 = f_p75['0']['Total'][()][::24][0:90] + # total_75 = f_p75['0']['Total'][()][::24][0:90] total_75_age = f_p75['0'][age_group_access[0]][()] for i in range(6): total_75_age += f_p75['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] @@ -376,7 +378,7 @@ def plot_icu(path): # same with 25 percentile f_p25 = h5py.File( path+"/infection_state_per_age_group/0/p25/Results.h5", 'r') - total_25 = f_p25['0']['Total'][()][::24][0:90] + # total_25 = f_p25['0']['Total'][()][::24][0:90] total_25_age = f_p25['0'][age_group_access[0]][()] for i in range(6): total_25_age += f_p25['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] @@ -385,7 +387,7 @@ def plot_icu(path): # same with 05 and 95 percentile f_p05 = h5py.File( path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') - total_05 = f_p05['0']['Total'][()][::24][0:90] + # total_05 = f_p05['0']['Total'][()][::24][0:90] total_05_age = f_p05['0'][age_group_access[0]][()] for i in range(6): total_05_age += f_p05['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] @@ -393,20 +395,20 @@ def plot_icu(path): f_p95 = h5py.File( path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') - total_95 = f_p95['0']['Total'][()][::24][0:90] + # total_95 = f_p95['0']['Total'][()][::24][0:90] total_95_age = f_p95['0'][age_group_access[0]][()] for i in range(6): total_95_age += f_p95['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] total_95_age = total_95_age[::24][0:90] - - ICU_Simulation = np.floor(total_50_age[:, 5]) - ICU_Simulation75 = np.floor(total_75_age[:, 5]) - ICU_Simulation25 = np.floor(total_25_age[:, 5]) - ICU_Simulation05 = np.floor(total_05_age[:, 5]) - ICU_Simulation95 = np.floor(total_95_age[:, 5]) - ICU_Real = np.ceil(df_abb['ICU'][0:90]) + ICU_Simulation_one_percentile = np.floor(total_50[:, 5]*perc_of_critical_in_icu) + ICU_Simulation = np.round(total_50_age[:, 5]) + ICU_Simulation75 = np.round(total_75_age[:, 5]) + ICU_Simulation25 = np.round(total_25_age[:, 5]) + ICU_Simulation05 = np.round(total_05_age[:, 5]) + ICU_Simulation95 = np.round(total_95_age[:, 5]) + ICU_Real = np.round(df_abb['ICU'][0:90]) #smooth the data # ICU_Real = gaussian_filter1d(ICU_Real, sigma=1, mode='nearest') @@ -423,6 +425,7 @@ def plot_icu(path): fig.set_figheight(9) # we plot the ICU_low and the ICU_high ax.plot(df_abb['Date'][0:90], ICU_Real,'x', color='tab:red') + ax.plot(df_abb['Date'][0:90], ICU_Simulation_one_percentile, color='tab:green') ax.fill_between(df_abb['Date'][0:90],ICU_Simulation75, ICU_Simulation25, alpha=0.5, color='tab:blue') ax.fill_between(df_abb['Date'][0:90],ICU_Simulation05, ICU_Simulation95, @@ -711,34 +714,37 @@ def plot_cumulative_detected_infections(path): f_p50 = h5py.File( path+"/cumulative_detected_infections/0/p50/Results.h5", 'r') - p50_bs = f_p50['0'] - total_50 = p50_bs['Total'][()] - total_50 = total_50[::24] - total_50 = np.floor(total_50[0:90].flatten()) + total_50 = np.floor(f_p50['0']['Total'][()][::24][0:90].flatten()) # we smooth this with a gaussian filter f_p95 = h5py.File( path+"/cumulative_detected_infections/0/p95/Results.h5", 'r') - p95_bs = f_p95['0'] - total_95 = p95_bs['Total'][()] - total_95 = total_95[::24] - total_95 = np.floor(total_95[0:90].flatten()) + total_95 = np.floor(f_p95['0']['Total'][()][::24][0:90].flatten()) f_p05 = h5py.File( path+"/cumulative_detected_infections/0/p05/Results.h5", 'r') - p05_bs = f_p05['0'] - total_05 = p05_bs['Total'][()] - total_05 = total_05[::24] - total_05 = np.floor(total_05[0:90].flatten()) + total_05 = np.floor(f_p05['0']['Total'][()][::24][0:90].flatten()) + + f_p25 = h5py.File( + path+"/cumulative_detected_infections/0/p25/Results.h5", 'r') + total_25 = np.floor(f_p25['0']['Total'][()][::24][0:90].flatten()) + + f_p75 = h5py.File( + path+"/cumulative_detected_infections/0/p75/Results.h5", 'r') + total_75 = np.floor(f_p75['0']['Total'][()][::24][0:90].flatten()) # we smooth this with a gaussian filter - time = p50_bs['Time'][()] + time = f_p50['0']['Time'][()] time = time[::24] time = time[0:90] # we also plot the amount of new detected infections with diff total_50_diff = np.diff(total_50) + total_95_diff = np.diff(total_95) + total_05_diff = np.diff(total_05) + total_25_diff = np.diff(total_25) + total_75_diff = np.diff(total_75) df_abb_diff = np.diff(df_abb) @@ -746,15 +752,21 @@ def plot_cumulative_detected_infections(path): # again the rmse rmse_detected = ((df_abb - total_50)**2).mean()*(0.01*0.01*0.05) total_50_diff = gaussian_filter1d(total_50_diff.flatten(), sigma=2, mode='nearest') - total_05_diff = gaussian_filter1d(total_05.flatten(), sigma=2, mode='nearest') - total_95_diff = gaussian_filter1d(total_95.flatten(), sigma=2, mode='nearest') + total_05_diff = gaussian_filter1d(total_05_diff.flatten(), sigma=2, mode='nearest') + total_95_diff = gaussian_filter1d(total_95_diff.flatten(), sigma=2, mode='nearest') + total_75_diff = gaussian_filter1d(total_75_diff.flatten(), sigma=2, mode='nearest') + total_25_diff = gaussian_filter1d(total_25_diff.flatten(), sigma=2, mode='nearest') total_50 = gaussian_filter1d(total_50.flatten(), sigma=2, mode='nearest') + # we plot this # we plot the tests positive and the real cases plt.plot(time, total_50, color='tab:blue') plt.plot(time, df_abb, 'x', color='tab:red') plt.fill_between(time, total_95, total_05, + alpha=0.75, color='tab:blue') + plt.fill_between(time, total_75, total_25, alpha=0.5, color='tab:blue') + plt.xlabel('time (days)') plt.ylabel('Cumulative Amount of detected infections') plt.title('Cumulative detected infections') @@ -774,6 +786,8 @@ def plot_cumulative_detected_infections(path): # we dont plot the real curve as a line but as x points and not every day but every 2nd day ax.plot(time[0:89], df_abb_diff[0:89], 'x', color='tab:red') ax.fill_between(time[0:89], total_95_diff[0:89], total_05_diff[0:89], + alpha=0.75, color='tab:blue') + ax.fill_between(time[0:89], total_75_diff[0:89], total_25_diff[0:89], alpha=0.5, color='tab:blue') ax.set_xlabel('time (days)') ax.set_ylabel('Number of new detected infections') @@ -848,7 +862,7 @@ def plot_positive_and_done_test(path): plot_icu(path) plot_dead(path) plot_cumulative_detected_infections(path) - # plot_positive_and_done_test(path) + plot_positive_and_done_test(path) # infer_positive_tests(path) From d453ce9df3019f1e94d034fe448eeaabbac6e23a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:37:05 +0200 Subject: [PATCH 331/488] better rmse icu Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 98c6afe0a6..4ed8d78e7b 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -417,7 +417,7 @@ def plot_icu(path): # we calculate the RMSE - rmse_ICU = ((ICU_Real - ICU_Simulation)**2).mean() + rmse_ICU = ((ICU_Real - ICU_Simulation_one_percentile)**2).mean() # plot the ICU beds and the ICU beds taken fig, ax = plt.subplots(1, 1, constrained_layout=True) From 0245dfb5d92630873331474dc88adc3a5fa9a234 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 17:50:53 +0200 Subject: [PATCH 332/488] 18 days dead and paper sim improvs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 8 +- cpp/models/ode_secir/parameters_io.cpp | 2 +- cpp/simulations/analyze_bs_run.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 424 ++++++++++------------- 4 files changed, 194 insertions(+), 242 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 32a5d953a1..4a29c1dfea 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for ) + // #pragma omp parallel for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - PRAGMA_OMP(parallel for) + // #pragma omp parallel for for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,10 +168,10 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); - PRAGMA_OMP(parallel for) + // #pragma omp parallel for for (auto i = size_t(0); i < m_locations.size(); ++i) { - auto&& location = m_locations[i]; + auto&& location = m_locations[i]; location->location_contaminated = false; // mio::unused(location, dt); location->adjust_contact_rates(parameters.get_num_groups()); diff --git a/cpp/models/ode_secir/parameters_io.cpp b/cpp/models/ode_secir/parameters_io.cpp index b179138211..bacbc677f9 100644 --- a/cpp/models/ode_secir/parameters_io.cpp +++ b/cpp/models/ode_secir/parameters_io.cpp @@ -170,7 +170,7 @@ IOResult read_confirmed_cases_data( 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, -16)) { + if (date_df == offset_date_by_days(date, -18)) { num_death[age] += region_entry.num_deaths; if (read_icu) { num_icu[age] -= mu_I_H[age] * mu_H_U[age] * scaling_factor_inf[age] * region_entry.num_confirmed; diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 4ed8d78e7b..3b6a2ea724 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -276,7 +276,7 @@ def plot_dead(path): # we just need the columns cases and date # we need to offset the dates by 19 day - df_abb['Date'] = df_abb['Date'] + pd.DateOffset(days=16) + df_abb['Date'] = df_abb['Date'] + pd.DateOffset(days=18) # we need just the dates bewteen 2021-03-01 and 2021-06-01 df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 70eade7bb2..a7ac3751fd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -576,8 +576,6 @@ std::pair get_my_and_sigma(std::pair mean_and_st void set_parameters(mio::abm::Parameters& params) { - mio::RandomNumberGenerator rng; - // Set the Time parameters for the infection same for every age group for now auto incubation_period_my_sigma = get_my_and_sigma({4.5, 1.5}); @@ -616,9 +614,9 @@ void set_parameters(mio::abm::Parameters& params) TimeInfectedCriticalToRecovered_my_sigma.second}; //Set testing parameters - auto pcr_test_values = mio::abm::TestParameters{0.9, 0.995}; - auto antigen_test_values = mio::abm::TestParameters{0.71, 0.993}; - auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; + auto pcr_test_values = mio::abm::TestParameters{0.9, 0.995}; + auto antigen_test_values = mio::abm::TestParameters{0.71, 0.996}; //https://doi.org/10.1016/j.eclinm.2021.100954 + auto generic_test_values = mio::abm::TestParameters{0.7, 0.95}; params.get()[mio::abm::TestType::PCR] = pcr_test_values; params.get()[mio::abm::TestType::Antigen] = antigen_test_values; params.get()[mio::abm::TestType::Generic] = generic_test_values; @@ -653,14 +651,14 @@ void set_parameters(mio::abm::Parameters& params) params.get()[{mio::abm::VirusVariant::Alpha, age_group_80_plus}] = 0.48; // Set infection parameters - // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 + // Set protection level against an severe infection. Information based on: https://doi.org/10.1016/j.ebiom.2023.104734, https://www.sciencedirect.com/science/article/pii/S2590113322000062 params.get() = [](ScalarType days) -> ScalarType { return mio::linear_interpolation_of_data_set({{0, 0.8}, {150, 0.8}}, days); }; - // Set protection level against an severe infection. Information based on: https://doi.org/10.1093/cid/ciaa886 + // Set protection level against an infection. Information based on: 10.1016/j.vaccine.2023.03.069 params.get() = [](ScalarType days) -> ScalarType { - return mio::linear_interpolation_of_data_set({{0, 0.6}, {150, 0.6}}, days); + return mio::linear_interpolation_of_data_set({{0, 0.0}, {150, 0.0}}, days); }; //Set other parameters @@ -866,37 +864,33 @@ void set_local_parameters(mio::abm::World& world) {mio::AgeGroup(n_age_groups), mio::AgeGroup(n_age_groups)}, 1.0); for (auto& loc : world.get_locations()) { - // # we assume that a 20:5:3:1:1 ratio of contacts is made at home:school:work:SocialEv:basicshopping - // 16hours home 3h arbeiten 1h school 3h social und 1h basic shopping - // First line: Sclaing according to which Timespan the contatcs have to be made - // Second Line: Normalizing to 24 hours - // Third Line: Scaling according intensity of contacts switch (loc.get_type()) { case mio::abm::LocationType::Home: loc.get_infection_parameters().get() = contacts_home; - loc.get_infection_parameters().get().array() *= 1.6; + loc.get_infection_parameters().get().array() *= 1.6; //15 hours break; case mio::abm::LocationType::School: loc.get_infection_parameters().get() = contacts_school; - loc.get_infection_parameters().get().array() *= 12.0; + loc.get_infection_parameters().get().array() *= 12.0; //2 hours break; case mio::abm::LocationType::Work: loc.get_infection_parameters().get() = contacts_work; - loc.get_infection_parameters().get().array() *= 8.0; + loc.get_infection_parameters().get().array() *= 8.0; // 3 hours break; case mio::abm::LocationType::SocialEvent: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= 1.2; - loc.get_infection_parameters().get().array() *= 8.0; + loc.get_infection_parameters().get().array() *= 8.0; // 3 hours break; case mio::abm::LocationType::BasicsShop: loc.get_infection_parameters().get() = contacts_other; loc.get_infection_parameters().get().array() *= 0.8; - loc.get_infection_parameters().get().array() *= 12.0; + loc.get_infection_parameters().get().array() *= 12.0; // 2 hours break; case mio::abm::LocationType::Event: loc.get_infection_parameters().get() = contacts_home; - loc.get_infection_parameters().get().array() *= 32; + loc.get_infection_parameters().get().array() *= + 8 * 4; //3 hours with special intensivity break; default: loc.get_infection_parameters().get() = contacts_random; @@ -905,41 +899,6 @@ void set_local_parameters(mio::abm::World& world) } } -/** - * @brief Add testing strategies to the world. -*/ -void add_testing_strategies(mio::abm::World& world, bool symptomatic, bool social_event) -{ - if (symptomatic) { - std::cout << "Adding symptomatic testing strategy" << std::endl; - auto testing_min_time_symptomatic = mio::abm::days(7); - auto probability_symptomatic = 0.1; - auto start_date_test_symptomatic = mio::abm::TimePoint(mio::abm::days(0).seconds()); // 2021-04-12 - auto end_date_test_symptomatic = mio::abm::TimePoint(mio::abm::days(90).seconds()); // 2021-05-30 - auto test_type_symptomatic = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = world.parameters.get()[test_type_symptomatic]; // Test parameters - auto testing_criteria_symptomatic = mio::abm::TestingCriteria(); - testing_criteria_symptomatic.add_infection_state(mio::abm::InfectionState::InfectedSymptoms); - auto testing_scheme_symptomatic = mio::abm::TestingScheme( - testing_criteria_symptomatic, testing_min_time_symptomatic, start_date_test_symptomatic, - end_date_test_symptomatic, test_parameters, probability_symptomatic); - world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Home, testing_scheme_symptomatic); - } - if (social_event) { - auto testing_min_time_socev = mio::abm::days(7); - auto probability_socev = 0.8; - auto start_date_test_socev = mio::abm::TimePoint(mio::abm::days(0).seconds()); - auto end_date_test_socev = mio::abm::TimePoint(mio::abm::days(90).seconds()); - auto test_type_socev = mio::abm::TestType::Antigen; // Antigen test - auto test_parameters = world.parameters.get()[test_type_socev]; // Test parameters - auto testing_criteria_socev = mio::abm::TestingCriteria(); - auto testing_scheme_socev = - mio::abm::TestingScheme(testing_criteria_socev, testing_min_time_socev, start_date_test_socev, - end_date_test_socev, test_parameters, probability_socev); - world.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::SocialEvent, testing_scheme_socev); - } -} - std::vector read_in_icu(std::vector divi_data, mio::Date start_date, int max_num_days) { std::vector icu_data; @@ -957,7 +916,7 @@ std::vector read_in_deaths(std::vector rki_da int max_num_days) { std::vector> death_data_age{num_age_groupss}; - auto date_need = mio::offset_date_by_days(start_date, -19); + auto date_need = mio::offset_date_by_days(start_date, -18); for (auto& entry : rki_data) { if (entry.county_id->get() == 3101) { if (entry.date >= date_need && entry.date < mio::offset_date_by_days(date_need, max_num_days)) { @@ -1052,7 +1011,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -PRAGMA_OMP(parallel for num_threads(90) ) -for (size_t i = 0; i < grid_search_rank.size(); i++) { - auto params = grid_search_rank[i]; - std::random_device rd; - std::mt19937 g(rd()); +#pragma omp parallel for num_threads(90) + for (size_t i = 0; i < grid_search_rank.size(); i++) { + auto params = grid_search_rank[i]; + std::random_device rd; + std::mt19937 g(rd()); - printf("I am Thread %d\n", omp_get_thread_num()); - - const double viral_shedding_rate = params[0]; - const double dark_figure = params[1]; - const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.036; - - const double lockdown_test_prob = 1.25; - const auto after_lockdown_test_prob = 0.75; - - const auto seasonality_april = 0.95; - const auto seasonality_may = 0.85; - - const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.55; - const double ratio_asympt_to_sympt = 20.0; - const double perc_easter_event = 0.25; - const auto quarantine_duration = mio::abm::days(10); - const double quarantine_effectiveness = 0.5; - - mio::Date start_date{2021, 3, 1}; - int date_of_lockdown = 29; - int end_date_of_lockdown = 61; - int max_num_days = 90; - auto max_num_persons = 400000; - - auto t0 = mio::abm::TimePoint(0); // Start time per simulation - auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation - - // Determine inital infection state distribution - restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date, dark_figure); - restart_timer(timer, "time for determine_initial_infection_states_world"); - prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), - (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); - restart_timer(timer, "time for vaccinaiton state"); - for (int j = 0; j < num_runs; j++) { + printf("I am Thread %d\n", omp_get_thread_num()); - // Loop over a number of runs - auto world = mio::abm::World(num_age_groupss); + const double viral_shedding_rate = params[0]; + const double dark_figure = params[1]; + const double contact_red_lockdown = params[2]; + const double damping_community_lockdown = 0.5; + const double testing_probability_sympt = 0.036; - create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); + const double lockdown_test_prob = 1.25; + const auto after_lockdown_test_prob = 0.75; - restart_timer(timer, "time taken for create sampled world"); - auto sim = mio::abm::Simulation(t0, std::move(world)); + const auto seasonality_april = 0.95; + const auto seasonality_may = 0.85; - //Logger - mio::History - historyInfectionPerLocationType{ - Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; - mio::History historyInfectionStatePerAgeGroup{ - Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; - mio::History - historyCumulativeDetectedInfectionsPerAgeGroup{Eigen::Index(sim.get_world().parameters.get_num_groups())}; + const double masks = 0.25; + const double after_lockdown_contact_reduction = 0.50; + const double ratio_asympt_to_sympt = 20.0; + const double perc_easter_event = 0.2; + const auto quarantine_duration = mio::abm::days(10); + const double quarantine_effectiveness = 0.5; - // / NPIS// + mio::Date start_date{2021, 3, 1}; + int date_of_lockdown = 29; + int end_date_of_lockdown = 60; + int max_num_days = 90; + auto max_num_persons = 400000; - const auto location_it = sim.get_world().get_locations(); + auto t0 = mio::abm::TimePoint(0); // Start time per simulation + auto tmax = mio::abm::TimePoint(0) + mio::abm::days(max_num_days); // End time per simulation - // 1. Add testing strategies + // Determine inital infection state distribution + restart_timer(timer, "time for initial setup"); + determine_initial_infection_states_world(input_dir, start_date, dark_figure); + restart_timer(timer, "time for determine_initial_infection_states_world"); + prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); + restart_timer(timer, "time for vaccinaiton state"); + for (int j = 0; j < num_runs; j++) { - add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, - lockdown_test_prob, after_lockdown_test_prob); + // Loop over a number of runs + auto world = mio::abm::World(num_age_groupss); - // 2. Mask schemes for all locations - // First set all locations to have mask usage, we need ffp2 masks - for (auto& location : location_it) { - location.set_required_mask(mio::abm::MaskType::FFP2); - if (location.get_type() == mio::abm::LocationType::Home) { - location.set_npi_active(false); - } - else { - location.set_npi_active(true); - } - } + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); - // 3. Dampings everywhere except home - for (auto& location : location_it) { - if (location.get_type() == mio::abm::LocationType::School) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 - location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.5); // from 2021-04-12 till 2021-05-30 - } - if (location.get_type() == mio::abm::LocationType::BasicsShop) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - damping_community_lockdown); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.8); // from 2021-03-15 - } - if (location.get_type() == mio::abm::LocationType::SocialEvent) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.5); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - damping_community_lockdown); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.8); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(mio::abm::days(72).seconds()).seconds()), - 0.2); // from 2021-03-15 + restart_timer(timer, "time taken for create sampled world"); + auto sim = mio::abm::Simulation(t0, std::move(world)); + + //Logger + mio::History + historyInfectionPerLocationType{ + Eigen::Index((size_t)mio::abm::LocationType::Count * sim.get_world().parameters.get_num_groups())}; + mio::History historyInfectionStatePerAgeGroup{ + Eigen::Index((size_t)mio::abm::InfectionState::Count * sim.get_world().parameters.get_num_groups())}; + mio::History + historyCumulativeDetectedInfectionsPerAgeGroup{ + Eigen::Index(sim.get_world().parameters.get_num_groups())}; + + // / NPIS// + + const auto location_it = sim.get_world().get_locations(); + + // 1. Add testing strategies + + add_npi_testing_strategies_to_world(sim, tmax, testing_probability_sympt, ratio_asympt_to_sympt, + lockdown_test_prob, after_lockdown_test_prob); + + // 2. Mask schemes for all locations + // First set all locations to have mask usage, we need ffp2 masks + for (auto& location : location_it) { + location.set_required_mask(mio::abm::MaskType::FFP2); + if (location.get_type() == mio::abm::LocationType::Home) { + location.set_npi_active(false); + } + else { + location.set_npi_active(true); + } } - if (location.get_type() == mio::abm::LocationType::Work) { - location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 - // location.get_infection_parameters().get().array() *= (0.75 * 0.75); - location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 - location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), - 0.75); // from 2021-03-15 + + // 3. Dampings everywhere except home + for (auto& location : location_it) { + if (location.get_type() == mio::abm::LocationType::School) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 + location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.00); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.5); // from 2021-04-12 till 2021-05-30 + } + if (location.get_type() == mio::abm::LocationType::BasicsShop) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + damping_community_lockdown); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::SocialEvent) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.8); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.5); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + damping_community_lockdown); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.8); // from 2021-03-15 + } + if (location.get_type() == mio::abm::LocationType::Work) { + location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 + // location.get_infection_parameters().get().array() *= (0.75 * 0.75); + location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + 0.7); // from 2021-03-15 + location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + 0.75); // from 2021-03-15 + } } - } - sim.get_world().parameters.get() = viral_shedding_rate; - sim.get_world().parameters.get() = masks; - sim.get_world().parameters.get() = quarantine_effectiveness; - sim.get_world().parameters.get() = quarantine_duration; - restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), historyInfectionPerLocationType, - historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); - sim.get_world().parameters.get() = - viral_shedding_rate * seasonality_april; - - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= - contact_red_lockdown * contact_red_lockdown; + sim.get_world().parameters.get() = viral_shedding_rate; + sim.get_world().parameters.get() = masks; + sim.get_world().parameters.get() = quarantine_effectiveness; + sim.get_world().parameters.get() = quarantine_duration; + + sim.advance(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), + historyInfectionPerLocationType, historyInfectionStatePerAgeGroup, + historyCumulativeDetectedInfectionsPerAgeGroup); + sim.get_world().parameters.get() = + viral_shedding_rate * seasonality_april; + + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= contact_red_lockdown; + } } - } - restart_timer(timer, "till advance 62 & lockdown ends"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), historyInfectionPerLocationType, - historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); + sim.advance(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), + historyInfectionPerLocationType, historyInfectionStatePerAgeGroup, + historyCumulativeDetectedInfectionsPerAgeGroup); - for (auto& location : location_it) { - if (location.get_type() != mio::abm::LocationType::Home) { - location.get_infection_parameters().get().array() *= - (1 / (contact_red_lockdown * contact_red_lockdown)) * after_lockdown_contact_reduction; + for (auto& location : location_it) { + if (location.get_type() != mio::abm::LocationType::Home) { + location.get_infection_parameters().get().array() *= + (1 / (contact_red_lockdown)) * after_lockdown_contact_reduction; + } } + sim.get_world().parameters.get() = + viral_shedding_rate * seasonality_may; + + sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationType, + historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); + + ////Advance till here + // Stop the clock after sim.advance and calculate the duration + + // TODO: update result of the simulation to be a vector of location result. + auto temp_sim_infection_per_loc_tpye = + std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; + auto temp_sim_infection_state_per_age_group = + std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; + auto temp_sim_cumulative_detected_infections_per_age_group = std::vector>{ + std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; + + auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], + temp_sim_cumulative_detected_infections_per_age_group[0], + max_num_days, start_date); + rmse_results_per_grid_point.at(i) += rmse; } - sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; - restart_timer(timer, "till advance tmax "); - sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationType, - historyInfectionStatePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup); - - ////Advance till here - // Stop the clock after sim.advance and calculate the duration - restart_timer(timer, "time taken for simulation end"); - // TODO: update result of the simulation to be a vector of location result. - auto temp_sim_infection_per_loc_tpye = - std::vector>{std::get<0>(historyInfectionPerLocationType.get_log())}; - auto temp_sim_infection_state_per_age_group = - std::vector>{std::get<0>(historyInfectionStatePerAgeGroup.get_log())}; - auto temp_sim_cumulative_detected_infections_per_age_group = std::vector>{ - std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; - - auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], - temp_sim_cumulative_detected_infections_per_age_group[0], max_num_days, - start_date); - rmse_results_per_grid_point.at(i) += rmse; - } - rmse_results_per_grid_point.at(i) /= num_runs; + rmse_results_per_grid_point.at(i) /= num_runs; #pragma omp critical - { - write_grid_search_prematurely_to_file(rank, result_dir, - std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); + { + write_grid_search_prematurely_to_file(rank, result_dir, + std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); + } } -} -// make the gathered results available to all ranks -std::vector, double>> my_results; -for (size_t i = 0; i < grid_search_rank.size(); i++) { - my_results.push_back(std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); -} + // make the gathered results available to all ranks + std::vector, double>> my_results; + for (size_t i = 0; i < grid_search_rank.size(); i++) { + my_results.push_back(std::make_pair(grid_search_rank[i], rmse_results_per_grid_point[i])); + } #ifdef MEMILIO_ENABLE_MPI -get_grid_search_results_and_write_them_to_file(rank, num_procs, result_dir, my_results); + get_grid_search_results_and_write_them_to_file(rank, num_procs, result_dir, my_results); #endif -printf("done.\n"); -return mio::success(); + printf("done.\n"); + return mio::success(); } std::vector distribute_runs(size_t num_runs, int num_procs) @@ -1996,8 +1953,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; - const double masks = 0.55; - const double after_lockdown_contact_reduction = 0.55; + const double masks = 0.25; + const double after_lockdown_contact_reduction = 0.50; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2008,7 +1965,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 29; - int end_date_of_lockdown = 61; + int end_date_of_lockdown = 60; int max_num_days = 90; auto max_num_persons = 400000; bool npis_on = true; @@ -2126,9 +2083,6 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s damping_community_lockdown); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.8); // from 2021-03-15 - location.add_damping( - mio::abm::TimePoint(mio::abm::days(mio::abm::days(72).seconds()).seconds()), - 0.2); // from 2021-03-15 } if (location.get_type() == mio::abm::LocationType::Work) { location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 @@ -2145,8 +2099,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s sim.get_world().parameters.get() = quarantine_effectiveness; sim.get_world().parameters.get() = quarantine_duration; - restart_timer(timer, "till advance 27 (march ends & lockdown starts)"); - sim.advance(mio::abm::TimePoint(mio::abm::days(27).seconds()), + sim.advance(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); @@ -2160,8 +2113,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } - restart_timer(timer, "till advance 62 & lockdown ends"); - sim.advance(mio::abm::TimePoint(mio::abm::days(61).seconds()), + sim.advance(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, historyCumulativeDetectedInfectionsPerAgeGroup, historyEstimatedReproductionNumber); @@ -2174,7 +2126,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } sim.get_world().parameters.get() = viral_shedding_rate * seasonality_may; - restart_timer(timer, "till advance tmax "); + sim.advance(mio::abm::TimePoint(tmax.seconds()), historyInfectionPerLocationTypePerAgeGroup, historyInfectionStatePerAgeGroup, historyTestPerLocationTypePerAgeGroup, historyPositiveTestPerLocationTypePerAgeGroup, @@ -2368,8 +2320,8 @@ int main(int argc, char** argv) rank = 0; #endif - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2434,7 +2386,7 @@ int main(int argc, char** argv) else { // std::vector> parameters = {{2.26}, {2.64}, {0.56}}; // std::vector> parameters = {{2.3}, {2.6}, {0.55}, {2, 4, 8, 16}, {0.1, 0.25, 0.5, 1.0}}; - std::vector> parameters = {{2.26}, {2.64}, {0.56}, {0.036}, {20.0}, {16}, {1.0}}; + std::vector> parameters = {{2.05}, {2.64}, {0.50}, {0.036}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 681a3bce8c1601449a4e2b6eacb7ce555e169ec5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:25:49 +0200 Subject: [PATCH 333/488] benchmark? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index c5472f0f3b..4ab2ed0c57 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -143,7 +143,7 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer state.ResumeTiming(); //simulated time should be long enough to have full infection runs and migration to every location - auto final_time = sim.get_time() + mio::abm::days(1); + auto final_time = sim.get_time() + mio::abm::days(5); sim.advance(final_time); //debug output can be enabled to check for unexpected results (e.g. infections dieing out) @@ -179,6 +179,10 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer // ->Unit(benchmark::kMillisecond); // BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) // ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_5000k_pt, 2500000, {14159265u, 35897932u}) +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_25000k_pt, 25000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50000k_pt, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100000k_pt, 100000, {14159265u, 35897932u}) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100000k_pt, 1000000, {14159265u, 35897932u}) ->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); From 09f472976087bb03be752976e2d284c880885b99 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:26:01 +0200 Subject: [PATCH 334/488] omp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/person.cpp | 4 ---- cpp/models/abm/world.cpp | 8 +++----- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index 6e01971844..5c3e4308dc 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -62,10 +62,6 @@ Person Person::copy_person(Location& location) void Person::interact(RandomNumberGenerator& rng, TimePoint t, TimeSpan dt, const Parameters& params) { - // if (get_infection_state(t) == InfectionState::Susceptible || - // get_infection_state(t) == InfectionState::Recovered) { // Susceptible or Recovered people can be (re)infected - // m_location->interact(rng, *this, t, dt, params); - // } if (get_infection_state(t) == InfectionState::Susceptible) { // Susceptible or Recovered people can be (re)infected if (m_location->location_contaminated) m_location->interact(rng, *this, t, dt, params); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 4a29c1dfea..26a83e3405 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { - // #pragma omp parallel +#pragma omp parallel for for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { - // #pragma omp parallel for +#pragma omp parallel for for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,12 +168,10 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); - // #pragma omp parallel for +#pragma omp parallel for for (auto i = size_t(0); i < m_locations.size(); ++i) { - auto&& location = m_locations[i]; location->location_contaminated = false; - // mio::unused(location, dt); location->adjust_contact_rates(parameters.get_num_groups()); location->cache_exposure_rates(t, dt, parameters.get_num_groups(), parameters); } From 9382e360de84149dbedf59aae99d687ef6034a84 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:51:12 +0200 Subject: [PATCH 335/488] improooovements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 109 ++++++++++++++++------- 1 file changed, 77 insertions(+), 32 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a7ac3751fd..90d46c8923 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1107,7 +1107,7 @@ std::vector> distribute_grid_search(int rank, int num_procs, } // we calculate every possible combination of the grid, independently of the rank std::vector> grid_search{}; - std::vector counter_per_dimension(grid.size(), 0); + std::vector counter_per_dimension(grid.size(), 0); for (int i = 0; i < number_of_points; i++) { std::vector temp; for (size_t j = 0; j < grid.size(); j++) { @@ -1115,10 +1115,10 @@ std::vector> distribute_grid_search(int rank, int num_procs, } grid_search.push_back(temp); // we increase the counter for the last dimension - counter_per_dimension.back()++; + counter_per_dimension[grid.size() - 1]++; // we increase the counter for the other dimensions if the last dimension has reached the end - for (int k = (int)grid.size(); k > 0; k--) { - if (counter_per_dimension[k] == (int)grid[k].size()) { + for (size_t k = grid.size() - 1; k > 0; k--) { + if (counter_per_dimension[k] == grid[k].size()) { counter_per_dimension[k] = 0; counter_per_dimension[k - 1]++; } @@ -1129,6 +1129,14 @@ std::vector> distribute_grid_search(int rank, int num_procs, for (int i = 0; i < points_per_rank; i++) { grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); } + // we print the grid search for the rank + std::cout << "Rank " << rank << " has the following grid search: " << std::endl; + for (size_t i = 0; i < grid_search_ranks.size(); i++) { + for (size_t j = 0; j < grid_search_ranks[i].size(); j++) { + std::cout << grid_search_ranks[i][j] << " "; + } + std::cout << std::endl; + } return grid_search_ranks; } @@ -1157,11 +1165,8 @@ void create_easter_social_event(mio::abm::World& world, double perc_easter_event person_per_age_group[determine_age_group_from_rki(p.get_age())].push_back(i); } - //shuffle this vector - std::random_device rd; - std::mt19937 g(rd()); for (size_t i = 0; i < person_per_age_group.size(); i++) { - std::shuffle(person_per_age_group[i].begin(), person_per_age_group[i].end(), g); + std::shuffle(person_per_age_group[i].begin(), person_per_age_group[i].end(), world.get_rng()); } int number_of_persons = (int)(perc_easter_event * world.get_persons().size()); int number_of_social_events = number_of_persons / (num_age_groupss + 1); @@ -1441,6 +1446,23 @@ struct LogEstimatedReproductionNumber : mio::LogAlways { } }; +mio::TimeSeries get_new_detected_infections(mio::TimeSeries cumulative_infections) +{ + mio::TimeSeries new_detected_infection(mio::TimeSeries::zero( + cumulative_infections.get_num_time_points() / 24, cumulative_infections.get_num_elements())); + for (Eigen::Index i = 1; i < cumulative_infections.get_num_time_points() / 24; i++) { + new_detected_infection[i] = cumulative_infections[i * 24] - cumulative_infections[(i - 1) * 24]; + } + // we print this for debugging + for (Eigen::Index i = 0; i < new_detected_infection.get_num_time_points(); i++) { + for (Eigen::Index j = 0; j < new_detected_infection.get_num_elements(); j++) { + std::cout << new_detected_infection[i][j] << " "; + } + std::cout << std::endl; + } + return new_detected_infection; +} + #ifdef MEMILIO_ENABLE_MPI template T gather_results(int rank, int num_procs, int num_runs, T ensemble_vec) @@ -1682,7 +1704,7 @@ void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, } mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::path& result_dir, int num_runs, - std::vector> grid_points) + std::vector> grid_points, mio::RandomNumberGenerator& rng) { int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI @@ -1697,12 +1719,6 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Distribute the grid search over the MPI ranks auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); // short debug print to see if everything worked. Printing rank and amount of grid points as well as first point - std::cout << "Rank: " << rank << " has " << grid_search_rank.size() << " grid points" << std::endl; - std::cout << "First grid point: "; - for (size_t j = 0; j < grid_search_rank[0].size(); j++) { - std::cout << grid_search_rank[0].at(j) << " "; - } - std::cout << std::endl; // Run the grid search std::vector rmse_results_per_grid_point; @@ -1712,8 +1728,6 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa #pragma omp parallel for num_threads(90) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; - std::random_device rd; - std::mt19937 g(rd()); printf("I am Thread %d\n", omp_get_thread_num()); @@ -1723,8 +1737,8 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double damping_community_lockdown = 0.5; const double testing_probability_sympt = 0.036; - const double lockdown_test_prob = 1.25; - const auto after_lockdown_test_prob = 0.75; + const double lockdown_test_prob = 1.1; + const auto after_lockdown_test_prob = 0.9; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; @@ -1756,6 +1770,10 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Loop over a number of runs auto world = mio::abm::World(num_age_groupss); + auto run_rng_counter = + mio::rng_totalsequence_counter(static_cast(j), mio::Counter(0)); + rng.set_counter(run_rng_counter); + world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); @@ -1914,7 +1932,8 @@ std::vector distribute_runs(size_t num_runs, int num_procs) } mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, - std::vector> parameter_values, bool save_single_runs = true) + std::vector> parameter_values, mio::RandomNumberGenerator rng, + bool save_single_runs = true) { int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI @@ -1947,8 +1966,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.25; - const double after_lockdown_test_prob = 0.75; + const double lockdown_test_prob = 1.1; + const double after_lockdown_test_prob = 0.9; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; @@ -1997,6 +2016,10 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::vector>>{}; // Vector of estimated reproduction number ensemble_estimated_reproduction_number.reserve(size_t(num_runs)); + auto ensemble_estimated_new_detected_infections = + std::vector>>{}; // Vector of estimated reproduction number + ensemble_estimated_new_detected_infections.reserve(size_t(num_runs)); + auto ensemble_params = std::vector>{}; // Vector of all worlds ensemble_params.reserve(size_t(num_runs)); @@ -2010,10 +2033,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { - std::random_device rd; - std::mt19937 g(rd()); - auto world = mio::abm::World(num_age_groupss); + auto run_rng_counter = + mio::rng_totalsequence_counter(static_cast(run_idx), mio::Counter(0)); + rng.set_counter(run_rng_counter); + world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); @@ -2151,8 +2175,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s std::get<0>(historyPositiveTestPerLocationTypePerAgeGroup.get_log())}; auto temp_sim_cumulative_detected_infections_per_age_group = std::vector>{ std::get<0>(historyCumulativeDetectedInfectionsPerAgeGroup.get_log())}; + auto temp_sim_estimated_new_detected_infections = std::vector>{ + get_new_detected_infections(temp_sim_cumulative_detected_infections_per_age_group[0])}; auto temp_sim_estimated_reproduction_number = std::vector>{std::get<0>(historyEstimatedReproductionNumber.get_log())}; + // Push result of the simulation back to the result vector ensemble_infection_per_loc_type_per_age_group.emplace_back(temp_sim_infection_per_loc_type_per_age_group); ensemble_infection_state_per_age_group.emplace_back(temp_sim_infection_state_per_age_group); @@ -2160,6 +2187,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s ensemble_positive_test_per_loc_type_per_age_group.emplace_back( temp_sim_positive_test_per_loc_type_per_age_group); ensemble_cumulative_detected_infections.emplace_back(temp_sim_cumulative_detected_infections_per_age_group); + ensemble_estimated_new_detected_infections.emplace_back(temp_sim_estimated_new_detected_infections); ensemble_estimated_reproduction_number.emplace_back(temp_sim_estimated_reproduction_number); std::cout << "Run " << run_idx + 1 << " of " << num_runs << " finished." << std::endl; @@ -2203,8 +2231,11 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); auto final_ensemble_cumulative_detected_infections = gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); + auto final_ensemble_estimated_new_reproduction_number = + gather_results(rank, num_procs, num_runs, ensemble_estimated_new_detected_infections); auto final_ensemble_estimated_reproduction_number = gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); + if (rank == 0) { BOOST_OUTCOME_TRY(save_results( final_ensemble_infection_per_loc_type_per_age_group, ensemble_params, {0}, @@ -2222,12 +2253,17 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, result_dir / "cumulative_detected_infections" / std::to_string(par_i), save_single_runs)); + BOOST_OUTCOME_TRY(save_results(ensemble_estimated_new_detected_infections, ensemble_params, {0}, + result_dir / "new_detected_infections" / std::to_string(par_i), + save_single_runs)); BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, result_dir / "estimated_reproduction_number" / std::to_string(par_i), save_single_runs, true, true)); } #else - + BOOST_OUTCOME_TRY(save_results(ensemble_infection_per_loc_type_per_age_group, ensemble_params, {0}, + result_dir / "infection_per_location_type_per_age_group" / std::to_string(par_i), + save_single_runs)); BOOST_OUTCOME_TRY(save_results(ensemble_infection_state_per_age_group, ensemble_params, {0}, result_dir / "infection_state_per_age_group" / std::to_string(par_i), save_single_runs)); @@ -2243,6 +2279,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s BOOST_OUTCOME_TRY(save_results(ensemble_estimated_reproduction_number, ensemble_params, {0}, result_dir / "estimated_reproduction_number" / std::to_string(par_i), save_single_runs, 1)); + BOOST_OUTCOME_TRY(save_results(ensemble_estimated_new_detected_infections, ensemble_params, {0}, + result_dir / "new_detected_infections" / std::to_string(par_i), save_single_runs, + 1)); #endif restart_timer(timer, "time taken for data gathering and saving results"); @@ -2270,6 +2309,7 @@ mio::IOResult create_result_folders(std::string const& result_dir, int n_p std::string pos_test_p_loc_t_p_ag = result_dir + "/positive_test_per_location_type_per_age_group/"; std::string cum_det_inf = result_dir + "/cumulative_detected_infections/"; std::string est_rep_num = result_dir + "/estimated_reproduction_number/"; + std::string new_det_inf = result_dir + "/new_detected_infections/"; BOOST_OUTCOME_TRY(mio::create_directory(result_dir)); BOOST_OUTCOME_TRY(mio::create_directory(inf_p_loc_t_p_ag)); @@ -2277,6 +2317,7 @@ mio::IOResult create_result_folders(std::string const& result_dir, int n_p BOOST_OUTCOME_TRY(mio::create_directory(test_p_loc_t_p_ag)); BOOST_OUTCOME_TRY(mio::create_directory(pos_test_p_loc_t_p_ag)); BOOST_OUTCOME_TRY(mio::create_directory(cum_det_inf)); + BOOST_OUTCOME_TRY(mio::create_directory(new_det_inf)); BOOST_OUTCOME_TRY(mio::create_directory(est_rep_num)); if (n_params > 0) { // we create n_param folders in each of the subfolders @@ -2287,6 +2328,7 @@ mio::IOResult create_result_folders(std::string const& result_dir, int n_p BOOST_OUTCOME_TRY(mio::create_directory(pos_test_p_loc_t_p_ag + "/" + std::to_string(i))); BOOST_OUTCOME_TRY(mio::create_directory(cum_det_inf + "/" + std::to_string(i))); BOOST_OUTCOME_TRY(mio::create_directory(est_rep_num + "/" + std::to_string(i))); + BOOST_OUTCOME_TRY(mio::create_directory(new_det_inf + "/" + std::to_string(i))); } } @@ -2310,6 +2352,11 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::err); auto start = std::chrono::system_clock::now(); + // we need one seed + std::initializer_list seeds = {14159265u, 35897932u}; + auto rng = mio::RandomNumberGenerator(); + rng.seed(seeds); + int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI mio::mpi::init(); @@ -2352,7 +2399,7 @@ int main(int argc, char** argv) num_runs = 9; run_grid_search = true; printf("running with grid search\n"); - printf("Running with number of runs = 1\n"); + printf("Running with number of runs %d.\n", (int)num_runs); } else { num_runs = 1; @@ -2381,12 +2428,10 @@ int main(int argc, char** argv) return created.error().code().value(); } } - auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid); + auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - // std::vector> parameters = {{2.26}, {2.64}, {0.56}}; - // std::vector> parameters = {{2.3}, {2.6}, {0.55}, {2, 4, 8, 16}, {0.1, 0.25, 0.5, 1.0}}; - std::vector> parameters = {{2.05}, {2.64}, {0.50}, {0.036}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{2.05}, {2.90}, {0.45}, {0.036}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); @@ -2395,7 +2440,7 @@ int main(int argc, char** argv) return created.error().code().value(); } } - auto result = run(input_dir, result_dir, num_runs, every_combination); + auto result = run(input_dir, result_dir, num_runs, every_combination, rng); } // copy results into a fixed name folder to have easier access From 481213b3d8dca8d8bbec822b3a77559266f0f22d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:51:24 +0200 Subject: [PATCH 336/488] picc improvs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 100 +++++++++++++++++++----------- 1 file changed, 64 insertions(+), 36 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 3b6a2ea724..9fb7d47ef1 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -282,7 +282,7 @@ def plot_dead(path): (df_abb['Date'] <= '2021-06-01')] # we just need the cases with id 3101 df_abb = df_abb[df_abb['ID_County'] == 3101] - df_abb['Deaths'] = np.floor(df_abb[['Deaths']].to_numpy()) + df_abb['Deaths'] = np.round(df_abb[['Deaths']].to_numpy()) # we need the amount of dead persons for each age group: These are A00-A04, A05-A14, A15-A34, A35-A59, A60-A79, A80+ age_groups = ['A00-A04', 'A05-A14', 'A15-A34', 'A35-A59', 'A60-A79', 'A80+'] @@ -323,7 +323,7 @@ def plot_dead(path): ax = fig.add_subplot(gs[1, i]) # we need the amount of dead persons for each age group df_abb_age_group = df_abb[df_abb['Age_RKI'] == age_groups[i]][0:90] - y_real = np.floor(df_abb_age_group['Deaths'].to_numpy()) + y_real = np.round(df_abb_age_group['Deaths'].to_numpy()) # we need to plot the dead persons from the real world and from the simulation ax.plot(df_abb_age_group['Date'], y_real, color='tab:red') ax.plot(df_abb_age_group['Date'], p50_bs[age_group_access[i]][()][:, 7][::24][0:90], color='tab:blue') @@ -402,7 +402,7 @@ def plot_icu(path): total_95_age = total_95_age[::24][0:90] - ICU_Simulation_one_percentile = np.floor(total_50[:, 5]*perc_of_critical_in_icu) + ICU_Simulation_one_percentile = np.round(total_50[:, 5]*perc_of_critical_in_icu) ICU_Simulation = np.round(total_50_age[:, 5]) ICU_Simulation75 = np.round(total_75_age[:, 5]) ICU_Simulation25 = np.round(total_25_age[:, 5]) @@ -706,32 +706,75 @@ def plot_cumulative_detected_infections(path): df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] df_abb = df_abb[df_abb['ID_County'] == 3101] - df_substract = np.floor(df_abb['Confirmed'][0:1]) - df_abb = np.floor(df_abb['Confirmed'][0:90]) + df_substract = np.round(df_abb['Confirmed'][0:1]) + df_abb = np.round(df_abb['Confirmed'][0:90]) df_abb = df_abb - df_substract.values[0] + + df_diff = df_abb.diff() f_p50 = h5py.File( path+"/cumulative_detected_infections/0/p50/Results.h5", 'r') - total_50 = np.floor(f_p50['0']['Total'][()][::24][0:90].flatten()) + total_50 = np.round(f_p50['0']['Total'][()][::24][0:90].flatten()) # we smooth this with a gaussian filter f_p95 = h5py.File( path+"/cumulative_detected_infections/0/p95/Results.h5", 'r') - total_95 = np.floor(f_p95['0']['Total'][()][::24][0:90].flatten()) + total_95 = np.round(f_p95['0']['Total'][()][::24][0:90].flatten()) f_p05 = h5py.File( path+"/cumulative_detected_infections/0/p05/Results.h5", 'r') - total_05 = np.floor(f_p05['0']['Total'][()][::24][0:90].flatten()) + total_05 = np.round(f_p05['0']['Total'][()][::24][0:90].flatten()) f_p25 = h5py.File( path+"/cumulative_detected_infections/0/p25/Results.h5", 'r') - total_25 = np.floor(f_p25['0']['Total'][()][::24][0:90].flatten()) + total_25 = np.round(f_p25['0']['Total'][()][::24][0:90].flatten()) f_p75 = h5py.File( path+"/cumulative_detected_infections/0/p75/Results.h5", 'r') - total_75 = np.floor(f_p75['0']['Total'][()][::24][0:90].flatten()) + total_75 = np.round(f_p75['0']['Total'][()][::24][0:90].flatten()) + + + # we do the same for the new infecitons (same as above but folder new_detected_infections) + f_p50_diff = h5py.File( + path+"/new_detected_infections/0/p50/Results.h5", 'r') + total_50_diff = np.round(f_p50_diff['0']['Total'][()].flatten()) + + f_p95_diff = h5py.File( + path+"/new_detected_infections/0/p95/Results.h5", 'r') + total_95_diff = np.round(f_p95_diff['0']['Total'][()].flatten()) + + f_p05_diff = h5py.File( + path+"/new_detected_infections/0/p05/Results.h5", 'r') + total_05_diff = np.round(f_p05_diff['0']['Total'][()].flatten()) + + f_p25_diff = h5py.File( + path+"/new_detected_infections/0/p25/Results.h5", 'r') + total_25_diff = np.round(f_p25_diff['0']['Total'][()].flatten()) + + f_p75_diff = h5py.File( + path+"/new_detected_infections/0/p75/Results.h5", 'r') + total_75_diff = np.round(f_p75_diff['0']['Total'][()].flatten()) + + # we need to sum every 24 entries to get the daily amount + total_50_diff = np.cumsum(total_50_diff, axis=0) + total_50_diff = np.diff(total_50_diff)[0:90] + + total_95_diff = np.cumsum(total_95_diff, axis=0) + total_95_diff = np.diff(total_95_diff)[0:90] + + total_05_diff = np.cumsum(total_05_diff, axis=0) + total_05_diff = np.diff(total_05_diff)[0:90] + + total_75_diff = np.cumsum(total_75_diff, axis=0) + total_75_diff = np.diff(total_75_diff)[0:90] + + total_25_diff = np.cumsum(total_25_diff, axis=0) + total_25_diff = np.diff(total_25_diff)[0:90] + + + # we smooth this with a gaussian filter @@ -739,24 +782,10 @@ def plot_cumulative_detected_infections(path): time = time[::24] time = time[0:90] - # we also plot the amount of new detected infections with diff - total_50_diff = np.diff(total_50) - total_95_diff = np.diff(total_95) - total_05_diff = np.diff(total_05) - total_25_diff = np.diff(total_25) - total_75_diff = np.diff(total_75) - df_abb_diff = np.diff(df_abb) - + # we calculate the RMSE + rmse_detected = ((df_abb - total_50)**2).mean() *0.01*0.01*0.1 - # again the rmse - rmse_detected = ((df_abb - total_50)**2).mean()*(0.01*0.01*0.05) - total_50_diff = gaussian_filter1d(total_50_diff.flatten(), sigma=2, mode='nearest') - total_05_diff = gaussian_filter1d(total_05_diff.flatten(), sigma=2, mode='nearest') - total_95_diff = gaussian_filter1d(total_95_diff.flatten(), sigma=2, mode='nearest') - total_75_diff = gaussian_filter1d(total_75_diff.flatten(), sigma=2, mode='nearest') - total_25_diff = gaussian_filter1d(total_25_diff.flatten(), sigma=2, mode='nearest') - total_50 = gaussian_filter1d(total_50.flatten(), sigma=2, mode='nearest') # we plot this # we plot the tests positive and the real cases @@ -784,11 +813,11 @@ def plot_cumulative_detected_infections(path): # we plot the tests positive and the real cases ax.plot(time[0:89], total_50_diff, color='tab:blue') # we dont plot the real curve as a line but as x points and not every day but every 2nd day - ax.plot(time[0:89], df_abb_diff[0:89], 'x', color='tab:red') - ax.fill_between(time[0:89], total_95_diff[0:89], total_05_diff[0:89], + ax.plot(time[0:89], df_diff[0:89], 'x', color='tab:red') + ax.fill_between(time[0:89], total_95_diff, total_05_diff, alpha=0.75, color='tab:blue') - ax.fill_between(time[0:89], total_75_diff[0:89], total_25_diff[0:89], - alpha=0.5, color='tab:blue') + ax.fill_between(time[0:89], total_75_diff, total_25_diff, + alpha=0.5, color='tab:blue') ax.set_xlabel('time (days)') ax.set_ylabel('Number of new detected infections') ax.title.set_text('New detected infections') @@ -857,13 +886,12 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infection_states_results(path) - plot_infections_loc_types_avarage(path) - plot_icu(path) - plot_dead(path) + # plot_infection_states_results(path) + # plot_infections_loc_types_avarage(path) + # plot_icu(path) + # plot_dead(path) plot_cumulative_detected_infections(path) - plot_positive_and_done_test(path) - + # plot_positive_and_done_test(path) # infer_positive_tests(path) # plot_estimated_reproduction_number(path) From 9d2fe9f4af16580dd388b480d2c2372d44ee01ee Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 00:17:49 +0200 Subject: [PATCH 337/488] don't save single results Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 90d46c8923..f5f37a8830 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1933,7 +1933,7 @@ std::vector distribute_runs(size_t num_runs, int num_procs) mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, size_t num_runs, std::vector> parameter_values, mio::RandomNumberGenerator rng, - bool save_single_runs = true) + bool save_single_runs = false) { int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI @@ -2231,7 +2231,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s gather_results(rank, num_procs, num_runs, ensemble_positive_test_per_loc_type_per_age_group); auto final_ensemble_cumulative_detected_infections = gather_results(rank, num_procs, num_runs, ensemble_cumulative_detected_infections); - auto final_ensemble_estimated_new_reproduction_number = + auto final_ensemble_estimated_new_detected_infections = gather_results(rank, num_procs, num_runs, ensemble_estimated_new_detected_infections); auto final_ensemble_estimated_reproduction_number = gather_results(rank, num_procs, num_runs, ensemble_estimated_reproduction_number); @@ -2253,7 +2253,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s BOOST_OUTCOME_TRY(save_results(final_ensemble_cumulative_detected_infections, ensemble_params, {0}, result_dir / "cumulative_detected_infections" / std::to_string(par_i), save_single_runs)); - BOOST_OUTCOME_TRY(save_results(ensemble_estimated_new_detected_infections, ensemble_params, {0}, + BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_new_detected_infections, ensemble_params, {0}, result_dir / "new_detected_infections" / std::to_string(par_i), save_single_runs)); BOOST_OUTCOME_TRY(save_results(final_ensemble_estimated_reproduction_number, ensemble_params, {0}, From 981026744d9226400a9a0d8e9460eb95faebb4a1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 00:21:08 +0200 Subject: [PATCH 338/488] test123 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f5f37a8830..793cd5c8a4 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2367,8 +2367,8 @@ int main(int argc, char** argv) rank = 0; #endif - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2396,13 +2396,13 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 9; + num_runs = 3; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); } else { - num_runs = 1; + num_runs = 9; printf("Running with number of runs = %d.\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); } @@ -2419,7 +2419,7 @@ int main(int argc, char** argv) // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {7, 7, 7}; + std::vector points_per_dim = {5, 5, 5}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From c35673352cc011e1330c5670a429e11453e174ae Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 00:25:56 +0200 Subject: [PATCH 339/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 793cd5c8a4..7308776207 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1725,7 +1725,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(90) +#pragma omp parallel for num_threads(96) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2419,7 +2419,7 @@ int main(int argc, char** argv) // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {5, 5, 5}; + std::vector points_per_dim = {5, 5, 6}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From c6f410ffaf788aedb19e137563563d34d426bb21 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:14:31 +0200 Subject: [PATCH 340/488] ewd Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7308776207..b3d4cbd085 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2419,7 +2419,7 @@ int main(int argc, char** argv) // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {5, 5, 6}; + std::vector points_per_dim = {5, 5, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 85855c3a1d9ceee0e9f26cafb774eead5e4fb861 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:26:37 +0200 Subject: [PATCH 341/488] omp??!" Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 26a83e3405..7c5f9d1140 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,7 +168,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b3d4cbd085..572d05ed93 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1725,7 +1725,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(96) +#pragma omp parallel for num_threads(64) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2396,13 +2396,13 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 3; + num_runs = 13; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); } else { - num_runs = 9; + num_runs = 1; printf("Running with number of runs = %d.\n", (int)num_runs); printf("Saving results to \"%s\".\n", result_dir.c_str()); } @@ -2416,8 +2416,8 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}, {0.03, 0.04}}; - std::vector grid_boundaries = {2.3, 2.6, 0.55}; + std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}}; + // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; std::vector points_per_dim = {5, 5, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); From 6ab0506b66177398aec4b2bd7d34e0a9253ab387 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:34:57 +0200 Subject: [PATCH 342/488] rest Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 572d05ed93..74c127bbbd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1724,8 +1724,8 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); - omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(64) + omp_set_max_active_levels(1); +#pragma omp parallel for num_threads(64) schedule(dynamic) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2416,10 +2416,10 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{1.8, 2.5}, {2.0, 4.0}, {0.5, 0.8}}; + std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {5, 5, 7}; + std::vector points_per_dim = {13, 13, 13}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 6fc5e6278b51236c21239a967183c4fa1948968e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:35:30 +0200 Subject: [PATCH 343/488] 423 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 74c127bbbd..91c9d2597e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2419,7 +2419,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {13, 13, 13}; + std::vector points_per_dim = {5, 5, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 0439107c853816b0248109b7a65df615914a551f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 01:58:13 +0200 Subject: [PATCH 344/488] fw Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 91c9d2597e..3e3f7a9df7 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1724,7 +1724,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); - omp_set_max_active_levels(1); + omp_set_max_active_levels(2); #pragma omp parallel for num_threads(64) schedule(dynamic) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2396,7 +2396,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 13; + num_runs = 9; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); @@ -2419,7 +2419,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {5, 5, 7}; + std::vector points_per_dim = {13, 13, 13}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From f8d1c4b4888fe3abb41a7534d65cbafeb57175b9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 02:04:04 +0200 Subject: [PATCH 345/488] 31 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3e3f7a9df7..47945007d2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2419,7 +2419,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {13, 13, 13}; + std::vector points_per_dim = {14, 14, 14}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 805d33ac6cb795ebc7fe379ea7b2f7632f21e876 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 11:53:40 +0200 Subject: [PATCH 346/488] paper grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 47945007d2..5bed92ef63 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1725,7 +1725,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(64) schedule(dynamic) +#pragma omp parallel for num_threads(64) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2419,7 +2419,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {14, 14, 14}; + std::vector points_per_dim = {11, 11, 11}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From e9e59628bf20baeba6fdd417b4f1008860db22c2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 12:50:45 +0200 Subject: [PATCH 347/488] mrlekw Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5bed92ef63..623c8e14dc 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1704,7 +1704,7 @@ void write_grid_search_prematurely_to_file(int rank, const fs::path& result_dir, } mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::path& result_dir, int num_runs, - std::vector> grid_points, mio::RandomNumberGenerator& rng) + std::vector> grid_points, mio::RandomNumberGenerator rng) { int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI @@ -1725,7 +1725,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(64) +#pragma omp parallel for num_threads(4) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -1773,6 +1773,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa auto run_rng_counter = mio::rng_totalsequence_counter(static_cast(j), mio::Counter(0)); rng.set_counter(run_rng_counter); + world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); @@ -2419,7 +2420,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {11, 11, 11}; + std::vector points_per_dim = {2, 2, 5}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From b9195f3711dbf92c85503981650b191cf31fe168 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 13:11:59 +0200 Subject: [PATCH 348/488] papersss Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 623c8e14dc..2e6d51902b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1725,7 +1725,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(4) firstprivate(rng) +#pragma omp parallel for num_threads(64) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2432,7 +2432,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{2.05}, {2.90}, {0.45}, {0.036}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.8}, {2.96}, {0.54}, {0.036}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 84b4272a3693c329fee2e77d1cae6203f8f6edc4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:02:58 +0200 Subject: [PATCH 349/488] clustere Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2e6d51902b..033f2a5fa8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1453,13 +1453,7 @@ mio::TimeSeries get_new_detected_infections(mio::TimeSeries run_with_grid_search(const fs::path& input_dir, const fs::pa const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.036; + const double testing_probability_sympt = 0.033; const double lockdown_test_prob = 1.1; const auto after_lockdown_test_prob = 0.9; @@ -2420,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {2, 2, 5}; + std::vector points_per_dim = {12, 12, 12}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2432,7 +2426,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.8}, {2.96}, {0.54}, {0.036}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.8}, {2.96}, {0.54}, {0.033}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 4b47a56e3eaf1f9c7bd2ebd15e604df8a9feec37 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:05:19 +0200 Subject: [PATCH 350/488] par_var_oimprocs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/parameter_varation.py | 192 +++++++++++++------------- 1 file changed, 94 insertions(+), 98 deletions(-) diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index a4f562c410..a2b204294a 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -24,21 +24,13 @@ def plot_of_cumuative_infections(path, index=0): path+"/infection_per_location_type_per_age_group/"+str(index)+"/p50/Results.h5", 'r') p50_bs = f_p50['0'] total_50 = p50_bs['Total'][()] - - time = p50_bs['Time'][()] - time = time[::24] - time = time[0:90] - - - states_plot = [0, 1, 2, 3, 4, 10] - np_y50_total = np.zeros(90) - for i in states_plot: - # we need to sum up every 24 hours - indexer = pd.api.indexers.FixedForwardWindowIndexer(window_size=24) - np_y50 = pd.DataFrame(total_50[:, i]).rolling(window=indexer, min_periods=1).sum().to_numpy() - np_y50=np_y50[0::24].flatten()[0:90] - np_y50_total += np_y50 - return np_y50_total + # we sum over all locations + total_50 = np.sum(total_50, axis=1) + total_50 = np.cumsum(total_50, axis=0) + total_50 = total_50[::24] + total_50 = total_50[0:91] # we still need to take the difference to get the daily amount + # we smooth this with a gaussian filter + return total_50 def plot_number_of_tests(path, index): f_p50_done = h5py.File( @@ -93,28 +85,38 @@ def get_maximum_cum_infected(path, index): cum_inf_normal_50 = np.cumsum(p50_bs_normal_all_locations) return np.max(cum_inf_normal_50) - +def get_maximum_daily_infections(path, index): + infected_p50_normal = h5py.File( + path+"/infection_per_location_type_per_age_group/"+str(index)+"/p50/Results.h5", 'r') + locations = [0, 1, 2, 3, 4, 10] + p50_bs_infected_normal = infected_p50_normal['0']['Total'][()] + p50_bs_normal_all_locations = np.zeros(len(p50_bs_infected_normal)) + for location in locations: + p50_bs_normal_all_locations += p50_bs_infected_normal[:, location] + cum_inf_normal_50 = np.cumsum(p50_bs_normal_all_locations) + daily_inf = np.diff(cum_inf_normal_50) + return np.max(daily_inf) if __name__ == "__main__": - # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-15140128" - variable_1 = "test_likelihood_symptom" - variable_2 = "test_likelihood_asymptom" - values_1 = [0.018,0.036,0.054,0.072,0.09] - values_2 = [40,30,20,10,1] + # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/par_var/memilio/data/results_2024-08-22225207" + # variable_1 = "test_likelihood_symptom" + # variable_2 = "test_likelihood_asymptom" + # values_1 = [0.018,0.036,0.054,0.072,0.09] + # values_2 = [40,30,20,10,1] - path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21224000" + path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/par_var/memilio/data/results_2024-08-22225357" variable_1 = "quarantine lenth" variable_2 = "quarantine efficiancy" values_1 = [1,4,7,10,13,16] values_2 = [0.0,0.25,0.5,0.75,1.0] - path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21224000" - variable_1 = "test_likelihood_symptom" - variable_2 = "quarantine lenth" - values_1 = [0.018,0.036,0.054,0.072,0.09] - values_2 = [1,4,7,10,13,16] + # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/par_var/memilio/data/results_2024-08-22225628" + # variable_1 = "test_likelihood_symptom" + # variable_2 = "quarantine lenth" + # values_1 = [0.018,0.036,0.054,0.072,0.09] + # values_2 = [1,4,7,10,13,16] # we want to have a Grid Plot with the size of the values @@ -123,74 +125,74 @@ def get_maximum_cum_infected(path, index): # we want to plot in the title of the plot # they all should have the same y-axis, so we can compare them, the highest value should be the maximum of all plots - # fig = plt.figure('Parameter Variation', figsize=(1, 1)) - # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - # fig.suptitle('Parameter Variation', fontsize=16) - # fig.show() - # highest_value = 0 - # for i in range(len(values_1)): - # for j in range(len(values_2)): - # index = (i)*len(values_2)+(j) - # plot_data = plot_of_cumuative_infections(path_data, index) - # if np.max(plot_data) > highest_value: - # highest_value = np.max(plot_data) + fig = plt.figure('Parameter Variation', figsize=(19, 10)) + gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + fig.suptitle('Parameter Variation', fontsize=16) + fig.show() + highest_value = 0 + for i in range(len(values_1)): + for j in range(len(values_2)): + index = (i)*len(values_2)+(j) + plot_data = plot_of_cumuative_infections(path_data, index) + if np.max(plot_data) > highest_value: + highest_value = np.max(plot_data) - # for i, value_1 in enumerate(values_1): - # for j, value_2 in enumerate(values_2): - # index = (i)*len(values_2)+(j) - # ax = fig.add_subplot(gs[i, j]) - # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - # plot_data = plot_of_cumuative_infections(path_data, index) - # ax.set_ylim(0, highest_value) - # ax.plot(plot_data, label='Cumulative Infections') - # ax.legend() - # plt.show() + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) + ax = fig.add_subplot(gs[i, j]) + ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + plot_data = plot_of_cumuative_infections(path_data, index) + ax.set_ylim(0, highest_value) + ax.plot(plot_data, label='Cumulative Infections') + ax.legend() + plt.show() - # fig = plt.figure('Parameter Variation', figsize=(1, 1)) - # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - # fig.suptitle('Parameter Variation', fontsize=16) - # fig.show() - # highest_value = 0 - # for i in range(len(values_1)): - # for j in range(len(values_2)): - # index = (i)*len(values_2)+(j) - # plot_data = plot_number_of_tests(path_data, index) - # if np.max(plot_data) > highest_value: - # highest_value = np.max(plot_data) - # for i, value_1 in enumerate(values_1): - # for j, value_2 in enumerate(values_2): - # index = (i)*len(values_2)+(j) + fig = plt.figure('Parameter Variation', figsize=(19, 10)) + gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + fig.suptitle('Parameter Variation', fontsize=16) + fig.show() + highest_value = 0 + for i in range(len(values_1)): + for j in range(len(values_2)): + index = (i)*len(values_2)+(j) + plot_data = plot_number_of_tests(path_data, index) + if np.max(plot_data) > highest_value: + highest_value = np.max(plot_data) + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) - # ax = fig.add_subplot(gs[i, j]) - # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - # ax.set_ylim(0, highest_value) - # plot_data = plot_number_of_tests(path_data, index) - # ax.plot(plot_data, label='Number of Tests') - # ax.legend() - # plt.show() - # fig = plt.figure('Parameter Variation', figsize=(1, 1)) - # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - # fig.suptitle('Parameter Variation', fontsize=16) - # fig.show() - # highest_value = 0 - # for i in range(len(values_1)): - # for j in range(len(values_2)): - # index = (i)*len(values_2)+(j) - # plot_data = plot_positive_tests(path_data, index) - # if np.max(plot_data) > highest_value: - # highest_value = np.max(plot_data) - # for i, value_1 in enumerate(values_1): - # for j, value_2 in enumerate(values_2): - # index = (i)*len(values_2)+(j) + ax = fig.add_subplot(gs[i, j]) + ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + ax.set_ylim(0, highest_value) + plot_data = plot_number_of_tests(path_data, index) + ax.plot(plot_data, label='Number of Tests') + ax.legend() + plt.show() + fig = plt.figure('Parameter Variation', figsize=(19, 10)) + gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + fig.suptitle('Parameter Variation', fontsize=16) + fig.show() + highest_value = 0 + for i in range(len(values_1)): + for j in range(len(values_2)): + index = (i)*len(values_2)+(j) + plot_data = plot_positive_tests(path_data, index) + if np.max(plot_data) > highest_value: + highest_value = np.max(plot_data) + for i, value_1 in enumerate(values_1): + for j, value_2 in enumerate(values_2): + index = (i)*len(values_2)+(j) - # ax = fig.add_subplot(gs[i, j]) - # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - # ax.set_ylim(0, highest_value) - # plot_data = plot_positive_tests(path_data, index) - # ax.plot(plot_data, label='Positive Tests') - # ax.legend() - # plt.show() + ax = fig.add_subplot(gs[i, j]) + ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + ax.set_ylim(0, highest_value) + plot_data = plot_positive_tests(path_data, index) + ax.plot(plot_data, label='Positive Tests') + ax.legend() + plt.show() # we want to have four plots in one figure # in each plot for each value of the parameter we want to plot a big square in a color which is defined by the value of the interesting value in that plot @@ -210,8 +212,6 @@ def get_maximum_cum_infected(path, index): index = (i)*len(values_2)+(j) value_for_values[i, j] = get_maximum_cum_infected(path_data, index) # permute the values, so that the plot is correct - value_for_values = np.flip(value_for_values, axis=1) - value_for_values = np.flip(value_for_values, axis=0) # we need a seaborn heatmap for the colorbar sns.heatmap(value_for_values, ax=axs[0, 0], cmap='viridis', cbar_kws={'label': 'Maximum Cumulative Infections'}, annot=True, fmt=".0f") @@ -234,8 +234,6 @@ def get_maximum_cum_infected(path, index): index = (i)*len(values_2)+(j) value_for_values[i, j] = get_maximum_dead(path_data, index) # permute the values, so that the plot is correct - value_for_values = np.flip(value_for_values, axis=1) - value_for_values = np.flip(value_for_values, axis=0) # we need a seaborn heatmap for the colorbar sns.heatmap(value_for_values, ax=axs[0, 1], cmap='viridis', cbar_kws={'label': 'Maximum Dead'}, annot=True, fmt=".0f") axs[0, 1].set_title('Maximum Dead') @@ -252,7 +250,6 @@ def get_maximum_cum_infected(path, index): index = (i)*len(values_2)+(j) value_for_values[i, j] = get_maximum_hospitalized(path_data, index) # permute the values, so that the plot is correct - value_for_values = np.flip(value_for_values, axis=1) # we need a seaborn heatmap for the colorbar sns.heatmap(value_for_values, ax=axs[1, 0], cmap='viridis', cbar_kws={'label': 'Maximum Hospitalized'}, annot=True, fmt=".0f") axs[1, 0].set_title('Maximum Hospitalized') @@ -267,12 +264,11 @@ def get_maximum_cum_infected(path, index): for i, value_1 in enumerate(values_1): for j, value_2 in enumerate(values_2): index = (i)*len(values_2)+(j) - value_for_values[i, j] = get_maximum_cum_infected(path_data, index) + value_for_values[i, j] = get_maximum_daily_infections(path_data, index) # permute the values, so that the plot is correct - value_for_values = np.flip(value_for_values, axis=1) # we need a seaborn heatmap for the colorbar sns.heatmap(value_for_values, ax=axs[1, 1], cmap='viridis', cbar_kws={'label': 'Maximum Cumulative Infections'}, annot=True, fmt=".0f") - axs[1, 1].set_title('Maximum Cumulative Infections') + axs[1, 1].set_title('Maximum Daily Infections') # x and y axis labels axs[1, 1].set_xticklabels(values_2) axs[1, 1].set_yticklabels(values_1) From 428db2a404894ca61fe83a8d61fd69d289cb79eb Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:29:03 +0200 Subject: [PATCH 351/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 033f2a5fa8..4e5c4269fd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2347,11 +2347,6 @@ int main(int argc, char** argv) mio::set_log_level(mio::LogLevel::err); auto start = std::chrono::system_clock::now(); - // we need one seed - std::initializer_list seeds = {14159265u, 35897932u}; - auto rng = mio::RandomNumberGenerator(); - rng.seed(seeds); - int num_procs, rank; #ifdef MEMILIO_ENABLE_MPI mio::mpi::init(); @@ -2361,6 +2356,11 @@ int main(int argc, char** argv) num_procs = 1; rank = 0; #endif + // we need one seed + std::initializer_list seeds = {14159265u, 35897932u}; + auto rng = mio::RandomNumberGenerator(); + rng.seed(seeds); + rng.synchronize(); std::string input_dir = "/p/project1/loki/memilio/memilio/data"; // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; @@ -2414,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {12, 12, 12}; + std::vector points_per_dim = {5, 5, 5}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2426,7 +2426,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.8}, {2.96}, {0.54}, {0.033}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.8}, {2.5}, {0.3}, {0.033}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 230595f515cb29744d818cecc588df6957e48029 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:31:17 +0200 Subject: [PATCH 352/488] 777 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4e5c4269fd..d6bc07ae33 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2414,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {5, 5, 5}; + std::vector points_per_dim = {7, 7, 7}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 50726d357b91eb3e1f48a300432ddd1c3aef97b9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:36:49 +0200 Subject: [PATCH 353/488] 999 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 10 +++++----- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- cpp/simulations/scenario_plots.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 9fb7d47ef1..57a29fc8af 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -886,12 +886,12 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - # plot_infection_states_results(path) - # plot_infections_loc_types_avarage(path) - # plot_icu(path) - # plot_dead(path) + plot_infection_states_results(path) + plot_infections_loc_types_avarage(path) + plot_icu(path) + plot_dead(path) plot_cumulative_detected_infections(path) - # plot_positive_and_done_test(path) + plot_positive_and_done_test(path) # infer_positive_tests(path) # plot_estimated_reproduction_number(path) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d6bc07ae33..5fde6b2c17 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2414,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {7, 7, 7}; + std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index 29d1450ab6..fbfe71d4bc 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -233,8 +233,8 @@ def plot_scenario(path, folder, folder_high, folder_enough): if __name__ == "__main__": - path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21181533" - path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_2024-08-21194839" + path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/scenarios/results_2024-08-22225823" # more tesring + path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/scenarios/results_2024-08-22230155" # no lockdown but much testing path_to_scenario_3 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" path_to_main_data = "0" path_to_high_testing_data = "1" From afe1d9da496343bc035fb29944cd06d39829c29e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:49:58 +0200 Subject: [PATCH 354/488] griddd Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5fde6b2c17..98857e87c0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2414,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {9, 9, 9}; + std::vector points_per_dim = {11 11, 11}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 01fd1c7b4779d01722c0bad6ee3bf1d10503cc5e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 14:50:51 +0200 Subject: [PATCH 355/488] bf Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 98857e87c0..13adc77990 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2414,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {11 11, 11}; + std::vector points_per_dim = {11, 11, 11}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 9ebdae9756463e434d204eda5aeed5ffd919978a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 15:11:38 +0200 Subject: [PATCH 356/488] 101010 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 13adc77990..66cecdb56e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2414,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {11, 11, 11}; + std::vector points_per_dim = {10, 10, 10}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 22f4e01e33fbce1601ada4861276c7f0ebd7f739 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 15:17:03 +0200 Subject: [PATCH 357/488] cluster test 1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 66cecdb56e..a1c293239d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1719,7 +1719,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(64) firstprivate(rng) +#pragma omp parallel for num_threads(1) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2414,7 +2414,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {10, 10, 10}; + std::vector points_per_dim = {2, 2, 2}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From f3b7850cf3ceb35fae5c387ee14eb9f75dfe4395 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 15:19:02 +0200 Subject: [PATCH 358/488] cluster test 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 7c5f9d1140..a9bd02fbd4 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,7 +168,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(4) +#pragma omp parallel for for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; From 7579fd1e681876bf7d339373ae7a4e0e5e3f905d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 15:33:17 +0200 Subject: [PATCH 359/488] omp change back Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 6 +++--- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index a7e9ae34bd..297c6f7edd 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for +#pragma omp parallel for omp_num_threads(4) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index a9bd02fbd4..42952503f2 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -65,7 +65,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for +#pragma omp parallel for omp_num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +75,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for +#pragma omp parallel for omp_num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,7 +168,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for +#pragma omp parallel for omp_num_threads(4) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a1c293239d..618602874c 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1719,7 +1719,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(1) firstprivate(rng) +#pragma omp parallel for num_threads(64) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; From a687fac4bfdba7fef14c328f1a20148542697e1e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:29:01 +0200 Subject: [PATCH 360/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/simulation.h | 11 +---------- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 7 ++++--- 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/cpp/models/abm/simulation.h b/cpp/models/abm/simulation.h index 47abe1b48f..c8d6c1be6e 100644 --- a/cpp/models/abm/simulation.h +++ b/cpp/models/abm/simulation.h @@ -65,22 +65,13 @@ class Simulation template void advance(TimePoint tmax, History&... history) { + //log initial system state (history.log(*this), ...); - double sum = 0; while (m_t < tmax) { evolve_world(tmax); - double start, end; - #ifdef MEMILIO_ENABLE_OPENMP - start = omp_get_wtime(); - #endif (history.log(*this), ...); - #ifdef MEMILIO_ENABLE_OPENMP - end = omp_get_wtime(); - #endif - sum = sum + (end - start); } - std::cout << "Time spent on logging: " << sum << std::endl; } /** diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 297c6f7edd..d70909877d 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for omp_num_threads(4) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 42952503f2..2677dc3dad 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -56,6 +56,7 @@ Person& World::add_person(const LocationId id, AgeGroup age) void World::evolve(TimePoint t, TimeSpan dt) { + begin_step(t, dt); log_info("ABM World interaction."); interaction(t, dt); @@ -65,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for omp_num_threads(4) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -75,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for omp_num_threads(4) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -168,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for omp_num_threads(4) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; From d84c4dbdd20764fb4988d54f6d58da0cc2090f21 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:29:19 +0200 Subject: [PATCH 361/488] clluster 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 618602874c..e786a9ba48 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1129,14 +1129,6 @@ std::vector> distribute_grid_search(int rank, int num_procs, for (int i = 0; i < points_per_rank; i++) { grid_search_ranks.push_back(grid_search[i + rank * points_per_rank]); } - // we print the grid search for the rank - std::cout << "Rank " << rank << " has the following grid search: " << std::endl; - for (size_t i = 0; i < grid_search_ranks.size(); i++) { - for (size_t j = 0; j < grid_search_ranks[i].size(); j++) { - std::cout << grid_search_ranks[i][j] << " "; - } - std::cout << std::endl; - } return grid_search_ranks; } @@ -1767,7 +1759,6 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa auto run_rng_counter = mio::rng_totalsequence_counter(static_cast(j), mio::Counter(0)); rng.set_counter(run_rng_counter); - world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); @@ -2411,10 +2402,10 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{1.8, 2.2}, {2.5, 4.0}, {0.3, 0.7}}; + std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {2, 2, 2}; + std::vector points_per_dim = {9, 9, 9}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From d97cb50a6d614efe93ab6bcb41479f9ba4dfbac5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 18:22:28 +0200 Subject: [PATCH 362/488] test1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e786a9ba48..238ba17fe0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2382,7 +2382,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 9; + num_runs = 1; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); @@ -2405,7 +2405,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {9, 9, 9}; + std::vector points_per_dim = {6, 6, 6}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2417,7 +2417,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.8}, {2.5}, {0.3}, {0.033}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.8}, {2.5}, {0.5}, {0.033}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 4066f1135974b63bcb99e18ae47bbbc830213321 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 20:25:59 +0200 Subject: [PATCH 363/488] cluster? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 238ba17fe0..668be10f3d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2382,7 +2382,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 1; + num_runs = 9; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); @@ -2405,7 +2405,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {6, 6, 6}; + std::vector points_per_dim = {2, 9, 2}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2417,7 +2417,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.8}, {2.5}, {0.5}, {0.033}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.9375}, {2.0}, {0.5125}, {0.033}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 3eb8cda9309132863b94d972228bebeaef86f16e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 20:45:57 +0200 Subject: [PATCH 364/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 668be10f3d..4facc3997a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1705,6 +1705,12 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Distribute the grid search over the MPI ranks auto grid_search_rank = distribute_grid_search(rank, num_procs, grid_points); // short debug print to see if everything worked. Printing rank and amount of grid points as well as first point + std::cout << "Rank: " << rank << " has " << grid_search_rank.size() << " grid points" << std::endl; + std::cout << "First grid point: "; + for (size_t j = 0; j < grid_search_rank[0].size(); j++) { + std::cout << grid_search_rank[0].at(j) << " "; + } + std::cout << std::endl; // Run the grid search std::vector rmse_results_per_grid_point; @@ -2353,8 +2359,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2382,10 +2388,11 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 9; + num_runs = 1; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); + printf("Saving results to \"%s\".\n", result_dir.c_str()); } else { num_runs = 1; @@ -2405,7 +2412,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {2, 9, 2}; + std::vector points_per_dim = {2, 4, 2}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2417,7 +2424,8 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.9375}, {2.0}, {0.5125}, {0.033}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.9375}, {2.0, 3.0, 4.0}, {0.5125}, {0.033}, {20.0}, {10}, + {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From d21833ac8d2296b5e8568a9eeab8945ead9fe896 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 20:46:30 +0200 Subject: [PATCH 365/488] path Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4facc3997a..d19982080c 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2359,8 +2359,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From 31e4baad311eb1b7ba3b388dbe2fd03e27179b49 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 22:37:36 +0200 Subject: [PATCH 366/488] fix bug Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index d19982080c..f202711d97 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1717,11 +1717,17 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(64) firstprivate(rng) +#pragma omp parallel for num_threads(3) firstprivate(rng, initial_infection_distribution) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; printf("I am Thread %d\n", omp_get_thread_num()); + // print my parameters + std::cout << "Rank: " << rank << " Thread: " << omp_get_thread_num() << " Parameters: "; + for (size_t j = 0; j < params.size(); j++) { + std::cout << params.at(j) << " "; + } + std::cout << std::endl; const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; @@ -1886,6 +1892,8 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa auto rmse = calculate_rmse_from_results(input_dir, temp_sim_infection_state_per_age_group[0], temp_sim_cumulative_detected_infections_per_age_group[0], max_num_days, start_date); + //write rmse as debug output + std::cout << "RMSE: " << rmse << std::endl; rmse_results_per_grid_point.at(i) += rmse; } rmse_results_per_grid_point.at(i) /= num_runs; @@ -2424,8 +2432,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.9375}, {2.0, 3.0, 4.0}, {0.5125}, {0.033}, {20.0}, {10}, - {0.5}}; + std::vector> parameters = {{1.9375}, {2.0, 3.6}, {0.5125}, {0.033}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 7ec1b4d5025e8c4e7d57c3c005124b37d9985e2f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 22:59:16 +0200 Subject: [PATCH 367/488] big fat bug fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 67 +++++++++--------------- 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f202711d97..8d7e35cca9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -74,44 +74,23 @@ const std::map infection_ {mio::osecir::InfectionState::Recovered, mio::abm::InfectionState::Recovered}, {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; -mio::CustomIndexArray initial_infection_distribution{ - {mio::AgeGroup(num_age_groupss), mio::osecir::InfectionState::Count}, 0.5}; - std::map>> vacc_map; /** * Determine initial distribution of infection states. */ -void determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date, double sclaling_infected) +mio::CustomIndexArray +determine_initial_infection_states_world(const fs::path& input_dir, const mio::Date date, double sclaling_infected) { // estimate intial population by ODE compartiments - auto initial_graph = get_graph(date, 1, input_dir, sclaling_infected); - const size_t braunschweig_id = 16; // Braunschweig has ID 16 - auto braunschweig_node = initial_graph.value()[braunschweig_id]; - initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); -} + auto initial_graph = get_graph(date, 1, input_dir, sclaling_infected); + const size_t braunschweig_id = 16; // Braunschweig has ID 16 + auto braunschweig_node = initial_graph.value()[braunschweig_id]; + mio::CustomIndexArray initial_infection_distribution{ + {mio::AgeGroup(num_age_groupss), mio::osecir::InfectionState::Count}, 0.5}; -/** - * Assign an infection state to each person according to real world data read in through the ODE secir model. - * Infections are set with probabilities computed by the values in the rows in initial_infection_distribution. - */ -void assign_infection_state_prob(mio::abm::World& world, mio::abm::TimePoint t) -{ - // convert initial population to ABM initial infections - for (auto& person : world.get_persons()) { - if (person.get_should_be_logged()) { - auto rng = mio::abm::Person::RandomNumberGenerator(world.get_rng(), person); - - auto infection_state = mio::osecir::InfectionState(mio::DiscreteDistribution::get_instance()( - rng, initial_infection_distribution.slice(person.get_age()).as_array().array())); - - if (infection_state != mio::osecir::InfectionState::Susceptible) { - person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Alpha, person.get_age(), - world.parameters, t, - infection_state_map.at(infection_state))); - } - } - } + initial_infection_distribution.array() = braunschweig_node.populations.array().cast(); + return initial_infection_distribution; } /** @@ -121,7 +100,9 @@ void assign_infection_state_prob(mio::abm::World& world, mio::abm::TimePoint t) * The number of agents in the model should fit to the sum of the rows in initial_infection_distribution, * otherwise many agents will be susceptible. */ -void assign_infection_state(mio::abm::World& world, mio::abm::TimePoint t) +void assign_infection_state( + mio::abm::World& world, mio::abm::TimePoint t, + mio::CustomIndexArray initial_infection_distribution) { // save all persons with age groups std::vector> persons_by_age(num_age_groupss); @@ -1205,8 +1186,10 @@ void create_easter_social_event(mio::abm::World& world, double perc_easter_event * Create a sampled simulation with start time t0. * @param t0 The start time of the Simulation. */ -void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, - int max_num_persons, mio::Date start_date_sim, double perc_easter_event) +void create_sampled_world( + mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, int max_num_persons, + mio::Date start_date_sim, double perc_easter_event, + mio::CustomIndexArray initial_infection_distribution) { mio::unused(start_date_sim); //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -1225,7 +1208,7 @@ void create_sampled_world(mio::abm::World& world, const fs::path& input_dir, con restart_timer(timer, "time taken for setting up easter social ebent"); // Assign an infection state to each person. - assign_infection_state(world, t0); + assign_infection_state(world, t0, initial_infection_distribution); restart_timer(timer, "time taken for assigning infection state"); // Assign vaccination status to each person. @@ -1717,7 +1700,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(3) firstprivate(rng, initial_infection_distribution) +#pragma omp parallel for num_threads(3) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -1759,7 +1742,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa // Determine inital infection state distribution restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date, dark_figure); + auto initial_infection = determine_initial_infection_states_world(input_dir, start_date, dark_figure); restart_timer(timer, "time for determine_initial_infection_states_world"); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); @@ -1773,7 +1756,8 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rng.set_counter(run_rng_counter); world.get_rng() = rng; - create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event, + initial_infection); restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -2025,7 +2009,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // Determine inital infection state distribution restart_timer(timer, "time for initial setup"); - determine_initial_infection_states_world(input_dir, start_date, dark_figure); + auto initial_infection = determine_initial_infection_states_world(input_dir, start_date, dark_figure); restart_timer(timer, "time for determine_initial_infection_states_world"); prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); @@ -2039,7 +2023,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s rng.set_counter(run_rng_counter); world.get_rng() = rng; - create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event); + create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event, + initial_infection); restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -2367,8 +2352,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From c8009811b55dcaf18e99e2d21172cf222579aaee Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 22:59:49 +0200 Subject: [PATCH 368/488] prep cluster run Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8d7e35cca9..a498b51f23 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2352,8 +2352,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2405,7 +2405,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; // std::vector grid_boundaries = {2.3, 2.6, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {2, 4, 2}; + std::vector points_per_dim = {11, 11, 11}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 7b340321eca1ddfb734c308394a9083df6edce55 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 23:00:10 +0200 Subject: [PATCH 369/488] secando Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a498b51f23..e1e4178db2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2381,7 +2381,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 1; + num_runs = 9; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); From 1fef381e49c686ffd30206d2434cc846b4fc6fb0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 24 Aug 2024 23:37:47 +0200 Subject: [PATCH 370/488] omp fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e1e4178db2..efd2ba632a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1700,7 +1700,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(3) firstprivate(rng) +#pragma omp parallel for num_threads(64) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; From 13efcfc0bbf9cb40f2a059675134b029085a2423 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:32:09 +0200 Subject: [PATCH 371/488] other gs Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index efd2ba632a..7ebcdd62cf 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2402,8 +2402,8 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; - // std::vector grid_boundaries = {2.3, 2.6, 0.55}; + // std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; + std::vector grid_boundaries = {1.78, 3.28, 0.55}; // std::vector points_per_dim = {11, 11, 7, 11}; std::vector points_per_dim = {11, 11, 11}; auto grid = grid_points(grid_boundaries, points_per_dim); @@ -2417,7 +2417,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.9375}, {2.0, 3.6}, {0.5125}, {0.033}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.78}, {3.28}, {0.52}, {0.033}, {20.0}, {10}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From def4b7d870bfec8df571df722dd47eda850f9426 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 25 Aug 2024 17:51:40 +0200 Subject: [PATCH 372/488] cluster run the second Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7ebcdd62cf..4ea22dbc94 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -999,7 +999,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries run_with_grid_search(const fs::path& input_dir, const fs::pa const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.033; + // const double testing_probability_sympt = 0.033; + // const double ratio_asympt_to_sympt = 20.0; + const double testing_probability_sympt = params[3]; + const double ratio_asympt_to_sympt = params[4]; const double lockdown_test_prob = 1.1; const auto after_lockdown_test_prob = 0.9; @@ -1726,10 +1729,10 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double masks = 0.25; const double after_lockdown_contact_reduction = 0.50; - const double ratio_asympt_to_sympt = 20.0; - const double perc_easter_event = 0.2; - const auto quarantine_duration = mio::abm::days(10); - const double quarantine_effectiveness = 0.5; + + const double perc_easter_event = 0.2; + const auto quarantine_duration = mio::abm::days(10); + const double quarantine_effectiveness = 0.5; mio::Date start_date{2021, 3, 1}; int date_of_lockdown = 29; @@ -2403,9 +2406,11 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; - std::vector grid_boundaries = {1.78, 3.28, 0.55}; + std::vector> grid_boundaries = { + {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; + // std::vector grid_boundaries = {1.78, 3.28, 0.55, 0.034, }; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {11, 11, 11}; + std::vector points_per_dim = {3, 2, 3, 20, 20}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); @@ -2417,7 +2422,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.78}, {3.28}, {0.52}, {0.033}, {20.0}, {10}, {0.5}}; + std::vector> parameters = {{1.79}, {3.28}, {0.52}, {0.036}, {20.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 8b69d37e6abdb9639ab6ec2bcace2cfae8502827 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 25 Aug 2024 18:15:40 +0200 Subject: [PATCH 373/488] grid Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4ea22dbc94..0493a624b9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2410,7 +2410,7 @@ int main(int argc, char** argv) {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; // std::vector grid_boundaries = {1.78, 3.28, 0.55, 0.034, }; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {3, 2, 3, 20, 20}; + std::vector points_per_dim = {3, 2, 3, 17, 17}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 3f43374b7a4f3a045d8516f57a1955bcb4b10e3f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 25 Aug 2024 23:21:49 +0200 Subject: [PATCH 374/488] cluster grid Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 0493a624b9..fd2b62a62f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -999,7 +999,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries run_with_grid_search(const fs::path& input_dir, const fs::pa const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - // const double testing_probability_sympt = 0.033; - // const double ratio_asympt_to_sympt = 20.0; - const double testing_probability_sympt = params[3]; - const double ratio_asympt_to_sympt = params[4]; + const double testing_probability_sympt = 0.037; + const double ratio_asympt_to_sympt = 20.0; + // const double testing_probability_sympt = params[3]; + // const double ratio_asympt_to_sympt = params[4]; const double lockdown_test_prob = 1.1; const auto after_lockdown_test_prob = 0.9; @@ -2384,7 +2384,7 @@ int main(int argc, char** argv) printf("Saving results to \"%s\".\n", result_dir.c_str()); } else if (argc == 3) { - num_runs = 9; + num_runs = 11; run_grid_search = true; printf("running with grid search\n"); printf("Running with number of runs %d.\n", (int)num_runs); @@ -2405,12 +2405,12 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; - std::vector> grid_boundaries = { - {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; + std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; + // std::vector> grid_boundaries = { + // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; // std::vector grid_boundaries = {1.78, 3.28, 0.55, 0.034, }; // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {3, 2, 3, 17, 17}; + std::vector points_per_dim = {13, 13, 13}; auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); From 8ed3a753057a2d7165d8c935cb29a5faa9f951f4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sun, 25 Aug 2024 23:27:34 +0200 Subject: [PATCH 375/488] paper weights Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fd2b62a62f..6ea5d08b0b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -999,7 +999,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries Date: Mon, 26 Aug 2024 09:56:17 +0200 Subject: [PATCH 376/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 16 ++++++++-------- cpp/simulations/paper_abm_bs_testing.cpp | 18 +++++++++++------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 57a29fc8af..30769f8ba1 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -272,7 +272,7 @@ def plot_dead(path): # we need the real data json file cases_all_state_repdate_ma7 df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_age_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_age_ma7.json") # we just need the columns cases and date # we need to offset the dates by 19 day @@ -338,7 +338,7 @@ def plot_dead(path): def plot_icu(path): - df_abb = pd.read_json(path+"/../pydata/Germany/county_divi.json") + df_abb = pd.read_json(path+"/../../../pydata/Germany/county_divi.json") perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.56,0.54,0.46] perc_of_critical_in_icu=0.55 @@ -417,7 +417,7 @@ def plot_icu(path): # we calculate the RMSE - rmse_ICU = ((ICU_Real - ICU_Simulation_one_percentile)**2).mean() + rmse_ICU = ((ICU_Real - ICU_Simulation_one_percentile)**2).mean()*0.1 # plot the ICU beds and the ICU beds taken fig, ax = plt.subplots(1, 1, constrained_layout=True) @@ -594,7 +594,7 @@ def infer_positive_tests(path): # we need the real data from the json file cases_all_county_age_repdate_ma7.json df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") # we just need the columns cases and date df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] # we need just the dates bewteen 2021-03-01 and 2021-06-01 @@ -701,7 +701,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -783,7 +783,7 @@ def plot_cumulative_detected_infections(path): time = time[0:90] # we calculate the RMSE - rmse_detected = ((df_abb - total_50)**2).mean() *0.01*0.01*0.1 + rmse_detected = ((df_abb - total_50)**2).mean() *0.01 @@ -877,8 +877,8 @@ def plot_positive_and_done_test(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/128_runs/results_2024-08-21224038" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/123/results_2024-08-25204206" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6ea5d08b0b..071fb62542 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2405,13 +2405,17 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; + // std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; + // std::vector points_per_dim = {13, 13, 13}; + + std::vector grid_boundaries = {2.025, 2.66, 0.4}; + std::vector points_per_dim = {9, 9, 9}; + // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; - // std::vector grid_boundaries = {1.78, 3.28, 0.55, 0.034, }; - // std::vector points_per_dim = {11, 11, 7, 11}; - std::vector points_per_dim = {13, 13, 13}; - auto grid = grid_points(grid_boundaries, points_per_dim); + // std::vector points_per_dim = {4, 4, 4, 9, 9}; + + auto grid = grid_points(grid_boundaries, points_per_dim); if (rank == 0) { auto created = create_result_folders(result_dir, 0, run_grid_search); if (!created) { @@ -2422,7 +2426,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.79}, {3.28}, {0.52}, {0.036}, {20.0}, {10.0}, {0.5}}; + std::vector> parameters = {{2.025}, {2.66}, {0.4}, {0.031}, {7.125}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); @@ -2447,4 +2451,4 @@ int main(int argc, char** argv) std::cout << "Time taken: " << elapsed_seconds.count() << "s\n"; return 0; -} +} \ No newline at end of file From 1c47df4d19d17f00d48e29246926b7ddf4692b9d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 09:59:15 +0200 Subject: [PATCH 377/488] grid 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 071fb62542..2e6ea64e82 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2408,7 +2408,7 @@ int main(int argc, char** argv) // std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; // std::vector points_per_dim = {13, 13, 13}; - std::vector grid_boundaries = {2.025, 2.66, 0.4}; + std::vector grid_boundaries = {1.85, 3.06, 0.45}; std::vector points_per_dim = {9, 9, 9}; // std::vector> grid_boundaries = { From 0f086c0939ae804c0e8f7bac2cadadd83f015fec Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:01:25 +0200 Subject: [PATCH 378/488] grid 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2e6ea64e82..384b938a11 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2408,7 +2408,7 @@ int main(int argc, char** argv) // std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; // std::vector points_per_dim = {13, 13, 13}; - std::vector grid_boundaries = {1.85, 3.06, 0.45}; + std::vector grid_boundaries = {1.85, 3.06, 0.425}; std::vector points_per_dim = {9, 9, 9}; // std::vector> grid_boundaries = { From 602ed7179d651a27dddf9cbae68a502e4ac9aa7b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:25:08 +0200 Subject: [PATCH 379/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 384b938a11..33891b8644 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1013,7 +1013,7 @@ std::vector> grid_points(std::vector temp; double step = (parameter_boundaries[i].second - parameter_boundaries[i].first) / (number_of_points.at(i) - 1); - for (int j = 0; j < number_of_points.at(i) - 1; j++) { + for (int j = 0; j < number_of_points.at(i); j++) { temp.push_back(parameter_boundaries[i].first + j * step); } grid.push_back(temp); @@ -2405,11 +2405,12 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = {{1.5, 2.2}, {2.0, 3.6}, {0.4, 0.7}}; - // std::vector points_per_dim = {13, 13, 13}; + std::vector> grid_boundaries = { + {1.6, 2.2}, {2.0, 4.0}, {0.3, 0.7}, {0.030, 0.040}, {5, 9}}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; - std::vector grid_boundaries = {1.85, 3.06, 0.425}; - std::vector points_per_dim = {9, 9, 9}; + // std::vector grid_boundaries = {1.85, 3.06, 0.425}; + // std::vector points_per_dim = {9, 9, 9}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; @@ -2426,7 +2427,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{2.025}, {2.66}, {0.4}, {0.031}, {7.125}, {10.0}, {0.5}}; + std::vector> parameters = {{1.85}, {3.066}, {0.45}, {0.033}, {20}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 28ca7e68d971ee3125a2ab8690712d35a2c4a9b6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 12:35:28 +0200 Subject: [PATCH 380/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 33891b8644..7a298ebbf5 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -999,7 +999,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries Date: Mon, 26 Aug 2024 14:08:05 +0200 Subject: [PATCH 381/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7a298ebbf5..78b2c6bd2b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2405,12 +2405,12 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = { - {1.6, 2.2}, {2.0, 4.0}, {0.3, 0.7}, {0.030, 0.040}, {5, 9}}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + // std::vector> grid_boundaries = { + // {1.6, 2.2}, {2.0, 4.0}, {0.3, 0.7}, {0.030, 0.040}, {5, 9}}; + // std::vector points_per_dim = {4, 4, 4, 4, 4}; - // std::vector grid_boundaries = {1.85, 3.06, 0.425}; - // std::vector points_per_dim = {9, 9, 9}; + std::vector grid_boundaries = {2.025, 2.66, 0.4}; + std::vector points_per_dim = {9, 9, 9}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; @@ -2427,7 +2427,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.85}, {3.066}, {0.45}, {0.033}, {20}, {10.0}, {0.5}}; + std::vector> parameters = {{1.91}, {3.02}, {0.425}, {0.033}, {7.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 8c00962d8e822e139525eb4bab736f2ebbd35fbe Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:18:32 +0200 Subject: [PATCH 382/488] everything wrooong Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 39 +++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 78b2c6bd2b..bd64869a3f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -952,10 +952,10 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries> parameters = {{1.91}, {3.02}, {0.425}, {0.033}, {7.0}, {10.0}, {0.5}}; + std::vector> parameters = {{2.05}, {2.9}, {0.45}, {0.033}, {7.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 837857f8c00740019567b0f89e88122d0ee011ac Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:19:07 +0200 Subject: [PATCH 383/488] params Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bd64869a3f..314d654efa 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1747,10 +1747,10 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; const double damping_community_lockdown = 0.5; - const double testing_probability_sympt = 0.037; - const double ratio_asympt_to_sympt = 20.0; - // const double testing_probability_sympt = params[3]; - // const double ratio_asympt_to_sympt = params[4]; + // const double testing_probability_sympt = 0.037; + // const double ratio_asympt_to_sympt = 20.0; + const double testing_probability_sympt = params[3]; + const double ratio_asympt_to_sympt = params[4]; const double lockdown_test_prob = 1.1; const auto after_lockdown_test_prob = 0.9; From 478435527f8352250945e350f60fa7b36f8803eb Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:20:01 +0200 Subject: [PATCH 384/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 314d654efa..508b20b49d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2386,8 +2386,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2437,11 +2437,11 @@ int main(int argc, char** argv) // 4: perc have to test if npi active // std::vector> grid_boundaries = { - // {1.6, 2.2}, {2.0, 4.0}, {0.3, 0.7}, {0.030, 0.040}, {5, 9}}; - // std::vector points_per_dim = {4, 4, 4, 4, 4}; + {1.6, 2.2}, {2.0, 4.0}, {0.3, 0.7}, {0.030, 0.040}, {5, 9}}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; - std::vector grid_boundaries = {2.025, 2.66, 0.4}; - std::vector points_per_dim = {9, 9, 9}; + // std::vector grid_boundaries = {2.025, 2.66, 0.4}; + // std::vector points_per_dim = {9, 9, 9}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 834431d7253c944e91ed437fa738253af3672e10 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:20:18 +0200 Subject: [PATCH 385/488] buggg Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 508b20b49d..bfe8038845 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2436,7 +2436,7 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = { + std::vector> grid_boundaries = { {1.6, 2.2}, {2.0, 4.0}, {0.3, 0.7}, {0.030, 0.040}, {5, 9}}; std::vector points_per_dim = {4, 4, 4, 4, 4}; From 6e1074b835dac245f51d3cb6f3d1d64771b0ecad Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:22:33 +0200 Subject: [PATCH 386/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 132 +++--------------------------- 1 file changed, 13 insertions(+), 119 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 30769f8ba1..9e81b9e078 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -270,9 +270,9 @@ def plot_dead(path): age_group_access = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Total'] - # we need the real data json file cases_all_state_repdate_ma7 + # we need the real data json file cases_all_county_age df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_age_ma7.json") + path+"/../pydata/Germany/cases_all_county_age_ma1.json") # we just need the columns cases and date # we need to offset the dates by 19 day @@ -282,7 +282,7 @@ def plot_dead(path): (df_abb['Date'] <= '2021-06-01')] # we just need the cases with id 3101 df_abb = df_abb[df_abb['ID_County'] == 3101] - df_abb['Deaths'] = np.round(df_abb[['Deaths']].to_numpy()) + # df_abb['Deaths'] = np.round(df_abb[['Deaths']].to_numpy()) # we need the amount of dead persons for each age group: These are A00-A04, A05-A14, A15-A34, A35-A59, A60-A79, A80+ age_groups = ['A00-A04', 'A05-A14', 'A15-A34', 'A35-A59', 'A60-A79', 'A80+'] @@ -338,7 +338,7 @@ def plot_dead(path): def plot_icu(path): - df_abb = pd.read_json(path+"/../../../pydata/Germany/county_divi.json") + df_abb = pd.read_json(path+"/../pydata/Germany/county_divi.json") perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.56,0.54,0.46] perc_of_critical_in_icu=0.55 @@ -402,13 +402,13 @@ def plot_icu(path): total_95_age = total_95_age[::24][0:90] - ICU_Simulation_one_percentile = np.round(total_50[:, 5]*perc_of_critical_in_icu) + ICU_Simulation_one_percentile = np.floor(total_50[:, 5]*perc_of_critical_in_icu) ICU_Simulation = np.round(total_50_age[:, 5]) ICU_Simulation75 = np.round(total_75_age[:, 5]) ICU_Simulation25 = np.round(total_25_age[:, 5]) ICU_Simulation05 = np.round(total_05_age[:, 5]) ICU_Simulation95 = np.round(total_95_age[:, 5]) - ICU_Real = np.round(df_abb['ICU'][0:90]) + ICU_Real = df_abb['ICU'][0:90] #smooth the data # ICU_Real = gaussian_filter1d(ICU_Real, sigma=1, mode='nearest') @@ -572,110 +572,6 @@ def calc_positive_tests_overall(infection_states, sensitivity, specificity, r_sn 1-specificity)+((infection_states[:, 1]+infection_states[:, 2])*lt_asympt)*sensitivity return inferred_positive_tests_sympt+inferred_positive_tests_asympt, inferred_positive_tests_sympt, inferred_positive_tests_asympt -def infer_positive_tests(path): - # First way: we just take x amount of eahc compartment and fit this to the positive tested category. - # A few assumptions: - # 1. The specificities of the tests are 99.9% this means that we have 0.1% false positives. We just assme, that nonsymptomatics test themselves very rarely, e.g. we just take a fraction of symptomatic persons. - # 2. We just have a around 60% sensitivity, this means that we have 40% false negatives. - # 3. We assume that it is way more likely to test yourself if you are symptomatic than if you are asymptomatic - - # we need every compartment of the model - f_p50 = h5py.File( - path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') - p50_bs = f_p50['0'] - total_50 = p50_bs['Total'][()] - total_50 = total_50[::24] - total_50 = total_50[0:90] - - time = p50_bs['Time'][()] - time = time[::24] - time = time[0:90] - - - # we need the real data from the json file cases_all_county_age_repdate_ma7.json - df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") - # we just need the columns cases and date - df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] - # we need just the dates bewteen 2021-03-01 and 2021-06-01 - df_abb = df_abb[(df_abb['Date'] >= '2021-02-28') & - (df_abb['Date'] <= '2021-06-01')] - # we just take the first 90 days - df_abb= df_abb[df_abb['ID_County'] == 3101] - df_abb = df_abb[0:91] - - # we need the amount of new positive tests each day insetad of cumulative - df_abb['Confirmed'] = df_abb['Confirmed'].diff() - df_abb['Confirmed'] = df_abb['Confirmed'] - - sensitivity = 0.69 - specificity = 0.99 - # we need to derive the lowest rmse for the real positive tests and the inferred positive tests we use a grid search - # we need to find the best r_sns and lt_sympt - best_rmse = 1000000000 - best_r_sns = 0 - best_lt_sympt = 0 - for r_sns in np.linspace(1, 50, 100): - for lt_sympt in np.linspace(0.005, 0.1, 500): - total_positive_tests, inferred_positive_tests_sympt, inferred_positive_tests_asympt = calc_positive_tests_overall(total_50, sensitivity, specificity, r_sns, lt_sympt) - rmse = np.sqrt(((df_abb['Confirmed'][1:91] - total_positive_tests)**2).mean()) - if rmse < best_rmse: - best_rmse = rmse - best_r_sns = r_sns - best_lt_sympt = lt_sympt - - print("Best RMSE: ", best_rmse) - print("Best r_sns: ", best_r_sns) - print("Best lt_sympt: ", best_lt_sympt) - - - total_positive_tests, inferred_positive_tests_sympt, inferred_positive_tests_asympt = calc_positive_tests_overall(total_50, sensitivity, specificity, best_r_sns, best_lt_sympt) - - - # we save the assumed tests done - assumed__amount_of_test = (total_50[:, 3]*lt_sympt+total_50[:, 4]*lt_sympt+total_50[:, 5]*lt_sympt)+( - total_50[:, 0]*(best_lt_sympt/best_r_sns))+(total_50[:, 1]+total_50[:, 2])*(best_lt_sympt/best_r_sns) - - #plot the assumed tests done - fig, ax = plt.subplots(1, 1, constrained_layout=True) - fig.set_figwidth(20) - fig.set_figheight(9) - ax.plot(time, assumed__amount_of_test, color='tab:red') - ax.set_xlabel('time (days)') - ax.set_ylabel('Number of tests') - ax.title.set_text('Assumed amount of tests done') - ax.legend(['Assumed amount of tests done']) - plt.show() - - - - # we plot this - # we plot the tests positive and the real cases - start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') - xx = [start_date + pd.Timedelta(days=int(i)) for i in time] - xx = [xx[i].strftime('%Y-%m-%d') for i in range(len(xx))] - - plt.gca().set_xticks(time[::5]) - plt.gca().set_xticklabels(xx[::5]) - plt.gcf().autofmt_xdate() - - - - plt.plot(xx, inferred_positive_tests_sympt, color='tab:red') - plt.plot(xx, inferred_positive_tests_asympt, color='tab:blue') - plt.plot(xx, total_positive_tests, color='tab:green') - plt.plot(xx, df_abb['Confirmed'][1:91], color='tab:orange') - plt.xlabel('time (days)') - plt.ylabel('Number of positive tests') - plt.legend(['Assumed positive from Symptomatic', 'Assumed positive from Asymptomatic', - 'Assumed positive from all Persons', 'Real positive tests']) - - # we also write calculated best rmse, r_sns and lt_sympt into the title - plt.title('Positive tests inferred from model and real positive tests, RMSE: '+str(float("{:.2f}".format(best_rmse)))+' r_sns: '+str(float("{:.2f}".format(best_r_sns)))+' lt_sympt: '+str(float("{:.3f}".format(best_lt_sympt)))) - - - - plt.show() def plot_estimated_reproduction_number(path): f_p50 = h5py.File( @@ -701,7 +597,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../../../pydata/Germany/cases_all_county_repdate_ma7.json") + path+"/../pydata/Germany/cases_all_county_repdate.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -783,7 +679,7 @@ def plot_cumulative_detected_infections(path): time = time[0:90] # we calculate the RMSE - rmse_detected = ((df_abb - total_50)**2).mean() *0.01 + rmse_detected = ((df_abb - total_50)**2).mean() * 0.01 * 0.01 * 0.2 @@ -874,11 +770,10 @@ def plot_positive_and_done_test(path): plt.show() - if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/123/results_2024-08-25204206" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/123/results_2024-08-25204206" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): @@ -886,12 +781,11 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infection_states_results(path) - plot_infections_loc_types_avarage(path) + # plot_infection_states_results(path) + # plot_infections_loc_types_avarage(path) plot_icu(path) plot_dead(path) plot_cumulative_detected_infections(path) - plot_positive_and_done_test(path) + # plot_positive_and_done_test(path) - # infer_positive_tests(path) # plot_estimated_reproduction_number(path) From 11f1c8e1f66909a24876b3f702ed65101d1c85b5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:23:15 +0200 Subject: [PATCH 387/488] cluster2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bfe8038845..41f712b46e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2386,8 +2386,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From a307a9105eead3a0a9155196406dfef6bda52dab Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:27:46 +0200 Subject: [PATCH 388/488] test run Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 41f712b46e..782b47cc30 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2458,7 +2458,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{2.05}, {2.9}, {0.45}, {0.033}, {7.0}, {10.0}, {0.5}}; + std::vector> parameters = {{1.95}, {2.9}, {0.45}, {0.033}, {7.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 38d1a76ee924de9b6392f65b6c0cd6dd12451edb Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 26 Aug 2024 21:09:44 +0200 Subject: [PATCH 389/488] cluster run Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 30 ++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 782b47cc30..640eafd277 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -955,7 +955,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries Date: Tue, 27 Aug 2024 00:42:11 +0200 Subject: [PATCH 390/488] send it Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 640eafd277..1aa7568f2d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1737,7 +1737,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa rmse_results_per_grid_point.resize(grid_search_rank.size()); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(64) firstprivate(rng) +#pragma omp parallel for num_threads(72) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2443,8 +2443,8 @@ int main(int argc, char** argv) // 4: perc have to test if npi active std::vector> grid_boundaries = { - {1.6, 2.2}, {2.0, 4.0}, {0.3, 0.7}, {0.030, 0.040}, {5, 9}}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + {1.6, 2.2}, {2.5, 4.5}, {0.2, 0.8}, {0.025, 0.040}, {3, 11}}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {2.025, 2.66, 0.4}; // std::vector points_per_dim = {9, 9, 9}; @@ -2464,7 +2464,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.95}, {2.9}, {0.45}, {0.033}, {7.0}, {10.0}, {0.5}}; + std::vector> parameters = {{2.0}, {3.33}, {0.3}, {0.033}, {5.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 62a98a1d9bbc8c55b335553030cf4d80527020a2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 00:56:25 +0200 Subject: [PATCH 391/488] new gird search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1aa7568f2d..21176c90d8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1036,7 +1036,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {2.025, 2.66, 0.4}; - // std::vector points_per_dim = {9, 9, 9}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; + // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; + // std::vector points_per_dim = {5, 9, 9}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 8e0142056a99d029b309e585520839ddb339cb91 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 01:01:22 +0200 Subject: [PATCH 392/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 21176c90d8..f491abe11f 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2442,16 +2442,16 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = { - {1.6, 2.2}, {2.5, 4.5}, {0.2, 0.8}, {0.025, 0.040}, {3, 11}}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector> grid_boundaries = { + // {1.6, 2.2}, {2.5, 4.5}, {0.2, 0.8}, {0.025, 0.040}, {3, 11}}; + // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; + std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; - // std::vector points_per_dim = {5, 9, 9}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From e29096955d705be9180a02ba952bb7cae7a375ac Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 01:02:44 +0200 Subject: [PATCH 393/488] 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f491abe11f..c4f799dbef 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2446,8 +2446,8 @@ int main(int argc, char** argv) // {1.6, 2.2}, {2.5, 4.5}, {0.2, 0.8}, {0.025, 0.040}, {3, 11}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; + std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; From a791e88a74ad108bed01f6d9c50bc36e2665f81f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 01:03:03 +0200 Subject: [PATCH 394/488] 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c4f799dbef..694bea46f2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2447,8 +2447,8 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; - std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; - // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; + std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; std::vector points_per_dim = {4, 4, 4, 4, 4}; From d6726bfc4197474ed562f0fe29c935137b0ab3b6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 01:03:50 +0200 Subject: [PATCH 395/488] 4 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 694bea46f2..1d70f864e2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2448,8 +2448,8 @@ int main(int argc, char** argv) // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; - std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; + // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; + std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; std::vector points_per_dim = {4, 4, 4, 4, 4}; From 117ff34b8c6fecdc7888835df011d81b14487707 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 01:06:12 +0200 Subject: [PATCH 396/488] 5 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1d70f864e2..0c74a0b4d1 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2449,9 +2449,9 @@ int main(int argc, char** argv) // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; - std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; + std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From de81d1518f783e6707bf7e4f8ccd47ca767a2f3c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 10:48:03 +0200 Subject: [PATCH 397/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 0c74a0b4d1..6b58c090a8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1071,7 +1071,7 @@ std::vector> grid_points(const std::vector& paramete double min_value = parameter_points[i] * 0.95; double max_value = parameter_points[i] * 1.05; double step = (max_value - min_value) / (number_of_points.at(i) - 1); - for (int j = 0; j < number_of_points.at(i) - 1; j++) { + for (int j = 0; j < number_of_points.at(i); j++) { temp.push_back(min_value + j * step); } grid.push_back(temp); @@ -2442,16 +2442,16 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = { - // {1.6, 2.2}, {2.5, 4.5}, {0.2, 0.8}, {0.025, 0.040}, {3, 11}}; - // std::vector points_per_dim = {6, 6, 6, 6, 6}; + std::vector> grid_boundaries = { + {1.6, 2.2}, {2.5, 4.5}, {0.2, 0.8}, {0.025, 0.040}, {3, 11}}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; - std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; + // std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; @@ -2468,7 +2468,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{2.0}, {3.33}, {0.3}, {0.033}, {5.0}, {10.0}, {0.5}}; + std::vector> parameters = {{2.0}, {3.27}, {0.3}, {0.031}, {6.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 24c7a6ccf0353133b7597c47496397221c541d12 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 12:24:24 +0200 Subject: [PATCH 398/488] cluster... Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6b58c090a8..26878df40e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1036,7 +1036,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries> grid_points(const std::vector& paramete std::vector> grid; for (size_t i = 0; i < parameter_points.size(); i++) { std::vector temp; - double min_value = parameter_points[i] * 0.95; - double max_value = parameter_points[i] * 1.05; + double min_value = parameter_points[i] * 0.9; + double max_value = parameter_points[i] * 1.0; double step = (max_value - min_value) / (number_of_points.at(i) - 1); for (int j = 0; j < number_of_points.at(i); j++) { temp.push_back(min_value + j * step); @@ -1758,8 +1758,8 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double testing_probability_sympt = params[3]; const double ratio_asympt_to_sympt = params[4]; - const double lockdown_test_prob = 1.1; - const auto after_lockdown_test_prob = 0.9; + const double lockdown_test_prob = 1.2; + const auto after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; @@ -1990,8 +1990,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.1; - const double after_lockdown_test_prob = 0.9; + const double lockdown_test_prob = 1.2; + const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; @@ -2443,7 +2443,7 @@ int main(int argc, char** argv) // 4: perc have to test if npi active std::vector> grid_boundaries = { - {1.6, 2.2}, {2.5, 4.5}, {0.2, 0.8}, {0.025, 0.040}, {3, 11}}; + {1.7, 2.1}, {2.5, 4.0}, {0.2, 0.8}, {0.02, 0.04}, {4, 11}}; std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; @@ -2468,7 +2468,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{2.0}, {3.27}, {0.3}, {0.031}, {6.0}, {10.0}, {0.5}}; + std::vector> parameters = {{2.0}, {3.27}, {0.45}, {0.025}, {8.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From b46bc4c764990c2e934b33e7569ef2c8278061cc Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:30:29 +0200 Subject: [PATCH 399/488] 4.0 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 9e81b9e078..b0d5bce229 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -679,7 +679,7 @@ def plot_cumulative_detected_infections(path): time = time[0:90] # we calculate the RMSE - rmse_detected = ((df_abb - total_50)**2).mean() * 0.01 * 0.01 * 0.2 + rmse_detected = ((df_abb - total_50)**2).mean() * 0.01 * 0.01 * 4.0 From d027eb8034192ddd5e11522e9096d9f0d28d8844 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:39:59 +0200 Subject: [PATCH 400/488] omp Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 26878df40e..b35fcc0112 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1736,8 +1736,9 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); + omp_set_nested(2); omp_set_max_active_levels(2); -#pragma omp parallel for num_threads(72) firstprivate(rng) +#pragma omp parallel for num_threads(64) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2444,7 +2445,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = { {1.7, 2.1}, {2.5, 4.0}, {0.2, 0.8}, {0.02, 0.04}, {4, 11}}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; From 808d3d7b37eb0af43f961c66686190f852efbeec Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:47:25 +0200 Subject: [PATCH 401/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b35fcc0112..26e8a2f868 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1736,8 +1736,8 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); - omp_set_nested(2); - omp_set_max_active_levels(2); + omp_set_nested(1); + omp_set_max_active_levels(1); #pragma omp parallel for num_threads(64) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2445,7 +2445,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = { {1.7, 2.1}, {2.5, 4.0}, {0.2, 0.8}, {0.02, 0.04}, {4, 11}}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + std::vector points_per_dim = {4, 4, 4, 1, 1}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; From 8b2d7cf56cfb1a54ceef6b4ae2b06839c585c03a Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:41:15 +0200 Subject: [PATCH 402/488] cluster test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 6 ++-- cpp/simulations/paper_abm_bs_testing.cpp | 40 ++++++++++++++---------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index d70909877d..7715b917e5 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 2677dc3dad..fee597724d 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 26e8a2f868..cd60d97fe3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -74,8 +74,6 @@ const std::map infection_ {mio::osecir::InfectionState::Recovered, mio::abm::InfectionState::Recovered}, {mio::osecir::InfectionState::Dead, mio::abm::InfectionState::Dead}}; -std::map>> vacc_map; - /** * Determine initial distribution of infection states. */ @@ -166,7 +164,8 @@ size_t determine_age_group_from_rki(mio::AgeGroup age) } } -void prepare_vaccination_state(mio::Date simulation_end, const std::string& filename) +std::map>> prepare_vaccination_state(mio::Date simulation_end, + const std::string& filename) { // for saving previous day of vaccination std::vector> vacc_vector_prev(num_age_groupss); @@ -174,6 +173,7 @@ void prepare_vaccination_state(mio::Date simulation_end, const std::string& file for (size_t i = 0; i < num_age_groupss; ++i) { vacc_vector_prev[i] = std::make_pair(0, 0); } + std::map>> vacc_map{}; //Read in file with vaccination data auto vacc_data = mio::read_vaccination_data(filename).value(); @@ -202,6 +202,7 @@ void prepare_vaccination_state(mio::Date simulation_end, const std::string& file } } } + return vacc_map; } /** @@ -210,7 +211,8 @@ void prepare_vaccination_state(mio::Date simulation_end, const std::string& file * @param input * @return int */ -void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_beginning) +void assign_vaccination_state(mio::abm::World& world, mio::Date simulation_beginning, + std::map>> vacc_map) { // we check if we even have enough people to vaccinate in each respective age group std::vector num_persons_by_age(num_age_groupss); @@ -1050,6 +1052,9 @@ std::vector> grid_points(std::vector temp; double step = (parameter_boundaries[i].second - parameter_boundaries[i].first) / (number_of_points.at(i) - 1); + if (number_of_points.at(i) == 1) { + step = 0; + } for (int j = 0; j < number_of_points.at(i); j++) { temp.push_back(parameter_boundaries[i].first + j * step); } @@ -1071,6 +1076,9 @@ std::vector> grid_points(const std::vector& paramete double min_value = parameter_points[i] * 0.9; double max_value = parameter_points[i] * 1.0; double step = (max_value - min_value) / (number_of_points.at(i) - 1); + if (number_of_points.at(i) == 1) { + step = 0; + } for (int j = 0; j < number_of_points.at(i); j++) { temp.push_back(min_value + j * step); } @@ -1226,7 +1234,8 @@ void create_easter_social_event(mio::abm::World& world, double perc_easter_event void create_sampled_world( mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, int max_num_persons, mio::Date start_date_sim, double perc_easter_event, - mio::CustomIndexArray initial_infection_distribution) + mio::CustomIndexArray initial_infection_distribution, + std::map>> vacc_map) { mio::unused(start_date_sim); //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -1249,7 +1258,7 @@ void create_sampled_world( restart_timer(timer, "time taken for assigning infection state"); // Assign vaccination status to each person. - assign_vaccination_state(world, start_date_sim); + assign_vaccination_state(world, start_date_sim, vacc_map); restart_timer(timer, "time taken for assigning vaccination state"); set_local_parameters(world); } @@ -1736,15 +1745,14 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); - omp_set_nested(1); - omp_set_max_active_levels(1); #pragma omp parallel for num_threads(64) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; printf("I am Thread %d\n", omp_get_thread_num()); // print my parameters - std::cout << "Rank: " << rank << " Thread: " << omp_get_thread_num() << " Parameters: "; + std::cout << "Rank: " << rank << " Thread: " << omp_get_thread_num() << "place bound: " << omp_get_place_num() + << " Parameters: "; for (size_t j = 0; j < params.size(); j++) { std::cout << params.at(j) << " "; } @@ -1785,8 +1793,8 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa restart_timer(timer, "time for initial setup"); auto initial_infection = determine_initial_infection_states_world(input_dir, start_date, dark_figure); restart_timer(timer, "time for determine_initial_infection_states_world"); - prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), - (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); + auto vacc_map = prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); restart_timer(timer, "time for vaccinaiton state"); for (int j = 0; j < num_runs; j++) { @@ -1798,7 +1806,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event, - initial_infection); + initial_infection, vacc_map); restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -2052,8 +2060,8 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s restart_timer(timer, "time for initial setup"); auto initial_infection = determine_initial_infection_states_world(input_dir, start_date, dark_figure); restart_timer(timer, "time for determine_initial_infection_states_world"); - prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), - (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); + auto vacc_map = prepare_vaccination_state(mio::offset_date_by_days(start_date, (int)tmax.days()), + (input_dir / "pydata/Germany/vacc_county_ageinf_ma7.json").string()); restart_timer(timer, "time for vaccinaiton state"); // Loop over a number of runs for (size_t run_idx = start_run_idx; run_idx < end_run_idx; run_idx++) { @@ -2065,7 +2073,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event, - initial_infection); + initial_infection, vacc_map); restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -2445,7 +2453,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = { {1.7, 2.1}, {2.5, 4.0}, {0.2, 0.8}, {0.02, 0.04}, {4, 11}}; - std::vector points_per_dim = {4, 4, 4, 1, 1}; + std::vector points_per_dim = {4, 4, 4, 2, 2}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; From f84a37ffdcdde6ebb0c7fd52d3b915275df0f6a7 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:43:40 +0200 Subject: [PATCH 403/488] cluster Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index fee597724d..2677dc3dad 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; From 2aa2dc85c67cc14472bc03f9e96679281f8edf85 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:43:49 +0200 Subject: [PATCH 404/488] ss Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 7715b917e5..d70909877d 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(4) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); From fc9b7145e352d61edca032d0dd022f2eb92247a0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:54:32 +0200 Subject: [PATCH 405/488] test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index d70909877d..7715b917e5 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); From 870e777a5b3b5cf9f968ec128764144e03f8cc23 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 16:54:42 +0200 Subject: [PATCH 406/488] 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/world.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 2677dc3dad..fee597724d 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(4) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; From 77c4f81410b9afd797c2757961c035c5cfc27722 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:09:41 +0200 Subject: [PATCH 407/488] 128 test Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cd60d97fe3..e93773844e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1745,7 +1745,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); -#pragma omp parallel for num_threads(64) firstprivate(rng) +#pragma omp parallel for num_threads(128) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; From 91b35158618e853381ae7bd0efc44c3f41962faa Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:30:25 +0200 Subject: [PATCH 408/488] chill Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e93773844e..cd60d97fe3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1745,7 +1745,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); -#pragma omp parallel for num_threads(128) firstprivate(rng) +#pragma omp parallel for num_threads(64) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; From 6aebe2ea3209b6b66594e18730ed337ecfebb17f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:54:22 +0200 Subject: [PATCH 409/488] cluster grid Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/find_best_rmse.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/find_best_rmse.py b/cpp/simulations/find_best_rmse.py index 88f865a2e4..5c80a9a517 100644 --- a/cpp/simulations/find_best_rmse.py +++ b/cpp/simulations/find_best_rmse.py @@ -1,6 +1,6 @@ import os # Define the folder path -folder_path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/2/grid_search/grid_search" +folder_path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/rmse_grid/grid_search" # Initialize a list to store the RMSE values and parameters rmse_values = [] diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index cd60d97fe3..1e2b1c261b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1038,7 +1038,7 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); -#pragma omp parallel for num_threads(64) firstprivate(rng) +#pragma omp parallel for num_threads(128) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2401,8 +2401,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; @@ -2452,8 +2452,8 @@ int main(int argc, char** argv) // 4: perc have to test if npi active std::vector> grid_boundaries = { - {1.7, 2.1}, {2.5, 4.0}, {0.2, 0.8}, {0.02, 0.04}, {4, 11}}; - std::vector points_per_dim = {4, 4, 4, 2, 2}; + {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + std::vector points_per_dim = {8, 8, 8, 8, 8}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; @@ -2477,7 +2477,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{2.0}, {3.27}, {0.45}, {0.025}, {8.0}, {10.0}, {0.5}}; + std::vector> parameters = {{1.7}, {3.7}, {0.56}, {0.028}, {5.4}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 2b1097044cb7e0a70615216a56d178be8614bc74 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 22:54:47 +0200 Subject: [PATCH 410/488] gridsearch Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1e2b1c261b..b8edc195fa 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2401,8 +2401,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From 110a7769ac9ece80e2d285203262e2e2ac4123b6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:12:34 +0200 Subject: [PATCH 411/488] cluster search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b8edc195fa..62800daf63 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1745,7 +1745,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); -#pragma omp parallel for num_threads(128) firstprivate(rng) +#pragma omp parallel for num_threads(96) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2453,7 +2453,7 @@ int main(int argc, char** argv) std::vector> grid_boundaries = { {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; - std::vector points_per_dim = {8, 8, 8, 8, 8}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; From df8f94be91d3d533b4f2fdc23c0c79ce208d7bef Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:16:21 +0200 Subject: [PATCH 412/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 62800daf63..b055c63d39 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2451,16 +2451,14 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = { - {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector> grid_boundaries = { + // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 5.0}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.03, 5}; - // std::vector grid_boundaries = {1.8, 4, 0.433333, 0.0366667, 9}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0366667, 6.33333}; - // std::vector grid_boundaries = {2, 3.33333, 0.3, 0.0333333, 6.33333}; - // std::vector points_per_dim = {4, 4, 4, 4, 4}; + std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; + // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; + // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From d5d6830adff2a86f8139f369c20199fdf2993659 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:16:47 +0200 Subject: [PATCH 413/488] 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b055c63d39..3f74f2b61d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,8 +2455,8 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; - // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; + // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; + std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From 361d03a8014eb21e343ac5ff6ac52c3a26fc1659 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:18:09 +0200 Subject: [PATCH 414/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3f74f2b61d..28fff16a29 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,9 +2456,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; - std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; - // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; + std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 0c0c7fa7f52310ae9927298ba91ba6d438317750 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:21:00 +0200 Subject: [PATCH 415/488] again Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 28fff16a29..3f74f2b61d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,9 +2456,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; - // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; - std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; + // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 6e61389e31ecfe3bf92a691020a876325cf0d6fc Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:22:08 +0200 Subject: [PATCH 416/488] big grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3f74f2b61d..bf8361201e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2451,12 +2451,12 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = { - // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + std::vector> grid_boundaries = { + {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; - std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; + // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From c4346885efb2c75b958a5430b45f0e73843372af Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:22:46 +0200 Subject: [PATCH 417/488] grid point 1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bf8361201e..b055c63d39 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2451,11 +2451,11 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = { - {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + // std::vector> grid_boundaries = { + // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; + std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From 6329bef646e24531bdf06c88de9abe75e70d1452 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:23:59 +0200 Subject: [PATCH 418/488] grid point 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b055c63d39..3f74f2b61d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,8 +2455,8 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; - // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; + // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; + std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From 0160e0e01072003f94dbd21f8d25d6a465ac9b83 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:25:46 +0200 Subject: [PATCH 419/488] grid poiint 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3f74f2b61d..28fff16a29 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,9 +2456,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; - std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; - // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; + std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From f9fbbaedc831258684c344344799bae37f57d121 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:30:40 +0200 Subject: [PATCH 420/488] big grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 28fff16a29..bf8361201e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2451,14 +2451,14 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = { - // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + std::vector> grid_boundaries = { + {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; - std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From d0ebf2a638107f931c483b5f6cc35540705a5ee0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:08:30 +0200 Subject: [PATCH 421/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 +- cpp/simulations/find_best_rmse.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index b0d5bce229..2f2de406da 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -679,7 +679,7 @@ def plot_cumulative_detected_infections(path): time = time[0:90] # we calculate the RMSE - rmse_detected = ((df_abb - total_50)**2).mean() * 0.01 * 0.01 * 4.0 + rmse_detected = ((df_abb - total_50)**2).mean() * 0.01 * 0.01 * 3.0 diff --git a/cpp/simulations/find_best_rmse.py b/cpp/simulations/find_best_rmse.py index 5c80a9a517..b3f6a04319 100644 --- a/cpp/simulations/find_best_rmse.py +++ b/cpp/simulations/find_best_rmse.py @@ -1,6 +1,6 @@ import os # Define the folder path -folder_path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/rmse_grid/grid_search" +folder_path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/mse_2/grid_search" # Initialize a list to store the RMSE values and parameters rmse_values = [] diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bf8361201e..3961e5972d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2451,13 +2451,13 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - std::vector> grid_boundaries = { - {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + // std::vector> grid_boundaries = { + // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {1.7, 3.7, 0.56, 0.028, 5.4}; - // std::vector grid_boundaries = {1.7, 4, 0.56, 0.036, 11}; - // std::vector grid_boundaries = {1.7, 4, 0.56, 0.024, 4}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { @@ -2475,7 +2475,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.7}, {3.7}, {0.56}, {0.028}, {5.4}, {10.0}, {0.5}}; + std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 61b3a1ca3e2e81a284c63819a612754e00c02407 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:18:06 +0200 Subject: [PATCH 422/488] grid 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3961e5972d..44dee4c2f6 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,8 +2455,8 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From e888680dbc129f6c1d8e7fb61ebe0606d26bb1a0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:19:41 +0200 Subject: [PATCH 423/488] grid 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 44dee4c2f6..998d6d037d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,9 +2456,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; - // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From d2a033f2a14363fe46a30b73ef95051bc4db98a0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:32:05 +0200 Subject: [PATCH 424/488] griddd Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 998d6d037d..7c3fc48837 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,8 +2456,8 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; - std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { From 43195fed79d95bc8126ba91ca344dcaf0a570bf1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:33:57 +0200 Subject: [PATCH 425/488] grid 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7c3fc48837..3961e5972d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,10 +2455,10 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 928bf5c38e239d7e05d79a5d201455dadb066166 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:34:36 +0200 Subject: [PATCH 426/488] scenario 1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3961e5972d..2f038db206 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2475,7 +2475,9 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; + // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; + std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.07, 0.105}, + {15.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From c3a444e788448a13e28f8170f1c31b3baf864422 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:42:01 +0200 Subject: [PATCH 427/488] scnario 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2f038db206..61bee28ff4 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1995,18 +1995,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; + const double damping_community_lockdown = 0.8; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.2; + const double lockdown_test_prob = 1.0; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.25; - const double after_lockdown_contact_reduction = 0.50; + const double after_lockdown_contact_reduction = 1.0; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2122,7 +2122,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 + 0.5); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2146,7 +2146,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 + 0.75); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2476,7 +2476,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; - std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.07, 0.105}, + std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.105, 0.175}, {15.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From 48b4cb656d7b4322771830c23bf260fda0509f88 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:46:21 +0200 Subject: [PATCH 428/488] Revert "scnario 2" This reverts commit c3a444e788448a13e28f8170f1c31b3baf864422. --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 61bee28ff4..2f038db206 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1995,18 +1995,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.8; + const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.0; + const double lockdown_test_prob = 1.2; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.25; - const double after_lockdown_contact_reduction = 1.0; + const double after_lockdown_contact_reduction = 0.50; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2122,7 +2122,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.5); // from 2021-03-15 + 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2146,7 +2146,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.75); // from 2021-03-15 + 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2476,7 +2476,7 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; - std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.105, 0.175}, + std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.07, 0.105}, {15.0}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From 8878acc279a524780faf39b08a44ddc1ad775f4d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:59:45 +0200 Subject: [PATCH 429/488] par variaiotn Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 2f038db206..73260e141b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2476,9 +2476,9 @@ int main(int argc, char** argv) } else { // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; - std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.07, 0.105}, - {15.0}, {10.0}, {0.5}}; - auto every_combination = every_combination_of_parameters(parameters); + std::vector> parameters = { + {1.76}, {3.7}, {0.53}, {0.0175, 0.035, 0.0525, 0.07, 0.0875}, {5.0, 8.0, 11.0, 14.0, 17.0}, {10.0}, {0.5}}; + auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); if (!created) { From f552f6887f5a501ee83cb30f67b1d1896ec7c66d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:05:12 +0200 Subject: [PATCH 430/488] par var 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 73260e141b..a3a0b4572b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2477,7 +2477,7 @@ int main(int argc, char** argv) else { // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; std::vector> parameters = { - {1.76}, {3.7}, {0.53}, {0.0175, 0.035, 0.0525, 0.07, 0.0875}, {5.0, 8.0, 11.0, 14.0, 17.0}, {10.0}, {0.5}}; + {1.76}, {3.7}, {0.53}, {0.0175, 0.035, 0.0525, 0.07, 0.0875}, {15.0}, {2, 5, 8, 11, 14}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From d9aa11ce7f0f27b99e5866e12b0da878ad397560 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 14:06:15 +0200 Subject: [PATCH 431/488] par var 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a3a0b4572b..bda1db5a54 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2477,7 +2477,7 @@ int main(int argc, char** argv) else { // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; std::vector> parameters = { - {1.76}, {3.7}, {0.53}, {0.0175, 0.035, 0.0525, 0.07, 0.0875}, {15.0}, {2, 5, 8, 11, 14}, {0.5}}; + {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From b7660624f3d78486c89847bc59488f831d1df03b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:27:43 +0200 Subject: [PATCH 432/488] cluster point 1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bda1db5a54..a470a6180d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1745,7 +1745,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); -#pragma omp parallel for num_threads(96) firstprivate(rng) +#pragma omp parallel for num_threads(128) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2458,7 +2458,7 @@ int main(int argc, char** argv) std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; @@ -2475,9 +2475,9 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; - std::vector> parameters = { - {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; + std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; + // std::vector> parameters = { + // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From bc20bddb6d2d4d6ee951c486f369483bcfc8691d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:32:57 +0200 Subject: [PATCH 433/488] grid point 2 paper Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index a470a6180d..150802c436 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,8 +2455,8 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; std::vector points_per_dim = {4, 4, 4, 4, 4}; From 008ef1700211aed1132f8ab556b4a3e343357d82 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:40:49 +0200 Subject: [PATCH 434/488] point 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 150802c436..8a2662f293 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,9 +2456,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; - // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 328b2366cf16558c04c326e247d4230c77e73d95 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:24:06 +0200 Subject: [PATCH 435/488] scenario 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8a2662f293..ddc94399c7 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1608,10 +1608,10 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti antigen_test_parameters, testing_probability_sympt); auto testing_scheme_asympt_easter = mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, lockdown_start_date, easter_end_date, - antigen_test_parameters, 0.66 * testing_probability_asympt); + antigen_test_parameters, 1.0 * testing_probability_asympt); auto testing_scheme_sympt_easter = mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, lockdown_start_date, easter_end_date, - antigen_test_parameters, 0.66 * testing_probability_sympt); + antigen_test_parameters, 1.0 * testing_probability_sympt); auto testing_scheme_asympt_wl = mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, easter_end_date, lockdown_end_date, antigen_test_parameters, lockdown_prob * testing_probability_asympt); @@ -1995,18 +1995,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; + const double damping_community_lockdown = 0.8; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.2; + const double lockdown_test_prob = 1.0; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.25; - const double after_lockdown_contact_reduction = 0.50; + const double after_lockdown_contact_reduction = 1.0; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2122,7 +2122,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 + 0.5); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2146,7 +2146,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 + 0.75); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2475,7 +2475,8 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; + std::vector> parameters = {{1.76}, {3.7}, {1.0}, {0.035, 0.105, 0.175}, + {15.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; auto every_combination = every_combination_of_parameters(parameters); From f803bfdc3d0fe7a1f31afbf094cbe19e70852573 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:30:33 +0200 Subject: [PATCH 436/488] Revert "scenario 2" This reverts commit 328b2366cf16558c04c326e247d4230c77e73d95. --- cpp/simulations/paper_abm_bs_testing.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ddc94399c7..8a2662f293 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1608,10 +1608,10 @@ void add_npi_testing_strategies_to_world(mio::abm::Simulation& sim, mio::abm::Ti antigen_test_parameters, testing_probability_sympt); auto testing_scheme_asympt_easter = mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, lockdown_start_date, easter_end_date, - antigen_test_parameters, 1.0 * testing_probability_asympt); + antigen_test_parameters, 0.66 * testing_probability_asympt); auto testing_scheme_sympt_easter = mio::abm::TestingScheme(testing_criteria_sympt, testing_min_time, lockdown_start_date, easter_end_date, - antigen_test_parameters, 1.0 * testing_probability_sympt); + antigen_test_parameters, 0.66 * testing_probability_sympt); auto testing_scheme_asympt_wl = mio::abm::TestingScheme(testing_criteria_asympt, testing_min_time, easter_end_date, lockdown_end_date, antigen_test_parameters, lockdown_prob * testing_probability_asympt); @@ -1995,18 +1995,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.8; + const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.0; + const double lockdown_test_prob = 1.2; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.25; - const double after_lockdown_contact_reduction = 1.0; + const double after_lockdown_contact_reduction = 0.50; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2122,7 +2122,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.5); // from 2021-03-15 + 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2146,7 +2146,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.75); // from 2021-03-15 + 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2475,8 +2475,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.76}, {3.7}, {1.0}, {0.035, 0.105, 0.175}, - {15.0}, {10.0}, {0.5}}; + std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; auto every_combination = every_combination_of_parameters(parameters); From b33f181f0f1418e49b1a0f661c4d75a64cec4b83 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Wed, 28 Aug 2024 17:30:46 +0200 Subject: [PATCH 437/488] revert for normal simulation Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 8 ++++---- cpp/simulations/parameter_varation.py | 2 +- cpp/simulations/scenario_plots.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 2f2de406da..e72c07df35 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -773,7 +773,7 @@ def plot_positive_and_done_test(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/123/results_2024-08-25204206" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113051" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): @@ -781,11 +781,11 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - # plot_infection_states_results(path) - # plot_infections_loc_types_avarage(path) + plot_infection_states_results(path) + plot_infections_loc_types_avarage(path) plot_icu(path) plot_dead(path) plot_cumulative_detected_infections(path) - # plot_positive_and_done_test(path) + plot_positive_and_done_test(path) # plot_estimated_reproduction_number(path) diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index a2b204294a..262832e24b 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -107,7 +107,7 @@ def get_maximum_daily_infections(path, index): # values_2 = [40,30,20,10,1] path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/par_var/memilio/data/results_2024-08-22225357" - variable_1 = "quarantine lenth" + variable_1 = "quarantine length" variable_2 = "quarantine efficiancy" values_1 = [1,4,7,10,13,16] values_2 = [0.0,0.25,0.5,0.75,1.0] diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index fbfe71d4bc..69d28506ce 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -233,8 +233,8 @@ def plot_scenario(path, folder, folder_high, folder_enough): if __name__ == "__main__": - path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/scenarios/results_2024-08-22225823" # more tesring - path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/scenarios/results_2024-08-22230155" # no lockdown but much testing + path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113737" # more tesring + path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28114331" # no lockdown but much testing path_to_scenario_3 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" path_to_main_data = "0" path_to_high_testing_data = "1" From 7ad764dbe72a9e27189b8fc7d78500089dc21f8f Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 29 Aug 2024 06:51:00 +0200 Subject: [PATCH 438/488] grid 1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8a2662f293..b0ec0dd0e8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1074,7 +1074,7 @@ std::vector> grid_points(const std::vector& paramete for (size_t i = 0; i < parameter_points.size(); i++) { std::vector temp; double min_value = parameter_points[i] * 0.9; - double max_value = parameter_points[i] * 1.0; + double max_value = parameter_points[i] * 1.1; double step = (max_value - min_value) / (number_of_points.at(i) - 1); if (number_of_points.at(i) == 1) { step = 0; From 53c7378ba216e5b9c5bdbd701915533c3ea93d56 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 29 Aug 2024 06:52:06 +0200 Subject: [PATCH 439/488] grid 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b0ec0dd0e8..ac09b08dcd 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,9 +2456,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; - std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From c92b252ccddc7f51b394a9bb168e58f40e630a94 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 29 Aug 2024 06:54:57 +0200 Subject: [PATCH 440/488] grid 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ac09b08dcd..c58e35c276 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,8 +2455,8 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; std::vector points_per_dim = {4, 4, 4, 4, 4}; From fb8cb3a4d1da62ef498e3fc68333e315b2959542 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 29 Aug 2024 06:56:25 +0200 Subject: [PATCH 441/488] grid 1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c58e35c276..b0ec0dd0e8 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,10 +2455,10 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; - // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; + std::vector points_per_dim = {4, 4, 4, 4, 4}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 5b11e2bda5e50a9e0d09f87fc34365d8c15f5eff Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 30 Aug 2024 09:35:23 +0200 Subject: [PATCH 442/488] grid search Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b0ec0dd0e8..7e9e990967 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1073,8 +1073,8 @@ std::vector> grid_points(const std::vector& paramete std::vector> grid; for (size_t i = 0; i < parameter_points.size(); i++) { std::vector temp; - double min_value = parameter_points[i] * 0.9; - double max_value = parameter_points[i] * 1.1; + double min_value = parameter_points[i] * 0.95; + double max_value = parameter_points[i] * 1.05; double step = (max_value - min_value) / (number_of_points.at(i) - 1); if (number_of_points.at(i) == 1) { step = 0; From 77788a8a85ef0bae0dfc7b9574cf095e7d7b1ef6 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 30 Aug 2024 09:38:16 +0200 Subject: [PATCH 443/488] grid point 1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 7e9e990967..4027dddf80 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1745,7 +1745,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa std::vector rmse_results_per_grid_point; rmse_results_per_grid_point.resize(grid_search_rank.size()); -#pragma omp parallel for num_threads(128) firstprivate(rng) +#pragma omp parallel for num_threads(96) firstprivate(rng) for (size_t i = 0; i < grid_search_rank.size(); i++) { auto params = grid_search_rank[i]; @@ -2458,7 +2458,7 @@ int main(int argc, char** argv) // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {4, 4, 4, 4, 4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 668d25d64339f796d81875bc6f00f33cfb2d09a8 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 30 Aug 2024 09:42:09 +0200 Subject: [PATCH 444/488] grid point 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4027dddf80..222319304c 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,9 +2456,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; - std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 6a9a5cf8140f89d88ae2ffb8e89ca757c536c2e0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 30 Aug 2024 09:42:38 +0200 Subject: [PATCH 445/488] grid point 3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 222319304c..97df5557d9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,8 +2455,8 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; + std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From 5a5190fb1fab88976359c217ec9bd31f730317d4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Mon, 16 Sep 2024 21:53:21 +0200 Subject: [PATCH 446/488] better formatation --- cpp/simulations/scaling results.py | 148 ++++++++++++++++++----------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/cpp/simulations/scaling results.py b/cpp/simulations/scaling results.py index b7153a3493..b1fa3122fb 100644 --- a/cpp/simulations/scaling results.py +++ b/cpp/simulations/scaling results.py @@ -1,78 +1,110 @@ +from matplotlib.ticker import ScalarFormatter, LogLocator + import matplotlib.pyplot as plt +from decimal import Decimal +fontsize = 18 # First plot: Runtime vs. Number of Processors on # processors = [1, 2, 4, 8] # Number of processors # runtime = [[0.6, 0.8, 1.1, 2.2], # 0.025 mio agents per processor # [1.4, 1.8, 2.5, 4.5], # 0.05 mio agents per processor # [3.3, 4.8, 6.4, 9.5]] # 0.1 mio agents per processor -processors = [1, 2, 4, 8, 16, 32] # Number of processors -runtime = [ [02.0, 02.9, 04.5, 05.3, 06.1, 08.2], # 0.025 mio agents per processor - [05.7, 06.2, 08.9, 10.0, 12.1, 16.7], # 0.05 mio agents per processor - [11.2, 12.5, 16.8, 19.0, 24.3, 32.1], # 0.1 mio agents per processor - [23.6, 24.9, 32.1, 37.5, 47.9, 63.4]] # 0.2 mio agents per processor - -plt.figure() -for i in range(len(runtime)): - plt.plot(processors, runtime[i], marker='o') -plt.legend(['25k agents per processor', '50k agents per processor', '100k agents per processor', '200k agents per processor']) -plt.xlabel('Number of Processors') -plt.ylabel('Runtime (seconds)') -plt.title('Runtime vs. Number of Processors for 25/50/100/200 k Agents per Processor for 10 days') +# processors = [1, 2, 4, 8, 16, 32] # Number of processors +# runtime = [ [02.0, 02.9, 04.5, 05.3, 06.1, 08.2], # 0.025 mio agents per processor +# [05.7, 06.2, 08.9, 10.0, 12.1, 16.7], # 0.05 mio agents per processor +# [11.2, 12.5, 16.8, 19.0, 24.3, 32.1], # 0.1 mio agents per processor +# [23.6, 24.9, 32.1, 37.5, 47.9, 63.4]] # 0.2 mio agents per processor +# fig = plt.figure(figsize=(12, 9)) +# for i in range(len(runtime)): +# plt.plot(processors, runtime[i], marker='o', linewidth=3) -plt.grid(True) -plt.show() +# plt.legend(['25k agents per processor', '50k agents per processor', '100k agents per processor', '200k agents per processor'], fontsize=fontsize) +# plt.xlabel('Number of Processors', fontsize=fontsize) +# plt.ylabel('Runtime (seconds)', fontsize=fontsize) +# plt.title('Node level weak scaling', fontsize=fontsize+4) +# plt.grid(True) +# plt.show() # Second plot: Speedup vs. Number of Processors # time for 6400k agents on x processors -processors = [1, 2, 4, 8, 16, 32] # Number of processors -time_800k = [95, 49, 32, 19, 12.1, 8.3] # Time in seconds -time_6400k = [741, 407, 220, 143, 93, 59] # Time in seconds -speedup = [time_6400k[0] / t for t in time_6400k] -ideal_speedup = [p for p in processors] +# processors = [1, 2, 4, 8, 16, 32] # Number of processors +# time_800k = [95, 49, 32, 19, 12.1, 8.3] # Time in seconds +# time_6400k = [741, 407, 220, 143, 93, 59] # Time in seconds +# speedup = [time_6400k[0] / t for t in time_6400k] +# ideal_speedup = [p for p in processors] + +# plt.figure() +# plt.plot(processors, speedup, marker='o') +# plt.plot(processors, ideal_speedup, marker='o') +# plt.xlabel('Number of Processors') +# plt.ylabel('Speedup') +# plt.title('Speedup vs. Number of Processors for 6.4mio Agents') +# plt.legend(['Speedup', 'Ideal Speedup']) +# plt.grid(True) +# plt.show() -plt.figure() -plt.plot(processors, speedup, marker='o') -plt.plot(processors, ideal_speedup, marker='o') -plt.xlabel('Number of Processors') -plt.ylabel('Speedup') -plt.title('Speedup vs. Number of Processors for 6.4mio Agents') -plt.legend(['Speedup', 'Ideal Speedup']) -plt.grid(True) -plt.show() -# Third plot: CPU Time vs. Population Size on 8 processors -population_size = [25, 50, 100, 200, 400, 800, 1600, 3200,6400] # Population size in thousand + +# # Third plot: CPU Time vs. Population Size on 8 processors +population_size = [25, 50, 100, 200, 400, 800, 1600, 3200, 6400] # Population size in thousand population_size = [p * 1000 for p in population_size] -cpu_time_real = [0.32,0.84,2.5,5.3,10.1,19.2,37.5,72.9,148] # CPU time in seconds -# we also need the avarage number of seconds per 1000 agents +cpu_time_real = [0.32, 0.84, 2.5, 5.3, 10.1, 19.2, 37.5, 72.9, 148] # CPU time in seconds +# we also need the average number of seconds per 1000 agents cpu_time_per_1000 = [t / p for t, p in zip(cpu_time_real, population_size)] -avarage_cpu_time_per_1000 = sum(cpu_time_per_1000) / len(cpu_time_per_1000) -#calculate the CP time with the avarage for above population sizes -cpu_time_av = [p * avarage_cpu_time_per_1000 for p in population_size] +average_cpu_time_per_1000 = sum(cpu_time_per_1000) / len(cpu_time_per_1000) +# calculate the CPU time with the average for above population sizes +cpu_time_av = [p * average_cpu_time_per_1000 for p in population_size] + +# Fourth plot: Memory Usage vs. Population Size +population_size_memory = [25, 50, 100, 200, 400, 800, 1600, 3200] # Population size in thousand +population_size_memory = [p * 1000 for p in population_size_memory] +memory_usage = [10, 22, 50, 111, 228, 455, 900, 1777] # Memory usage in MB +average_memory_usage = sum(memory_usage) / len(memory_usage) * 1e-6 +mem_av = [p * average_memory_usage for p in population_size_memory] -plt.figure() -#logarithmic scale -plt.yscale('log') -plt.xscale('log') -plt.plot(population_size, cpu_time_real, marker='o') -plt.plot(population_size, cpu_time_av, marker='x', alpha=0.5) -plt.legend(['Real CPU Time', 'Constant CPU time = '+str(avarage_cpu_time_per_1000)+' * Population Size']) -plt.xlabel('Population Size') -plt.ylabel('CPU Time (seconds)') -plt.title('CPU Time vs. Population Size in thousand') -plt.grid(True) -plt.show() +fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 9)) -# Fourth plot: Memory Usage vs. Population Size -population_size = [25, 50, 100, 200, 400, 800, 1600, 3200] # Population size in thousand -population_size = [p * 1000 for p in population_size] -memory_usage = [10,22, 50, 111, 228,455,900,1777] # Memory usage in MB +# Plot for CPU Time vs. Population Size + +ax1.plot(population_size, cpu_time_real, marker='o', linewidth=3) +ax1.plot(population_size, cpu_time_av, linewidth=3, linestyle='dashed', color='black', label='Average CPU time') +ax1.set_yscale('log') +ax1.set_xscale('log') +ax1.legend(['Runtime Simulation', 'Linear Scaling:' +'%.2E' % Decimal(average_cpu_time_per_1000)+' Seconds / Agent'], fontsize=fontsize) +ax1.set_xlabel('Population Size',fontsize=fontsize) +ax1.set_ylabel('Runtime (seconds)',fontsize=fontsize) +ax1.tick_params(axis='both', which='major', labelsize=fontsize-4) +ax1.yaxis.set_major_formatter(ScalarFormatter()) +ax1.yaxis.set_minor_formatter(ScalarFormatter()) +ax1.yaxis.set_major_locator(LogLocator(base=10.0, numticks=15)) +ax1.yaxis.set_minor_locator(LogLocator(base=10.0, numticks=15)) +# x ticks should be from 10000 to 10000000 +ax1.set_xticks([10000, 100000, 1000000, 10000000]) +ax1.get_xaxis().set_major_locator(LogLocator(base=10.0, numticks=15)) +ax1.get_xaxis().set_minor_locator(LogLocator(base=10.0, numticks=15)) +ax1.set_title('Runtime Scaling',fontsize=fontsize+4) +ax1.grid(True) + +# Plot for Memory Usage vs. Population Size +ax2.plot(population_size_memory, memory_usage, marker='o', linewidth=3) +ax2.plot(population_size_memory, mem_av, linewidth=3, linestyle='dashed', color='black', label='Average Memory Usage') +ax2.legend(['Memory Usage Simulation', 'Linear Scaling:' + '%.2E' % Decimal(average_memory_usage)+' MB / Agent'], fontsize=fontsize) +ax2.set_xscale('log') +ax2.set_yscale('log') +ax2.set_xlabel('Population Size',fontsize=fontsize) +ax2.set_ylabel('Memory Usage (MB)',fontsize=fontsize) +ax2.set_title('Memory Usage Scaling',fontsize=fontsize+4) +ax2.tick_params(axis='both', which='major', labelsize=fontsize-4) +ax2.yaxis.set_major_formatter(ScalarFormatter()) +ax2.yaxis.set_minor_formatter(ScalarFormatter()) +ax2.yaxis.set_major_locator(LogLocator(base=10.0, numticks=15)) +ax2.yaxis.set_minor_locator(LogLocator(base=10.0, numticks=15)) +# x ticks should be from 10000 to 10000000 +ax2.set_xticks([10000, 100000, 1000000, 10000000]) +ax2.get_xaxis().set_major_locator(LogLocator(base=10.0, numticks=15)) +ax2.get_xaxis().set_minor_locator(LogLocator(base=10.0, numticks=15)) +ax2.grid(True) -plt.figure() -plt.plot(population_size, memory_usage, marker='o') -plt.xlabel('Population Size') -plt.ylabel('Memory Usage (MB)') -plt.title('Memory Usage vs. Population Size') -plt.grid(True) +plt.tight_layout() plt.show() \ No newline at end of file From 78f88a1318e12e5f1a97b5eba25a6208e5ecf92d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:21:59 +0200 Subject: [PATCH 447/488] benchmark Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/benchmarks/abm.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/cpp/benchmarks/abm.cpp b/cpp/benchmarks/abm.cpp index 4ab2ed0c57..acdf8cf293 100644 --- a/cpp/benchmarks/abm.cpp +++ b/cpp/benchmarks/abm.cpp @@ -169,20 +169,16 @@ void abm_benchmark(benchmark::State& state, size_t num_persons, std::initializer //have to be adjusted to get the benchmark back to normal. //For small sizes (e.g. 10k) extreme cases are too likely, i.e. infections die out //or overwhelm everything, so we don't benchmark these. Results should be mostly transferrable. -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_25k_pt, 25000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50k_pt, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100k_pt, 100000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_200k_pt, 200000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_400k_pt, 400000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_800k_pt, 800000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_1600k_pt, 1600000, {14159265u, 35897932u}) -// ->Unit(benchmark::kMillisecond); -// BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) -// ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_25000k_pt, 25000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50000k_pt, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100000k_pt, 100000, {14159265u, 35897932u}) +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_25k_pt, 25000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_50k_pt, 50000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100k_pt, 100000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_200k_pt, 200000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_400k_pt, 400000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_800k_pt, 800000, {14159265u, 35897932u})->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_1600k_pt, 1600000, {14159265u, 35897932u}) ->Unit(benchmark::kMillisecond); -BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_100000k_pt, 1000000, {14159265u, 35897932u}) +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 3200000, {14159265u, 35897932u}) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(abm_benchmark, abm_benchmark_3200k_pt, 6400000, {14159265u, 35897932u}) ->Unit(benchmark::kMillisecond); BENCHMARK_MAIN(); From 1ce9b87cd1a602d394543f67b627cf4bad44373b Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 17 Sep 2024 20:24:17 +0200 Subject: [PATCH 448/488] benchmakr_change Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 7715b917e5..d6e4937488 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index fee597724d..7375516f99 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; From c2bc07ce2c057869765f8c4ef54e6f70e4c4e33e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:14:29 +0200 Subject: [PATCH 449/488] some imrpvoements Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/infection.cpp | 13 +++----- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 6 ++-- cpp/simulations/paper_abm_bs_testing.cpp | 38 +++++++++++++----------- cpp/simulations/setup.md | 12 ++++---- 5 files changed, 34 insertions(+), 37 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index e33e6bbc22..66daa866a0 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -60,17 +60,12 @@ Infection::Infection(Person::RandomNumberGenerator& rng, VirusVariant virus, Age ScalarType Infection::get_viral_load(TimePoint t) const { - if (t >= m_viral_load.start_date && t <= m_viral_load.end_date) { - if (t.days() <= m_viral_load.start_date.days() + m_viral_load.peak / m_viral_load.incline) { - return m_viral_load.incline * (t - m_viral_load.start_date).days(); - } - else { - return m_viral_load.peak + m_viral_load.decline * (t.days() - m_viral_load.peak / m_viral_load.incline - - m_viral_load.start_date.days()); - } + if (t.days() <= m_viral_load.start_date.days() + m_viral_load.peak / m_viral_load.incline) { + return m_viral_load.incline * (t - m_viral_load.start_date).days(); } else { - return 0.; + return m_viral_load.peak + m_viral_load.decline * (t.days() - m_viral_load.peak / m_viral_load.incline - + m_viral_load.start_date.days()); } } diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index d6e4937488..a7e9ae34bd 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for num_threads(8) +#pragma omp parallel for for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 7375516f99..1f3e80ab39 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(8) +#pragma omp parallel for for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(8) +#pragma omp parallel for for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(8) +#pragma omp parallel for for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 97df5557d9..ff7d5f5ab1 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1008,17 +1008,17 @@ double calculate_rmse_from_results(const fs::path& data_dir, mio::TimeSeries()[antigen_test]; // Test parameters - auto testing_min_time = mio::abm::days(3); - auto vector_sympt_states = std::vector{mio::abm::InfectionState::InfectedSymptoms}; - auto vector_asympt_states = - std::vector{mio::abm::InfectionState::InfectedNoSymptoms, - mio::abm::InfectionState::Exposed, mio::abm::InfectionState::Susceptible}; + auto testing_min_time = mio::abm::days(3); + auto vector_sympt_states = std::vector{mio::abm::InfectionState::InfectedSymptoms, + mio::abm::InfectionState::InfectedSevere, + mio::abm::InfectionState::InfectedCritical}; + auto vector_asympt_states = std::vector{ + mio::abm::InfectionState::InfectedNoSymptoms, mio::abm::InfectionState::Exposed, + mio::abm::InfectionState::Susceptible, mio::abm::InfectionState::Recovered}; auto testing_criteria_asympt = mio::abm::TestingCriteria({}, vector_asympt_states); auto testing_criteria_sympt = mio::abm::TestingCriteria({}, vector_sympt_states); @@ -2401,8 +2403,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; diff --git a/cpp/simulations/setup.md b/cpp/simulations/setup.md index 20dc743b80..fa716655b1 100644 --- a/cpp/simulations/setup.md +++ b/cpp/simulations/setup.md @@ -4,9 +4,9 @@ 2. You need to save this file into the folder:"/memilio/data/mobility/braunschweig_result_ffa8.csv" 3. You need to run cleanup_data.py (install numpy and pandas beforehand) please change the folders 4. You need to download the simulation files. Please follow the installation instructions at "" -5. Run "python getSimulationData.py -s 2021-01-01 -e 2021-07-01 -m 7" -6. Run "python getSimulationData.py -s 2021-01-01 -e 2021-07-01 -m 7 --rep-date" -6. Copy the Germany folder into data/mobility/Germany -9. Change the folder in paper_abm_testing to your data folder. -10. cmake --build /Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/build --config Release --target paper_abm_bs_testing -j 6 -- -11. ./memilio/cpp/build/bin/paper_abm_bs_testing +5. Run "python getSimulationData.py -s 2021-01-01 -e 2021-07-01 -m 1" +6. Run "python getSimulationData.py -s 2021-01-01 -e 2021-07-01 -m 1 --rep-date" +7. Copy the Germany folder into data/mobility/Germany +8. Change the folder in paper_abm_testing to your data folder. +9. cmake --build /Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/build --config Release --target paper_abm_bs_testing -j 6 -- +10. ./memilio/cpp/build/bin/paper_abm_bs_testing From 1110be82eee0e40088189959a4ade8831821e842 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 19 Sep 2024 01:52:50 +0200 Subject: [PATCH 450/488] counter per person Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/person.cpp | 3 ++- cpp/models/abm/person.h | 4 ++-- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 10 +++++----- cpp/models/abm/world.h | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 19 ++++++++++--------- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/cpp/models/abm/person.cpp b/cpp/models/abm/person.cpp index 5c3e4308dc..243d91ac5c 100755 --- a/cpp/models/abm/person.cpp +++ b/cpp/models/abm/person.cpp @@ -32,7 +32,7 @@ namespace mio namespace abm { -Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t person_id) +Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t counter, uint32_t person_id) : m_location(&location) , m_assigned_locations((uint32_t)LocationType::Count, INVALID_LOCATION_INDEX) , m_quarantine_start(TimePoint(-(std::numeric_limits::max() / 2))) @@ -45,6 +45,7 @@ Person::Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age , m_person_id(person_id) , m_cells{0} , m_last_transport_mode(TransportMode::Unknown) + , m_rng_counter{counter} { m_random_workgroup = UniformDistribution::get_instance()(rng); m_random_schoolgroup = UniformDistribution::get_instance()(rng); diff --git a/cpp/models/abm/person.h b/cpp/models/abm/person.h index d3ed51095e..e43652734d 100755 --- a/cpp/models/abm/person.h +++ b/cpp/models/abm/person.h @@ -128,7 +128,7 @@ class Person * @param[in] age The AgeGroup of the Person. * @param[in] person_id Index of the Person. */ - explicit Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, + explicit Person(mio::RandomNumberGenerator& rng, Location& location, AgeGroup age, uint32_t counter = 0, uint32_t person_id = INVALID_PERSON_ID); /** @@ -553,7 +553,7 @@ class Person uint32_t m_person_id; ///< Id of the Person. std::vector m_cells; ///< Vector with all Cell%s the Person visits at its current Location. mio::abm::TransportMode m_last_transport_mode; ///< TransportMode the Person used to get to its current Location. - Counter m_rng_counter{0}; ///< counter for RandomNumberGenerator. + Counter m_rng_counter; ///< counter for RandomNumberGenerator. bool m_should_be_logged = true; ///< Flag to determine if the Person should be logged. bool m_goes_to_easter_event = false; ///< Flag to determine if the Person goes to an Easter event. }; diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index a7e9ae34bd..7715b917e5 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 1f3e80ab39..6091444851 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -43,11 +43,11 @@ LocationId World::add_location(LocationType type, uint32_t num_cells) return id; } -Person& World::add_person(const LocationId id, AgeGroup age) +Person& World::add_person(const LocationId id, AgeGroup age, uint32_t counter) { assert(age.get() < parameters.get_num_groups()); uint32_t person_id = static_cast(m_persons.size()); - m_persons.push_back(std::make_unique(m_rng, get_individualized_location(id), age, person_id)); + m_persons.push_back(std::make_unique(m_rng, get_individualized_location(id), age, counter, person_id)); auto& person = *m_persons.back(); person.set_assigned_location(m_cemetery_id); get_individualized_location(id).add_person(person); @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; diff --git a/cpp/models/abm/world.h b/cpp/models/abm/world.h index d9b2e0b552..2ae8d8585d 100644 --- a/cpp/models/abm/world.h +++ b/cpp/models/abm/world.h @@ -174,7 +174,7 @@ class World * @param[in] age AgeGroup of the person. * @return Reference to the newly created Person. */ - Person& add_person(const LocationId id, AgeGroup age); + Person& add_person(const LocationId id, AgeGroup age, uint32_t counter = 0); /** * @brief Get a range of all Location%s in the World. diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ff7d5f5ab1..f7e00f143d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -381,7 +381,8 @@ mio::AgeGroup determine_age_group(uint32_t age) } } -void create_world_from_data(mio::abm::World& world, const std::string& filename, const int max_number_persons) +void create_world_from_data(mio::abm::World& world, const std::string& filename, const int max_number_persons, + const int run_number) { // Open File; we use the cleaned up version of https://zenodo.org/records/13318436 @@ -525,7 +526,7 @@ void create_world_from_data(mio::abm::World& world, const std::string& filename, auto it_person = persons.find(person_id); if (it_person == persons.end()) { auto home = locations.find(home_id)->second; - auto& person = world.add_person(home, determine_age_group(age)); + auto& person = world.add_person(home, determine_age_group(age), run_number * 1000000); person.set_mask_preferences({0.0, -0.1, -0.1, -0.3, -0.2, -0.0, -0.0, -0.0, -0.0, -0.0, 0.0, -0.0}); person.set_assigned_location(home); person.set_assigned_location(hospital); @@ -1235,7 +1236,7 @@ void create_sampled_world( mio::abm::World& world, const fs::path& input_dir, const mio::abm::TimePoint& t0, int max_num_persons, mio::Date start_date_sim, double perc_easter_event, mio::CustomIndexArray initial_infection_distribution, - std::map>> vacc_map) + std::map>> vacc_map, uint32_t run_number) { mio::unused(start_date_sim); //Set global infection parameters (similar to infection parameters in SECIR model) and initialize the world @@ -1246,7 +1247,7 @@ void create_sampled_world( // Create the world object from statistical data. create_world_from_data(world, (input_dir / "mobility/braunschweig_result_ffa8_modified2.csv").generic_string(), - max_num_persons); + max_num_persons, run_number); world.use_migration_rules(false); restart_timer(timer, "time taken for braunschweig trip input"); @@ -1808,7 +1809,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event, - initial_infection, vacc_map); + initial_infection, vacc_map, j); restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -2075,7 +2076,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s world.get_rng() = rng; create_sampled_world(world, input_dir, t0, max_num_persons, start_date, perc_easter_event, - initial_infection, vacc_map); + initial_infection, vacc_map, (uint32_t)run_idx); restart_timer(timer, "time taken for create sampled world"); auto sim = mio::abm::Simulation(t0, std::move(world)); @@ -2453,11 +2454,11 @@ int main(int argc, char** argv) // 3: testing prob symptomatic // 4: perc have to test if npi active - // std::vector> grid_boundaries = { - // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + std::vector> grid_boundaries = { + {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; + // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From f1a251f1c2e09d6891aa87c4d816ad711b003cad Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 19 Sep 2024 01:55:01 +0200 Subject: [PATCH 451/488] cluster run? Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index f7e00f143d..ded802e3c7 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2404,8 +2404,8 @@ int main(int argc, char** argv) rng.seed(seeds); rng.synchronize(); - // std::string input_dir = "/p/project1/loki/memilio/memilio/data"; - std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; + std::string input_dir = "/p/project1/loki/memilio/memilio/data"; + // std::string input_dir = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data"; // std::string input_dir = "/Users/david/Documents/HZI/memilio/data"; // std::string input_dir = "C:/Users/korf_sa/Documents/rep/data"; From 598f0174d5827386ef9a57227c6085b518f751eb Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 19 Sep 2024 22:23:10 +0200 Subject: [PATCH 452/488] grid search again --- cpp/simulations/paper_abm_bs_testing.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index ded802e3c7..b117aafbaa 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2451,11 +2451,12 @@ int main(int argc, char** argv) // grid search for parameters: // 1: Viral Shed // 2: Dark figure - // 3: testing prob symptomatic - // 4: perc have to test if npi active + // 3: Contact reduction lockdown + // 4: testing prob symptomatic + // 5: odds ratio for asymptomatic to symptomatic std::vector> grid_boundaries = { - {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.8}, {0.02, 0.045}, {3, 15}}; + {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.7}, {0.01, 0.045}, {2, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; @@ -2478,7 +2479,7 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {10.0}, {0.5}}; + std::vector> parameters = {{1.52}, {4.9}, {0.71}, {0.02}, {3.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; auto every_combination = every_combination_of_parameters(parameters); From 228ae1b35d31194591dfe449b1a6f4aefab9e8e0 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 19 Sep 2024 23:05:19 +0200 Subject: [PATCH 453/488] grid search again22 --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b117aafbaa..e748e152fe 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2456,7 +2456,7 @@ int main(int argc, char** argv) // 5: odds ratio for asymptomatic to symptomatic std::vector> grid_boundaries = { - {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.7}, {0.01, 0.045}, {2, 15}}; + {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.85}, {0.01, 0.045}, {2, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; From 39656d0d643754e0383a900ef3aab9a3968d0f13 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 01:45:07 +0200 Subject: [PATCH 454/488] some plotting changes --- cpp/simulations/parameter_varation.py | 230 ++++++++++++++------------ cpp/simulations/scaling results.py | 137 +++++++-------- cpp/simulations/scenario_plots.py | 112 +++++++------ cpp/simulations/viral_shed.py | 80 +++++++++ 4 files changed, 340 insertions(+), 219 deletions(-) create mode 100644 cpp/simulations/viral_shed.py diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index 262832e24b..3c15e9b0d1 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -18,6 +18,9 @@ from scipy.signal import savgol_filter import seaborn as sns + +fontsize = 18 + def plot_of_cumuative_infections(path, index=0): # plot cumulative infections f_p50 = h5py.File( @@ -65,7 +68,7 @@ def plot_positive_tests(path, index): def get_maximum_dead(path, index): deaths_p50_normal = h5py.File( path+"/infection_state_per_age_group/"+str(index)+"/p50/Results.h5", 'r') - p50_bs_deaths_normal = deaths_p50_normal['0']['Total'][()][:, 7][::24][0:90] + p50_bs_deaths_normal = deaths_p50_normal['0']['Total'][()][:, 7][::24][0:90]-deaths_p50_normal['0']['Total'][()][:, 7][::24][0] return np.max(p50_bs_deaths_normal) def get_maximum_hospitalized(path, index): @@ -100,23 +103,23 @@ def get_maximum_daily_infections(path, index): if __name__ == "__main__": - # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/par_var/memilio/data/results_2024-08-22225207" - # variable_1 = "test_likelihood_symptom" - # variable_2 = "test_likelihood_asymptom" - # values_1 = [0.018,0.036,0.054,0.072,0.09] - # values_2 = [40,30,20,10,1] + # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28120457" + # variable_1 = "Test likelihood with symptoms" + # variable_2 = "Ratio for asymptomatic agents to test" + # values_1 = [0.0175,0.035,0.0525,0.07,0.0875] + # values_2 = ["1/5","1/8","1/11","1/14","1/17"] - path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/par_var/memilio/data/results_2024-08-22225357" - variable_1 = "quarantine length" - variable_2 = "quarantine efficiancy" - values_1 = [1,4,7,10,13,16] - values_2 = [0.0,0.25,0.5,0.75,1.0] + # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28120954" + # variable_1 = "Quarantine length (days)" + # variable_2 = "Quarantine efficiency" + # values_1 = [2,5,8,11,14] + # values_2 = [0.0,0.25,0.5,0.75,1.0] - # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/par_var/memilio/data/results_2024-08-22225628" - # variable_1 = "test_likelihood_symptom" - # variable_2 = "quarantine lenth" - # values_1 = [0.018,0.036,0.054,0.072,0.09] - # values_2 = [1,4,7,10,13,16] + path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28120655" + variable_1 = "Test likelihood with symptoms" + variable_2 = "Quarantine length (days)" + values_1 = [0.0175,0.035,0.0525,0.07,0.0875] + values_2 = [2,5,8,11,14] # we want to have a Grid Plot with the size of the values @@ -125,74 +128,73 @@ def get_maximum_daily_infections(path, index): # we want to plot in the title of the plot # they all should have the same y-axis, so we can compare them, the highest value should be the maximum of all plots - fig = plt.figure('Parameter Variation', figsize=(19, 10)) - gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - fig.suptitle('Parameter Variation', fontsize=16) - fig.show() - highest_value = 0 - for i in range(len(values_1)): - for j in range(len(values_2)): - index = (i)*len(values_2)+(j) - plot_data = plot_of_cumuative_infections(path_data, index) - if np.max(plot_data) > highest_value: - highest_value = np.max(plot_data) + # fig = plt.figure('Parameter Variation', figsize=(19, 10)) + # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + # # fig.suptitle('Parameter Variation', fontsize=fontsize) + # fig.show() + # highest_value = 0 + # for i in range(len(values_1)): + # for j in range(len(values_2)): + # index = (i)*len(values_2)+(j) + # plot_data = plot_of_cumuative_infections(path_data, index) + # if np.max(plot_data) > highest_value: + # highest_value = np.max(plot_data) - for i, value_1 in enumerate(values_1): - for j, value_2 in enumerate(values_2): - index = (i)*len(values_2)+(j) - ax = fig.add_subplot(gs[i, j]) - ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - plot_data = plot_of_cumuative_infections(path_data, index) - ax.set_ylim(0, highest_value) - ax.plot(plot_data, label='Cumulative Infections') - ax.legend() - plt.show() - - - fig = plt.figure('Parameter Variation', figsize=(19, 10)) - gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - fig.suptitle('Parameter Variation', fontsize=16) - fig.show() - highest_value = 0 - for i in range(len(values_1)): - for j in range(len(values_2)): - index = (i)*len(values_2)+(j) - plot_data = plot_number_of_tests(path_data, index) - if np.max(plot_data) > highest_value: - highest_value = np.max(plot_data) - for i, value_1 in enumerate(values_1): - for j, value_2 in enumerate(values_2): - index = (i)*len(values_2)+(j) - - ax = fig.add_subplot(gs[i, j]) - ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - ax.set_ylim(0, highest_value) - plot_data = plot_number_of_tests(path_data, index) - ax.plot(plot_data, label='Number of Tests') - ax.legend() - plt.show() - fig = plt.figure('Parameter Variation', figsize=(19, 10)) - gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) - fig.suptitle('Parameter Variation', fontsize=16) - fig.show() - highest_value = 0 - for i in range(len(values_1)): - for j in range(len(values_2)): - index = (i)*len(values_2)+(j) - plot_data = plot_positive_tests(path_data, index) - if np.max(plot_data) > highest_value: - highest_value = np.max(plot_data) - for i, value_1 in enumerate(values_1): - for j, value_2 in enumerate(values_2): - index = (i)*len(values_2)+(j) + # for i, value_1 in enumerate(values_1): + # for j, value_2 in enumerate(values_2): + # index = (i)*len(values_2)+(j) + # ax = fig.add_subplot(gs[i, j]) + # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + # plot_data = plot_of_cumuative_infections(path_data, index) + # ax.set_ylim(0, highest_value) + # ax.plot(plot_data, label='Cumulative Infections') + # ax.legend() + # plt.show() + + + # fig = plt.figure('Parameter Variation', figsize=(19, 10)) + # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + # fig.suptitle('Parameter Variation', fontsize=16) + # fig.show() + # highest_value = 0 + # for i in range(len(values_1)): + # for j in range(len(values_2)): + # index = (i)*len(values_2)+(j) + # plot_data = plot_number_of_tests(path_data, index) + # if np.max(plot_data) > highest_value: + # highest_value = np.max(plot_data) + # for i, value_1 in enumerate(values_1): + # for j, value_2 in enumerate(values_2): + # index = (i)*len(values_2)+(j) + # ax = fig.add_subplot(gs[i, j]) + # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + # ax.set_ylim(0, highest_value) + # plot_data = plot_number_of_tests(path_data, index) + # ax.plot(plot_data, label='Number of Tests') + # ax.legend() + # plt.show() + # fig = plt.figure('Parameter Variation', figsize=(19, 10)) + # gs = fig.add_gridspec(len(values_1), len(values_2), hspace=0.4, wspace=0.4) + # fig.suptitle('Parameter Variation', fontsize=16) + # fig.show() + # highest_value = 0 + # for i in range(len(values_1)): + # for j in range(len(values_2)): + # index = (i)*len(values_2)+(j) + # plot_data = plot_positive_tests(path_data, index) + # if np.max(plot_data) > highest_value: + # highest_value = np.max(plot_data) + # for i, value_1 in enumerate(values_1): + # for j, value_2 in enumerate(values_2): + # index = (i)*len(values_2)+(j) - ax = fig.add_subplot(gs[i, j]) - ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') - ax.set_ylim(0, highest_value) - plot_data = plot_positive_tests(path_data, index) - ax.plot(plot_data, label='Positive Tests') - ax.legend() - plt.show() + # ax = fig.add_subplot(gs[i, j]) + # ax.set_title(f'{variable_1}={value_1}, {variable_2}={value_2}') + # ax.set_ylim(0, highest_value) + # plot_data = plot_positive_tests(path_data, index) + # ax.plot(plot_data, label='Positive Tests') + # ax.legend() + # plt.show() # we want to have four plots in one figure # in each plot for each value of the parameter we want to plot a big square in a color which is defined by the value of the interesting value in that plot @@ -201,10 +203,11 @@ def get_maximum_daily_infections(path, index): # third plot that value is the maximum of persons dead # fourth plot that value is the maximum of persons in the hospital - fig, axs = plt.subplots(2, 2, figsize=(10, 10)) - fig.suptitle('Parameter Variation', fontsize=16) + fig, axs = plt.subplots(2, 2, figsize=(15, 10)) + # space between the upper and lower plots + plt.subplots_adjust(hspace=0.3, wspace=0.2) fig.show() - + sns.set(font_scale=1.2) # first plot value_for_values = np.zeros((len(values_1), len(values_2))) for i, value_1 in enumerate(values_1): @@ -214,17 +217,18 @@ def get_maximum_daily_infections(path, index): # permute the values, so that the plot is correct # we need a seaborn heatmap for the colorbar - sns.heatmap(value_for_values, ax=axs[0, 0], cmap='viridis', cbar_kws={'label': 'Maximum Cumulative Infections'}, annot=True, fmt=".0f") - axs[0, 0].set_title('Maximum Cumulative Infections') + sns.heatmap(value_for_values, ax=axs[0, 0], cmap='viridis', annot=True, fmt=".0f") + axs[0, 0].set_title('Cumulative Infections', fontsize=fontsize+4) # x and y axis labels + # axs[0, 0].invert_xaxis() axs[0, 0].set_xticklabels(values_2) axs[0, 0].set_yticklabels(values_1) - axs[0, 0].set_xlabel(variable_2) - axs[0, 0].set_ylabel(variable_1) - + axs[0, 0].set_ylabel(variable_1, fontsize=fontsize-4) + axs[0, 0].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[0, 0].tick_params(axis='both', which='minor', labelsize=fontsize-4) - - + + # second plot @@ -235,13 +239,18 @@ def get_maximum_daily_infections(path, index): value_for_values[i, j] = get_maximum_dead(path_data, index) # permute the values, so that the plot is correct # we need a seaborn heatmap for the colorbar - sns.heatmap(value_for_values, ax=axs[0, 1], cmap='viridis', cbar_kws={'label': 'Maximum Dead'}, annot=True, fmt=".0f") - axs[0, 1].set_title('Maximum Dead') + sns.heatmap(value_for_values, ax=axs[0, 1], cmap='viridis', annot=True, fmt=".0f") + # invert x axis + # axs[0, 1].invert_xaxis() + axs[0, 1].set_title('Deaths', fontsize=fontsize+4) # x and y axis labels axs[0, 1].set_xticklabels(values_2) axs[0, 1].set_yticklabels(values_1) - axs[0, 1].set_xlabel(variable_2) - axs[0, 1].set_ylabel(variable_1) + axs[0, 1].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[0, 1].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + + # third plot value_for_values = np.zeros((len(values_1), len(values_2))) @@ -251,13 +260,18 @@ def get_maximum_daily_infections(path, index): value_for_values[i, j] = get_maximum_hospitalized(path_data, index) # permute the values, so that the plot is correct # we need a seaborn heatmap for the colorbar - sns.heatmap(value_for_values, ax=axs[1, 0], cmap='viridis', cbar_kws={'label': 'Maximum Hospitalized'}, annot=True, fmt=".0f") - axs[1, 0].set_title('Maximum Hospitalized') + sns.heatmap(value_for_values, ax=axs[1, 0], cmap='viridis', annot=True, fmt=".0f") + axs[1, 0].set_title('Maximum Hospitalized Persons', fontsize=fontsize+4) # x and y axis labels axs[1, 0].set_xticklabels(values_2) axs[1, 0].set_yticklabels(values_1) - axs[1, 0].set_xlabel(variable_2) - axs[1, 0].set_ylabel(variable_1) + axs[1, 0].set_ylabel(variable_1, fontsize=fontsize-4) + axs[1, 0].set_xlabel(variable_2, fontsize=fontsize-4) + axs[1, 0].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[1, 0].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + # axs[1, 0].invert_xaxis() + # fourth plot value_for_values = np.zeros((len(values_1), len(values_2))) @@ -267,15 +281,21 @@ def get_maximum_daily_infections(path, index): value_for_values[i, j] = get_maximum_daily_infections(path_data, index) # permute the values, so that the plot is correct # we need a seaborn heatmap for the colorbar - sns.heatmap(value_for_values, ax=axs[1, 1], cmap='viridis', cbar_kws={'label': 'Maximum Cumulative Infections'}, annot=True, fmt=".0f") - axs[1, 1].set_title('Maximum Daily Infections') + sns.heatmap(value_for_values, ax=axs[1, 1], cmap='viridis', annot=True, fmt=".0f") + axs[1, 1].set_title('Maximum Daily Infections', fontsize=fontsize+4) # x and y axis labels axs[1, 1].set_xticklabels(values_2) axs[1, 1].set_yticklabels(values_1) - axs[1, 1].set_xlabel(variable_2) - axs[1, 1].set_ylabel(variable_1) + axs[1, 1].set_xlabel(variable_2, fontsize=fontsize-4) + axs[1, 1].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[1, 1].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + + # axs[1, 1].invert_xaxis() + + - plt.show() + plt.savefig('parameter_variation.png', dpi=300) diff --git a/cpp/simulations/scaling results.py b/cpp/simulations/scaling results.py index b1fa3122fb..75696f88a7 100644 --- a/cpp/simulations/scaling results.py +++ b/cpp/simulations/scaling results.py @@ -1,29 +1,34 @@ from matplotlib.ticker import ScalarFormatter, LogLocator - +import numpy as np import matplotlib.pyplot as plt from decimal import Decimal -fontsize = 18 +fontsize = 24 # First plot: Runtime vs. Number of Processors on # processors = [1, 2, 4, 8] # Number of processors -# runtime = [[0.6, 0.8, 1.1, 2.2], # 0.025 mio agents per processor -# [1.4, 1.8, 2.5, 4.5], # 0.05 mio agents per processor -# [3.3, 4.8, 6.4, 9.5]] # 0.1 mio agents per processor -# processors = [1, 2, 4, 8, 16, 32] # Number of processors -# runtime = [ [02.0, 02.9, 04.5, 05.3, 06.1, 08.2], # 0.025 mio agents per processor -# [05.7, 06.2, 08.9, 10.0, 12.1, 16.7], # 0.05 mio agents per processor -# [11.2, 12.5, 16.8, 19.0, 24.3, 32.1], # 0.1 mio agents per processor -# [23.6, 24.9, 32.1, 37.5, 47.9, 63.4]] # 0.2 mio agents per processor -# fig = plt.figure(figsize=(12, 9)) -# for i in range(len(runtime)): -# plt.plot(processors, runtime[i], marker='o', linewidth=3) +# runtime = [[0.2, 0.3, 0.6, 1.1], # 0.025 mio agents per processor +# [0.6, 0.8, 1.2, 2.3], # 0.05 mio agents per processor +# [1.3, 1.7, 2.4, 4.9], # 0.1 mio agents per processor +# [2.7, 3.5, 5.3, 11]] # 0.2 mio agents per processor +processors = [1, 2, 4, 8, 16, 32] # Number of processors +runtime = [ [0.9, 1.3, 1.5, 1.9, 2.6, 3.9], # 0.025 mio agents per processor + [2.5, 2.8, 3.0, 3.9, 5.4, 7.0], # 0.05 mio agents per processor + [5.2, 5.8, 6.3, 7.9, 10.4, 14.7], # 0.1 mio agents per processor + [10.6, 11.1, 12.8, 15.6, 21.1, 32.1]] # 0.2 mio agents per processor +runtime = np.array(runtime) # Convert to seconds +fig = plt.figure(figsize=(12, 9)) +for i in range(len(runtime)): + plt.plot(processors, runtime[i], marker='o', linewidth=3) -# plt.legend(['25k agents per processor', '50k agents per processor', '100k agents per processor', '200k agents per processor'], fontsize=fontsize) -# plt.xlabel('Number of Processors', fontsize=fontsize) -# plt.ylabel('Runtime (seconds)', fontsize=fontsize) -# plt.title('Node level weak scaling', fontsize=fontsize+4) -# plt.grid(True) -# plt.show() +plt.legend(['25k agents per processor', '50k agents per processor', '100k agents per processor', '200k agents per processor'], fontsize=fontsize-4) +plt.xlabel('Number of Processors', fontsize=fontsize) +plt.ylabel('Runtime (seconds)', fontsize=fontsize) +plt.title('Node level weak scaling', fontsize=fontsize+4) +plt.yscale('log') +plt.tick_params(axis='both', which='major', labelsize=fontsize-4) +plt.tick_params(axis='both', which='minor', labelsize=fontsize-4) +plt.grid(True) +plt.show() # Second plot: Speedup vs. Number of Processors # time for 6400k agents on x processors @@ -45,10 +50,12 @@ -# # Third plot: CPU Time vs. Population Size on 8 processors +# Third plot: CPU Time vs. Population Size on 8 processors population_size = [25, 50, 100, 200, 400, 800, 1600, 3200, 6400] # Population size in thousand population_size = [p * 1000 for p in population_size] -cpu_time_real = [0.32, 0.84, 2.5, 5.3, 10.1, 19.2, 37.5, 72.9, 148] # CPU time in seconds +cpu_time_real = np.array([0.14, 0.36, 0.9, 1.8, 3.9, 7.92, 15.61, 31.2, 65.5])*(1/120.0) # CPU time in seconds +cpu_time_real_1core = np.array([0.9, 2.51, 5.1, 10.4, 21.1, 42.5, 85.2, 173.2, 349.2])*(1/120.0) # CPU time in seconds + # we also need the average number of seconds per 1000 agents cpu_time_per_1000 = [t / p for t, p in zip(cpu_time_real, population_size)] average_cpu_time_per_1000 = sum(cpu_time_per_1000) / len(cpu_time_per_1000) @@ -56,55 +63,55 @@ cpu_time_av = [p * average_cpu_time_per_1000 for p in population_size] # Fourth plot: Memory Usage vs. Population Size -population_size_memory = [25, 50, 100, 200, 400, 800, 1600, 3200] # Population size in thousand +population_size_memory = [25, 50, 100, 200, 400, 800, 1600, 3200, 6400] # Population size in thousand population_size_memory = [p * 1000 for p in population_size_memory] -memory_usage = [10, 22, 50, 111, 228, 455, 900, 1777] # Memory usage in MB -average_memory_usage = sum(memory_usage) / len(memory_usage) * 1e-6 +memory_usage = [10, 22, 50, 111, 228, 455, 984, 1910, 3780] # Memory usage in MB +# we also need the average memory usage per 1000 agents +average_memory_time_per_1000 = [m / p for m, p in zip(memory_usage, population_size_memory)] +average_memory_usage = sum(average_memory_time_per_1000) / len(average_memory_time_per_1000) mem_av = [p * average_memory_usage for p in population_size_memory] -fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 9)) - # Plot for CPU Time vs. Population Size - -ax1.plot(population_size, cpu_time_real, marker='o', linewidth=3) -ax1.plot(population_size, cpu_time_av, linewidth=3, linestyle='dashed', color='black', label='Average CPU time') -ax1.set_yscale('log') -ax1.set_xscale('log') -ax1.legend(['Runtime Simulation', 'Linear Scaling:' +'%.2E' % Decimal(average_cpu_time_per_1000)+' Seconds / Agent'], fontsize=fontsize) -ax1.set_xlabel('Population Size',fontsize=fontsize) -ax1.set_ylabel('Runtime (seconds)',fontsize=fontsize) -ax1.tick_params(axis='both', which='major', labelsize=fontsize-4) -ax1.yaxis.set_major_formatter(ScalarFormatter()) -ax1.yaxis.set_minor_formatter(ScalarFormatter()) -ax1.yaxis.set_major_locator(LogLocator(base=10.0, numticks=15)) -ax1.yaxis.set_minor_locator(LogLocator(base=10.0, numticks=15)) -# x ticks should be from 10000 to 10000000 -ax1.set_xticks([10000, 100000, 1000000, 10000000]) -ax1.get_xaxis().set_major_locator(LogLocator(base=10.0, numticks=15)) -ax1.get_xaxis().set_minor_locator(LogLocator(base=10.0, numticks=15)) -ax1.set_title('Runtime Scaling',fontsize=fontsize+4) -ax1.grid(True) +plt.figure(figsize=(12, 9)) +plt.plot(population_size, cpu_time_real, marker='o', linewidth=3) +plt.plot(population_size, cpu_time_av, linewidth=3, linestyle='dashed', color='black', label='Average CPU time') +plt.yscale('log') +plt.xscale('log') +plt.legend(['Runtime Simulation', 'Linear Scaling: ' +'%.2E' % Decimal(average_cpu_time_per_1000)+' Seconds / Agent'], fontsize=fontsize) +plt.xlabel('Population Size', fontsize=fontsize) +plt.ylabel('Runtime (seconds)', fontsize=fontsize) +plt.tick_params(axis='both', which='major', labelsize=fontsize-4) +plt.gca().yaxis.set_major_formatter(ScalarFormatter()) +plt.gca().yaxis.set_minor_formatter(ScalarFormatter()) +plt.gca().yaxis.set_major_locator(LogLocator(base=10.0, numticks=15)) +plt.gca().yaxis.set_minor_locator(LogLocator(base=10.0, numticks=15)) +plt.xticks([10000, 100000, 1000000, 10000000]) +plt.gca().get_xaxis().set_major_locator(LogLocator(base=10.0, numticks=15)) +plt.gca().get_xaxis().set_minor_locator(LogLocator(base=10.0, numticks=15)) +plt.title('Runtime Scaling', fontsize=fontsize+4) +plt.grid(True) +plt.tight_layout() +plt.show() # Plot for Memory Usage vs. Population Size -ax2.plot(population_size_memory, memory_usage, marker='o', linewidth=3) -ax2.plot(population_size_memory, mem_av, linewidth=3, linestyle='dashed', color='black', label='Average Memory Usage') -ax2.legend(['Memory Usage Simulation', 'Linear Scaling:' + '%.2E' % Decimal(average_memory_usage)+' MB / Agent'], fontsize=fontsize) -ax2.set_xscale('log') -ax2.set_yscale('log') -ax2.set_xlabel('Population Size',fontsize=fontsize) -ax2.set_ylabel('Memory Usage (MB)',fontsize=fontsize) -ax2.set_title('Memory Usage Scaling',fontsize=fontsize+4) -ax2.tick_params(axis='both', which='major', labelsize=fontsize-4) -ax2.yaxis.set_major_formatter(ScalarFormatter()) -ax2.yaxis.set_minor_formatter(ScalarFormatter()) -ax2.yaxis.set_major_locator(LogLocator(base=10.0, numticks=15)) -ax2.yaxis.set_minor_locator(LogLocator(base=10.0, numticks=15)) -# x ticks should be from 10000 to 10000000 -ax2.set_xticks([10000, 100000, 1000000, 10000000]) -ax2.get_xaxis().set_major_locator(LogLocator(base=10.0, numticks=15)) -ax2.get_xaxis().set_minor_locator(LogLocator(base=10.0, numticks=15)) -ax2.grid(True) - +plt.figure(figsize=(12, 9)) +plt.plot(population_size_memory, memory_usage, marker='o', linewidth=3) +plt.plot(population_size_memory, mem_av, linewidth=3, linestyle='dashed', color='black', label='Average Memory Usage') +plt.legend(['Memory Usage Simulation', 'Linear Scaling: ' + '%.2E' % Decimal(average_memory_usage)+' MB / Agent'], fontsize=fontsize) +plt.xscale('log') +plt.yscale('log') +plt.xlabel('Population Size', fontsize=fontsize) +plt.ylabel('Memory Usage (MB)', fontsize=fontsize) +plt.title('Memory Usage Scaling', fontsize=fontsize+4) +plt.tick_params(axis='both', which='major', labelsize=fontsize-4) +plt.gca().yaxis.set_major_formatter(ScalarFormatter()) +plt.gca().yaxis.set_minor_formatter(ScalarFormatter()) +plt.gca().yaxis.set_major_locator(LogLocator(base=10.0, numticks=15)) +plt.gca().yaxis.set_minor_locator(LogLocator(base=10.0, numticks=15)) +plt.xticks([10000, 100000, 1000000, 10000000]) +plt.gca().get_xaxis().set_major_locator(LogLocator(base=10.0, numticks=15)) +plt.gca().get_xaxis().set_minor_locator(LogLocator(base=10.0, numticks=15)) +plt.grid(True) plt.tight_layout() -plt.show() \ No newline at end of file +plt.show() diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index 69d28506ce..12edcdaebc 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -15,6 +15,8 @@ from scipy.ndimage import gaussian_filter1d from scipy.signal import savgol_filter +fontsize = 18 + def plot_scenario(path, folder, folder_high, folder_enough): # four plots with 3 lines for each scenario and another one for the real data @@ -33,8 +35,8 @@ def plot_scenario(path, folder, folder_high, folder_enough): folders = [folder, folder_high, folder_enough] # for folder in [folder_normal, folder_high, folder_enough]: # we plot both in separate plots - fig, axs = plt.subplots(3, 2, figsize=(19, 10)) - fig.suptitle('Infection and Tests during the first 90 days for normal and high testing scenarios') + fig, axs = plt.subplots(3, 2, figsize=(19, 12)) + fig.subplots_adjust(hspace=0.5) inf_p50_normal = h5py.File( path+"/infection_per_location_type_per_age_group/"+folder+"/p50/Results.h5", 'r') @@ -44,6 +46,9 @@ def plot_scenario(path, folder, folder_high, folder_enough): xx = [xx[i].strftime('%m-%d') for i in range(len(xx))] xx = xx[1:][::24][:90] + #label string for each folder + labels = ['Standart Testing', 'High Testing Scenario', 'Very High Testing Scenario'] + for folder in folders: inf_p50_normal = h5py.File( path+"/infection_per_location_type_per_age_group/"+folder+"/p50/Results.h5", 'r') @@ -67,14 +72,14 @@ def plot_scenario(path, folder, folder_high, folder_enough): test_p_pos_p50_normal = h5py.File( - path+"/positive_test_per_location_type_per_age_group/"+folder+"/p50/Results.h5", 'r') + path+"/new_detected_infections/"+folder+"/p50/Results.h5", 'r') test_p_pos_p25_normal = h5py.File( - path+"/positive_test_per_location_type_per_age_group/"+folder+"/p25/Results.h5", 'r') + path+"/new_detected_infections/"+folder+"/p25/Results.h5", 'r') test_p_pos_p75_normal = h5py.File( - path+"/positive_test_per_location_type_per_age_group/"+folder+"/p75/Results.h5", 'r') - p50_bs_test_p_pos_normal = test_p_pos_p50_normal['0']['Total'][()] - p25_bs_test_p_pos_normal = test_p_pos_p25_normal['0']['Total'][()] - p75_bs_test_p_pos_normal = test_p_pos_p75_normal['0']['Total'][()] + path+"/new_detected_infections/"+folder+"/p75/Results.h5", 'r') + p50_bs_test_p_pos_normal = test_p_pos_p50_normal['0']['Total'][()].flatten() + p25_bs_test_p_pos_normal = test_p_pos_p25_normal['0']['Total'][()].flatten() + p75_bs_test_p_pos_normal = test_p_pos_p75_normal['0']['Total'][()].flatten() deaths_p50_normal = h5py.File( path+"/infection_state_per_age_group/"+folder+"/p50/Results.h5", 'r') @@ -99,26 +104,23 @@ def plot_scenario(path, folder, folder_high, folder_enough): - total_50_positive = np.sum(p50_bs_test_p_pos_normal, axis=1) - total_50_positive = np.cumsum(total_50_positive, axis=0) - total_50_positive = total_50_positive[::24] + # total_50_positive = np.sum(p50_bs_test_p_pos_normal, axis=1) + total_50_positive = np.cumsum(p50_bs_test_p_pos_normal, axis=0) + # total_50_positive = total_50_positive[::24] total_50_positive = total_50_positive[0:91] # we still need to take the difference to get the daily amount total_50_positive = np.diff(total_50_positive, axis=0).flatten() - total_50_positive = gaussian_filter1d(total_50_positive, sigma=1, mode='nearest') - total_25_positive = np.sum(p25_bs_test_p_pos_normal, axis=1) - total_25_positive = np.cumsum(total_25_positive, axis=0) - total_25_positive = total_25_positive[::24] + # total_25_positive = np.sum(p25_bs_test_p_pos_normal, axis=1) + total_25_positive = np.cumsum(p25_bs_test_p_pos_normal, axis=0) + # total_25_positive = total_25_positive[::24] total_25_positive = total_25_positive[0:91] # we still need to take the difference to get the daily amount total_25_positive = np.diff(total_25_positive, axis=0).flatten() - total_25_positive = gaussian_filter1d(total_25_positive, sigma=1, mode='nearest') - total_75_positive = np.sum(p75_bs_test_p_pos_normal, axis=1) - total_75_positive = np.cumsum(total_75_positive, axis=0) - total_75_positive = total_75_positive[::24] + # total_75_positive = np.sum(p75_bs_test_p_pos_normal, axis=1) + total_75_positive = np.cumsum(p75_bs_test_p_pos_normal, axis=0) + # total_75_positive = total_75_positive[::24] total_75_positive = total_75_positive[0:91] # we still need to take the difference to get the daily amount total_75_positive = np.diff(total_75_positive, axis=0).flatten() - total_75_positive = gaussian_filter1d(total_75_positive, sigma=1, mode='nearest') total_50_done = np.sum(p50_bs_tests_normal, axis=1) total_50_done = np.cumsum(total_50_done, axis=0) @@ -126,7 +128,6 @@ def plot_scenario(path, folder, folder_high, folder_enough): total_50_done = total_50_done[0:91] # we still need to take the difference to get the daily amount total_50_done = np.diff(total_50_done, axis=0).flatten() # we smooth this with a gaussian filter - total_50_done = gaussian_filter1d(total_50_done, sigma=2, mode='nearest') total_25_done = np.sum(p25_bs_tests_normal, axis=1) total_25_done = np.cumsum(total_25_done, axis=0) @@ -134,7 +135,6 @@ def plot_scenario(path, folder, folder_high, folder_enough): total_25_done = total_25_done[0:91] # we still need to take the difference to get the daily amount total_25_done = np.diff(total_25_done, axis=0).flatten() # we smooth this with a gaussian filter - total_25_done = gaussian_filter1d(total_25_done, sigma=2, mode='nearest') total_75_done = np.sum(p75_bs_tests_normal, axis=1) total_75_done = np.cumsum(total_75_done, axis=0) @@ -142,7 +142,6 @@ def plot_scenario(path, folder, folder_high, folder_enough): total_75_done = total_75_done[0:91] # we still need to take the difference to get the daily amount total_75_done = np.diff(total_75_done, axis=0).flatten() # we smooth this with a gaussian filter - total_75_done = gaussian_filter1d(total_75_done, sigma=2, mode='nearest') p50_bs_normal_all_locations = np.zeros(len(p50_bs_normal)) @@ -177,7 +176,7 @@ def plot_scenario(path, folder, folder_high, folder_enough): # second plot - axs[0, 1].plot(xx, cum_inf_normal_50[0:90], label='Normal') + axs[0, 1].plot(xx, cum_inf_normal_50[0:90], label=labels[folders.index(folder)]) axs[0, 1].fill_between(xx, cum_inf_normal_25[0:90], cum_inf_normal_75[0:90], alpha=0.5) # third plot @@ -187,8 +186,8 @@ def plot_scenario(path, folder, folder_high, folder_enough): axs[1, 0].set_ylim([0, max(total_75_done)*1.5]) # fourth plot - axs[1, 1].plot(xx, total_50_positive, label='Normal') - axs[1, 1].fill_between(xx, total_25_positive, total_75_positive, alpha=0.5) + axs[1, 1].plot(xx[:89], total_50_positive, label='Normal') + axs[1, 1].fill_between(xx[:89], total_25_positive, total_75_positive, alpha=0.5) # plot dead in last row axs[2, 0].plot(xx, p50_bs_deaths_normal, label='Normal') @@ -203,43 +202,58 @@ def plot_scenario(path, folder, folder_high, folder_enough): - axs[0, 0].set_title('Daily New Infections') - axs[0, 0].set_ylabel('Number of Infections') - axs[0, 0].set_xlabel('Date') - axs[0, 1].set_title('Cumulative Infections') - axs[0, 1].set_ylabel('Number of Infections') - axs[0, 1].set_xlabel('Date') - axs[1, 0].set_title('Daily Tests') - axs[1, 0].set_ylabel('Number of Tests') - axs[1, 0].set_xlabel('Date') - axs[1, 1].set_title('Daily Positive Tests') - axs[1, 1].set_ylabel('Number of Positive Tests') - axs[1, 1].set_xlabel('Date') - axs[2, 0].set_title('Cumulative Deaths') - axs[2, 0].set_ylabel('Number of Deaths') - axs[2, 0].set_xlabel('Date') - axs[2, 1].set_title('Reproduction Number') - axs[2, 1].set_ylabel('Reproduction Number') - axs[2, 1].set_xlabel('Date') + axs[0, 0].set_title('Daily New Infections', fontsize=fontsize+5) + axs[0, 0].set_ylabel('Number of infections', fontsize=fontsize-2) + axs[0, 0].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[0, 0].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + axs[0, 1].set_title('Cumulative Infections', fontsize=fontsize+5) + axs[0, 1].set_ylabel('Number of infections', fontsize=fontsize-2) + axs[0, 1].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[0, 1].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + axs[1, 0].set_title('Daily Tests', fontsize=fontsize+5) + axs[1, 0].set_ylabel('Number of tests', fontsize=fontsize-2) + axs[1, 0].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[1, 0].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + axs[1, 1].set_title('Daily Positive Tests', fontsize=fontsize+5) + axs[1, 1].set_ylabel('Number of positive tests', fontsize=fontsize-2) + axs[1, 1].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[1, 1].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + axs[2, 0].set_title('Cumulative Deaths', fontsize=fontsize+5) + axs[2, 0].set_ylabel('Number of deaths' , fontsize=fontsize-2) + axs[2, 0].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[2, 0].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + axs[2, 1].set_title('Reproduction Number', fontsize=fontsize+5) + axs[2, 1].set_ylabel('Reproduction number', fontsize=fontsize-2) + axs[2, 1].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[2, 1].tick_params(axis='both', which='minor', labelsize=fontsize-4) + + # We still need one legend for all plots, we plot these in the first plot + axs[0, 1].legend(loc='upper left', fontsize=fontsize-4) + for ax in axs.flat: ax.set_xticks(xx[::10]) ax.set_xticklabels(xx[::10]) - ax.tick_params(axis='x', rotation=45) - plt.show() + ax.tick_params(axis='x') + plt.savefig('scenario_plot.jpg', dpi=300) if __name__ == "__main__": - path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113737" # more tesring - path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28114331" # no lockdown but much testing + path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28211441" # more tesring + path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113737" # no lockdown but much testing path_to_scenario_3 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" path_to_main_data = "0" path_to_high_testing_data = "1" path_to_enough_testing_data = "2" plot_scenario(path_to_scenario_1, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) - plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + # plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) # plot_scenario(path_to_scenario_3, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) diff --git a/cpp/simulations/viral_shed.py b/cpp/simulations/viral_shed.py new file mode 100644 index 0000000000..5257e2b6d9 --- /dev/null +++ b/cpp/simulations/viral_shed.py @@ -0,0 +1,80 @@ +import numpy as np +import scipy as sp +import matplotlib.pyplot as plt +fontsize = 24 + +def viral_load(t, increase, decrease, peak): + peak_time = peak / increase + if t < peak_time: + return increase * t + else: + return peak - decrease * (t - peak_time) + +class viral_load_with_params: + def __init__(self, increase, decrease, peak): + self.increase = increase + self.decrease = decrease + self.peak = peak + + def __call__(self, t): + return viral_load(t, self.increase, self.decrease, self.peak) + +def viral_shedding(t, personal_viral_shed, alpha, beta, viral_load_with_params): + return personal_viral_shed * 1/(1+np.exp(-(alpha + beta* viral_load_with_params(t)))) + +def return_my_sigma(mean, stddev): + my = np.log(mean * mean / np.sqrt(mean * mean + stddev * stddev)); + sigma = np.sqrt(np.log(1 + stddev * stddev / mean / mean)); + return my, sigma + +def draw_timepoints_infectious_and_not(): + + mean_incubation = 4.5 + stddev_incubation = 1.5 + my_sigma_incubation = return_my_sigma(mean_incubation, stddev_incubation) + exposed_length = sp.stats.lognorm(s=my_sigma_incubation[0], scale=my_sigma_incubation[1]).rvs(1) + + + + + return timepoints_infectious, timepoints_not_infectious + +viral_load_increase = 2.0 +viral_load_decrease = 0.5 +viral_load_peak = 8.1 +personal_viral_shed = sp.stats.gamma(a=1.6, scale=1/22).rvs(20) +alpha = -7 +beta = 1 + +viral_load_with_params = viral_load_with_params(viral_load_increase, viral_load_decrease, viral_load_peak) + +t = np.linspace(0.0000001, 20, 100) +viral_shedding_values_for_each_person = [[viral_shedding(t, personal_viral_shed, alpha, beta, viral_load_with_params) for t in t] for personal_viral_shed in personal_viral_shed] + +plt.figure(figsize=(12, 8)) +for viral_shedding_values in viral_shedding_values_for_each_person: + plt.plot(t, viral_shedding_values) +plt.title('Viral shedding', fontsize=fontsize) +plt.xlabel('Time (days)', fontsize=fontsize-4) +plt.ylabel('Viral shed', fontsize=fontsize-4) +plt.setp(plt.gca().get_xticklabels(), fontsize=fontsize-8) +plt.setp(plt.gca().get_yticklabels(), fontsize=fontsize-8) + +# we need to save the figure with high resolution and jpeg format +plt.savefig('/Users/saschakorf/Downloads/viral_shedding.jpg', dpi=300) + + +# we do the same for viral load +viral_load_values = [np.exp(viral_load_with_params(t)) for t in t] + +plt.figure(figsize=(12, 8)) +plt.plot(t, viral_load_values) +plt.title('Viral load', fontsize=fontsize) +plt.xlabel('Time (days)', fontsize=fontsize-4) +plt.ylabel('Viral load', fontsize=fontsize-4) +plt.setp(plt.gca().get_xticklabels(), fontsize=fontsize-8) +plt.setp(plt.gca().get_yticklabels(), fontsize=fontsize-8) + +# we need to save the figure with high resolution and jpeg format +plt.savefig('viral_load.jpg', dpi=300) + From 889c9a3b3c77c3a12aede23412f8d9cd9717a135 Mon Sep 17 00:00:00 2001 From: Sascha <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 02:27:58 +0200 Subject: [PATCH 455/488] short bugfix --- cpp/simulations/viral_shed.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/viral_shed.py b/cpp/simulations/viral_shed.py index 5257e2b6d9..68d15f4fd2 100644 --- a/cpp/simulations/viral_shed.py +++ b/cpp/simulations/viral_shed.py @@ -61,7 +61,7 @@ def draw_timepoints_infectious_and_not(): plt.setp(plt.gca().get_yticklabels(), fontsize=fontsize-8) # we need to save the figure with high resolution and jpeg format -plt.savefig('/Users/saschakorf/Downloads/viral_shedding.jpg', dpi=300) +plt.savefig('viral_shedding.jpg', dpi=300) # we do the same for viral load From be90d043e88d9090f86bf37b153a6f15448a684e Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 02:41:56 +0200 Subject: [PATCH 456/488] some plotting changes --- cpp/simulations/scenario_plots.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index 12edcdaebc..d07b44a425 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -217,8 +217,8 @@ def plot_scenario(path, folder, folder_high, folder_enough): axs[1, 0].tick_params(axis='both', which='major', labelsize=fontsize-4) axs[1, 0].tick_params(axis='both', which='minor', labelsize=fontsize-4) - axs[1, 1].set_title('Daily Positive Tests', fontsize=fontsize+5) - axs[1, 1].set_ylabel('Number of positive tests', fontsize=fontsize-2) + axs[1, 1].set_title('Daily New Detected Infections', fontsize=fontsize+5) + axs[1, 1].set_ylabel('Number of infections', fontsize=fontsize-2) axs[1, 1].tick_params(axis='both', which='major', labelsize=fontsize-4) axs[1, 1].tick_params(axis='both', which='minor', labelsize=fontsize-4) @@ -254,6 +254,6 @@ def plot_scenario(path, folder, folder_high, folder_enough): path_to_high_testing_data = "1" path_to_enough_testing_data = "2" - plot_scenario(path_to_scenario_1, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) - # plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + # plot_scenario(path_to_scenario_1, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) # plot_scenario(path_to_scenario_3, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) From fe1c312c689d925cf359ff675f65c5d9abd531e2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 02:45:17 +0200 Subject: [PATCH 457/488] some plotting changes Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 448 +++++++++++++++++++++++++----- 1 file changed, 384 insertions(+), 64 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index e72c07df35..d100bc0c80 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -23,6 +23,8 @@ from scipy.ndimage import gaussian_filter1d from scipy.signal import savgol_filter +fontsize = 20 + def plot_infections_loc_types_avarage(path): # 50-percentile @@ -286,13 +288,14 @@ def plot_dead(path): # we need the amount of dead persons for each age group: These are A00-A04, A05-A14, A15-A34, A35-A59, A60-A79, A80+ age_groups = ['A00-A04', 'A05-A14', 'A15-A34', 'A35-A59', 'A60-A79', 'A80+'] + age_grous_string = ['Age 0-4', 'Age 5-14', 'Age 15-34', 'Age 35-59', 'Age 60-79', 'Age 80+'] # we need to sum up the amount of dead persons for each age group # we want the deaths for the age groups df_abb = df_abb[['Date', 'Deaths', 'Age_RKI']] # we want a plot with 2 rows. Second row has a plot with each age group and the simulated and real dead persons # First row has the cumulative dead persons - fig = plt.figure('Dead') + fig = plt.figure('Deaths') fig.set_figwidth(20) fig.set_figheight(9) gs = fig.add_gridspec(2,6) @@ -301,22 +304,42 @@ def plot_dead(path): ax = fig.add_subplot(gs[0, :]) df_total_dead = df_abb.groupby('Date').sum()[0:90] y_real = df_total_dead['Deaths'].to_numpy() + # we need to substract the first value from the rest + y_real = y_real - y_real[0] + + y_sim = p50_bs['Total'][()][:, 7][::24][0:90] + y_sim = y_sim - y_sim[0] + + y_sim25 = p25_bs['Total'][()][:, 7][::24][0:90] + y_sim25 = y_sim25 - y_sim25[0] + + y_sim75 = p75_bs['Total'][()][:, 7][::24][0:90] + y_sim75 = y_sim75 - y_sim75[0] + + y_sim05 = p05_bs['Total'][()][:, 7][::24][0:90] + y_sim05 = y_sim05 - y_sim05[0] + + y_sim95 = p95_bs['Total'][()][:, 7][::24][0:90] + y_sim95 = y_sim95 - y_sim95[0] + + # we calculate the RMSE - rmse_dead = (((y_real- p50_bs['Total'][()][:, 7][::24][0:90])**2).mean()) + rmse_dead = np.sqrt(((y_real- y_sim)**2).mean()) # we need to plot the cumulative dead persons from the real world and from the simulation - ax.plot(df_total_dead.index, y_real, 'v',color='tab:red') - ax.plot(df_total_dead.index, p50_bs['Total'][()][:, 7][::24][0:90], color='tab:blue') - ax.fill_between(df_total_dead.index, p75_bs['Total'][()][:, 7][::24][0:90], p25_bs['Total'][()][:, 7][::24][0:90], - alpha=0.5, color='tab:blue') - ax.fill_between(df_total_dead.index, p95_bs['Total'][()][:, 7][::24][0:90], p05_bs['Total'][()][:, 7][::24][0:90], - alpha=0.25, color='tab:blue') - ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_dead))), horizontalalignment='center', - verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) - ax.set_xlabel('Date') - ax.set_label('Number of dead') - ax.set_title('Cumulative Dead') - ax.legend(['Real dead', 'Simulated dead']) + + ax.plot(df_total_dead.index, y_sim, color='tab:blue',label='Simulated deaths') + ax.plot(df_total_dead.index, y_real, 'v',color='tab:red', linewidth=4, label='Extrapolated deaths from reported infection case data') + ax.fill_between(df_total_dead.index, y_sim75, y_sim25, + alpha=0.5, color='tab:blue', label='50% Confidence interval') + ax.fill_between(df_total_dead.index,y_sim95, y_sim05, + alpha=0.25, color='tab:blue', label='90% Confidence interval') + # ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_dead))), horizontalalignment='center', + # verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + ax.set_label('Number of individuals') + ax.set_title('Cumulative Deaths', fontsize=fontsize) + ax.set_ylabel('Number of individuals', fontsize=fontsize-8) + ax.legend(fontsize=fontsize-8) # now for each age group for i, age_group in zip(range(6), age_group_access): @@ -325,14 +348,18 @@ def plot_dead(path): df_abb_age_group = df_abb[df_abb['Age_RKI'] == age_groups[i]][0:90] y_real = np.round(df_abb_age_group['Deaths'].to_numpy()) # we need to plot the dead persons from the real world and from the simulation - ax.plot(df_abb_age_group['Date'], y_real, color='tab:red') - ax.plot(df_abb_age_group['Date'], p50_bs[age_group_access[i]][()][:, 7][::24][0:90], color='tab:blue') - ax.fill_between(df_abb_age_group['Date'], p75_bs[age_group_access[i]][()][:, 7][::24][0:90], p25_bs[age_group_access[i]][()][:, 7][::24][0:90], + ax.plot(df_abb_age_group['Date'], y_real-y_real[0], color='tab:red') + ax.plot(df_abb_age_group['Date'], p50_bs[age_group_access[i]][()][:, 7][::24][0:90]-p50_bs[age_group_access[i]][()][:, 7][::24][0], color='tab:blue') + ax.fill_between(df_abb_age_group['Date'], p75_bs[age_group_access[i]][()][:, 7][::24][0:90]-p75_bs[age_group_access[i]][()][:, 7][::24][0], p25_bs[age_group_access[i]][()][:, 7][::24][0:90]-p25_bs[age_group_access[i]][()][:, 7][::24][0], alpha=0.5, color='tab:blue') - ax.set_title('Dead, Age{}'.format(i)) - ax.set_xlabel('Date') + ax.set_title('Deaths, '+age_grous_string[i]) + ax.set_ybound(lower=0) ax.set_xticks(df_abb_age_group['Date'][::50]) - ax.legend(['Real dead, Age{}'.format(i), 'Simulated dead, Age{}'.format(i)]) + ax.tick_params(axis='both', which='major', labelsize=fontsize-10) + ax.tick_params(axis='both', which='minor', labelsize=fontsize-10) + if i == 0: + ax.set_ylabel('Number of individuals',fontsize=fontsize-8) + ax.set_ybound(upper=1) plt.show() @@ -417,28 +444,30 @@ def plot_icu(path): # we calculate the RMSE - rmse_ICU = ((ICU_Real - ICU_Simulation_one_percentile)**2).mean()*0.1 + rmse_ICU = np.sqrt(((ICU_Real - ICU_Simulation_one_percentile)**2).mean()) # plot the ICU beds and the ICU beds taken fig, ax = plt.subplots(1, 1, constrained_layout=True) - fig.set_figwidth(20) + fig.set_figwidth(12) fig.set_figheight(9) # we plot the ICU_low and the ICU_high - ax.plot(df_abb['Date'][0:90], ICU_Real,'x', color='tab:red') - ax.plot(df_abb['Date'][0:90], ICU_Simulation_one_percentile, color='tab:green') + ax.plot(df_abb['Date'][0:90], ICU_Real,'x', color='tab:red', linewidth=10, label='Data') + ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:blue', label='Simulation') + # ax.plot(df_abb['Date'][0:90], ICU_Simulation_one_percentile, color='tab:green', label='Simulated ICU beds') ax.fill_between(df_abb['Date'][0:90],ICU_Simulation75, ICU_Simulation25, - alpha=0.5, color='tab:blue') + alpha=0.5, color='tab:blue', label='50% Confidence interval') ax.fill_between(df_abb['Date'][0:90],ICU_Simulation05, ICU_Simulation95, - alpha=0.25, color='tab:blue') - ax.plot(df_abb['Date'][0:90], ICU_Simulation, color='tab:blue') + alpha=0.25, color='tab:blue', label='90% Confidence interval') + # we also write the rmse - ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', - verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) - ax.set_xlabel('Date') - ax.set_ylabel('Number of persons in an ICU') - ax.title.set_text('Simulated and real ICU beds occupied') - ax.legend(['Real in ICU, smoothed','Simulated in ICU']) + # ax.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_ICU))), horizontalalignment='center', + # verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + ax.tick_params(axis='both', which='major', labelsize=fontsize-4) + ax.tick_params(axis='both', which='minor', labelsize=fontsize-4) + ax.set_ylabel('Occupied ICU beds', fontsize=fontsize) + ax.set_title('ICU beds', fontsize=fontsize+4) + ax.legend(fontsize=fontsize-4) plt.show() def plot_tests(path): @@ -572,7 +601,6 @@ def calc_positive_tests_overall(infection_states, sensitivity, specificity, r_sn 1-specificity)+((infection_states[:, 1]+infection_states[:, 2])*lt_asympt)*sensitivity return inferred_positive_tests_sympt+inferred_positive_tests_asympt, inferred_positive_tests_sympt, inferred_positive_tests_asympt - def plot_estimated_reproduction_number(path): f_p50 = h5py.File( path+"/estimated_reproduction_number/0/p50/Results.h5", 'r') @@ -605,9 +633,11 @@ def plot_cumulative_detected_infections(path): df_substract = np.round(df_abb['Confirmed'][0:1]) df_abb = np.round(df_abb['Confirmed'][0:90]) df_abb = df_abb - df_substract.values[0] - df_diff = df_abb.diff() + # we also want to plot the amount of new detected infections on a 7 day rolling average + df_abb_rolling = df_diff.rolling(window=7, min_periods=1, center=True).mean() + f_p50 = h5py.File( @@ -679,45 +709,81 @@ def plot_cumulative_detected_infections(path): time = time[0:90] # we calculate the RMSE - rmse_detected = ((df_abb - total_50)**2).mean() * 0.01 * 0.01 * 3.0 + rmse_detected = np.sqrt(((df_abb - total_50)**2).mean()) # we plot this # we plot the tests positive and the real cases - plt.plot(time, total_50, color='tab:blue') - plt.plot(time, df_abb, 'x', color='tab:red') - plt.fill_between(time, total_95, total_05, - alpha=0.75, color='tab:blue') + fig = plt.figure('Cumulative detected infections', constrained_layout=True) + fig.set_figwidth(20) + fig.set_figheight(9) + plt.plot(time, total_50, color='tab:blue', label='Simulation') + plt.plot(time, df_abb, 'x', color='tab:red', label='Data', linewidth=4) plt.fill_between(time, total_75, total_25, - alpha=0.5, color='tab:blue') + alpha=0.5, color='tab:blue', label='90% Confidence interval') + plt.fill_between(time, total_95, total_05, + alpha=0.25, color='tab:blue', label='50% Confidence interval') + - plt.xlabel('time (days)') - plt.ylabel('Cumulative Amount of detected infections') - plt.title('Cumulative detected infections') - plt.legend(['Simulated detected infections', 'Real detected infections']) + plt.ylabel('Cumulative detected infections', fontsize=fontsize-8) + plt.title('Cumulative detected infections', fontsize=fontsize) + plt.legend(fontsize=fontsize-8) + # currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in time] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(90)] + # but just take every 10th date to make it more readable + plt.gca().set_xticks(time[::14]) + plt.gca().set_xticklabels(xx[::14]) + plt.gcf().autofmt_xdate() #rmse - plt.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_detected))), horizontalalignment='center', - verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + # plt.text(0.25, 0.8, 'RMSE: '+str(float("{:.2f}".format(rmse_detected))), horizontalalignment='center', + # verticalalignment='center', transform=plt.gca().transAxes, color='pink', fontsize=15) + plt.show() + test_p_pos_p50_normal = h5py.File( + path+"/positive_test_per_location_type_per_age_group/"+"0"+"/p50/Results.h5", 'r') + p50_bs_test_p_pos_normal = test_p_pos_p50_normal['0']['Total'][()] + + # we need to sum every 24 entries to get the daily amount + total_50_positive = np.sum(p50_bs_test_p_pos_normal, axis=1) + total_50_positive = np.cumsum(total_50_positive, axis=0) + total_50_positive = total_50_positive[::24] + total_50_positive = total_50_positive[0:90] # we still need to take the difference to get the daily amount + total_50_positive = np.diff(total_50_positive, axis=0).flatten() + + # also the amount of new detected infections - fig, ax = plt.subplots(1, 1, constrained_layout=True) + fig = plt.figure('New detected infections', constrained_layout=True) fig.set_figwidth(20) fig.set_figheight(9) # we plot the tests positive and the real cases - ax.plot(time[0:89], total_50_diff, color='tab:blue') + plt.plot(time[0:89], total_50_diff, color='tab:blue', label='Simulation') # we dont plot the real curve as a line but as x points and not every day but every 2nd day - ax.plot(time[0:89], df_diff[0:89], 'x', color='tab:red') - ax.fill_between(time[0:89], total_95_diff, total_05_diff, - alpha=0.75, color='tab:blue') - ax.fill_between(time[0:89], total_75_diff, total_25_diff, - alpha=0.5, color='tab:blue') - ax.set_xlabel('time (days)') - ax.set_ylabel('Number of new detected infections') - ax.title.set_text('New detected infections') - ax.legend(['Simulated new detected infections', 'Real new detected infections']) + plt.plot(time[0:89], df_diff[0:89], 'x', color='tab:red', label='Data', linewidth=4) + plt.plot(time[0:89], total_50_positive, color='tab:green', label='Data 7 day rolling average', linewidth=3, linestyle='dashed') + # also the rolling average + plt.plot(time[0:89], df_abb_rolling[0:89], color='tab:red', label='Data 7 day rolling average', linewidth=3, linestyle='dashed') + plt.fill_between(time[0:89], total_75_diff, total_25_diff, + alpha=0.5, color='tab:blue', label='90% Confidence interval') + plt.fill_between(time[0:89], total_95_diff, total_05_diff, + alpha=0.25, color='tab:blue', label='50% Confidence interval') + + plt.ylabel('New detected infections', fontsize=fontsize-8) + plt.title('Daily detected infections', fontsize=fontsize) + plt.legend(fontsize=fontsize-5) + # currently the x axis has the values of the time steps, we need to convert them to dates and set the x axis to dates + start_date = datetime.strptime('2021-03-01', '%Y-%m-%d') + xx = [start_date + pd.Timedelta(days=int(i)) for i in time] + xx = [xx[i].strftime('%Y-%m-%d') for i in range(90)] + # but just take every 10th date to make it more readable + plt.gca().set_xticks(time[0:89][::14]) + plt.gca().set_xticklabels(xx[::14]) + plt.gcf().autofmt_xdate() + plt.show() def plot_positive_and_done_test(path): @@ -770,6 +836,259 @@ def plot_positive_and_done_test(path): plt.show() +def plot_fitting_plots(path): + + # We want to have the fitting for the four things we fittet against: Cumulative deaths, ICU, Cumulative detected infections and new detected infections + # readin of the data + db_abb_deaths = pd.read_json( + path+"/../pydata/Germany/cases_all_county_age_ma1.json") + + db_abb_icu = pd.read_json( + path+"/../pydata/Germany/county_divi.json") + + db_abb_detected = pd.read_json( + path+"/../pydata/Germany/cases_all_county_repdate_ma1.json") + + # we want to plot the plots in a 4x1 grid and we want to have the same x axis for all of them + # the first plot has also the legend + # in each plot we want to plot the real data and the simulated data, as well as the confidence intervals 50% and 90% + + fig, axs = plt.subplots(2, 2, figsize=(25, 15), constrained_layout=True) + + # we want to plot the cumulative deaths + # we need the cumulative dead persons + df_total_dead = db_abb_deaths + df_total_dead['Date'] = df_total_dead['Date']+pd.DateOffset(days=18) + df_total_dead = df_total_dead[(df_total_dead['Date'] >= '2021-03-01') & + (df_total_dead['Date'] <= '2021-06-01')] + df_total_dead = df_total_dead[df_total_dead['ID_County'] == 3101] + df_total_dead = df_total_dead.groupby('Date').sum()[0:90] + deaths_real = df_total_dead['Deaths'].to_numpy() + deaths_real = deaths_real[0:90] - deaths_real[0] + + # simulation deaths and confidence intervals + f_p50_deaths = h5py.File( + path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') + total_50_deaths = f_p50_deaths['0']['Total'][()][:, 7][::24][0:90] + total_50_deaths = total_50_deaths - total_50_deaths[0] + + f_p75_deaths = h5py.File( + path+"/infection_state_per_age_group/0/p75/Results.h5", 'r') + total_75_deaths = f_p75_deaths['0']['Total'][()][:, 7][::24][0:90] + total_75_deaths = total_75_deaths - total_75_deaths[0] + + f_p25_deaths = h5py.File( + path+"/infection_state_per_age_group/0/p25/Results.h5", 'r') + total_25_deaths = f_p25_deaths['0']['Total'][()][:, 7][::24][0:90] + total_25_deaths = total_25_deaths - total_25_deaths[0] + + f_p05_deaths = h5py.File( + path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') + total_05_deaths = f_p05_deaths['0']['Total'][()][:, 7][::24][0:90] + total_05_deaths = total_05_deaths - total_05_deaths[0] + + f_p95_deaths = h5py.File( + path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') + total_95_deaths = f_p95_deaths['0']['Total'][()][:, 7][::24][0:90] + total_95_deaths = total_95_deaths - total_95_deaths[0] + + # we plot the deaths + axs[0,0].plot(df_total_dead.index, deaths_real, 'v', color='tab:red',linewidth=4, label='Extrapolated deaths from reported infection case data') + axs[0,0].plot(df_total_dead.index, total_50_deaths, color='tab:blue', label='Simulated deaths') + axs[0,0].fill_between(df_total_dead.index, total_75_deaths, total_25_deaths, + alpha=0.5, color='tab:blue', label='50% Confidence interval') + axs[0,0].fill_between(df_total_dead.index, total_95_deaths, total_05_deaths, + alpha=0.25, color='tab:blue', label='90% Confidence interval') + axs[0,0].set_ylabel('Cumulative deaths', fontsize=fontsize) + axs[0,0].set_title('Cumulative deaths', fontsize=fontsize+4) + axs[0,0].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[0,0].tick_params(axis='both', which='minor', labelsize=fontsize-4) + axs[0,0].legend(fontsize=fontsize-4, loc='upper left') + + # we want to plot the ICU + + perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.56,0.54,0.46] + age_group_access = ['Group1', 'Group2', 'Group3', + 'Group4', 'Group5', 'Group6', 'Total'] + df_abb_icu = db_abb_icu[['ID_County', 'ICU', 'Date']] + df_abb_icu = df_abb_icu[df_abb_icu['ID_County'] == 3101] + df_abb_icu = df_abb_icu[(df_abb_icu['Date'] >= '2021-03-01') & + (df_abb_icu['Date'] <= '2021-06-01')] + ICU_real = df_abb_icu['ICU'].to_numpy() + + # we need to get the simulated ICU values + f_p50_icu = h5py.File( + path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') + total_50_icu = f_p50_icu['0']['Total'][()] + total_50_icu = total_50_icu[::24][0:90] + total_50_age = f_p50_icu['0'][age_group_access[0]][()] + for i in range(6): + total_50_age += f_p50_icu['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_50_age = total_50_age[::24][0:90] + + # we plot this against this the Amount of persons in the ICU from our model + f_p75_icu = h5py.File( + path+"/infection_state_per_age_group/0/p75/Results.h5", 'r') + # total_75 = f_p75['0']['Total'][()][::24][0:90] + total_75_age = f_p75_icu['0'][age_group_access[0]][()] + for i in range(6): + total_75_age += f_p75_icu['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_75_age = total_75_age[::24][0:90] + + # same with 25 percentile + f_p25_icu = h5py.File( + path+"/infection_state_per_age_group/0/p25/Results.h5", 'r') + # total_25 = f_p25['0']['Total'][()][::24][0:90] + total_25_age = f_p25_icu['0'][age_group_access[0]][()] + for i in range(6): + total_25_age += f_p25_icu['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_25_age = total_25_age[::24][0:90] + + # same with 05 and 95 percentile + f_p05_icu = h5py.File( + path+"/infection_state_per_age_group/0/p05/Results.h5", 'r') + # total_05 = f_p05['0']['Total'][()][::24][0:90] + total_05_age = f_p05_icu['0'][age_group_access[0]][()] + for i in range(6): + total_05_age += f_p05_icu['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_05_age = total_05_age[::24][0:90] + + f_p95_icu = h5py.File( + path+"/infection_state_per_age_group/0/p95/Results.h5", 'r') + # total_95 = f_p95['0']['Total'][()][::24][0:90] + total_95_age = f_p95_icu['0'][age_group_access[0]][()] + for i in range(6): + total_95_age += f_p95_icu['0'][age_group_access[i]][()]*perc_of_critical_in_icu_age[i] + total_95_age = total_95_age[::24][0:90] + + ICU_Simulation = np.round(total_50_age[:, 5]) + ICU_Simulation75 = np.round(total_75_age[:, 5]) + ICU_Simulation25 = np.round(total_25_age[:, 5]) + ICU_Simulation05 = np.round(total_05_age[:, 5]) + ICU_Simulation95 = np.round(total_95_age[:, 5]) + + # we plot the ICU beds and the ICU beds taken + axs[1,0].plot(df_abb_icu['Date'][0:90], ICU_real[0:90], 'v', color='tab:red', linewidth=10, label='Reported ICU beds taken') + axs[1,0].plot(df_abb_icu['Date'][0:90], ICU_Simulation[0:90], color='tab:blue', label='Simulation') + axs[1,0].fill_between(df_abb_icu['Date'][0:90], ICU_Simulation75, ICU_Simulation25, + alpha=0.5, color='tab:blue', label='50% Confidence interval') + axs[1,0].fill_between(df_abb_icu['Date'][0:90], ICU_Simulation05, ICU_Simulation95, + alpha=0.25, color='tab:blue', label='90% Confidence interval') + axs[1,0].set_ylabel('Occupied ICU beds', fontsize=fontsize) + axs[1,0].set_title('ICU beds', fontsize=fontsize+4) + axs[1,0].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[1,0].tick_params(axis='both', which='minor', labelsize=fontsize-4) + axs[1,0].legend(fontsize=fontsize-4) + + # we want to plot the cumulative detected infections + df_total_detected = db_abb_detected[['Date', 'Confirmed', 'ID_County']] + df_total_detected = df_total_detected[(df_total_detected['Date'] >= '2021-03-01') & + (df_total_detected['Date'] <= '2021-06-01')] + df_total_detected = df_total_detected[df_total_detected['ID_County'] == 3101] + df_substract = np.round(df_total_detected['Confirmed'][0:1]) + df_total_detected = np.round(df_total_detected['Confirmed'][0:90]) + df_total_detected = df_total_detected - df_substract.values[0] + df_detected_diff = df_total_detected.diff() + df_detected_rolling_diff = df_detected_diff.rolling(window=7, min_periods=1, center=True).mean() + + # simulation deaths and confidence intervals + f_p50_detected = h5py.File( + path+"/cumulative_detected_infections/0/p50/Results.h5", 'r') + total_50_detected = np.round(f_p50_detected['0']['Total'][()][:, 0][::24][0:90].flatten()) + + f_p75_detected = h5py.File( + path+"/cumulative_detected_infections/0/p75/Results.h5", 'r') + total_75_detected = np.round(f_p75_detected['0']['Total'][()][:, 0][::24][0:90].flatten()) + + f_p25_detected = h5py.File( + path+"/cumulative_detected_infections/0/p25/Results.h5", 'r') + total_25_detected = np.round(f_p25_detected['0']['Total'][()][:, 0][::24][0:90].flatten()) + + f_p05_detected = h5py.File( + path+"/cumulative_detected_infections/0/p05/Results.h5", 'r') + total_05_detected = np.round(f_p05_detected['0']['Total'][()][:, 0][::24][0:90].flatten()) + + f_p95_detected = h5py.File( + path+"/cumulative_detected_infections/0/p95/Results.h5", 'r') + total_95_detected = np.round(f_p95_detected['0']['Total'][()][:, 0][::24][0:90].flatten()) + + # we do the same for the new infecitons (same as above but folder new_detected_infections) + f_p50_diff_detected = h5py.File( + path+"/new_detected_infections/0/p50/Results.h5", 'r') + total_50_diff_detected = np.round(f_p50_diff_detected['0']['Total'][()].flatten()) + + f_p95_diff_detected = h5py.File( + path+"/new_detected_infections/0/p95/Results.h5", 'r') + total_95_diff_detected = np.round(f_p95_diff_detected['0']['Total'][()].flatten()) + + f_p05_diff_detected = h5py.File( + path+"/new_detected_infections/0/p05/Results.h5", 'r') + total_05_diff_detected = np.round(f_p05_diff_detected['0']['Total'][()].flatten()) + + f_p25_diff_detected = h5py.File( + path+"/new_detected_infections/0/p25/Results.h5", 'r') + total_25_diff_detected = np.round(f_p25_diff_detected['0']['Total'][()].flatten()) + + f_p75_diff_detected = h5py.File( + path+"/new_detected_infections/0/p75/Results.h5", 'r') + total_75_diff_detected = np.round(f_p75_diff_detected['0']['Total'][()].flatten()) + + # we need to sum every 24 entries to get the daily amount + total_50_detected = np.cumsum(total_50_detected, axis=0) + total_50_detected = np.diff(total_50_detected)[0:90] + + total_95_detected = np.cumsum(total_95_detected, axis=0) + total_95_detected = np.diff(total_95_detected)[0:90] + + total_05_detected = np.cumsum(total_05_detected, axis=0) + total_05_detected = np.diff(total_05_detected)[0:90] + + total_75_detected = np.cumsum(total_75_detected, axis=0) + total_75_detected = np.diff(total_75_detected)[0:90] + + total_25_detected = np.cumsum(total_25_detected, axis=0) + total_25_detected = np.diff(total_25_detected)[0:90] + + time = f_p50_detected['0']['Time'][()] + time = time[::24] + time = time[0:90] + + # we plot the cumulative detected infections + axs[0,1].plot(df_abb_icu['Date'][0:89], total_50_detected, color='tab:blue', label='Simulation') + axs[0,1].plot(df_abb_icu['Date'][0:89], df_total_detected[0:89], 'v', color='tab:red', label='Cumulative reported detected infections', linewidth=4) + axs[0,1].fill_between(df_abb_icu['Date'][0:89], total_75_detected, total_25_detected, + alpha=0.5, color='tab:blue', label='50% Confidence interval') + axs[0,1].fill_between(df_abb_icu['Date'][0:89], total_95_detected, total_05_detected, + alpha=0.25, color='tab:blue', label='90% Confidence interval') + axs[0,1].set_ylabel('Cumulative detected infections', fontsize=fontsize) + axs[0,1].set_title('Cumulative detected infections', fontsize=fontsize+4) + axs[0,1].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[0,1].tick_params(axis='both', which='minor', labelsize=fontsize-4) + axs[0,1].legend(fontsize=fontsize-4) + + + # we want to plot the new detected infections + axs[1,1].plot(df_abb_icu['Date'][0:90], total_50_diff_detected, color='tab:blue', label='Simulation') + axs[1,1].plot(df_abb_icu['Date'][0:90], df_detected_diff[0:90], 'v', color='tab:red', label='Daily reported detected infections', linewidth=4) + axs[1,1].plot(df_abb_icu['Date'][0:90], df_detected_rolling_diff, '--', color='tab:red', label='Reported detected infections 7 day rolling average', linewidth=4) + axs[1,1].fill_between(df_abb_icu['Date'][0:90], total_75_diff_detected, total_25_diff_detected, + alpha=0.5, color='tab:blue', label='50% Confidence interval') + axs[1,1].fill_between(df_abb_icu['Date'][0:90], total_95_diff_detected, total_05_diff_detected, + alpha=0.25, color='tab:blue', label='90% Confidence interval') + axs[1,1].set_ylabel('New detected infections', fontsize=fontsize) + axs[1,1].set_title('New detected infections', fontsize=fontsize+4) + axs[1,1].tick_params(axis='both', which='major', labelsize=fontsize-4) + axs[1,1].tick_params(axis='both', which='minor', labelsize=fontsize-4) + axs[1,1].legend(fontsize=fontsize-4) + + + + + plt.savefig('fitting_plots.png', dpi=300) + + + + if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" @@ -781,11 +1100,12 @@ def plot_positive_and_done_test(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infection_states_results(path) - plot_infections_loc_types_avarage(path) - plot_icu(path) - plot_dead(path) - plot_cumulative_detected_infections(path) - plot_positive_and_done_test(path) + # plot_infection_states_results(path) + # plot_infections_loc_types_avarage(path) + # plot_icu(path) + # plot_dead(path) + # plot_cumulative_detected_infections(path) + # plot_positive_and_done_test(path) # plot_estimated_reproduction_number(path) + plot_fitting_plots(path) From 0f9d9f1434f6402ee6b311ec9485f4794976d44d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:26:29 +0200 Subject: [PATCH 458/488] grid_search_step2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/analyze_bs_run.py | 2 +- cpp/simulations/paper_abm_bs_testing.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index d100bc0c80..471c175087 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -625,7 +625,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate.json") + path+"/../pydata/Germany/cases_all_county_repdate_ma1.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e748e152fe..727225b73c 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2455,13 +2455,13 @@ int main(int argc, char** argv) // 4: testing prob symptomatic // 5: odds ratio for asymptomatic to symptomatic - std::vector> grid_boundaries = { - {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.85}, {0.01, 0.045}, {2, 15}}; + // std::vector> grid_boundaries = { + // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.85}, {0.01, 0.045}, {2, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.035, 15.0}; - // std::vector grid_boundaries = {1.76, 3.7, 0.53, 0.03, 7.8}; - // std::vector grid_boundaries = {1.88, 3.7, 0.35, 0.035, 12.6}; + std::vector grid_boundaries = {1.52 4.3 0.85 0.024 4.6}; + // std::vector grid_boundaries = {1.52 4.3 0.75 0.024 4.6}; + // std::vector grid_boundaries = {11.64 4.3 0.55 0.038 12.4}; std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { From c69f6e12739005f6e5588cc4d9cdd4d6635790a9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:32:06 +0200 Subject: [PATCH 459/488] bugfix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 727225b73c..3902f41e2e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2459,7 +2459,7 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.85}, {0.01, 0.045}, {2, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.52 4.3 0.85 0.024 4.6}; + std::vector grid_boundaries = {1.52, 4.3, 0.85, 0.024, 4.6}; // std::vector grid_boundaries = {1.52 4.3 0.75 0.024 4.6}; // std::vector grid_boundaries = {11.64 4.3 0.55 0.038 12.4}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From 5d66fa4327b9da38fe3a5a948c98e6dafb144a82 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:36:02 +0200 Subject: [PATCH 460/488] grid point 2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3902f41e2e..8555645c36 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2459,8 +2459,8 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.85}, {0.01, 0.045}, {2, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - std::vector grid_boundaries = {1.52, 4.3, 0.85, 0.024, 4.6}; - // std::vector grid_boundaries = {1.52 4.3 0.75 0.024 4.6}; + // std::vector grid_boundaries = {1.52, 4.3, 0.85, 0.024, 4.6}; + std::vector grid_boundaries = {1.52, 4.3, 0.75, 0.024, 4.6}; // std::vector grid_boundaries = {11.64 4.3 0.55 0.038 12.4}; std::vector points_per_dim = {6, 6, 6, 6, 6}; From b0dccd6568149e09a4dd24853c51d87dad54648c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:36:54 +0200 Subject: [PATCH 461/488] grid_point3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 8555645c36..e3ac96f23d 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2460,9 +2460,9 @@ int main(int argc, char** argv) // std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector grid_boundaries = {1.52, 4.3, 0.85, 0.024, 4.6}; - std::vector grid_boundaries = {1.52, 4.3, 0.75, 0.024, 4.6}; - // std::vector grid_boundaries = {11.64 4.3 0.55 0.038 12.4}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector grid_boundaries = {1.52, 4.3, 0.75, 0.024, 4.6}; + std::vector grid_boundaries = {1.64, 4.3, 0.55, 0.038, 12.4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; From 4526a403d625b799d3664f67da1ca1e9fce3c9a5 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 21:18:09 +0200 Subject: [PATCH 462/488] 128ergridruns Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index e3ac96f23d..b2217de5ab 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2459,10 +2459,10 @@ int main(int argc, char** argv) // {1.4, 2.0}, {2.5, 5.5}, {0.35, 0.85}, {0.01, 0.045}, {2, 15}}; // std::vector points_per_dim = {6, 6, 6, 6, 6}; - // std::vector grid_boundaries = {1.52, 4.3, 0.85, 0.024, 4.6}; + std::vector grid_boundaries = {1.52, 4.3, 0.85, 0.024, 4.6}; // std::vector grid_boundaries = {1.52, 4.3, 0.75, 0.024, 4.6}; - std::vector grid_boundaries = {1.64, 4.3, 0.55, 0.038, 12.4}; - std::vector points_per_dim = {6, 6, 6, 6, 6}; + // std::vector grid_boundaries = {1.64, 4.3, 0.55, 0.038, 12.4}; + std::vector points_per_dim = {6, 6, 6, 6, 6}; // std::vector> grid_boundaries = { // {1.79, 1.83}, {3.28, 3.29}, {0.52, 0.56}, {0.03, 0.04}, {1.0, 15.0}}; @@ -2479,9 +2479,12 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - std::vector> parameters = {{1.52}, {4.9}, {0.71}, {0.02}, {3.0}, {10.0}, {0.5}}; + // std::vector> parameters = {{1.52}, {4.9}, {0.71}, {0.02}, {3.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; + std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; + // std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; + // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); From 44816b60a1a538061560b58a33b7a20480329024 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 21:19:58 +0200 Subject: [PATCH 463/488] 128gs2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index b2217de5ab..0a488897f9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2482,8 +2482,8 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.52}, {4.9}, {0.71}, {0.02}, {3.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; - std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; - // std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; + // std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; + std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From 7991cfbc327e025ba88ef063d31e506be86ac1e7 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 20 Sep 2024 21:21:15 +0200 Subject: [PATCH 464/488] 128rungs3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 0a488897f9..1887b035f0 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2483,9 +2483,9 @@ int main(int argc, char** argv) // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; // std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; - std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; - // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - auto every_combination = every_combination_of_parameters(parameters); + // std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; + std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; + auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); if (!created) { From 1bf16dd7f7396361356f5c85508eb706ef828542 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:01:02 +0200 Subject: [PATCH 465/488] grid_Search128_par1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 1887b035f0..4a5b9c7cb2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2255,6 +2255,9 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } } + rmse_results_per_grid_point.at(par_i) /= num_runs; + printf("RMSE: %f\n, par_i: %d\n", rmse_results_per_grid_point.at(par_i), par_i); + #ifdef MEMILIO_ENABLE_MPI //gather results @@ -2482,10 +2485,10 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.52}, {4.9}, {0.71}, {0.02}, {3.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; - // std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; + std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; // std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; - std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - auto every_combination = every_combination_of_parameters(parameters); + // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; + auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); if (!created) { From 4485299898a65ff6b706e36ff8840253353d3069 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:02:19 +0200 Subject: [PATCH 466/488] gs128_1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 4a5b9c7cb2..3db9a6ba55 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2256,7 +2256,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s } rmse_results_per_grid_point.at(par_i) /= num_runs; - printf("RMSE: %f\n, par_i: %d\n", rmse_results_per_grid_point.at(par_i), par_i); + printf("RMSE: %f\n, par_i: %ld\n", rmse_results_per_grid_point.at(par_i), par_i); #ifdef MEMILIO_ENABLE_MPI From 8157a43832be65bddb8cc88f680e7dbfc1a72dcb Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:04:09 +0200 Subject: [PATCH 467/488] grid128_2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3db9a6ba55..32193c8a0b 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2485,8 +2485,8 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.52}, {4.9}, {0.71}, {0.02}, {3.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; - std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; - // std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; + // std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; + std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From 4f8b73258b652ca39ec45652ed94b0e04ff77b86 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 00:05:22 +0200 Subject: [PATCH 468/488] gs128_3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 32193c8a0b..fc09b130b3 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2486,9 +2486,9 @@ int main(int argc, char** argv) // std::vector> parameters = { // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; // std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; - std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; - // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - auto every_combination = every_combination_of_parameters(parameters); + // std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; + std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; + auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); if (!created) { From 4b14b9e438a6e42ad88617f7de787eca97d4bac4 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:18:27 +0200 Subject: [PATCH 469/488] par_var1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 6 ++-- cpp/simulations/analyze_bs_run.py | 41 ++++++++++++++++-------- cpp/simulations/averagemse | 29 +++++++++++++++++ cpp/simulations/paper_abm_bs_testing.cpp | 19 ++++++++--- 5 files changed, 74 insertions(+), 23 deletions(-) create mode 100644 cpp/simulations/averagemse diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index 7715b917e5..d6e4937488 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index 6091444851..d473fe1b1f 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(2) +#pragma omp parallel for num_threads(8) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index 471c175087..f9b9f2d6fe 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -274,7 +274,7 @@ def plot_dead(path): # we need the real data json file cases_all_county_age df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_age_ma1.json") + path+"/../../../pydata/Germany/cases_all_county_age_ma1.json") # we just need the columns cases and date # we need to offset the dates by 19 day @@ -365,7 +365,7 @@ def plot_dead(path): def plot_icu(path): - df_abb = pd.read_json(path+"/../pydata/Germany/county_divi.json") + df_abb = pd.read_json(path+"/../../../pydata/Germany/county_divi.json") perc_of_critical_in_icu_age = [0.55,0.55,0.55,0.56,0.54,0.46] perc_of_critical_in_icu=0.55 @@ -625,7 +625,7 @@ def plot_estimated_reproduction_number(path): def plot_cumulative_detected_infections(path): df_abb = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma1.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma1.json") # we need the df_abb = df_abb[['Date', 'Confirmed', 'ID_County']] df_abb = df_abb[(df_abb['Date'] >= '2021-03-01') & (df_abb['Date'] <= '2021-06-01')] @@ -841,13 +841,13 @@ def plot_fitting_plots(path): # We want to have the fitting for the four things we fittet against: Cumulative deaths, ICU, Cumulative detected infections and new detected infections # readin of the data db_abb_deaths = pd.read_json( - path+"/../pydata/Germany/cases_all_county_age_ma1.json") + path+"/../../../pydata/Germany/cases_all_county_age_ma1.json") db_abb_icu = pd.read_json( - path+"/../pydata/Germany/county_divi.json") + path+"/../../../pydata/Germany/county_divi.json") db_abb_detected = pd.read_json( - path+"/../pydata/Germany/cases_all_county_repdate_ma1.json") + path+"/../../../pydata/Germany/cases_all_county_repdate_ma1.json") # we want to plot the plots in a 4x1 grid and we want to have the same x axis for all of them # the first plot has also the legend @@ -864,12 +864,15 @@ def plot_fitting_plots(path): df_total_dead = df_total_dead[df_total_dead['ID_County'] == 3101] df_total_dead = df_total_dead.groupby('Date').sum()[0:90] deaths_real = df_total_dead['Deaths'].to_numpy() + mse_death = deaths_real deaths_real = deaths_real[0:90] - deaths_real[0] + # simulation deaths and confidence intervals f_p50_deaths = h5py.File( path+"/infection_state_per_age_group/0/p50/Results.h5", 'r') total_50_deaths = f_p50_deaths['0']['Total'][()][:, 7][::24][0:90] + mse_sim_dead = total_50_deaths total_50_deaths = total_50_deaths - total_50_deaths[0] f_p75_deaths = h5py.File( @@ -1081,6 +1084,16 @@ def plot_fitting_plots(path): axs[1,1].tick_params(axis='both', which='minor', labelsize=fontsize-4) axs[1,1].legend(fontsize=fontsize-4) + # we also need to calculate the MSE for the fitting + mse_deaths = ((mse_death - mse_sim_dead)**2).mean() + mse_icu = ((ICU_real[0:90] - ICU_Simulation[0:90])**2).mean() + mse_detected = ((df_total_detected[0:89] - total_50_detected)**2).mean() + + mse_final = mse_deaths + mse_icu*0.1 + mse_detected*0.01*0.01*3 + print('MSE Deaths: ', mse_deaths) + print('MSE ICU: ', mse_icu) + print('MSE Detected: ', mse_detected) + print('MSE Final: ', mse_final) @@ -1091,8 +1104,8 @@ def plot_fitting_plots(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113051" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" + path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/final_results/results_2024-09-20192904_best" # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" if (len(sys.argv) > 1): @@ -1100,12 +1113,12 @@ def plot_fitting_plots(path): else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - # plot_infection_states_results(path) - # plot_infections_loc_types_avarage(path) - # plot_icu(path) - # plot_dead(path) - # plot_cumulative_detected_infections(path) - # plot_positive_and_done_test(path) + plot_infection_states_results(path) + plot_infections_loc_types_avarage(path) + plot_icu(path) + plot_dead(path) + plot_cumulative_detected_infections(path) + plot_positive_and_done_test(path) # plot_estimated_reproduction_number(path) plot_fitting_plots(path) diff --git a/cpp/simulations/averagemse b/cpp/simulations/averagemse new file mode 100644 index 0000000000..22179558c1 --- /dev/null +++ b/cpp/simulations/averagemse @@ -0,0 +1,29 @@ +import re + +def extract_rmse(filename): + with open(filename, 'r') as file: + content = file.read() + + # Find all RMSE values using regex + rmse_values = re.findall(r'RMSE:\s*(\d+\.\d+)', content) + + # Convert the extracted values to floats + rmse_values = [float(value) for value in rmse_values] + + if not rmse_values: + return None, None + + # Calculate the average RMSE + average_rmse = sum(rmse_values) / len(rmse_values) + + return rmse_values, average_rmse + +# Example usage +filename = '/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/final_results/results_2024-09-20192904/mpi-out.13147295.txt' +rmse_values, average_rmse = extract_rmse(filename) + +if rmse_values is not None: + print(f"Extracted RMSE values: {rmse_values}") + print(f"Average RMSE: {average_rmse}") +else: + print("No RMSE values found in the file.") \ No newline at end of file diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index fc09b130b3..234aade887 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2482,13 +2482,22 @@ int main(int argc, char** argv) auto result = run_with_grid_search(input_dir, result_dir, num_runs, grid, rng); } else { - // std::vector> parameters = {{1.52}, {4.9}, {0.71}, {0.02}, {3.0}, {10.0}, {0.5}}; - // std::vector> parameters = { - // {1.76}, {3.7}, {0.53}, {0.035}, {15.0}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; // std::vector> parameters = {{1.596}, {4.171}, {0.7275}, {0.02472}, {4.83}, {10.0}, {0.5}}; // std::vector> parameters = {{1.52}, {4.3}, {0.85}, {0.024}, {4.6}, {10.0}, {0.5}}; - std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - auto every_combination = every_combination_of_parameters(parameters); + + // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; + + // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.07, 0.105}, + // {15.0}, {10.0}, {0.5}}; + + std::vector> parameters = { + {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {2.0, 5.0, 8.0, 11.0, 14.0}, {10.0}, {0.5}}; + // std::vector> parameters = { + // {1.596}, {4.171}, {0.7125},{0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {2, 5, 8, 11, 14}, {0.5}}; + // std::vector> parameters = { + // {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; + + auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { auto created = create_result_folders(result_dir, every_combination.size(), run_grid_search); if (!created) { From 7939221d92297cd72c0621992534c5eafc6b0e72 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:20:08 +0200 Subject: [PATCH 470/488] parvar2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 234aade887..5b66d3dec9 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2490,10 +2490,10 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.07, 0.105}, // {15.0}, {10.0}, {0.5}}; - std::vector> parameters = { - {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {2.0, 5.0, 8.0, 11.0, 14.0}, {10.0}, {0.5}}; // std::vector> parameters = { - // {1.596}, {4.171}, {0.7125},{0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {2, 5, 8, 11, 14}, {0.5}}; + // {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {2.0, 5.0, 8.0, 11.0, 14.0}, {10.0}, {0.5}}; + std::vector> parameters = { + {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {2, 5, 8, 11, 14}, {0.5}}; // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; From 36d3bb94740fa6e7b4bd1c9b8da226a4b2ae8598 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:21:26 +0200 Subject: [PATCH 471/488] parvar3 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5b66d3dec9..3bbd2003dc 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2492,10 +2492,10 @@ int main(int argc, char** argv) // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {2.0, 5.0, 8.0, 11.0, 14.0}, {10.0}, {0.5}}; - std::vector> parameters = { - {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {2, 5, 8, 11, 14}, {0.5}}; // std::vector> parameters = { - // {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; + // {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {2, 5, 8, 11, 14}, {0.5}}; + std::vector> parameters = { + {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From 89ada50b90527e93601ba8f3e6c9726731f552ea Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:27:49 +0200 Subject: [PATCH 472/488] scenario1 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 3bbd2003dc..21076c9e83 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2487,15 +2487,15 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - // std::vector> parameters = {{1.76}, {3.7}, {0.53}, {0.035, 0.07, 0.105}, - // {15.0}, {10.0}, {0.5}}; + std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472, 0.04944, 0.07416}, + {4.83}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {2.0, 5.0, 8.0, 11.0, 14.0}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {2, 5, 8, 11, 14}, {0.5}}; - std::vector> parameters = { - {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; + // std::vector> parameters = { + // {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From fa8dd7696d871d0cc7c8b4630a6111318a450655 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:31:30 +0200 Subject: [PATCH 473/488] omp change Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/testing_strategy.cpp | 2 +- cpp/models/abm/world.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/models/abm/testing_strategy.cpp b/cpp/models/abm/testing_strategy.cpp index d6e4937488..7715b917e5 100644 --- a/cpp/models/abm/testing_strategy.cpp +++ b/cpp/models/abm/testing_strategy.cpp @@ -169,7 +169,7 @@ void TestingStrategy::update_location_testing_schemes( } if (std::find(m_update_ts_scheduler.begin(), m_update_ts_scheduler.end(), t) != m_update_ts_scheduler.end()) { -#pragma omp parallel for num_threads(8) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < locations.size(); ++i) { auto& location = locations[i]; auto loc_id = location.get_index(); diff --git a/cpp/models/abm/world.cpp b/cpp/models/abm/world.cpp index d473fe1b1f..6091444851 100755 --- a/cpp/models/abm/world.cpp +++ b/cpp/models/abm/world.cpp @@ -66,7 +66,7 @@ void World::evolve(TimePoint t, TimeSpan dt) void World::interaction(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(8) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; auto personal_rng = Person::RandomNumberGenerator(m_rng, *person); @@ -76,7 +76,7 @@ void World::interaction(TimePoint t, TimeSpan dt) void World::migration(TimePoint t, TimeSpan dt) { -#pragma omp parallel for num_threads(8) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_persons.size(); ++i) { auto&& person = m_persons[i]; @@ -169,7 +169,7 @@ void World::migration(TimePoint t, TimeSpan dt) void World::begin_step(TimePoint t, TimeSpan dt) { m_testing_strategy.update_location_testing_schemes(t, get_locations()); -#pragma omp parallel for num_threads(8) +#pragma omp parallel for num_threads(2) for (auto i = size_t(0); i < m_locations.size(); ++i) { auto&& location = m_locations[i]; location->location_contaminated = false; From 8671d2a9cbedea2bf04e0b6a7af85fb1380951e7 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:46:06 +0200 Subject: [PATCH 474/488] short fix Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/scenario_plots.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index d07b44a425..f19b1e5f0e 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -87,9 +87,9 @@ def plot_scenario(path, folder, folder_high, folder_enough): path+"/infection_state_per_age_group/"+folder+"/p25/Results.h5", 'r') deaths_p75_normal = h5py.File( path+"/infection_state_per_age_group/"+folder+"/p75/Results.h5", 'r') - p50_bs_deaths_normal = deaths_p50_normal['0']['Total'][()][:, 7][::24][0:90] - p25_bs_deaths_normal = deaths_p25_normal['0']['Total'][()][:, 7][::24][0:90] - p75_bs_deaths_normal = deaths_p75_normal['0']['Total'][()][:, 7][::24][0:90] + p50_bs_deaths_normal = deaths_p50_normal['0']['Total'][()][:, 7][::24][0:90]-deaths_p50_normal['0']['Total'][()][:, 7][::24][0] + p25_bs_deaths_normal = deaths_p25_normal['0']['Total'][()][:, 7][::24][0:90]-deaths_p25_normal['0']['Total'][()][:, 7][::24][0] + p75_bs_deaths_normal = deaths_p75_normal['0']['Total'][()][:, 7][::24][0:90]-deaths_p75_normal['0']['Total'][()][:, 7][::24][0] reproduction_p50_normal = h5py.File( path+"/estimated_reproduction_number/"+folder+"/p50/Results.h5", 'r') From a12fc8ade5aaae5f6003d9d2d149e43b68719459 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 01:58:11 +0200 Subject: [PATCH 475/488] scenario2 Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 21076c9e83..5ecabe2949 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1764,7 +1764,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; + const double damping_community_lockdown = 0.8; // const double testing_probability_sympt = 0.037; // const double ratio_asympt_to_sympt = 20.0; const double testing_probability_sympt = params[3]; @@ -1998,18 +1998,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; + const double damping_community_lockdown = 0.8; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.2; + const double lockdown_test_prob = 1.0; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.25; - const double after_lockdown_contact_reduction = 0.50; + const double after_lockdown_contact_reduction = 1.0; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2125,7 +2125,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 + 0.5); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2149,7 +2149,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 + 0.75); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2487,7 +2487,7 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472, 0.04944, 0.07416}, + std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472, 0.07416, 0.1236}, {4.83}, {10.0}, {0.5}}; // std::vector> parameters = { From 5be6985c2357b6d5dd26e3f10416f2fd2e0c094d Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 02:00:39 +0200 Subject: [PATCH 476/488] Revert "scenario2" This reverts commit a12fc8ade5aaae5f6003d9d2d149e43b68719459. --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 5ecabe2949..21076c9e83 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1764,7 +1764,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.8; + const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.037; // const double ratio_asympt_to_sympt = 20.0; const double testing_probability_sympt = params[3]; @@ -1998,18 +1998,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.8; + const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.0; + const double lockdown_test_prob = 1.2; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.25; - const double after_lockdown_contact_reduction = 1.0; + const double after_lockdown_contact_reduction = 0.50; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2125,7 +2125,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.5); // from 2021-03-15 + 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2149,7 +2149,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.75); // from 2021-03-15 + 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2487,7 +2487,7 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472, 0.07416, 0.1236}, + std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472, 0.04944, 0.07416}, {4.83}, {10.0}, {0.5}}; // std::vector> parameters = { From 3ba3c16310d123ab8036c9a858c20dffdcce5d61 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Sat, 21 Sep 2024 03:36:42 +0200 Subject: [PATCH 477/488] scenario 2 again Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/simulations/paper_abm_bs_testing.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 21076c9e83..6cb040db1e 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1764,7 +1764,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; + const double damping_community_lockdown = 0.8; // const double testing_probability_sympt = 0.037; // const double ratio_asympt_to_sympt = 20.0; const double testing_probability_sympt = params[3]; @@ -1998,18 +1998,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.5; + const double damping_community_lockdown = 0.8; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.2; + const double lockdown_test_prob = 1.0; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = 0.25; - const double after_lockdown_contact_reduction = 0.50; + const double after_lockdown_contact_reduction = 1.0; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2125,7 +2125,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.00); // from 2021-03-15 + 0.5); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2149,7 +2149,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.7); // from 2021-03-15 + 0.75); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } @@ -2487,7 +2487,7 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472, 0.04944, 0.07416}, + std::vector> parameters = {{1.596}, {4.171}, {1.0}, {0.02472, 0.07416, 0.1236}, {4.83}, {10.0}, {0.5}}; // std::vector> parameters = { From 29162960c597b3c89e85c9798f1c73079c8da1eb Mon Sep 17 00:00:00 2001 From: Sascha <51127093+xsaschako@users.noreply.github.com> Date: Sat, 28 Sep 2024 03:58:56 +0200 Subject: [PATCH 478/488] mask change --- cpp/simulations/paper_abm_bs_testing.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 6cb040db1e..c5c13f43b2 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2008,7 +2008,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; - const double masks = 0.25; + const double masks = params[7]; const double after_lockdown_contact_reduction = 1.0; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; @@ -2487,8 +2487,8 @@ int main(int argc, char** argv) // std::vector> parameters = {{1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {10.0}, {0.5}}; - std::vector> parameters = {{1.596}, {4.171}, {1.0}, {0.02472, 0.07416, 0.1236}, - {4.83}, {10.0}, {0.5}}; + // std::vector> parameters = {{1.596}, {4.171}, {1.0}, {0.02472, 0.07416, 0.1236}, + // {4.83}, {10.0}, {0.5}}; // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {2.0, 5.0, 8.0, 11.0, 14.0}, {10.0}, {0.5}}; @@ -2496,6 +2496,8 @@ int main(int argc, char** argv) // {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {2, 5, 8, 11, 14}, {0.5}}; // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; + std::vector> parameters = { + {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {10.0}, {0.5},{0.15,0.2,0.25,0.3,0.35}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From eb7aa126919a82ce1c9c01ef8ae7050422ad72a7 Mon Sep 17 00:00:00 2001 From: Sascha <51127093+xsaschako@users.noreply.github.com> Date: Wed, 2 Oct 2024 00:52:22 +0200 Subject: [PATCH 479/488] mask change --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index c5c13f43b2..65731e3cca 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2497,7 +2497,7 @@ int main(int argc, char** argv) // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; std::vector> parameters = { - {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {10.0}, {0.5},{0.15,0.2,0.25,0.3,0.35}}; + {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {10.0}, {0.5},{0.2, 0.225, 0.25, 0.275, 3.0}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From 72fb84ba2d2c3e8df67c9648f2dfc802014a41cc Mon Sep 17 00:00:00 2001 From: Sascha <51127093+xsaschako@users.noreply.github.com> Date: Wed, 2 Oct 2024 10:32:35 +0200 Subject: [PATCH 480/488] cluster urn --- cpp/simulations/paper_abm_bs_testing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index 65731e3cca..bc2929c668 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -2497,7 +2497,7 @@ int main(int argc, char** argv) // std::vector> parameters = { // {1.596}, {4.171}, {0.7125}, {0.02472}, {4.83}, {2, 5, 8, 11, 14}, {0.0, 0.25, 0.5, 0.75, 1.0}}; std::vector> parameters = { - {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {10.0}, {0.5},{0.2, 0.225, 0.25, 0.275, 3.0}}; + {1.596}, {4.171}, {0.7125}, {0.012, 0.024, 0.036, 0.048, 0.06}, {4.83}, {10.0}, {0.5},{0.2, 0.225, 0.25, 0.275, 0.3}}; auto every_combination = every_combination_of_parameters(parameters); if (rank == 0) { From 010154453142637386a4819c26d87ca65c9fb511 Mon Sep 17 00:00:00 2001 From: Sascha <51127093+xsaschako@users.noreply.github.com> Date: Wed, 2 Oct 2024 22:33:02 +0200 Subject: [PATCH 481/488] Revert "scenario 2 again" This reverts commit 3ba3c16310d123ab8036c9a858c20dffdcce5d61. --- cpp/simulations/paper_abm_bs_testing.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/simulations/paper_abm_bs_testing.cpp b/cpp/simulations/paper_abm_bs_testing.cpp index bc2929c668..08b22ad19a 100644 --- a/cpp/simulations/paper_abm_bs_testing.cpp +++ b/cpp/simulations/paper_abm_bs_testing.cpp @@ -1764,7 +1764,7 @@ mio::IOResult run_with_grid_search(const fs::path& input_dir, const fs::pa const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.8; + const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.037; // const double ratio_asympt_to_sympt = 20.0; const double testing_probability_sympt = params[3]; @@ -1998,18 +1998,18 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s const double viral_shedding_rate = params[0]; const double dark_figure = params[1]; const double contact_red_lockdown = params[2]; - const double damping_community_lockdown = 0.8; + const double damping_community_lockdown = 0.5; // const double testing_probability_sympt = 0.036; const double testing_probability_sympt = params[3]; - const double lockdown_test_prob = 1.0; + const double lockdown_test_prob = 1.2; const double after_lockdown_test_prob = 1.0; const auto seasonality_april = 0.95; const auto seasonality_may = 0.85; const double masks = params[7]; - const double after_lockdown_contact_reduction = 1.0; + const double after_lockdown_contact_reduction = 0.50; // const double ratio_asympt_to_sympt = 20.0; const double ratio_asympt_to_sympt = params[4]; const double perc_easter_event = 0.2; @@ -2125,7 +2125,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.5); // from 2021-03-01 location.get_infection_parameters().get().array() *= (0.5); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.5); // from 2021-03-15 + 0.00); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.5); // from 2021-04-12 till 2021-05-30 } @@ -2149,7 +2149,7 @@ mio::IOResult run(const fs::path& input_dir, const fs::path& result_dir, s location.add_damping(mio::abm::TimePoint(mio::abm::days(0).seconds()), 0.75); // from 2021-03-15 // location.get_infection_parameters().get().array() *= (0.75 * 0.75); location.add_damping(mio::abm::TimePoint(mio::abm::days(date_of_lockdown).seconds()), - 0.75); // from 2021-03-15 + 0.7); // from 2021-03-15 location.add_damping(mio::abm::TimePoint(mio::abm::days(end_date_of_lockdown).seconds()), 0.75); // from 2021-03-15 } From 1fb68d897e4ef6d6a3425416fcd0edf1f8d3cc4e Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:51:24 +0200 Subject: [PATCH 482/488] Add function for constant viral shed to compare results --- cpp/models/abm/infection.cpp | 15 +++++++++++++-- cpp/models/abm/infection.h | 2 ++ cpp/models/abm/parameters.h | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 66daa866a0..088c981420 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -76,6 +76,17 @@ ScalarType Infection::get_viral_shed(TimePoint t) const return m_individual_virus_shed_factor / (1 + exp(-(m_log_norm_alpha + m_log_norm_beta * get_viral_load(t)))); } +ScalarType Infection::get_viral_shed_constant(TimePoint t) const +{ + auto t_begin = m_infection_course.frost().first; + auto t_end = + m_infection_course.back().first; // take last value of infection course: this is either recovered or dead + + return m_individual_virus_shed_factor * get_viral_shed_integral(t_begin, t_end) / + (t_end.days() - t_begin.days()); // average viral shed + // .days() because the incline and decline are measured in days, thus the shed and it's integral is normalized to days +} + ScalarType Infection::get_viral_shed_integral() const { ScalarType integral = std::log(std::exp(m_log_norm_alpha + m_log_norm_beta * m_viral_load.peak) + 1) / @@ -340,13 +351,13 @@ TimePoint Infection::draw_infection_course_backward(Person::RandomNumberGenerato time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedNoSymptoms; } - else if (p > params.get()[{m_virus_variant, age}] * + else if (p < params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; time_period = days(time_in_state.get_distribution_instance()(rng, time_in_state.params)); previous_state = InfectionState::InfectedSymptoms; } - else if (p > params.get()[{m_virus_variant, age}] * + else if (p < params.get()[{m_virus_variant, age}] * params.get()[{m_virus_variant, age}] * (1 - params.get()[{m_virus_variant, age}]) / (1 - p_death)) { time_in_state = params.get()[{m_virus_variant, age}]; diff --git a/cpp/models/abm/infection.h b/cpp/models/abm/infection.h index ad48d3e9cb..be28616dad 100644 --- a/cpp/models/abm/infection.h +++ b/cpp/models/abm/infection.h @@ -89,6 +89,8 @@ class Infection */ ScalarType get_viral_shed(TimePoint t) const; + ScalarType get_viral_shed_constant(TimePoint t) const; + /** * @brief Get total viral shed. */ diff --git a/cpp/models/abm/parameters.h b/cpp/models/abm/parameters.h index bc23f75d9f..9bdfbc60a2 100644 --- a/cpp/models/abm/parameters.h +++ b/cpp/models/abm/parameters.h @@ -452,7 +452,7 @@ struct TestParameters { TestParameters(UncertainValue value) { sensitivity = value; - sensitivity = value; + specificity = value; } }; From cf89d799f4c6e522bc578392a464d72037c37d33 Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 4 Oct 2024 16:29:42 +0200 Subject: [PATCH 483/488] Fixed unused t in constant viral shed --- cpp/models/abm/infection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 088c981420..3149201509 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -78,6 +78,7 @@ ScalarType Infection::get_viral_shed(TimePoint t) const ScalarType Infection::get_viral_shed_constant(TimePoint t) const { + unused(t); // unused as assumed constant auto t_begin = m_infection_course.frost().first; auto t_end = m_infection_course.back().first; // take last value of infection course: this is either recovered or dead From f829c5ae2d99c4dfab7d97415010350a85554fa5 Mon Sep 17 00:00:00 2001 From: Sascha <51127093+xsaschako@users.noreply.github.com> Date: Sat, 5 Oct 2024 02:54:21 +0200 Subject: [PATCH 484/488] some improvs --- cpp/simulations/analyze_bs_run.py | 16 +++---- cpp/simulations/parameter_varation.py | 23 +++++---- cpp/simulations/scenario_plots.py | 68 +++++++++++++++++++++++---- 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/cpp/simulations/analyze_bs_run.py b/cpp/simulations/analyze_bs_run.py index f9b9f2d6fe..068c4ece00 100644 --- a/cpp/simulations/analyze_bs_run.py +++ b/cpp/simulations/analyze_bs_run.py @@ -1105,20 +1105,20 @@ def plot_fitting_plots(path): if __name__ == "__main__": # path = "/Users/david/Documents/HZI/memilio/data/results_last_run" # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/results_last_run" - path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/final_results/results_2024-09-20192904_best" - # path = r"C:\Users\korf_sa\Documents\rep\data\results_last_run" + # path = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113051" + path = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\final_results\results_2024-09-20222109" if (len(sys.argv) > 1): n_runs = sys.argv[1] else: n_runs = len([entry for entry in os.listdir(path) if os.path.isfile(os.path.join(path, entry))]) - plot_infection_states_results(path) - plot_infections_loc_types_avarage(path) - plot_icu(path) - plot_dead(path) - plot_cumulative_detected_infections(path) - plot_positive_and_done_test(path) + # plot_infection_states_results(path) + # plot_infections_loc_types_avarage(path) + # plot_icu(path) + # plot_dead(path) + # plot_cumulative_detected_infections(path) + # plot_positive_and_done_test(path) # plot_estimated_reproduction_number(path) plot_fitting_plots(path) diff --git a/cpp/simulations/parameter_varation.py b/cpp/simulations/parameter_varation.py index 3c15e9b0d1..01f6adba5b 100644 --- a/cpp/simulations/parameter_varation.py +++ b/cpp/simulations/parameter_varation.py @@ -19,7 +19,7 @@ import seaborn as sns -fontsize = 18 +fontsize = 20 def plot_of_cumuative_infections(path, index=0): # plot cumulative infections @@ -104,23 +104,30 @@ def get_maximum_daily_infections(path, index): if __name__ == "__main__": # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28120457" + # path_data = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\final_results\results_2024-09-20233035" # variable_1 = "Test likelihood with symptoms" # variable_2 = "Ratio for asymptomatic agents to test" - # values_1 = [0.0175,0.035,0.0525,0.07,0.0875] - # values_2 = ["1/5","1/8","1/11","1/14","1/17"] + # values_1 = [0.012, 0.024, 0.036, 0.048, 0.06] + # values_2 = ["1/2","1/5","1/8","1/11","1/14"] # path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28120954" + # path_data = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\final_results\results_2024-09-20233103" # variable_1 = "Quarantine length (days)" # variable_2 = "Quarantine efficiency" # values_1 = [2,5,8,11,14] # values_2 = [0.0,0.25,0.5,0.75,1.0] - path_data = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28120655" - variable_1 = "Test likelihood with symptoms" - variable_2 = "Quarantine length (days)" - values_1 = [0.0175,0.035,0.0525,0.07,0.0875] - values_2 = [2,5,8,11,14] + # path_data = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\final_results\results_2024-09-29002004" + # variable_1 = "Test likelihood with symptoms" + # variable_2 = "Quarantine length (days)" + # values_1 = [0.012, 0.024, 0.036, 0.048, 0.06] + # values_2 = [2,5,8,11,14] + path_data = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\final_results\results_2024-10-01225821" + variable_1 = "Test likelihood with symptoms" + variable_2 = "Mask Efficiency" + values_1 = [0.012, 0.024, 0.036, 0.048, 0.06] + values_2 = [0.2, 0.225, 0.25, 0.275, 0.3] # we want to have a Grid Plot with the size of the values # in each grid we plot a certain plot which we can define diff --git a/cpp/simulations/scenario_plots.py b/cpp/simulations/scenario_plots.py index f19b1e5f0e..e3abd2bf9f 100644 --- a/cpp/simulations/scenario_plots.py +++ b/cpp/simulations/scenario_plots.py @@ -17,7 +17,7 @@ fontsize = 18 -def plot_scenario(path, folder, folder_high, folder_enough): +def plot_scenario(path, folder, folder_high, folder_enough, folder_comp=0): # four plots with 3 lines for each scenario and another one for the real data # we do one plot with 3 subplots first two plots in upper left and right are @@ -47,7 +47,50 @@ def plot_scenario(path, folder, folder_high, folder_enough): xx = xx[1:][::24][:90] #label string for each folder - labels = ['Standart Testing', 'High Testing Scenario', 'Very High Testing Scenario'] + labels = ['Standard Testing', 'High Testing Scenario', 'Very High Testing Scenario'] + + if folder_comp != 0: + inf_p50_normal_comp = h5py.File( + folder_comp+"/infection_per_location_type_per_age_group/"+"0"+"/p50/Results.h5", 'r') + p50_bs_normal_comp = inf_p50_normal_comp['0']['Total'][()] + + tests_p50_normal_comp = h5py.File( + folder_comp+"/test_per_location_type_per_age_group/"+"0"+"/p50/Results.h5", 'r') + p50_bs_tests_normal_comp = tests_p50_normal_comp['0']['Total'][()] + + test_p_pos_p50_normal_comp = h5py.File( + folder_comp+"/new_detected_infections/"+"0"+"/p50/Results.h5", 'r') + p50_bs_test_p_pos_normal_comp = test_p_pos_p50_normal_comp['0']['Total'][()].flatten() + + deaths_p50_normal_comp = h5py.File( + folder_comp+"/infection_state_per_age_group/"+"0"+"/p50/Results.h5", 'r') + p50_bs_deaths_normal_comp = deaths_p50_normal_comp['0']['Total'][()][:, 7][::24][0:90]-deaths_p50_normal_comp['0']['Total'][()][:, 7][::24][0] + + reproduction_p50_normal_comp = h5py.File( + folder_comp+"/estimated_reproduction_number/"+"0"+"/p50/Results.h5", 'r') + p50_bs_reproduction_normal_comp = reproduction_p50_normal_comp['0']['Total'][()][::24][0:90].flatten() + + p50_bs_normal_comp_all_locations = np.zeros(len(p50_bs_normal_comp)) + for location in locations: + p50_bs_normal_comp_all_locations += p50_bs_normal_comp[:, location] + + + + cum_inf_normal_comp_50 = np.cumsum(p50_bs_normal_comp_all_locations) + cum_inf_normal_comp_50 = cum_inf_normal_comp_50[::24] + cum_inf_normal_comp_50 = cum_inf_normal_comp_50[:91] + new_inf_normal_comp_50 = np.diff(cum_inf_normal_comp_50) + + total_50_positive_comp = np.cumsum(p50_bs_test_p_pos_normal_comp, axis=0) + total_50_positive_comp = total_50_positive_comp[0:91] # we still need to take the difference to get the daily amount + total_50_positive_comp = np.diff(total_50_positive_comp, axis=0).flatten() + + total_50_done_comp = np.sum(p50_bs_tests_normal_comp, axis=1) + total_50_done_comp = np.cumsum(total_50_done_comp, axis=0) + total_50_done_comp = total_50_done_comp[::24] + total_50_done_comp = total_50_done_comp[0:91] # we still need to take the difference to get the daily amount + total_50_done_comp = np.diff(total_50_done_comp, axis=0).flatten() + for folder in folders: inf_p50_normal = h5py.File( @@ -173,6 +216,7 @@ def plot_scenario(path, folder, folder_high, folder_enough): # first plot axs[0, 0].plot(xx, new_inf_normal_50, label='Normal') axs[0, 0].fill_between(xx, new_inf_normal_25, new_inf_normal_75, alpha=0.5) + # second plot @@ -198,7 +242,14 @@ def plot_scenario(path, folder, folder_high, folder_enough): axs[2, 1].fill_between(xx, p25_bs_reproduction_normal, p75_bs_reproduction_normal, alpha=0.5) axs[2, 1].set_ylim([0, max(p75_bs_reproduction_normal)*1.5]) - + if folder_comp != 0: + axs[0, 0].plot(xx, new_inf_normal_comp_50[0:90], label='Comparison', linestyle='dashed', color='black') + axs[0, 1].plot(xx, cum_inf_normal_comp_50[0:90], label='Lockdown Scenario Standard', linestyle='dashed', color='black') + axs[1, 0].plot(xx, total_50_done_comp, label='Comparison', linestyle='dashed', color='black') + axs[1, 1].plot(xx[:89], total_50_positive_comp, label='Comparison', linestyle='dashed', color='black') + axs[2, 0].plot(xx, p50_bs_deaths_normal_comp, label='Comparison', linestyle='dashed', color='black') + axs[2, 1].plot(xx, p50_bs_reproduction_normal_comp, label='Comparison', linestyle='dashed', color='black') + @@ -247,13 +298,14 @@ def plot_scenario(path, folder, folder_high, folder_enough): if __name__ == "__main__": - path_to_scenario_1 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28211441" # more tesring - path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113737" # no lockdown but much testing - path_to_scenario_3 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/" + path_to_scenario_1 = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\final_results\results_2024-09-21014651" # more tesring + path_to_scenario_2 = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\final_results\results_2024-09-20233958" # more tesring + # path_to_scenario_2 = "/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/cluster_results/vorlaufige_ergebnisse/results_2024-08-28113737" # no lockdown but much testing + # path_to_scenario_3 = r"C:\Users\korf_sa\Documents\memilio\data\cluster_results\vorlaufige_ergebnisse\results_2024-08-28211441" path_to_main_data = "0" path_to_high_testing_data = "1" path_to_enough_testing_data = "2" - # plot_scenario(path_to_scenario_1, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) - plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) + plot_scenario(path_to_scenario_1, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data,path_to_scenario_2) + # plot_scenario(path_to_scenario_2, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) # plot_scenario(path_to_scenario_3, path_to_main_data, path_to_high_testing_data, path_to_enough_testing_data) From 2df2edd25af150c0fab975535f9a33f0d4ae6b5b Mon Sep 17 00:00:00 2001 From: DavidKerkmann <44698825+DavidKerkmann@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:16:48 +0200 Subject: [PATCH 485/488] Fix typo and improve viral shed plot --- cpp/models/abm/infection.cpp | 2 +- cpp/simulations/viral_shed.py | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/cpp/models/abm/infection.cpp b/cpp/models/abm/infection.cpp index 3149201509..72393d2869 100644 --- a/cpp/models/abm/infection.cpp +++ b/cpp/models/abm/infection.cpp @@ -79,7 +79,7 @@ ScalarType Infection::get_viral_shed(TimePoint t) const ScalarType Infection::get_viral_shed_constant(TimePoint t) const { unused(t); // unused as assumed constant - auto t_begin = m_infection_course.frost().first; + auto t_begin = m_infection_course.front().first; auto t_end = m_infection_course.back().first; // take last value of infection course: this is either recovered or dead diff --git a/cpp/simulations/viral_shed.py b/cpp/simulations/viral_shed.py index 68d15f4fd2..78b3f858dd 100644 --- a/cpp/simulations/viral_shed.py +++ b/cpp/simulations/viral_shed.py @@ -1,7 +1,8 @@ import numpy as np import scipy as sp import matplotlib.pyplot as plt -fontsize = 24 +import matplotlib as mpl +fontsize = 30 # 24 def viral_load(t, increase, decrease, peak): peak_time = peak / increase @@ -23,8 +24,8 @@ def viral_shedding(t, personal_viral_shed, alpha, beta, viral_load_with_params): return personal_viral_shed * 1/(1+np.exp(-(alpha + beta* viral_load_with_params(t)))) def return_my_sigma(mean, stddev): - my = np.log(mean * mean / np.sqrt(mean * mean + stddev * stddev)); - sigma = np.sqrt(np.log(1 + stddev * stddev / mean / mean)); + my = np.log(mean * mean / np.sqrt(mean * mean + stddev * stddev)) + sigma = np.sqrt(np.log(1 + stddev * stddev / mean / mean)) return my, sigma def draw_timepoints_infectious_and_not(): @@ -35,14 +36,10 @@ def draw_timepoints_infectious_and_not(): exposed_length = sp.stats.lognorm(s=my_sigma_incubation[0], scale=my_sigma_incubation[1]).rvs(1) - - - return timepoints_infectious, timepoints_not_infectious - viral_load_increase = 2.0 viral_load_decrease = 0.5 viral_load_peak = 8.1 -personal_viral_shed = sp.stats.gamma(a=1.6, scale=1/22).rvs(20) +personal_viral_shed = sorted(sp.stats.gamma(a=1.6, scale=1/22).rvs(20)) alpha = -7 beta = 1 @@ -52,8 +49,10 @@ def draw_timepoints_infectious_and_not(): viral_shedding_values_for_each_person = [[viral_shedding(t, personal_viral_shed, alpha, beta, viral_load_with_params) for t in t] for personal_viral_shed in personal_viral_shed] plt.figure(figsize=(12, 8)) -for viral_shedding_values in viral_shedding_values_for_each_person: - plt.plot(t, viral_shedding_values) +colors = mpl.colormaps['brg'](np.linspace(0, 1, 40)) # only take blue-red +for i, viral_shedding_values in zip(range(len(viral_shedding_values_for_each_person)), viral_shedding_values_for_each_person): + plt.plot(t, viral_shedding_values, linewidth=2, color=colors[i]) +print(personal_viral_shed[0], personal_viral_shed[-1]) plt.title('Viral shedding', fontsize=fontsize) plt.xlabel('Time (days)', fontsize=fontsize-4) plt.ylabel('Viral shed', fontsize=fontsize-4) @@ -65,10 +64,10 @@ def draw_timepoints_infectious_and_not(): # we do the same for viral load -viral_load_values = [np.exp(viral_load_with_params(t)) for t in t] +viral_load_values = [viral_load_with_params(t) for t in t] plt.figure(figsize=(12, 8)) -plt.plot(t, viral_load_values) +plt.plot(t, viral_load_values, linewidth=2) plt.title('Viral load', fontsize=fontsize) plt.xlabel('Time (days)', fontsize=fontsize-4) plt.ylabel('Viral load', fontsize=fontsize-4) From 749c3a7746da7db8341bcc3fe42f1a44e5010422 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 9 Jan 2025 01:21:33 +0100 Subject: [PATCH 486/488] some new testthings Signed-off-by: Sascha Korf <51127093+xsaschako@users.noreply.github.com> --- cpp/models/abm/common_abm_loggers.h | 38 ++- cpp/simulations/check_formatted_bs_data.py | 354 +++++++++++++++++++++ cpp/simulations/cleanup_data.py | 4 +- cpp/simulations/mov_data_analysis.py | 69 ++++ 4 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 cpp/simulations/check_formatted_bs_data.py create mode 100644 cpp/simulations/mov_data_analysis.py diff --git a/cpp/models/abm/common_abm_loggers.h b/cpp/models/abm/common_abm_loggers.h index 3fe1602e98..cea5fe3034 100644 --- a/cpp/models/abm/common_abm_loggers.h +++ b/cpp/models/abm/common_abm_loggers.h @@ -104,6 +104,28 @@ struct LogLocationInformation : mio::LogOnce { } }; +struct LogLocationInformationOcc : mio::LogAlways { + using Type = std::vector>; + /** + * @brief Log the LocationInformation of the simulation. + * @param[in] sim The simulation of the abm. + * @return A vector of tuples with the LocationInformation, where each tuple contains the following information: + * -# The index of the location. + * -# Location type. + * -# The amount of persons @ location. + */ + static Type log(const mio::abm::Simulation& sim) + { + Type location_information{}; + location_information.reserve(sim.get_world().get_locations().size()); + for (auto&& location : sim.get_world().get_locations()) { + location_information.push_back( + std::make_tuple(location.get_index(), location.get_type(), location.get_number_persons())); + } + return location_information; + } +}; + /** * @brief Logger to log the Person%s Information in the simulation. */ @@ -151,7 +173,6 @@ struct LogDataForMovement : mio::LogAlways { { Type movement_data{}; movement_data.reserve(sim.get_world().get_persons().size()); - PRAGMA_OMP(parallel for) for (auto&& p : sim.get_world().get_persons()) { movement_data.push_back(std::make_tuple( p.get_person_id(), p.get_location().get_index(), sim.get_time(), p.get_last_transport_mode(), @@ -259,6 +280,7 @@ struct LogInfectionPerAgeGroup : mio::LogAlways { * @brief This is like the DataWriterToMemory, but it only logs time series data. * @tparam Loggers The loggers that are used to log data. The loggers must return a touple with a TimePoint and a value. */ + template struct TimeSeriesWriter { using Data = std::tuple>; @@ -274,6 +296,20 @@ struct TimeSeriesWriter { } }; +template +struct DataWriter { + using Data = std::tuple...>; + template + /** + * @brief This function adds an entry to the TimeSeries consisting of the TimePoint and the value. The Loggers must return a touple with a TimePoint and a value of return type Eigen::VectorXd. + * @param[in] t The data from the logger. + * @param[in,out] data The data tuple. + */ + static void add_record(const typename Logger::Type& t, Data& data) + { + std::get>(data).push_back(t); + } +}; /** * @brief This class writes data retrieved from loggers to memory. It can be used as the Writer template parameter for the History class. * This specialization just saves the difference to the last saved data. Suitable when one wants to save huge data with a few changes. diff --git a/cpp/simulations/check_formatted_bs_data.py b/cpp/simulations/check_formatted_bs_data.py new file mode 100644 index 0000000000..22aaf64266 --- /dev/null +++ b/cpp/simulations/check_formatted_bs_data.py @@ -0,0 +1,354 @@ +import pandas as pd +import matplotlib +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import os +from datetime import datetime, date + + +####### minimal sanity check on data ####### +bd = pd.read_csv( + '/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/data/mobility/braunschweig_result_ffa8_modified4.csv', header=None, skiprows=1) + + +bd.rename( + columns={0: 'personID', 1: 'locID', 2: 'home_id', 3: 'startTime', 4: 'lon_end',5:'lat_end', 10:'home_in_bs', 11:'has_home_trip', 12:'location_type', + 8:'map_feature_key', 9:'map_feat_value',7:'age', 6:'activity'}, + inplace=True) + +def calc_minutes(time): + #calculate minutes from string with this format hh:mm + return int(time.split(':')[0])*60 + int(time.split(':')[1]) + +location_type_dict = {'Home': 0, 'School': 2, + 'Work': 1, 'BasicShop': 3, 'SocialEvent': 4} + +minutes_long_trip = 420 + +bd=bd[['personID', 'startTime', 'map_feature_key','map_feat_value','has_home_trip','location_type','activity','locID','age','home_id']] +#for debug purposes we just use the first 20000 entries +# bd = bd.head(100000) + +# find out if we have a locID with different location types +locID_location_type = bd[['locID', 'location_type']].drop_duplicates() +locID_location_type_grouped = locID_location_type.groupby(['locID']).agg({'location_type': 'nunique'}).reset_index() +print('Number of locID with different location types: ', len(locID_location_type_grouped[locID_location_type_grouped['location_type'] > 1])) +# print which locID have different location types +print('locID with different location types: ', locID_location_type_grouped[locID_location_type_grouped['location_type'] > 1], 'percentually: ', len(locID_location_type_grouped[locID_location_type_grouped['location_type'] > 1])/len(locID_location_type_grouped)) + +#take out trips which go to locIDs with different location types +# bd = bd[~bd['locID'].isin(locID_location_type_grouped[locID_location_type_grouped['location_type'] > 1]['locID'])] +# locID_location_type = bd[['locID', 'location_type']].drop_duplicates() +# locID_location_type_grouped = locID_location_type.groupby(['locID']).agg({'location_type': 'nunique'}).reset_index() +# print('Number of locID with different location types: ', len(locID_location_type_grouped[locID_location_type_grouped['location_type'] > 1])) +# # print which locID have different location types +# print('locID with different location types: ', locID_location_type_grouped[locID_location_type_grouped['location_type'] > 1], 'percentually: ', len(locID_location_type_grouped[locID_location_type_grouped['location_type'] > 1])/len(locID_location_type_grouped)) + +# now we want to see who is where at each timestep with all the trips and see how many persons are at each location type +# for this we fill a matrix, where on the y-axis represent unique locations and on the x-axis the time for each timestep (one hour) and we fill the matrix with a vector the amount of persons at each location at each timestep +# we need to iterate over the data and fill the matrix +bd_who_where = bd.copy()[['personID', 'startTime', 'locID', 'location_type']] +bd_who_where['startTime'] = pd.to_datetime(bd_who_where['startTime'], format='%H:%M') +bd_who_where['startTime'] = bd_who_where['startTime'].dt.hour +# we need to get the unique locations +unique_locations = bd_who_where['locID'].unique() +# we need to get the unique persons +unique_persons = bd_who_where['personID'].unique() + +# we need to fill the matrix with the amount of persons at each location at each timestep +matrix = np.zeros((len(unique_locations), 24)) +for i, row in bd_who_where.iterrows(): + next_trip_time = bd_who_where.iloc[i + 1]['startTime'] if i < len(bd_who_where) - 1 and bd_who_where.iloc[i + 1]['personID'] == row['personID'] else bd_who_where.iloc[bd_who_where[bd_who_where['personID'] == row['personID']].index[0]]['startTime'] + for hour in range(row['startTime'], next_trip_time): + matrix[np.where(unique_locations == row['locID'])[0][0], hour % 24] += 1 + if next_trip_time < row['startTime']: + for hour in range(row['startTime'] , 24): + matrix[np.where(unique_locations == row['locID'])[0][0], hour % 24] += 1 + for hour in range(0, next_trip_time): + matrix[np.where(unique_locations == row['locID'])[0][0], hour] += 1 + # if next_trip_time == row['startTime'] and its the last trip of the person we need to fill the matrix for the last trip for the rest of the day + if next_trip_time == row['startTime'] &(i == len(bd_who_where) - 1 or bd_who_where.iloc[i + 1]['personID'] != row['personID']): + for hour in range(row['startTime'], 24): + matrix[np.where(unique_locations == row['locID'])[0][0], hour % 24] += 1 + for hour in range(0, row['startTime']): + matrix[np.where(unique_locations == row['locID'])[0][0], hour] += 1 + + +# quick check: for every hour we we need the sum of the matrix column to be the amount of persons +print('Sum of the matrix columns: ', matrix.sum(axis=0)) +print('Should be the amount of persons: ', len(unique_persons)) + +# we assign each unique location the most amount of persons at this location at any timestep +unique_locations_with_location_type = bd_who_where[['locID']].drop_duplicates() +#vector with max for each location +max_persons = matrix.max(axis=1) +#assign eacj location the max amount of persons +unique_locations_with_location_type['max_persons'] = max_persons +#add column with location type +unique_locations_with_location_type=unique_locations_with_location_type.sort_values(by=['max_persons'], ascending=False, ignore_index=True).head(1000) + + + +# find the first trip of the 10 locations with the most persons + + +#print top ten locations with the most persons +print('Top ten locations with the most persons: ',unique_locations_with_location_type) +#find the location type of the top ten locations +unique_locations_with_location_type['location_type'] = 0 +for i, row in unique_locations_with_location_type.iterrows(): + unique_locations_with_location_type.at[i, 'location_type'] = bd_who_where[bd_who_where['locID'] == row['locID']].iloc[0]['location_type'] +print('Top ten locations with the most persons and their location type: ',unique_locations_with_location_type) +##count the location type of these locaitons +unique_locations_with_location_type = unique_locations_with_location_type['location_type'].value_counts().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +print('Top ten locations with the most persons and their location type: ',unique_locations_with_location_type) + + + +# bd_hour_same=bd.copy() +# # how many trips haappen in the same hour as the previous trip of the same person the time before the forst trip is the last trip of the person +# bd_hour_same['startTime'] = pd.to_datetime(bd_hour_same['startTime'], format='%H:%M') +# bd_hour_same['startTime_prev'] = bd_hour_same.groupby(['personID'])['startTime'].shift(1) +# bd_last_trip = bd_hour_same.groupby(['personID']).last() +# # to fill NaN we take those and fill them with the last trip of the person with fillna and bd_last_trip['startTime'] +# bd_hour_same['startTime_prev'] = bd_hour_same['startTime_prev'].fillna(bd_last_trip['startTime'].values[0]) +# bd_hour_same['same_hour_as_prev'] = bd_hour_same['startTime'].dt.hour == bd_hour_same['startTime_prev'].dt.hour +# same_hour_as_prev = bd_hour_same['same_hour_as_prev'].value_counts(normalize=False).reset_index(name='counts') +# print('Percentage of trips that happen in the same hour as the previous trip of the same person: ', same_hour_as_prev) +# #also get the amount of trips that are hometrips and happen before another trip in the same hour + +# # we iterate over the data and save the trip before a trip in the same hour +# bd_hour_same['trip_before_same_hour'] = 0 +# for i, row in bd_hour_same.iterrows(): +# if row['same_hour_as_prev']: +# bd_hour_same.at[i-1, 'trip_before_same_hour'] = 1 + +# # we want to see how many trips are home trips and happen before another trip in the same hour +# home_trip_before_same_hour = bd_hour_same[(bd_hour_same['trip_before_same_hour'] == 1) & (bd_hour_same['location_type'] == location_type_dict['Home'])] +# print('Number of home trips that happen before another trip in the same hour: ', len(home_trip_before_same_hour), '(which is percentually from home trips: ', len(home_trip_before_same_hour)/(bd_hour_same['location_type'] == location_type_dict['Home']).sum(), ')') + + + + +# # we meed to add a home trip for each person if they have no home trip at 17:00 into the data +# # ths easiest done when we go though it iteratively and add a trip when we see that the person has no home trip and it is either the last trip and before 17 or not the last trip but the first after 17 +# # the trip has the same personID, location_type = 0, startTime = 17:00, map_feature_key = 0, map_feat_value = 0, has_home_trip = 1 +# # the bd is sorted so we can go through it iteratively +# bd_addendum = pd.DataFrame(columns=['personID', 'startTime', 'map_feature_key','map_feat_value','has_home_trip','location_type']) +# for i, row in bd.iterrows(): +# is_new_person = i == 0 or bd.iloc[i-1]['personID'] != row['personID'] +# if is_new_person: +# home_trip_added = False +# is_last_trip_of_person = i == len(bd) - 1 or bd.iloc[i+1]['personID'] != row['personID'] +# is_first_trip_after_17 = row['startTime'] > '17:00' and bd.iloc[i-1]['startTime'] < '17:00' +# if row['has_home_trip'] == 0 and (is_last_trip_of_person or is_first_trip_after_17): +# add_trip = {'personID': row['personID'], 'startTime': '17:00', 'has_home_trip': 0, 'location_type': 0, 'map_feature_key': 'home', 'map_feat_value': 'Nan', 'activity': 'home'} +# #we save this trip in a new dataframe and append it to the bd at the end and sort it again +# bd_addendum = pd.concat([bd_addendum, pd.DataFrame([add_trip])], ignore_index=True) +# home_trip_added = True + +# bd = pd.concat([bd, bd_addendum], ignore_index=True) +# bd = bd.sort_values(by=['personID', 'startTime'], ignore_index=True) + +# # for a quick check: see how many trips where added and how many unique persons are there with no home trip +# print('Number of trips added: ', len(bd_addendum)) +# print('Number of unique persons with no home trip: ', len(bd[bd['has_home_trip'] == 0]['personID'].unique())) + + +# # now we want to get a dataframe with every trip of a person which is above 6 hours. for this we go through it again and save the length of each trip in a new column +# # add column for trip length +# bd['trip_length'] = 0 +# # if the trip is longer than 6 hours we save it in a new dataframe +# long_trips = pd.DataFrame(columns=['personID', 'startTime', 'map_feature_key','map_feat_value','has_home_trip','location_type', 'trip_length','activity']) + +# for i, row in bd.iterrows(): +# last_trip_of_person = i == len(bd) - 1 or bd.iloc[i+1]['personID'] != row['personID'] +# first_trip_of_person = i == 0 or bd.iloc[i-1]['personID'] != row['personID'] +# if first_trip_of_person: +# time_of_first_trip = calc_minutes(row['startTime']) +# if not last_trip_of_person: +# duration = calc_minutes(bd.iloc[i+1]['startTime']) - calc_minutes(row['startTime']) +# else: +# duration = 1440 - calc_minutes(row['startTime']) + time_of_first_trip +# bd.at[i, 'trip_length'] = duration +# if duration > minutes_long_trip: +# long_trips = pd.concat([long_trips, pd.DataFrame(bd.iloc[i]).T], ignore_index=True) + +# # add the value in trip_length for every person in a seperate datafram +# bd_trip_length_cum = bd.groupby(['personID']).agg({'trip_length': 'sum'}).reset_index() +# # quick check: every person has 24 hours in minutes in the trip_length column +# print('Number of persons without 24 hours in trip_length: ', len(bd_trip_length_cum[ +# bd_trip_length_cum['trip_length'] != 1440])) + + +# # now we want to discard the trips which are longer than 6 hours and are home trips +# long_trips_wo_homes = long_trips[long_trips['location_type'] != location_type_dict['Home']] +# # quick check: how many long trips are home trips +# print('Number of long trips which are home trips: ', len(long_trips[long_trips['location_type'] == location_type_dict['Home']])) +# # quick check: how many long trips are not home trips +# print('Number of long trips which are not home trips: ', len(long_trips_wo_homes), 'which is percentually: ', len(long_trips_wo_homes)/len(long_trips)) +# # quick check: how many long trips are there in total +# print('Number of long trips: ', len(long_trips)) + +# # now we want to get the location types of the long trips and sort it by location type +# long_trips_location_type = long_trips['location_type'].value_counts().reset_index(name='counts').sort_values(by=['location_type'], ascending=True, ignore_index=True) +# # quick check: how many long trips are there for each location type +# print('Number of long trips for each location type: ', long_trips_location_type, 'where the location types are: ', location_type_dict) + +# # now we want to see the avarage amount of the long trips for each location type +# long_trips_location_type_avg = long_trips['location_type'].value_counts(normalize=True).reset_index(name='counts').sort_values(by=['location_type'], ascending=True, ignore_index=True) +# # quick check: how many long trips are there for each location type +# print('Avarage amount of long trips for each location type: ', long_trips_location_type_avg) + +# # now we want to substract 6 hours from the long trips length +# long_trips_substracted = long_trips.copy() +# long_trips_substracted['trip_length'] = long_trips_substracted['trip_length'] - minutes_long_trip +# # sum over the trip lengths for each location type +# long_trips_substracted_sum = long_trips_substracted.groupby(['location_type']).agg({'trip_length': 'sum'}).reset_index() +# long_trips_substracted_avg = long_trips_substracted_sum.copy() +# long_trips_substracted_avg['trip_length'] = long_trips_substracted_avg['trip_length'] / long_trips_location_type['counts'] + +# print('Avarage amount of long trips for each location type after substracting long_trip minutes: ', long_trips_substracted_avg) + +# # show me the long trips of basicShop +# long_trips_SE = long_trips[long_trips['location_type'] == location_type_dict['SocialEvent']] +# #group by the map_feature_key and map_feat_value +# long_trips_SE_grouped = long_trips_SE.groupby(['map_feature_key', 'map_feat_value']).agg({'trip_length': 'sum'}).reset_index().sort_values(by=['trip_length'], ascending=False, ignore_index=True) +# #note: most time is spend in commercial, supermarket and reatil which is classified as BS but maybe is work (short test around 40% is work i guess) + +# # show me the long trips of basicShop +# long_trips_BS = long_trips[long_trips['location_type'] == location_type_dict['BasicShop']] +# #group by the map_feature_key and map_feat_value +# long_trips_BS_grouped = long_trips_BS.groupby(['map_feature_key', 'map_feat_value','activity']).agg({'trip_length': 'sum'}).reset_index().sort_values(by=['trip_length'], ascending=False, ignore_index=True) + + +# print('Long trips of SocialEvent: ', long_trips_SE_grouped.head(10)) +# print('Long trips of BasicShop: ', long_trips_BS_grouped.head(10)) + + + + + + + + +############################# + + + +# #### Counting people #### +# bd_persons = bd.groupby(['personID']).size().reset_index( +# name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) +# # Get the frequency of each number in the 'numbers' column +# # bd_personss = bd_persons['counts'].value_counts().sort_index() +# # # Plot the frequency of each number +# # bd_personss.plot(kind='bar') +# # plt.xlabel('Number of trips per day') +# # plt.ylabel('Number of persons') +# # plt.title('Number of trips per person tripcount (Braunschweig)') +# # plt.savefig(os.path.join(figs_path, 'number_of_trips_per_person.png'), dpi=300) + +# # we want to calculate a matrix: the rows are the persons and the columns are the location types they visited in each cell we want to save the longest amount of time they spent in this location type +# # the time they spent in the location is the the startTime of the next trip minus the startTime of the current trip +# # we want to calculate the time they spent in each location type# + +# def calc_minutes(time): +# #calculate minutes from string with this format hh:mm +# return int(time.split(':')[0])*60 + int(time.split(':')[1]) + +# #chekc how many have their last trip to home and how many not +# bd_last_trip = bd.groupby(['personID']).last() +# not_home = bd_last_trip[bd_last_trip['location_type'] != 0] +# home = bd_last_trip[bd_last_trip['location_type'] == 0] +# not_home_and_no_home_trip = bd_last_trip[(bd_last_trip['location_type'] != 0) & (bd_last_trip['has_home_trip'] == 0)] +# print('Number of last trips that are home trips: ', len(home)) +# print('Number of last trips that are not home trips: ', len(not_home)) + +# #check how many persons have no home trip +# no_home_trip = bd[bd['has_home_trip'] == 0] +# print('Number of persons with no home trip: ', len(no_home_trip)) + +# # check how many persons habe no home trip and the last trip is not home +# no_home_trip_and_not_home = no_home_trip[no_home_trip['location_type'] != 0] +# print('Number of persons with no home trip and the last trip is not home: ', len(no_home_trip_and_not_home)) + +# #check how many of these are after 17:00 +# no_home_trip_and_not_home_after_17 = no_home_trip_and_not_home[no_home_trip_and_not_home['startTime'] > '17:00'] +# print('Number of persons with no home trip and the last trip is not home and after 17:00: ', len(no_home_trip_and_not_home_after_17)) + +# #show a distribution of the location types of the last trips of persons with no home trip and the last trip is not home and after 17:00 +# no_home_trip_and_not_home_after_17['location_type'].value_counts().plot(kind='bar') +# plt.xlabel('Location type') +# plt.ylabel('Number of persons') +# plt.title('Location type of the last trips of persons with no home trip and the last trip is not home and after 17:00') +# plt.show() + + + + + +# # number_of_persons times number_of_location_types matrix +# matrix = np.zeros((len(bd_persons), 8)) +# long_trips_matrix = [] # Matrix to store persons with long trips +# bd = bd[bd['personID'] == 900971] + +# # iterate over the persons +# for i, person in enumerate(bd_persons['personID']): +# # get the trips of the person +# trips_person = bd.loc[bd['personID'] == person] + +# #if person has no home trip add one with starttime 17:00 +# if len(trips_person[trips_person['has_home_trip'] == 1]) == 0: +# add_trip = {'personID': +# person, 'loc_d_end': 0, 'home_id': 0, 'startTime': '17:00', 'lon_end': 0, 'lat_end': 0, 'lon_end_2': 0, 'home_in_bs': 0, 'has_home_trip': 1, 'location_type': 0, 'map_feature_key': 0, 'map_feat_value': 0} +# trips_person.loc[len(trips_person)] = add_trip + +# # iterate over the trips +# for k, trip in enumerate(trips_person.iterrows()): +# # if it is the last trip +# if k == len(trips_person) - 1: +# duration = 1440 - calc_minutes(trips_person.iloc[k]['startTime']) + calc_minutes(trips_person.iloc[0]['startTime']) +# else: +# duration = calc_minutes(trips_person.iloc[k+1]['startTime']) - calc_minutes(trips_person.iloc[k]['startTime']) + +# matrix[i, trips_person.iloc[k]['location_type']] = max(duration, matrix[i, trips_person.iloc[k]['location_type']]) +# if duration > 480 and k != len(trips_person) - 1: # 8 hours and not the last trip +# long_trips_matrix.append(trips_person.iloc[k]) + +# # Convert list of long trips to DataFrame +# long_trips_df = pd.DataFrame(long_trips_matrix) + +# long_trips_df = long_trips_df[['personID', 'startTime', 'location_type']] + +# # amount of trips for each location type +# location_type_counts = long_trips_df.groupby(['location_type']).size().reset_index(name='counts').sort_values(by=['counts'], ascending=False, ignore_index=True) + +# print(f"Number of persons with trips over 8 hours: {len(long_trips_matrix)}") + +# # how many long trips have their last trip to home +# long_trips_df_last_trip = long_trips_df.groupby(['personID']).last() +# long_trips_df_last_trip_home = long_trips_df_last_trip[long_trips_df_last_trip['location_type'] == 0] +# print('Number of last trips that are home trips: ', len(long_trips_df_last_trip_home)) +# long_trips_df_last_trip_not_home = long_trips_df_last_trip[long_trips_df_last_trip['location_type'] != 0] +# print('Number of last trips that are not home trips: ', len(long_trips_df_last_trip_not_home)) + +# # how many persons have no home trip +# long_trips_df_no_home_trip = long_trips_df[long_trips_df['has_home_trip'] == 0] +# print('Number of persons with no home trip: ', len(long_trips_df_no_home_trip)) + +# # group the trips which are longer than 8 hours by the tuple (map_feature_key, map_feat_value) +# grouped = long_trips_df.groupby(['personID', 'location_type']).agg({'startTime': 'count'}).reset_index() + + + + +# # save matrix as heatmap +# sns.heatmap(matrix) +# plt.show() +# # save matrix as png +# plt.savefig(os.path.join("/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/models/abm", 'matrix.png'), dpi=300) + + +# matrix \ No newline at end of file diff --git a/cpp/simulations/cleanup_data.py b/cpp/simulations/cleanup_data.py index 889be45751..26b3ec3997 100644 --- a/cpp/simulations/cleanup_data.py +++ b/cpp/simulations/cleanup_data.py @@ -457,8 +457,8 @@ def add_time_if_null(pd): # we need to remove unnecessary columns bd_new = bd_new.drop(columns=['start_zone', 'end_zone', 'loc_id_start', 'start_county', 'end_county', 'trip_distance', 'travel_time_sec', - 'lon_start', 'lat_start', 'travel_mode', 'activity_start', 'activity_end', 'map_feature_key', 'map_feature_value']) + 'lon_start', 'lat_start', 'travel_mode', 'activity_start']) # sort for better search performance bd_new = bd_new.sort_values(by=['puid', 'start_time']) # Write data back to disk -bd_new.to_csv(PATH + "braunschweig_result_ffa8_modified2.csv", index=False) +bd_new.to_csv(PATH + "braunschweig_result_ffa8_modified4.csv", index=False) diff --git a/cpp/simulations/mov_data_analysis.py b/cpp/simulations/mov_data_analysis.py new file mode 100644 index 0000000000..ca33a235bf --- /dev/null +++ b/cpp/simulations/mov_data_analysis.py @@ -0,0 +1,69 @@ +import pandas as pd +import matplotlib +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import os +from datetime import datetime, date + + + +# txt file structure is as follows +# timestep Nr.: 0 +# x,y,z +# and so on +# timestep Nr.: 1 +# x,y,z +# and so on + +#where x is location id, y is location type, z is amount of agents at location + +# read in data +def read_data(file): + with open(file) as f: + lines = f.readlines() + f.close() + return lines + +# extract data from txt file +def extract_data(lines): + data = [] + for line in lines: + if 'timestep' in line: + timestep = int(line.split(' ')[-1]) + data.append([]) + else: + data[-1].append(line.strip().split(',')) + return data + +# create dataframe from data + +def create_df(data): + # we want a dataframe, data has the following structure: + # [[x,y,z],[x,y,z],...] for each timestep + return pd.DataFrame([[int(x[0]), x[1], int(x[2]), timestep] for timestep, timestep_data in enumerate(data) for x in timestep_data], columns=['location_id', 'location_type', 'amount', 'timestep']) + + +def print_info(df): + #sort by amount of persons concurrently at location (amount) + df = df.sort_values('amount', ascending=False) + print(df.head(10)) + print(df.tail(10)) + + +# main function +def main(): + file = '/Users/saschakorf/Documents/Arbeit.nosynch/memilio/memilio/cpp/simulations/loc_data_occupancy.txt' + lines = read_data(file) + #first line is garbage + data = extract_data(lines[1:]) + df = create_df(data) + print_info(df) + return + +if __name__ == '__main__': + main() + + + From bf5a1697f7c59a797d7ec00fa9c8b0b313b3a53c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 1 Apr 2025 09:53:36 +0200 Subject: [PATCH 487/488] vis_script --- cpp/simulations/compare_mobility_data.py | 382 +++++++++++++++++++++++ 1 file changed, 382 insertions(+) create mode 100644 cpp/simulations/compare_mobility_data.py diff --git a/cpp/simulations/compare_mobility_data.py b/cpp/simulations/compare_mobility_data.py new file mode 100644 index 0000000000..6c6cd85d1c --- /dev/null +++ b/cpp/simulations/compare_mobility_data.py @@ -0,0 +1,382 @@ +import pandas as pd +import matplotlib.pyplot as plt +import seaborn as sns +import numpy as np +import os + +# Set global plot parameters for publication quality +plt.rcParams['font.size'] = 16 +plt.rcParams['axes.titlesize'] = 18 +plt.rcParams['axes.labelsize'] = 16 +plt.rcParams['xtick.labelsize'] = 14 +plt.rcParams['ytick.labelsize'] = 14 +plt.rcParams['legend.fontsize'] = 14 +plt.rcParams['figure.titlesize'] = 20 +plt.rcParams['figure.figsize'] = (10, 8) + +# Define paths +brunswick_data_path = '/Users/saschakorf/Nosynch/Arbeit/memilio/memilio/data/mobility/braunschweig_result_ffa8.csv' +munich_data_path = '/Users/saschakorf/Nosynch/Arbeit/memilio/memilio/data/mobility/muenchen_microscopic_result.csv' + +# Define output path for figures +output_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'mobility_comparison_figures') +if not os.path.exists(output_path): + os.makedirs(output_path) + +# Dictionary for leisure activities and vehicle choice +dict_leisure = {1: 'work', 2: 'education', 3: 'shopping', 4: 'free time', + 5: 'private matters', 6: 'others', 7: 'home', 0: 'not specified'} +dict_vehicle = {1: 'bicyle', 2: 'car_driver', + 3: 'car_codriver', 4: 'public transport', 5: 'walk'} + +# Define age groups as in C++ code +age_group_0_to_4 = 0 +age_group_5_to_14 = 1 +age_group_15_to_34 = 2 +age_group_35_to_59 = 3 +age_group_60_to_79 = 4 +age_group_80_plus = 5 + +# Map age cohorts to readable labels +age_group_labels = { + age_group_0_to_4: '0-4', + age_group_5_to_14: '5-14', + age_group_15_to_34: '15-34', + age_group_35_to_59: '35-59', + age_group_60_to_79: '60-79', + age_group_80_plus: '80+' +} + +# Load data +print("Loading Brunswick data...") +bs = pd.read_csv(brunswick_data_path, header=None, skiprows=1) +bs.rename( + columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', + 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', + 10: 'travelTime', 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', + 16: 'ActivityBefore', 17: 'ActivityAfter', 18: 'age', 19: 'home_in_bs', + 20: 'location_type'}, + inplace=True) + +print("Loading Munich data...") +mu = pd.read_csv(munich_data_path, header=None, skiprows=1) +mu.rename( + columns={0: 'personID', 1: 'startZone', 2: 'destZone', 3: 'loc_id_start', 4: 'loc_id_end', + 5: 'countyStart', 6: 'countyEnd', 7: 'hhID', 8: 'tripDistance', 9: 'startTime', + 10: 'travelTime', 11: 'loCs', 12: 'laCs', 13: 'loCe', 14: 'laCe', 15: 'vehicleChoice', + 16: 'ActivityBefore', 17: 'ActivityAfter', 18: 'age', 19: 'home_in_mu', + 20: 'location_type'}, + inplace=True) + +# Replace invalid ages with NaN +bs.loc[bs['age'] == 999, 'age'] = np.nan +mu.loc[mu['age'] == 999, 'age'] = np.nan + +print(f"Brunswick data loaded: {len(bs)} trips") +print(f"Munich data loaded: {len(mu)} trips") + +# Function to create side-by-side plots +def create_comparison_plot(title, filename, figsize=(16, 7)): + fig, (ax1, ax2) = plt.subplots(1, 2, figsize=figsize) + fig.suptitle(title, fontsize=16) + return fig, ax1, ax2 + +# Map ages to our defined age groups +def map_to_age_group(age): + if pd.isna(age): + return np.nan + elif age <= 4: + return age_group_0_to_4 + elif age <= 14: + return age_group_5_to_14 + elif age <= 34: + return age_group_15_to_34 + elif age <= 59: + return age_group_35_to_59 + elif age <= 79: + return age_group_60_to_79 + else: + return age_group_80_plus + +# Apply age group mapping to both datasets +bs['AgeGroup'] = bs['age'].apply(map_to_age_group) +mu['AgeGroup'] = mu['age'].apply(map_to_age_group) + +# 1. Age Distribution Comparison +print("Creating age distribution comparison...") +fig, ax_bs, ax_mu = create_comparison_plot("Age Distribution Comparison", "age_distribution.png") + +# Brunswick +bs_persons_ages = bs[['personID', 'AgeGroup']].drop_duplicates() +bs_persons_ages = bs_persons_ages[bs_persons_ages['AgeGroup'].notna()] +bs_persons_ages_cohorts = bs_persons_ages.groupby(['AgeGroup']).size().reset_index(name='counts') +bs_persons_ages_cohorts['AgeGroupLabel'] = bs_persons_ages_cohorts['AgeGroup'].map(age_group_labels) + +bs_persons_ages_cohorts.plot.bar(x='AgeGroupLabel', y='counts', ax=ax_bs, color='tab:blue') +ax_bs.set_title("Brunswick") +ax_bs.set_xlabel("Age groups") +ax_bs.set_ylabel("Number of persons") +ax_bs.grid(axis='y', linestyle='--', alpha=0.7) + +# Munich +mu_persons_ages = mu[['personID', 'AgeGroup']].drop_duplicates() +mu_persons_ages = mu_persons_ages[mu_persons_ages['AgeGroup'].notna()] +mu_persons_ages_cohorts = mu_persons_ages.groupby(['AgeGroup']).size().reset_index(name='counts') +mu_persons_ages_cohorts['AgeGroupLabel'] = mu_persons_ages_cohorts['AgeGroup'].map(age_group_labels) + +mu_persons_ages_cohorts.plot.bar(x='AgeGroupLabel', y='counts', ax=ax_mu, color='tab:orange') +ax_mu.set_title("Munich") +ax_mu.set_xlabel("Age groups") +ax_mu.set_ylabel("Number of persons") +ax_mu.grid(axis='y', linestyle='--', alpha=0.7) + +plt.tight_layout() +plt.subplots_adjust(top=0.9) +plt.savefig(os.path.join(output_path, 'age_distribution_comparison.png'), dpi=300) + +# 2. Heatmap Leisure Comparison (excluding "not specified") +print("Creating leisure heatmap comparison...") +fig, ax_bs, ax_mu = create_comparison_plot("Leisure Activities Transition Comparison", "heatmap_leisure.png") + +# Function to create filtered heatmap excluding "not specified" (key 0) +def create_filtered_heatmap(data, ax, title): + # Filter out "not specified" category (key 0) + filtered_data = data[data['ActivityBefore'] != 0] + filtered_data = filtered_data[filtered_data['ActivityAfter'] != 0] + + # Create crosstab + matrix_leisure = pd.crosstab( + filtered_data['ActivityBefore'], + filtered_data['ActivityAfter'], + normalize='index') + + # Get filtered dictionary without "not specified" + filtered_dict_leisure = {k: v for k, v in dict_leisure.items() if k != 0} + + # Create heatmap + sns.heatmap(matrix_leisure, vmin=0, vmax=1, + xticklabels=[filtered_dict_leisure.get(i) for i in matrix_leisure.columns], + yticklabels=[filtered_dict_leisure.get(i) for i in matrix_leisure.index], + cmap="Blues", ax=ax) + ax.set_title(title) + ax.set_xlabel('Activity after trip') + ax.set_ylabel('Activity before trip') + +# Brunswick +create_filtered_heatmap(bs, ax_bs, "Brunswick") + +# Munich +create_filtered_heatmap(mu, ax_mu, "Munich") + +plt.tight_layout() +plt.subplots_adjust(top=0.9) +plt.savefig(os.path.join(output_path, 'heatmap_leisure_comparison.png'), dpi=300) + +# 3. Number of trips to different location types (with dict_leisure mapping) +print("Creating location types comparison...") +fig, ax_bs, ax_mu = create_comparison_plot("Number of Trips to Different Location Types", "location_types.png") + +# Function to map activity codes to names +def map_activity_to_name(series): + return series.map(lambda x: dict_leisure.get(x, f'Unknown ({x})')) + +# Brunswick +bs_location_types = bs.groupby(['ActivityAfter']).size() +bs_location_types.index = map_activity_to_name(bs_location_types.index) +bs_location_types.plot(kind='bar', ax=ax_bs, color='tab:blue') +ax_bs.set_title("Brunswick") +ax_bs.set_xlabel("Location type") +ax_bs.set_ylabel("Number of trips") +ax_bs.grid(axis='y', linestyle='--', alpha=0.7) + +# Munich +mu_location_types = mu.groupby(['ActivityAfter']).size() +mu_location_types.index = map_activity_to_name(mu_location_types.index) +mu_location_types.plot(kind='bar', ax=ax_mu, color='tab:orange') +ax_mu.set_title("Munich") +ax_mu.set_xlabel("Location type") +ax_mu.set_ylabel("Number of trips") +ax_mu.grid(axis='y', linestyle='--', alpha=0.7) + +plt.tight_layout() +plt.subplots_adjust(top=0.9) +plt.savefig(os.path.join(output_path, 'location_types_comparison.png'), dpi=300) + +# 4. Number of trips per person +print("Creating trips per person comparison...") +fig, ax_bs, ax_mu = create_comparison_plot("Number of Trips per Person", "trips_per_person.png") + +# Brunswick +bs_persons = bs.groupby(['personID']).size().reset_index(name='counts') +bs_trips_per_person = bs_persons['counts'].value_counts().sort_index() +bs_trips_per_person.plot(kind='bar', ax=ax_bs, color='tab:blue') +ax_bs.set_title("Brunswick") +ax_bs.set_xlabel("Number of trips per day") +ax_bs.set_ylabel("Number of persons") +ax_bs.grid(axis='y', linestyle='--', alpha=0.7) + +# Munich +mu_persons = mu.groupby(['personID']).size().reset_index(name='counts') +mu_trips_per_person = mu_persons['counts'].value_counts().sort_index() +mu_trips_per_person.plot(kind='bar', ax=ax_mu, color='tab:orange') +ax_mu.set_title("Munich") +ax_mu.set_xlabel("Number of trips per day") +ax_mu.set_ylabel("Number of persons") +ax_mu.grid(axis='y', linestyle='--', alpha=0.7) + +plt.tight_layout() +plt.subplots_adjust(top=0.9) +plt.savefig(os.path.join(output_path, 'trips_per_person_comparison.png'), dpi=300) + +# 5. Trip purpose comparison by age group - using pie charts +print("Creating trip purpose comparison by age group...") + +# Define age group labels for plot titles +age_group_title_labels = { + age_group_0_to_4: '0-4 years', + age_group_5_to_14: '5-14 years', + age_group_15_to_34: '15-34 years', + age_group_35_to_59: '35-59 years', + age_group_60_to_79: '60-79 years', + age_group_80_plus: '80+ years' +} + +# Create a subplot for each age group (2 cities × 6 age groups) +fig, axes = plt.subplots(2, 6, figsize=(24, 10)) +fig.suptitle("Trip Purpose Distribution by Age Group", fontsize=22) + +# Custom colors +colors = plt.cm.tab10(np.arange(len(dict_leisure))) + +# Function to create pie chart with improved percentage display +def create_better_pie(ax, data_dict, title): + if not data_dict or sum(data_dict.values()) == 0: + ax.set_title(title) + ax.axis('off') # Hide axis if no data + return + + labels = list(data_dict.keys()) + sizes = list(data_dict.values()) + + # Only show percentages for slices that are large enough (>= 5%) + total = sum(sizes) + autopct_func = lambda pct: f'{pct:.1f}%' if pct >= 5 else '' + + wedges, texts, autotexts = ax.pie(sizes, labels=None, + autopct=autopct_func, + startangle=90, + colors=colors, + wedgeprops={'linewidth': 1, 'edgecolor': 'white'}) + + # Increase font size for percentage labels and move them inward + plt.setp(autotexts, size=12, weight='bold') + for autotext in autotexts: + # Move text closer to center to avoid overlap + x, y = autotext.get_position() + autotext.set_position((1.1*x, 1.1*y)) + + ax.set_title(title, fontsize=16) + ax.axis('equal') # Equal aspect ratio ensures pie is drawn as a circle + +# Process each age group +for i, age_group in enumerate([age_group_0_to_4, age_group_5_to_14, age_group_15_to_34, + age_group_35_to_59, age_group_60_to_79, age_group_80_plus]): + + # Brunswick - top row + bs_age_group = bs[bs['AgeGroup'] == age_group] + bs_trip_purpose = bs_age_group.groupby(['ActivityAfter']).size() + + # Map activity codes to names and create dictionary for the pie chart + bs_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in bs_trip_purpose.items() if idx in dict_leisure} + + # Create improved pie chart + create_better_pie(axes[0, i], bs_trip_purpose_dict, f"Brunswick: {age_group_title_labels[age_group]}") + + # Munich - bottom row + mu_age_group = mu[mu['AgeGroup'] == age_group] + mu_trip_purpose = mu_age_group.groupby(['ActivityAfter']).size() + + mu_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in mu_trip_purpose.items() if idx in dict_leisure} + + create_better_pie(axes[1, i], mu_trip_purpose_dict, f"Munich: {age_group_title_labels[age_group]}") + +# Create a common legend for all pie charts +all_activities = list(dict_leisure.values()) +legend_handles = [plt.Rectangle((0, 0), 1, 1, color=colors[i % len(colors)]) for i in range(len(all_activities))] +fig.legend(legend_handles, all_activities, loc='lower center', ncol=len(all_activities)//2, bbox_to_anchor=(0.5, 0), fontsize=20) + +plt.tight_layout() +plt.subplots_adjust(bottom=0.15, top=0.9) +plt.savefig(os.path.join(output_path, 'trip_purpose_by_age_comparison.png'), dpi=300) + +# Apply the same improvements to the overall pie charts +print("Creating overall trip purpose comparison...") +fig, (ax_bs, ax_mu) = plt.subplots(1, 2, figsize=(16, 8)) +fig.suptitle("Trip Purpose Distribution", fontsize=18) + +# Convert numeric activity codes to human-readable labels +# Brunswick +bs_trip_purpose = bs.groupby(['ActivityAfter']).size() +bs_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in bs_trip_purpose.items() if idx in dict_leisure} +create_better_pie(ax_bs, bs_trip_purpose_dict, "Brunswick") + +# Munich +mu_trip_purpose = mu.groupby(['ActivityAfter']).size() +mu_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in mu_trip_purpose.items() if idx in dict_leisure} +create_better_pie(ax_mu, mu_trip_purpose_dict, "Munich") + +plt.tight_layout() +plt.subplots_adjust(top=0.9) +plt.savefig(os.path.join(output_path, 'trip_purpose_comparison.png'), dpi=300) + +# 6. Overall Trip Purpose Distribution with bigger captions +print("Creating overall trip purpose comparison...") +fig, (ax_bs, ax_mu) = plt.subplots(1, 2, figsize=(16, 8)) +fig.suptitle("Trip Purpose Distribution", fontsize=20) + +# Convert numeric activity codes to human-readable labels +# Brunswick +bs_trip_purpose = bs.groupby(['ActivityAfter']).size() +bs_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in bs_trip_purpose.items() if idx in dict_leisure} +labels_bs = list(bs_trip_purpose_dict.keys()) +sizes_bs = list(bs_trip_purpose_dict.values()) + +# Munich +mu_trip_purpose = mu.groupby(['ActivityAfter']).size() +mu_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in mu_trip_purpose.items() if idx in dict_leisure} +labels_mu = list(mu_trip_purpose_dict.keys()) +sizes_mu = list(mu_trip_purpose_dict.values()) + +# Function for enhanced pie charts with bigger labels and percentages +def create_big_caption_pie(ax, sizes, labels, title): + # Create the pie chart + wedges, texts, autotexts = ax.pie( + sizes, + labels=labels, + autopct='%1.1f%%', + startangle=90, + colors=colors, + textprops={'fontsize': 16}, # Bigger label font size + wedgeprops={'linewidth': 1, 'edgecolor': 'white'} + ) + + # Make percentage labels bigger and bolder + plt.setp(autotexts, size=16, weight='bold') + + # Adjust position of labels for better readability + for text in texts: + x, y = text.get_position() + text.set_position((1.0*x, 1.0*y)) # Move labels further out + + ax.set_title(title, fontsize=18) + ax.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle + +# Plot enhanced pie charts +create_big_caption_pie(ax_bs, sizes_bs, labels_bs, "Brunswick") +create_big_caption_pie(ax_mu, sizes_mu, labels_mu, "Munich") + +plt.tight_layout() +plt.subplots_adjust(top=0.9) +plt.savefig(os.path.join(output_path, 'trip_purpose_comparison.png'), dpi=300) + +print(f"All comparison plots saved to: {output_path}") \ No newline at end of file From 4e16152e6e8a302c32ae9848eb32b1e2552ceb26 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Tue, 1 Apr 2025 14:38:16 +0200 Subject: [PATCH 488/488] no titles and 0 fix --- cpp/simulations/compare_mobility_data.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/cpp/simulations/compare_mobility_data.py b/cpp/simulations/compare_mobility_data.py index 6c6cd85d1c..23cdd4a8f2 100644 --- a/cpp/simulations/compare_mobility_data.py +++ b/cpp/simulations/compare_mobility_data.py @@ -76,9 +76,8 @@ print(f"Munich data loaded: {len(mu)} trips") # Function to create side-by-side plots -def create_comparison_plot(title, filename, figsize=(16, 7)): +def create_comparison_plot(filename, figsize=(16, 7)): fig, (ax1, ax2) = plt.subplots(1, 2, figsize=figsize) - fig.suptitle(title, fontsize=16) return fig, ax1, ax2 # Map ages to our defined age groups @@ -104,7 +103,7 @@ def map_to_age_group(age): # 1. Age Distribution Comparison print("Creating age distribution comparison...") -fig, ax_bs, ax_mu = create_comparison_plot("Age Distribution Comparison", "age_distribution.png") +fig, ax_bs, ax_mu = create_comparison_plot( "age_distribution.png") # Brunswick bs_persons_ages = bs[['personID', 'AgeGroup']].drop_duplicates() @@ -136,7 +135,7 @@ def map_to_age_group(age): # 2. Heatmap Leisure Comparison (excluding "not specified") print("Creating leisure heatmap comparison...") -fig, ax_bs, ax_mu = create_comparison_plot("Leisure Activities Transition Comparison", "heatmap_leisure.png") +fig, ax_bs, ax_mu = create_comparison_plot("heatmap_leisure.png") # Function to create filtered heatmap excluding "not specified" (key 0) def create_filtered_heatmap(data, ax, title): @@ -174,7 +173,7 @@ def create_filtered_heatmap(data, ax, title): # 3. Number of trips to different location types (with dict_leisure mapping) print("Creating location types comparison...") -fig, ax_bs, ax_mu = create_comparison_plot("Number of Trips to Different Location Types", "location_types.png") +fig, ax_bs, ax_mu = create_comparison_plot( "location_types.png") # Function to map activity codes to names def map_activity_to_name(series): @@ -204,7 +203,7 @@ def map_activity_to_name(series): # 4. Number of trips per person print("Creating trips per person comparison...") -fig, ax_bs, ax_mu = create_comparison_plot("Number of Trips per Person", "trips_per_person.png") +fig, ax_bs, ax_mu = create_comparison_plot( "trips_per_person.png") # Brunswick bs_persons = bs.groupby(['personID']).size().reset_index(name='counts') @@ -243,7 +242,6 @@ def map_activity_to_name(series): # Create a subplot for each age group (2 cities × 6 age groups) fig, axes = plt.subplots(2, 6, figsize=(24, 10)) -fig.suptitle("Trip Purpose Distribution by Age Group", fontsize=22) # Custom colors colors = plt.cm.tab10(np.arange(len(dict_leisure))) @@ -273,7 +271,7 @@ def create_better_pie(ax, data_dict, title): for autotext in autotexts: # Move text closer to center to avoid overlap x, y = autotext.get_position() - autotext.set_position((1.1*x, 1.1*y)) + autotext.set_position((1.2*x, 1.2*y)) ax.set_title(title, fontsize=16) ax.axis('equal') # Equal aspect ratio ensures pie is drawn as a circle @@ -284,7 +282,7 @@ def create_better_pie(ax, data_dict, title): # Brunswick - top row bs_age_group = bs[bs['AgeGroup'] == age_group] - bs_trip_purpose = bs_age_group.groupby(['ActivityAfter']).size() + bs_trip_purpose = bs_age_group.groupby(['ActivityAfter']).size().reindex(dict_leisure.keys(), fill_value=0) # Map activity codes to names and create dictionary for the pie chart bs_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in bs_trip_purpose.items() if idx in dict_leisure} @@ -294,7 +292,7 @@ def create_better_pie(ax, data_dict, title): # Munich - bottom row mu_age_group = mu[mu['AgeGroup'] == age_group] - mu_trip_purpose = mu_age_group.groupby(['ActivityAfter']).size() + mu_trip_purpose = mu_age_group.groupby(['ActivityAfter']).size().reindex(dict_leisure.keys(), fill_value=0) mu_trip_purpose_dict = {dict_leisure[idx]: count for idx, count in mu_trip_purpose.items() if idx in dict_leisure} @@ -312,7 +310,6 @@ def create_better_pie(ax, data_dict, title): # Apply the same improvements to the overall pie charts print("Creating overall trip purpose comparison...") fig, (ax_bs, ax_mu) = plt.subplots(1, 2, figsize=(16, 8)) -fig.suptitle("Trip Purpose Distribution", fontsize=18) # Convert numeric activity codes to human-readable labels # Brunswick @@ -326,13 +323,12 @@ def create_better_pie(ax, data_dict, title): create_better_pie(ax_mu, mu_trip_purpose_dict, "Munich") plt.tight_layout() -plt.subplots_adjust(top=0.9) +# plt.subplots_adjust(top=0.9) plt.savefig(os.path.join(output_path, 'trip_purpose_comparison.png'), dpi=300) # 6. Overall Trip Purpose Distribution with bigger captions print("Creating overall trip purpose comparison...") fig, (ax_bs, ax_mu) = plt.subplots(1, 2, figsize=(16, 8)) -fig.suptitle("Trip Purpose Distribution", fontsize=20) # Convert numeric activity codes to human-readable labels # Brunswick