-
Notifications
You must be signed in to change notification settings - Fork 19
1294 add LCT SECIR model with two disease strains #1340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
an-jung
wants to merge
13
commits into
main
Choose a base branch
from
1294-add-lct-secir-model-with-two-disease-strains
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
3ef230f
change year in copyright
an-jung 1caf0d0
lct for 2 diseases on basis of lct_secir model,
an-jung a75cb66
lct for 2 diseases on basis of lct_secir model,
an-jung e2dcde1
Working LCT2D Model (no age groups) with test
an-jung 62945e1
LCT2D Model with age groups
an-jung 424020a
fix gitignore
an-jung 2d2ade6
Merge branch 'main' into 1294-add-lct-secir-model-with-two-disease-st…
an-jung 72678a5
header fix
an-jung 4165ebe
new test for codecov
an-jung f5b26f0
readthedocs for lct 2 diseases model
an-jung 1da5cf5
lct_infectionstate fix
an-jung d7ce14a
revert changes in lct_secir exmple, explain numbers in template
an-jung ab75b17
CI fix in test_lct_secir_2_diseases
an-jung File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
/* | ||
* Copyright (C) 2020-2024 MEmilio | ||
* Copyright (C) 2020-2025 MEmilio | ||
* | ||
* Authors: Julia Bicker | ||
* | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
/* | ||
* Copyright (C) 2020-2025 MEmilio | ||
* | ||
* Authors: Annika Jungklaus, Lena Ploetzke | ||
* | ||
* Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de> | ||
* | ||
* 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 "lct_secir_2_diseases/model.h" | ||
#include "lct_secir_2_diseases/infection_state.h" | ||
#include "memilio/config.h" | ||
#include "memilio/utils/time_series.h" | ||
#include "memilio/epidemiology/lct_infection_state.h" | ||
#include "memilio/utils/logging.h" | ||
#include "memilio/compartments/simulation.h" | ||
#include "memilio/data/analyze_result.h" | ||
#include <vector> | ||
|
||
int main() | ||
{ | ||
// Simple example to demonstrate how to run a simulation using an LCT-SECIR-2-DISEASE model. | ||
// One single AgeGroup/Category member is used here. | ||
// Parameters, initial values and the number of subcompartments are not meant to represent a realistic scenario. | ||
// The number of subcompartments can be chosen for most of the compartments: | ||
constexpr size_t NumExposed_1a = 2, NumInfectedNoSymptoms_1a = 3, NumInfectedSymptoms_1a = 3, | ||
NumInfectedSevere_1a = 3, NumInfectedCritical_1a = 2, NumExposed_2a = 1, | ||
NumInfectedNoSymptoms_2a = 2, NumInfectedSymptoms_2a = 2, NumInfectedSevere_2a = 2, | ||
NumInfectedCritical_2a = 1, NumExposed_1b = 2, NumInfectedNoSymptoms_1b = 3, | ||
NumInfectedSymptoms_1b = 3, NumInfectedSevere_1b = 3, NumInfectedCritical_1b = 2, | ||
NumExposed_2b = 1, NumInfectedNoSymptoms_2b = 2, NumInfectedSymptoms_2b = 2, | ||
NumInfectedSevere_2b = 2, NumInfectedCritical_2b = 1; | ||
// The compartment for Susceptible people and all compartments for Dead and Recovered people must have exactly one subcompartment: | ||
constexpr size_t NumSusceptible = 1, NumDead_a = 1, NumDead_b = 1, NumRecovered_a = 1, NumRecovered_b = 1, | ||
NumRecovered_ab = 1; | ||
using InfState = mio::lsecir2d::InfectionState; | ||
using LctState = | ||
mio::LctInfectionState<InfState, NumSusceptible, NumExposed_1a, NumInfectedNoSymptoms_1a, | ||
NumInfectedSymptoms_1a, NumInfectedSevere_1a, NumInfectedCritical_1a, NumRecovered_a, | ||
NumDead_a, NumExposed_2a, NumInfectedNoSymptoms_2a, NumInfectedSymptoms_2a, | ||
NumInfectedSevere_2a, NumInfectedCritical_2a, NumExposed_1b, NumInfectedNoSymptoms_1b, | ||
NumInfectedSymptoms_1b, NumInfectedSevere_1b, NumInfectedCritical_1b, NumRecovered_b, | ||
NumDead_b, NumExposed_2b, NumInfectedNoSymptoms_2b, NumInfectedSymptoms_2b, | ||
NumInfectedSevere_2b, NumInfectedCritical_2b, NumRecovered_ab>; | ||
using Model = mio::lsecir2d::Model<LctState>; | ||
Model model; | ||
|
||
ScalarType tmax = 10; | ||
|
||
// Set Parameters. | ||
model.parameters.get<mio::lsecir2d::TimeExposed_a>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeExposed_b>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedNoSymptoms_a>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedNoSymptoms_b>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedSymptoms_a>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedSymptoms_b>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedSevere_a>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedSevere_b>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedCritical_a>()[0] = 3.; | ||
model.parameters.get<mio::lsecir2d::TimeInfectedCritical_b>()[0] = 3.; | ||
|
||
model.parameters.get<mio::lsecir2d::TransmissionProbabilityOnContact_a>()[0] = 0.1; | ||
model.parameters.get<mio::lsecir2d::TransmissionProbabilityOnContact_b>()[0] = 0.1; | ||
|
||
mio::ContactMatrixGroup& contact_matrix = model.parameters.get<mio::lsecir2d::ContactPatterns>(); | ||
contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 10)); | ||
// From SimulationTime 5, the contact pattern is reduced to 30% of the initial value. | ||
contact_matrix[0].add_damping(0.7, mio::SimulationTime(5.)); | ||
|
||
model.parameters.get<mio::lsecir2d::RelativeTransmissionNoSymptoms_a>()[0] = 0.7; | ||
model.parameters.get<mio::lsecir2d::RelativeTransmissionNoSymptoms_b>()[0] = 0.7; | ||
model.parameters.get<mio::lsecir2d::RiskOfInfectionFromSymptomatic_a>()[0] = 0.25; | ||
model.parameters.get<mio::lsecir2d::RiskOfInfectionFromSymptomatic_b>()[0] = 0.25; | ||
model.parameters.get<mio::lsecir2d::RecoveredPerInfectedNoSymptoms_a>()[0] = 0.09; | ||
model.parameters.get<mio::lsecir2d::RecoveredPerInfectedNoSymptoms_b>()[0] = 0.09; | ||
model.parameters.get<mio::lsecir2d::SeverePerInfectedSymptoms_a>()[0] = 0.2; | ||
model.parameters.get<mio::lsecir2d::SeverePerInfectedSymptoms_b>()[0] = 0.2; | ||
model.parameters.get<mio::lsecir2d::CriticalPerSevere_a>()[0] = 0.25; | ||
model.parameters.get<mio::lsecir2d::CriticalPerSevere_b>()[0] = 0.25; | ||
model.parameters.get<mio::lsecir2d::DeathsPerCritical_a>()[0] = 0.3; | ||
model.parameters.get<mio::lsecir2d::DeathsPerCritical_b>()[0] = 0.3; | ||
|
||
// Simple example how to initialize model without flows. | ||
// Define the initial values with the distribution of the population into subcompartments. | ||
// This method of defining the initial values using a vector of vectors is not necessary, but should remind you | ||
// how the entries of the initial value vector relate to the defined template parameters of the model or the number | ||
// of subcompartments. It is also possible to define the initial values directly. | ||
std::vector<std::vector<ScalarType>> initial_populations = { | ||
{200}, {0, 0}, {30, 10, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0}, {0}, {0}, {0}, | ||
{0, 0}, {10, 0}, {0, 0}, {0}, {10, 0}, {30, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0}, | ||
{0}, {0}, {100}, {0, 0}, {0, 0}, {0, 0}, {0}, {0}}; | ||
|
||
// Assert that initial_populations has the right shape. | ||
if (initial_populations.size() != (size_t)InfState::Count) { | ||
mio::log_error("The number of vectors in initial_populations does not match the number of InfectionStates."); | ||
return 1; | ||
} | ||
if ((initial_populations[(size_t)InfState::Susceptible].size() != | ||
LctState::get_num_subcompartments<InfState::Susceptible>()) || | ||
(initial_populations[(size_t)InfState::Exposed_1a].size() != NumExposed_1a) || | ||
(initial_populations[(size_t)InfState::InfectedNoSymptoms_1a].size() != NumInfectedNoSymptoms_1a) || | ||
(initial_populations[(size_t)InfState::InfectedSymptoms_1a].size() != NumInfectedSymptoms_1a) || | ||
(initial_populations[(size_t)InfState::InfectedSevere_1a].size() != NumInfectedSevere_1a) || | ||
(initial_populations[(size_t)InfState::InfectedCritical_1a].size() != NumInfectedCritical_1a) || | ||
(initial_populations[(size_t)InfState::Exposed_2a].size() != NumExposed_2a) || | ||
(initial_populations[(size_t)InfState::InfectedNoSymptoms_2a].size() != NumInfectedNoSymptoms_2a) || | ||
(initial_populations[(size_t)InfState::InfectedSymptoms_2a].size() != NumInfectedSymptoms_2a) || | ||
(initial_populations[(size_t)InfState::InfectedSevere_2a].size() != NumInfectedSevere_2a) || | ||
(initial_populations[(size_t)InfState::InfectedCritical_2a].size() != NumInfectedCritical_2a) || | ||
(initial_populations[(size_t)InfState::Recovered_a].size() != | ||
LctState::get_num_subcompartments<InfState::Recovered_a>()) || | ||
(initial_populations[(size_t)InfState::Dead_a].size() != | ||
LctState::get_num_subcompartments<InfState::Dead_a>()) || | ||
(initial_populations[(size_t)InfState::Exposed_1b].size() != NumExposed_1b) || | ||
(initial_populations[(size_t)InfState::InfectedNoSymptoms_1b].size() != NumInfectedNoSymptoms_1b) || | ||
(initial_populations[(size_t)InfState::InfectedSymptoms_1b].size() != NumInfectedSymptoms_1b) || | ||
(initial_populations[(size_t)InfState::InfectedSevere_1b].size() != NumInfectedSevere_1b) || | ||
(initial_populations[(size_t)InfState::InfectedCritical_1b].size() != NumInfectedCritical_1b) || | ||
(initial_populations[(size_t)InfState::Exposed_2b].size() != NumExposed_2b) || | ||
(initial_populations[(size_t)InfState::InfectedNoSymptoms_2b].size() != NumInfectedNoSymptoms_2b) || | ||
(initial_populations[(size_t)InfState::InfectedSymptoms_2b].size() != NumInfectedSymptoms_2b) || | ||
(initial_populations[(size_t)InfState::InfectedSevere_2b].size() != NumInfectedSevere_2b) || | ||
(initial_populations[(size_t)InfState::InfectedCritical_2b].size() != NumInfectedCritical_2b) || | ||
(initial_populations[(size_t)InfState::Recovered_ab].size() != | ||
LctState::get_num_subcompartments<InfState::Recovered_ab>())) { | ||
mio::log_error("The length of at least one vector in initial_populations does not match the related number of " | ||
"subcompartments."); | ||
return 1; | ||
} | ||
// Transfer the initial values in initial_populations to the model. | ||
std::vector<ScalarType> flat_initial_populations; | ||
for (auto&& vec : initial_populations) { | ||
flat_initial_populations.insert(flat_initial_populations.end(), vec.begin(), vec.end()); | ||
} | ||
for (size_t i = 0; i < LctState::Count; i++) { | ||
model.populations[i] = flat_initial_populations[i]; | ||
} | ||
|
||
// Perform a simulation. | ||
mio::TimeSeries<ScalarType> result = mio::simulate<ScalarType, Model>(0, tmax, 0.5, model); | ||
// The simulation result is divided by subcompartments. | ||
// We call the function calculate_compartments to get a result according to the InfectionStates. | ||
mio::TimeSeries<ScalarType> population_no_subcompartments = model.calculate_compartments(result); | ||
auto interpolated_results = mio::interpolate_simulation_result(population_no_subcompartments); | ||
|
||
interpolated_results.print_table({" S", " E1a", " C1a", " I1a", " H1a", " U1a", " Ra", | ||
" Da", " E2a", " C2a", " I2a", " H2a", " U2a", " E1b", | ||
" C1b", " I1b", " H1b", " U1b", " Rb", " Db", " E2b", | ||
" C2b", " I2b", " H2b", " U2b", " Rab"}, | ||
6, 2); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
add_library(lct_secir_2_diseases | ||
infection_state.h | ||
model.h | ||
model.cpp | ||
parameters.h | ||
) | ||
target_link_libraries(lct_secir_2_diseases PUBLIC memilio) | ||
target_include_directories(lct_secir_2_diseases PUBLIC | ||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..> | ||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> | ||
) | ||
target_compile_options(lct_secir_2_diseases PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS}) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure whether the naming of the parameters and also of infection states is the best choice. Maybe we should use longer but more self-speaking names, like TimeExposedDisease1,... and for infection states something like: InfectedNoSymptomsDisease1Naive and InfectedNoSymptomsDisease1RecoveredDisease2? Or is that too long? @annawendler what do you think?