From 5df2c3ed13146017c801490f0f9984b1b5e3d8b0 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 10:37:00 +0100 Subject: [PATCH 01/62] NEW: Added structure --- docs/source/c++.rst | 8 ++++++++ docs/source/c++/aggregated_models.rst | 0 docs/source/c++/c++.rst | 8 ++++++++ docs/source/c++/ide.rst | 0 docs/source/c++/individual_models.rst | 0 docs/source/c++/io.rst | 0 docs/source/c++/mobility.rst | 0 docs/source/c++/model_creation.rst | 11 +++++++++++ docs/source/c++/model_usage.rst | 11 +++++++++++ docs/source/c++/ode.rst | 0 docs/source/c++/sde.rst | 0 docs/source/c++/structure.rst | 0 docs/source/c++/visualization.rst | 0 docs/source/faq.rst | 0 docs/source/index.rst | 11 +++++++++-- docs/source/{ => models}/abm.rst | 0 docs/source/{ => models}/glsecir.rst | 0 docs/source/{models.rst => models/index.rst} | 0 docs/source/{ => models}/isecir | 0 docs/source/{ => models}/iseir.rst | 0 docs/source/{ => models}/lsecir.rst | 0 docs/source/{ => models}/ode_seir.rst | 0 docs/source/{ => models}/ode_sir.rst | 0 docs/source/{ => models}/oseair.rst | 0 docs/source/{ => models}/osecir.rst | 0 docs/source/{ => models}/sde_sirs.rst | 0 docs/source/{ => models}/sdeseir.rst | 0 docs/source/{ => models}/sdesir.rst | 0 docs/source/{ => models}/secirts.rst | 0 docs/source/{ => models}/secirvvs.rst | 0 docs/source/python.rst | 8 ++++++++ docs/source/python/mode_creation.rst | 7 +++++++ docs/source/python/model_usage.rst | 7 +++++++ 33 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 docs/source/c++.rst create mode 100644 docs/source/c++/aggregated_models.rst create mode 100644 docs/source/c++/c++.rst create mode 100644 docs/source/c++/ide.rst create mode 100644 docs/source/c++/individual_models.rst create mode 100644 docs/source/c++/io.rst create mode 100644 docs/source/c++/mobility.rst create mode 100644 docs/source/c++/model_creation.rst create mode 100644 docs/source/c++/model_usage.rst create mode 100644 docs/source/c++/ode.rst create mode 100644 docs/source/c++/sde.rst create mode 100644 docs/source/c++/structure.rst create mode 100644 docs/source/c++/visualization.rst create mode 100644 docs/source/faq.rst rename docs/source/{ => models}/abm.rst (100%) rename docs/source/{ => models}/glsecir.rst (100%) rename docs/source/{models.rst => models/index.rst} (100%) rename docs/source/{ => models}/isecir (100%) rename docs/source/{ => models}/iseir.rst (100%) rename docs/source/{ => models}/lsecir.rst (100%) rename docs/source/{ => models}/ode_seir.rst (100%) rename docs/source/{ => models}/ode_sir.rst (100%) rename docs/source/{ => models}/oseair.rst (100%) rename docs/source/{ => models}/osecir.rst (100%) rename docs/source/{ => models}/sde_sirs.rst (100%) rename docs/source/{ => models}/sdeseir.rst (100%) rename docs/source/{ => models}/sdesir.rst (100%) rename docs/source/{ => models}/secirts.rst (100%) rename docs/source/{ => models}/secirvvs.rst (100%) create mode 100644 docs/source/python.rst create mode 100644 docs/source/python/mode_creation.rst create mode 100644 docs/source/python/model_usage.rst diff --git a/docs/source/c++.rst b/docs/source/c++.rst new file mode 100644 index 0000000000..fd57f17262 --- /dev/null +++ b/docs/source/c++.rst @@ -0,0 +1,8 @@ +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + model_usage + model_creation \ No newline at end of file diff --git a/docs/source/c++/aggregated_models.rst b/docs/source/c++/aggregated_models.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/c++.rst b/docs/source/c++/c++.rst new file mode 100644 index 0000000000..fd57f17262 --- /dev/null +++ b/docs/source/c++/c++.rst @@ -0,0 +1,8 @@ +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + model_usage + model_creation \ No newline at end of file diff --git a/docs/source/c++/ide.rst b/docs/source/c++/ide.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/individual_models.rst b/docs/source/c++/individual_models.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/io.rst b/docs/source/c++/io.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/mobility.rst b/docs/source/c++/mobility.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/model_creation.rst b/docs/source/c++/model_creation.rst new file mode 100644 index 0000000000..7b6bf3fe55 --- /dev/null +++ b/docs/source/c++/model_creation.rst @@ -0,0 +1,11 @@ +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + structure + ode + sde + ide + \ No newline at end of file diff --git a/docs/source/c++/model_usage.rst b/docs/source/c++/model_usage.rst new file mode 100644 index 0000000000..f0274921f3 --- /dev/null +++ b/docs/source/c++/model_usage.rst @@ -0,0 +1,11 @@ +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + aggregated_models + individual_models + mobility + io + visualization \ No newline at end of file diff --git a/docs/source/c++/ode.rst b/docs/source/c++/ode.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/sde.rst b/docs/source/c++/sde.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/structure.rst b/docs/source/c++/structure.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/visualization.rst b/docs/source/c++/visualization.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/faq.rst b/docs/source/faq.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/index.rst b/docs/source/index.rst index 43d9020e24..f0f6a1b1f3 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,6 +1,10 @@ **MEmilio** - a high performance Modular EpideMIcs simuLatIOn software ========================================================================== + +**Welcome** + + **MEmilio** is a framework that .. Check out the :doc:`usage` section for further information, including @@ -16,8 +20,11 @@ Contents .. toctree:: :maxdepth: 1 - usage - models + getting_started + c++/c++ + python/python + faq + models/models pythonapi api/library_root diff --git a/docs/source/abm.rst b/docs/source/models/abm.rst similarity index 100% rename from docs/source/abm.rst rename to docs/source/models/abm.rst diff --git a/docs/source/glsecir.rst b/docs/source/models/glsecir.rst similarity index 100% rename from docs/source/glsecir.rst rename to docs/source/models/glsecir.rst diff --git a/docs/source/models.rst b/docs/source/models/index.rst similarity index 100% rename from docs/source/models.rst rename to docs/source/models/index.rst diff --git a/docs/source/isecir b/docs/source/models/isecir similarity index 100% rename from docs/source/isecir rename to docs/source/models/isecir diff --git a/docs/source/iseir.rst b/docs/source/models/iseir.rst similarity index 100% rename from docs/source/iseir.rst rename to docs/source/models/iseir.rst diff --git a/docs/source/lsecir.rst b/docs/source/models/lsecir.rst similarity index 100% rename from docs/source/lsecir.rst rename to docs/source/models/lsecir.rst diff --git a/docs/source/ode_seir.rst b/docs/source/models/ode_seir.rst similarity index 100% rename from docs/source/ode_seir.rst rename to docs/source/models/ode_seir.rst diff --git a/docs/source/ode_sir.rst b/docs/source/models/ode_sir.rst similarity index 100% rename from docs/source/ode_sir.rst rename to docs/source/models/ode_sir.rst diff --git a/docs/source/oseair.rst b/docs/source/models/oseair.rst similarity index 100% rename from docs/source/oseair.rst rename to docs/source/models/oseair.rst diff --git a/docs/source/osecir.rst b/docs/source/models/osecir.rst similarity index 100% rename from docs/source/osecir.rst rename to docs/source/models/osecir.rst diff --git a/docs/source/sde_sirs.rst b/docs/source/models/sde_sirs.rst similarity index 100% rename from docs/source/sde_sirs.rst rename to docs/source/models/sde_sirs.rst diff --git a/docs/source/sdeseir.rst b/docs/source/models/sdeseir.rst similarity index 100% rename from docs/source/sdeseir.rst rename to docs/source/models/sdeseir.rst diff --git a/docs/source/sdesir.rst b/docs/source/models/sdesir.rst similarity index 100% rename from docs/source/sdesir.rst rename to docs/source/models/sdesir.rst diff --git a/docs/source/secirts.rst b/docs/source/models/secirts.rst similarity index 100% rename from docs/source/secirts.rst rename to docs/source/models/secirts.rst diff --git a/docs/source/secirvvs.rst b/docs/source/models/secirvvs.rst similarity index 100% rename from docs/source/secirvvs.rst rename to docs/source/models/secirvvs.rst diff --git a/docs/source/python.rst b/docs/source/python.rst new file mode 100644 index 0000000000..fd57f17262 --- /dev/null +++ b/docs/source/python.rst @@ -0,0 +1,8 @@ +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + model_usage + model_creation \ No newline at end of file diff --git a/docs/source/python/mode_creation.rst b/docs/source/python/mode_creation.rst new file mode 100644 index 0000000000..28bc7f87da --- /dev/null +++ b/docs/source/python/mode_creation.rst @@ -0,0 +1,7 @@ +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + \ No newline at end of file diff --git a/docs/source/python/model_usage.rst b/docs/source/python/model_usage.rst new file mode 100644 index 0000000000..28bc7f87da --- /dev/null +++ b/docs/source/python/model_usage.rst @@ -0,0 +1,7 @@ +Contents +-------- + +.. toctree:: + :maxdepth: 1 + + \ No newline at end of file From 823a5341c90aa4fbd3b311b2a281190c18b4667a Mon Sep 17 00:00:00 2001 From: jubicker Date: Mon, 17 Mar 2025 11:17:53 +0100 Subject: [PATCH 02/62] Overview ABMs --- docs/source/c++/diffusive_abm.rst | 0 docs/source/c++/individual_models.rst | 16 ++++++++++++++++ docs/source/c++/mobility_based_abm.rst | 0 3 files changed, 16 insertions(+) create mode 100644 docs/source/c++/diffusive_abm.rst create mode 100644 docs/source/c++/mobility_based_abm.rst diff --git a/docs/source/c++/diffusive_abm.rst b/docs/source/c++/diffusive_abm.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/c++/individual_models.rst b/docs/source/c++/individual_models.rst index e69de29bb2..4a481bb1d3 100644 --- a/docs/source/c++/individual_models.rst +++ b/docs/source/c++/individual_models.rst @@ -0,0 +1,16 @@ +Individual-based models +======================= + +Contents +-------- + +There are two individual- or agent-based models (ABMs) implemented in MEmilio. +The diffusive ABM realizes agent movement through a diffusion process with disease transmission and progression modeled by stochastic jump processes. +The mobility-based ABM is much more advanced and realizes agent movement between discrete locations by either mobility rules or so-called trips. +Additionally, agents have much more features e.g. an individual infection history as well as features related to quarantine or immunization. + +.. toctree:: + :maxdepth: 1 + + mobility_based_abm + diffusive_abm diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst new file mode 100644 index 0000000000..e69de29bb2 From 7a507a74d3da251b4d0ce70877307f534c7ab4b6 Mon Sep 17 00:00:00 2001 From: HenrZu <69154294+HenrZu@users.noreply.github.com> Date: Mon, 17 Mar 2025 13:22:53 +0100 Subject: [PATCH 03/62] [ci skip] wip index rst --- docs/source/index.rst | 57 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/docs/source/index.rst b/docs/source/index.rst index f0f6a1b1f3..734ef84b61 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,8 +1,65 @@ **MEmilio** - a high performance Modular EpideMIcs simuLatIOn software ========================================================================== +.. image:: https://github.com/SciCompMod/memilio/actions/workflows/main.yml/badge.svg?branch=main + :target: https://github.com/SciCompMod/memilio/actions/workflows/main.yml + :alt: CI Badge + +.. image:: https://codecov.io/gh/SciCompMod/memilio/branch/main/graph/badge.svg?token=DVQXIQJHBM + :target: https://codecov.io/gh/SciCompMod/memilio + **Welcome** +MEmilio implements various models for infectious disease dynamics, ranging from simple compartmental models to complex Integro-Differential and agent-based models. Its modular design enables the combination of different models with distinct mobility patterns. Through efficient implementation and parallelization, MEmilio delivers cutting-edge and compute-intensive epidemiological models at a large scale, providing precise and high-resolution spatiotemporal infectious disease dynamics. MEmilio is continuously extended and is available open-source for community use. + +If you use MEmilio, please cite our works: + +- Kühn, Martin Joachim et al. (2022). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `GitHub `_ and `DLR `_. + +- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` + +Getting Started +=============== + +MEmilio supports various model types including equation-based, agent-based, and hybrid graph-ODE-based models. Among the equation-based models, we provide ordinary differential equation (ODE) and integro-differential equation (IDE) based models. + +- The C++ backend powers the model and simulation components for optimal efficiency. +- Data acquisition, plotting, and machine-learned models are handled via Python. + +For more details on the C++ implementation, see the `cpp directory README `_. + +Regularly used data for simulations of pathogen spread in Germany, such as contact and inter-county mobility, is provided in the `data directory README `_. + +Python Packages +=============== + +- **memilio-simulation**: Interface to run the C++ backend via Python using `pybind11 `_. +- **memilio-epidata**: Tools for downloading and structuring key datasets like infection or mobility data. + +More information is available in the `Python README `_. + +Documentation +============= + +Each core component is described in detail within its corresponding README file, including configuration and usage instructions for both users and developers. + +Code is documented using Doxygen, and further instructions can be found in the `docs` folder. + +The latest documentation for the main branch is available here: +`https://scicompmod.github.io/memilio/documentation/index.html` + +Installation, Usage, and Requirements +===================================== + +Each module has its own set of requirements and usage instructions, detailed in the corresponding READMEs. + +Development +=========== + +- `Git workflow and change process `_ +- `Coding Guidelines `_ +.. image:: https://github.com/user-attachments/assets/65af6012-106e-43c6-9e0e-c96a73aa7b1e + :alt: Memilio_overview **MEmilio** is a framework that .. From 58d058eacc450148ece5f48c3fe00fcd16820a93 Mon Sep 17 00:00:00 2001 From: HenrZu <69154294+HenrZu@users.noreply.github.com> Date: Mon, 17 Mar 2025 14:09:48 +0100 Subject: [PATCH 04/62] add references --- docs/source/index.rst | 62 ++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 734ef84b61..b3008bac4b 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -9,58 +9,76 @@ :target: https://codecov.io/gh/SciCompMod/memilio -**Welcome** +Welcome +=============== + MEmilio implements various models for infectious disease dynamics, ranging from simple compartmental models to complex Integro-Differential and agent-based models. Its modular design enables the combination of different models with distinct mobility patterns. Through efficient implementation and parallelization, MEmilio delivers cutting-edge and compute-intensive epidemiological models at a large scale, providing precise and high-resolution spatiotemporal infectious disease dynamics. MEmilio is continuously extended and is available open-source for community use. -If you use MEmilio, please cite our works: +.. image:: https://github.com/user-attachments/assets/65af6012-106e-43c6-9e0e-c96a73aa7b1e + :alt: Memilio_overview + +If you use MEmilio, please cite our work: - Kühn, Martin Joachim et al. (2022). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `GitHub `_ and `DLR `_. -- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` Getting Started =============== -MEmilio supports various model types including equation-based, agent-based, and hybrid graph-ODE-based models. Among the equation-based models, we provide ordinary differential equation (ODE) and integro-differential equation (IDE) based models. +MEmilio supports various model types including equation-based, agent-based, and hybrid graph-ODE-based models. Among the equation-based models, we provide ordinary differential equation (ODE), linear chain trick (LCT), integro-differential equation (IDE) based models. - The C++ backend powers the model and simulation components for optimal efficiency. - Data acquisition, plotting, and machine-learned models are handled via Python. For more details on the C++ implementation, see the `cpp directory README `_. -Regularly used data for simulations of pathogen spread in Germany, such as contact and inter-county mobility, is provided in the `data directory README `_. +Some regularly used data for simulations of a pathogen's spread in Germany, like contact and inter-county mobility, can be found in the `data directory README `_. -Python Packages -=============== +In `pycode`, different MEmilio Python packages are defined. Via our `memilio-simulation` package, you can run our C++ backend from Python; this package uses `pybind11` to bind our C++ model code. The `memilio-epidata` package provides tools to download and structure important data such as infection or mobility data. More about the Python packages can be found in the `Python README `_. + +References +=========== -- **memilio-simulation**: Interface to run the C++ backend via Python using `pybind11 `_. -- **memilio-epidata**: Tools for downloading and structuring key datasets like infection or mobility data. +Recently Submitted Publications +-------------------------------------- -More information is available in the `Python README `_. +**2024** -Documentation -============= +- Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` +- Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` +- Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` -Each core component is described in detail within its corresponding README file, including configuration and usage instructions for both users and developers. +**2025** -Code is documented using Doxygen, and further instructions can be found in the `docs` folder. +- Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` -The latest documentation for the main branch is available here: -`https://scicompmod.github.io/memilio/documentation/index.html` +Peer-Reviewed Publications +-------------------------- + +**2021** + +- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` + +**2022** + +- Kühn MJ, Abele D, Binder S, Rack K, Klitz M, et al. (2022). *Regional opening strategies with commuter testing and containment of new SARS-CoV-2 variants in Germany*. *BMC Infectious Diseases* 22(1): 333. `https://doi.org/10.1186/s12879-022-07302-9` +- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` + +**2024** + +- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` + +**2025** + +- Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` -Installation, Usage, and Requirements -===================================== -Each module has its own set of requirements and usage instructions, detailed in the corresponding READMEs. Development =========== - `Git workflow and change process `_ - `Coding Guidelines `_ -.. image:: https://github.com/user-attachments/assets/65af6012-106e-43c6-9e0e-c96a73aa7b1e - :alt: Memilio_overview - **MEmilio** is a framework that .. From 75fa3d8d464eb421d7483b3f2a35e35205eb03f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Joachim=20K=C3=BChn?= Date: Mon, 17 Mar 2025 14:22:45 +0100 Subject: [PATCH 05/62] readmes --- README.md | 14 +++++++++++--- docs/source/index.rst | 38 ++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 2de10cf760..a28ac75adc 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,19 @@ MEmilio implements various models for infectious disease dynamics, from simple compartmental models through Integro-Differential equation-based models to agent- or individual-based models. Its modular design allows the combination of different models with different mobility patterns. Through efficient implementation and parallelization, MEmilio brings cutting edge and compute intensive epidemiological models to a large scale, enabling a precise and high-resolution spatiotemporal infectious disease dynamics. MEmilio will be extended continuously. It is available open-source and we encourage everyone to make use of it. -If you use MEmilio, please cite our works: +If you use MEmilio, please cite our work -- Kühn, Martin Joachim und Abele, Daniel und Kerkmann, David und Korf, Sascha Alexander und Zunker, Henrik und Wendler, Anna Clara und Bicker, Julia und Nguyen, Dang Khoa und Klitz, Margrit und Koslow, Wadim und Siggel, Martin und Kleinert, Jan und Rack, Kathrin und Binder, Sebastian und Plötzke, Lena und Schmieding, René und Lenz, Patrick und Betz, Maximilian Franz und Lutz, Annette und Gerstein, Carlotta und Schmidt, Agatha und Meyer-Hermann, Michael und Basermann, Achim (2022) MEmilio - a high performance Modular EpideMIcs simuLatIOn software (2022). https://github.com/SciCompMod/memilio, https://elib.dlr.de/192140/. +- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `https://github.com/SciCompMod/memilio` and `https://elib.dlr.de/209739/`. -- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022) Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant. PLOS Computational Biology 18(5): e1010054. https://doi.org/10.1371/journal.pcbi.1010054 +and, in particular, for + +- Ordinary differential equation-based (ODE) and Graph-ODE models: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` +- Integro-differential equation-based (IDE) models: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` +- Agent-based models (ABMs): Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` +- Hybrid agent-metapopulation-based models: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` +- Graph Neural Networks: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` +- ODE-based models with Linear Chain Trick: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` +- Behavior-based ODE models: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` **Getting started** diff --git a/docs/source/index.rst b/docs/source/index.rst index b3008bac4b..528a1f245e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -17,9 +17,19 @@ MEmilio implements various models for infectious disease dynamics, ranging from .. image:: https://github.com/user-attachments/assets/65af6012-106e-43c6-9e0e-c96a73aa7b1e :alt: Memilio_overview -If you use MEmilio, please cite our work: +If you use MEmilio, please cite our work -- Kühn, Martin Joachim et al. (2022). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `GitHub `_ and `DLR `_. +- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `https://github.com/SciCompMod/memilio` and `https://elib.dlr.de/209739/`. + +and, in particular, for + +- Ordinary differential equation-based (ODE) and Graph-ODE models: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` +- Integro-differential equation-based (IDE) models: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` +- Agent-based models (ABMs): Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` +- Hybrid agent-metapopulation-based models: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` +- Graph Neural Networks: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` +- ODE-based models with Linear Chain Trick: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` +- Behavior-based ODE models: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` Getting Started @@ -42,36 +52,32 @@ References Recently Submitted Publications -------------------------------------- -**2024** - +- Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` +- Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` - Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` - Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` - Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` -**2025** - -- Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` Peer-Reviewed Publications -------------------------- -**2021** - -- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` - -**2022** +**2025** -- Kühn MJ, Abele D, Binder S, Rack K, Klitz M, et al. (2022). *Regional opening strategies with commuter testing and containment of new SARS-CoV-2 variants in Germany*. *BMC Infectious Diseases* 22(1): 333. `https://doi.org/10.1186/s12879-022-07302-9` -- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` +- Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` **2024** - Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` -**2025** +**2022** -- Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` +- Kühn MJ, Abele D, Binder S, Rack K, Klitz M, et al. (2022). *Regional opening strategies with commuter testing and containment of new SARS-CoV-2 variants in Germany*. *BMC Infectious Diseases* 22(1): 333. `https://doi.org/10.1186/s12879-022-07302-9` +- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` +**2021** + +- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` Development From 29282672912bfb7badf8527ec822cc7b702d97d3 Mon Sep 17 00:00:00 2001 From: HenrZu <69154294+HenrZu@users.noreply.github.com> Date: Mon, 17 Mar 2025 14:26:13 +0100 Subject: [PATCH 06/62] titles bold --- docs/source/index.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 528a1f245e..b57f043c3c 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -23,13 +23,13 @@ If you use MEmilio, please cite our work and, in particular, for -- Ordinary differential equation-based (ODE) and Graph-ODE models: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` -- Integro-differential equation-based (IDE) models: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` -- Agent-based models (ABMs): Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` -- Hybrid agent-metapopulation-based models: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` -- Graph Neural Networks: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` -- ODE-based models with Linear Chain Trick: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` -- Behavior-based ODE models: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` +- **Ordinary differential equation-based (ODE) and Graph-ODE models**: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` +- **Integro-differential equation-based (IDE) models**: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` +- **Agent-based models (ABMs)**: Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` +- **Hybrid agent-metapopulation-based models**: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` +- **Graph Neural Networks**: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` +- **ODE-based models with Linear Chain Trick**: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` +- **Behavior-based ODE models**: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` Getting Started From c8a772c59a9453196d9fb8f1f7d376be97d82b8c Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 14:43:55 +0100 Subject: [PATCH 07/62] CHG: remove furo from requirements --- docs/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 3862d839f0..5c132004ec 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,5 @@ sphinx==7.1.2 sphinx-rtd-theme==1.3.0rc1 -furo sphinx-copybutton breathe sphinx-hoverxref From f86457fc15233134c47d909e143ba9b6c5d33703 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 14:45:08 +0100 Subject: [PATCH 08/62] CHG: Update dummy files --- docs/source/c++.rst | 2 +- docs/source/c++/aggregated_models.rst | 2 ++ docs/source/c++/c++.rst | 10 ++++++---- docs/source/c++/ide.rst | 2 ++ docs/source/c++/io.rst | 2 ++ docs/source/c++/mobility.rst | 2 ++ docs/source/c++/model_creation.rst | 14 ++++++++------ docs/source/c++/model_usage.rst | 16 +++++++++------- docs/source/c++/ode.rst | 2 ++ docs/source/c++/sde.rst | 2 ++ docs/source/c++/structure.rst | 2 ++ docs/source/c++/visualization.rst | 2 ++ docs/source/faq.rst | 2 ++ docs/source/{usage.rst => getting_started.rst} | 2 +- docs/source/python.rst | 8 -------- .../{mode_creation.rst => model_creation.rst} | 5 +++-- docs/source/python/model_usage.rst | 6 +++--- docs/source/python/python.rst | 10 ++++++++++ docs/source/pythonapi.rst | 3 +++ 19 files changed, 62 insertions(+), 32 deletions(-) rename docs/source/{usage.rst => getting_started.rst} (80%) delete mode 100644 docs/source/python.rst rename docs/source/python/{mode_creation.rst => model_creation.rst} (53%) create mode 100644 docs/source/python/python.rst diff --git a/docs/source/c++.rst b/docs/source/c++.rst index fd57f17262..85e362205d 100644 --- a/docs/source/c++.rst +++ b/docs/source/c++.rst @@ -2,7 +2,7 @@ Contents -------- .. toctree:: - :maxdepth: 1 + :maxdepth: 1 model_usage model_creation \ No newline at end of file diff --git a/docs/source/c++/aggregated_models.rst b/docs/source/c++/aggregated_models.rst index e69de29bb2..3902a4b97c 100644 --- a/docs/source/c++/aggregated_models.rst +++ b/docs/source/c++/aggregated_models.rst @@ -0,0 +1,2 @@ +Aggregated models +================= \ No newline at end of file diff --git a/docs/source/c++/c++.rst b/docs/source/c++/c++.rst index fd57f17262..2b1657e799 100644 --- a/docs/source/c++/c++.rst +++ b/docs/source/c++/c++.rst @@ -1,8 +1,10 @@ -Contents --------- +C++ Interface +============= + .. toctree:: :maxdepth: 1 + :caption: C++ Interface - model_usage - model_creation \ No newline at end of file + model_usage + model_creation \ No newline at end of file diff --git a/docs/source/c++/ide.rst b/docs/source/c++/ide.rst index e69de29bb2..c3e5cd0901 100644 --- a/docs/source/c++/ide.rst +++ b/docs/source/c++/ide.rst @@ -0,0 +1,2 @@ +IDE Models +========== \ No newline at end of file diff --git a/docs/source/c++/io.rst b/docs/source/c++/io.rst index e69de29bb2..d3e4213ad6 100644 --- a/docs/source/c++/io.rst +++ b/docs/source/c++/io.rst @@ -0,0 +1,2 @@ +Input/Output +============ \ No newline at end of file diff --git a/docs/source/c++/mobility.rst b/docs/source/c++/mobility.rst index e69de29bb2..2609f471dd 100644 --- a/docs/source/c++/mobility.rst +++ b/docs/source/c++/mobility.rst @@ -0,0 +1,2 @@ +Mobility +======== \ No newline at end of file diff --git a/docs/source/c++/model_creation.rst b/docs/source/c++/model_creation.rst index 7b6bf3fe55..7f07d88546 100644 --- a/docs/source/c++/model_creation.rst +++ b/docs/source/c++/model_creation.rst @@ -1,11 +1,13 @@ -Contents --------- +Model Creation +============== + + .. toctree:: :maxdepth: 1 - structure - ode - sde - ide + structure + ode + sde + ide \ No newline at end of file diff --git a/docs/source/c++/model_usage.rst b/docs/source/c++/model_usage.rst index f0274921f3..8fa23d7778 100644 --- a/docs/source/c++/model_usage.rst +++ b/docs/source/c++/model_usage.rst @@ -1,11 +1,13 @@ -Contents --------- +Model Usage +=========== + + .. toctree:: :maxdepth: 1 - aggregated_models - individual_models - mobility - io - visualization \ No newline at end of file + aggregated_models + individual_models + mobility + io + visualization \ No newline at end of file diff --git a/docs/source/c++/ode.rst b/docs/source/c++/ode.rst index e69de29bb2..9ba9cc59ff 100644 --- a/docs/source/c++/ode.rst +++ b/docs/source/c++/ode.rst @@ -0,0 +1,2 @@ +ODE Models +========== \ No newline at end of file diff --git a/docs/source/c++/sde.rst b/docs/source/c++/sde.rst index e69de29bb2..c3c35139fa 100644 --- a/docs/source/c++/sde.rst +++ b/docs/source/c++/sde.rst @@ -0,0 +1,2 @@ +SDE Models +========== diff --git a/docs/source/c++/structure.rst b/docs/source/c++/structure.rst index e69de29bb2..3449e67166 100644 --- a/docs/source/c++/structure.rst +++ b/docs/source/c++/structure.rst @@ -0,0 +1,2 @@ +Structure +========= \ No newline at end of file diff --git a/docs/source/c++/visualization.rst b/docs/source/c++/visualization.rst index e69de29bb2..27e80a1334 100644 --- a/docs/source/c++/visualization.rst +++ b/docs/source/c++/visualization.rst @@ -0,0 +1,2 @@ +Visualizations +============== \ No newline at end of file diff --git a/docs/source/faq.rst b/docs/source/faq.rst index e69de29bb2..9a2bc461d8 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -0,0 +1,2 @@ +FAQ +==== \ No newline at end of file diff --git a/docs/source/usage.rst b/docs/source/getting_started.rst similarity index 80% rename from docs/source/usage.rst rename to docs/source/getting_started.rst index 5dc831b621..739d01e537 100644 --- a/docs/source/usage.rst +++ b/docs/source/getting_started.rst @@ -23,6 +23,6 @@ For example: >>> import memilio.epidata import progress_indicator -Other examples can be found in the :doc:`models` page. +Other examples can be found in the :doc:`models/index` page. diff --git a/docs/source/python.rst b/docs/source/python.rst deleted file mode 100644 index fd57f17262..0000000000 --- a/docs/source/python.rst +++ /dev/null @@ -1,8 +0,0 @@ -Contents --------- - -.. toctree:: - :maxdepth: 1 - - model_usage - model_creation \ No newline at end of file diff --git a/docs/source/python/mode_creation.rst b/docs/source/python/model_creation.rst similarity index 53% rename from docs/source/python/mode_creation.rst rename to docs/source/python/model_creation.rst index 28bc7f87da..1834ced0c2 100644 --- a/docs/source/python/mode_creation.rst +++ b/docs/source/python/model_creation.rst @@ -1,5 +1,6 @@ -Contents --------- +Model Creation +============== + .. toctree:: :maxdepth: 1 diff --git a/docs/source/python/model_usage.rst b/docs/source/python/model_usage.rst index 28bc7f87da..661aa96cd4 100644 --- a/docs/source/python/model_usage.rst +++ b/docs/source/python/model_usage.rst @@ -1,7 +1,7 @@ -Contents --------- +Model Usage +=========== + .. toctree:: :maxdepth: 1 - \ No newline at end of file diff --git a/docs/source/python/python.rst b/docs/source/python/python.rst new file mode 100644 index 0000000000..78326acd44 --- /dev/null +++ b/docs/source/python/python.rst @@ -0,0 +1,10 @@ +Python Interface +================ + + +.. toctree:: + :maxdepth: 1 + :caption: Python Interface + + model_usage + model_creation \ No newline at end of file diff --git a/docs/source/pythonapi.rst b/docs/source/pythonapi.rst index 37ad602b02..d3672dab48 100644 --- a/docs/source/pythonapi.rst +++ b/docs/source/pythonapi.rst @@ -7,9 +7,12 @@ Python API .. autosummary:: :toctree: generated :recursive: + :imported-members: + :caption: Pyhton Module API memilio.generation memilio.epidata memilio.simulation memilio.surrogatemodel memilio.plot + From e6c1e310e3940725843af2a09c7429065c170e28 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 14:45:30 +0100 Subject: [PATCH 09/62] CHG: Update index --- docs/source/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index b57f043c3c..aede995871 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -100,12 +100,12 @@ Contents .. toctree:: :maxdepth: 1 + :caption: Getting Started getting_started + faq c++/c++ python/python - faq models/models pythonapi - api/library_root - + api/library_root \ No newline at end of file From 87dd639eb1b567dc7f7bcaef36dcd363fe17e692 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:00:23 +0100 Subject: [PATCH 10/62] FIX: Renamed usage --- docs/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index aede995871..c15ecf1a94 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -88,7 +88,7 @@ Development **MEmilio** is a framework that .. -Check out the :doc:`usage` section for further information, including +Check out the :doc:`getting_started` section for further information, including how to :hoverxref:`installation` the project. .. note:: From c8da215cd3ebf6fa0042b0982fa76b295aa8539a Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:26:11 +0100 Subject: [PATCH 11/62] CHG: remove duplicate c++ index file --- docs/source/c++.rst | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 docs/source/c++.rst diff --git a/docs/source/c++.rst b/docs/source/c++.rst deleted file mode 100644 index 85e362205d..0000000000 --- a/docs/source/c++.rst +++ /dev/null @@ -1,8 +0,0 @@ -Contents --------- - -.. toctree:: - :maxdepth: 1 - - model_usage - model_creation \ No newline at end of file From cac10210b35cb70abf6f2e6e469f3a93be18c4be Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:26:32 +0100 Subject: [PATCH 12/62] CHG: Change layout of Individual based model --- docs/source/c++/individual_models.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/source/c++/individual_models.rst b/docs/source/c++/individual_models.rst index 4a481bb1d3..f3859321aa 100644 --- a/docs/source/c++/individual_models.rst +++ b/docs/source/c++/individual_models.rst @@ -1,16 +1,14 @@ Individual-based models ======================= -Contents --------- - There are two individual- or agent-based models (ABMs) implemented in MEmilio. The diffusive ABM realizes agent movement through a diffusion process with disease transmission and progression modeled by stochastic jump processes. The mobility-based ABM is much more advanced and realizes agent movement between discrete locations by either mobility rules or so-called trips. Additionally, agents have much more features e.g. an individual infection history as well as features related to quarantine or immunization. + .. toctree:: - :maxdepth: 1 + :maxdepth: 1 mobility_based_abm diffusive_abm From 700b82f67107b49d56c31ebeca7d4246ba0559cf Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:58:11 +0100 Subject: [PATCH 13/62] CHG: Fix some layout issues regarding long lines --- docs/source/_static/custom.css | 41 ++++++++++++++++++++++++++++++++++ docs/source/conf.py | 10 +++++---- 2 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 docs/source/_static/custom.css diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css new file mode 100644 index 0000000000..fc86d8fd05 --- /dev/null +++ b/docs/source/_static/custom.css @@ -0,0 +1,41 @@ +/* Newlines (\a) and spaces (\20) before each parameter +.sig-param::before { + content: "\a\20\20\20\20\20\20\20\20\20\20\20\20\20\20\20\20"; + white-space: pre; +} + +/* Newline after the last parameter (so the closing bracket is on a new line) +dt em.sig-param:last-of-type::after { + content: "\a"; + white-space: pre; +} + +/* To have blue background of width of the block (instead of width of content) +dl.class > dt:first-of-type { + display: block !important; +} */ + +/* Take out pointless vertical whitespace in the signatures. */ +.rst-content dl .sig dl, +.rst-content dl .sig dd { + margin-bottom: 0; +} + +/* Make signature boxes full-width, with view-source and header links right-aligned. */ +.rst-content dl .sig { + width: -webkit-fill-available; +} +.rst-content .viewcode-link { + display: inline-flex; + float: inline-end; + margin-right: 1.5em; +} +.rst-content .headerlink { + position: absolute; + right: 0.5em; +} + +.wy-table-responsive table td, +.wy-table-responsive table th { + white-space: normal; +} diff --git a/docs/source/conf.py b/docs/source/conf.py index b0f963249d..8e5c4060dd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -76,14 +76,16 @@ templates_path = ['_templates'] # -- Options for HTML output -# html_static_path = ['_static'] -# html_css_files = [ -# 'custom.css', -# ] +html_static_path = ['_static'] +html_css_files = [ + 'custom.css', +] # html_js_files = [ # 'custom.js', # ] +maximum_signature_line_length = 40 + html_theme = 'sphinx_rtd_theme' html_logo = "../memilio-small.png" html_theme_options = { From d48d952855eba8a1ebbccc87a1ce9c13af88904b Mon Sep 17 00:00:00 2001 From: jubicker Date: Mon, 17 Mar 2025 16:02:40 +0100 Subject: [PATCH 14/62] Documentation diffusive ABM --- docs/source/c++/diffusive_abm.rst | 122 ++++++++++++++++++++++++++ docs/source/c++/individual_models.rst | 6 +- 2 files changed, 125 insertions(+), 3 deletions(-) diff --git a/docs/source/c++/diffusive_abm.rst b/docs/source/c++/diffusive_abm.rst index e69de29bb2..7eda6eaf7a 100644 --- a/docs/source/c++/diffusive_abm.rst +++ b/docs/source/c++/diffusive_abm.rst @@ -0,0 +1,122 @@ +Diffusive Agent-Based Model +=========================== + +This agent-based model uses a Markov process to simulate disease dynamics. The Markov process is given by agent movement and the evolution of disease dynamics i.e. disease transmission and progression. +The features of an agent are its position and its infection state. The evolution of the system state is determined by the following master equation + +:math:`\partial_t p(X,Z;t) = G p(X,Z;t) + L p(X,Z;t)` + +with :math:`X` the vector of all agents' positions and :math:`Z` the vector of all agents' infection states. The operator :math:`G` defines the infection state adoptions and only acts on :math:`Z`, while :math:`L` defines movement, i.e. location changes, only acting on :math:`X`. Infection state adoptions are modeled with independent Poisson processes given by adoption rate functions. Adoption rates always depend on the source infection state. If an adoption event requires interaction of agents (e.g. disease transmission), the corresponding rate depends not only on the source infection states, but also on other infection state, the `influences`. An adoption rate that only depends on the source compartment, e.g. recovery or worsening of disease symptoms, is called `first-order` adoption rate and an adoption rate that has influences is called `second-order` adoption rate. Movement is modeled with independent diffusion processes. A temporal Gillespie algorithm (a direct method without rejection sampling) is used for simulation. Therefore, :math:`G` and :math:`L` are not implemented explicitly, instead their effects are sampled via the `move` and `adoption_rate` functions, respectively. + +The Model class needs an Implementation class as template argument which provides the domain agents move and interact in. A quadwell potential given in the class QuadWellModel is implemented, but any other suitable potential can be used as implementation. + +Simulation +----------- + +The simulation runs in discrete time steps. In every step the model is advanced until the next infection state adoption event. Then the corresponding agent's infection state is adopted and a new waiting time until the next adoption event is srawn. If the waiting time until the next adoption event is bigger than the remaining time in the time step, we advance the model until the end of the time step. + +For a detailed description and application of the model, see: + +- Bicker J, Schmieding R, et al. (2025) Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing. Infectious Disease Modelling, Volume 10, Issue 2. https://doi.org/10.1016/j.idm.2024.12.015 + +How to: Set up and run a simulation of the diffusive ABM +--------------------------------------------------------- + +The infection states used need to be defined in an enum before initializing the model and are passed as template argument to the model. +Using the infection states Susceptible (S), Exposed (E), Carrier (C), Infected (I), Recovered (R) and Dead (D) this ca be done as follows: + +.. code-block:: cpp + + enum class InfectionState + { + S, + E, + C, + I, + R, + D, + Count + + }; + + using Model = mio::dabm::Model>; + +To initialze the model using the quad well potential, the following inputs need to be passed to the model constructor: + +- a vector containing the agents, +- a vector containing the adoption rates for infection state adoptions, +- the interaction radius of agents, +- the noise term for the diffusion process. + +Agents have two attributes: A position on the domain and an infection states. The example below initializes 100 agents with an agent's position sampled uniformly from :math:`\left[-2,2\right]\times\left[-2,2\right]` and its infection state sampled from a discrete distribution with probabilities given by :math:`98\%` (S), :math:`1\%` (E), :math:`0.5\%` (C), :math:`0.5\%` (I), :math:`0\%` (R), :math:`0\%` (D). + +.. code-block:: cpp + + std::vector agents(1000); + + //Random variables for initialization of agents' position and infection state + auto& pos_rng = mio::UniformDistribution::get_instance(); + auto& sta_rng = mio::DiscreteDistribution::get_instance(); + + //Infection state distribution + std::vector pop_dist{0.98, 0.01, 0.005, 0.005, 0., 0.}; + + for (auto& a : agents) { + //Agents are uniformly distributed in [-2,2]x[-2,2] + a.position = Eigen::Vector2d{pos_rng(mio::thread_local_rng(), -2., 2.), pos_rng(mio::thread_local_rng(), -2., 2.)}; + a.status = static_cast(sta_rng(mio::thread_local_rng(), pop_dist)); + } + +As already mentioned above, infection state adoption rates can only depend on the source infection state (first-order) or they can be influenced by other infection states (second-order). An influence consists of an infection state and the corresponding multiplicative factor. Additionally, adoption rates are region-dependent with a region corresponding to the potential wells for the implemented quad well potential. That means the quad well potential has four regions given by :math:`\Omega_0=\left(-\infty,0\right)\times\left(0,\infty\right), \Omega_1=\left(0,\infty\right)\times\left(0,\infty\right), \Omega_2=\left(-\infty,0\right)\times\left(-\infty,0\right)` and :math:`\Omega_3=\left(0,\infty\right)\times\left(-\infty,0\right)`. + +In the example below, regions 0-2 have the same adoption rates while region 3 has a two times higher transmission rate (adoption from S to E): + +.. code-block:: cpp + + std::vector> adoption_rates; + + //First-order adoption rates + for (size_t region = 0; region < 4; ++region) { + adoption_rates.push_back({InfectionState::E, InfectionState::C, mio::regions::Region(region), 1.0 / 5., {}}); + adoption_rates.push_back({InfectionState::C, InfectionState::R, mio::regions::Region(region), 0.2 / 3., {}}); + adoption_rates.push_back({InfectionState::C, InfectionState::I, mio::regions::Region(region), 0.8 / 3., {}}); + adoption_rates.push_back({InfectionState::I, InfectionState::R, mio::regions::Region(region), 0.99 / 5., {}}); + adoption_rates.push_back({InfectionState::I, InfectionState::D, mio::regions::Region(region), 0.01 / 5., {}}); + } + + //Second-order adoption rate for region 0-2 + for (size_t region = 0; region < 3; ++region) { + adoption_rates.push_back({InfectionState::S, InfectionState::E, mio::regions::Region(region), 0.1, {{InfectionState::C, 1}, {InfectionState::I, 0.5}}}); + } + + //Second order adoption rate for region 3 + adoption_rates.push_back({InfectionState::S, InfectionState::E, mio::regions::Region(3), 0.2, {{InfectionState::C, 1}, {InfectionState::I, 0.5}}}); + +Choosing an interaction radius of 0.5 and a noise term of 0.4, the model is initialized by + +.. code-block:: cpp + + double interaction_radius = 0.5; + double noise = 0.4; + + Model model(agents, adoption_rates, interaction_radius, noise); + +There is the option to pass a vector of non-moving state to the model. Defining that agents having infection state D do not move, the model initialization would be + +.. code-block:: cpp + + Model model(agents, adoption_rates, interaction_radius, noise, {InfectionState::D}); + +A to simulate the model from `t0` to `tmax` with given step size `dt`, a Simulation has to be created and the advanced until `tmax`, which is done as follows: + +.. code-block:: cpp + + double t0 = 0.0; + double dt = 0.1; + double tmax = 30.; + + //Pass the model, t0 and dt to the Simulation + auto sim = mio::dabm::Simulation(model, t0, dt); + + //Advance the simulation until tmax + sim.advance(tmax); diff --git a/docs/source/c++/individual_models.rst b/docs/source/c++/individual_models.rst index 4a481bb1d3..28cbf7d2e5 100644 --- a/docs/source/c++/individual_models.rst +++ b/docs/source/c++/individual_models.rst @@ -1,14 +1,14 @@ Individual-based models ======================= -Contents --------- - There are two individual- or agent-based models (ABMs) implemented in MEmilio. The diffusive ABM realizes agent movement through a diffusion process with disease transmission and progression modeled by stochastic jump processes. The mobility-based ABM is much more advanced and realizes agent movement between discrete locations by either mobility rules or so-called trips. Additionally, agents have much more features e.g. an individual infection history as well as features related to quarantine or immunization. +Contents +-------- + .. toctree:: :maxdepth: 1 From 83d4feb5822a73dadafb0f88dc54cebeae4e2d7f Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 16:21:51 +0100 Subject: [PATCH 15/62] CHG: Use Captions in toctrees for main structure --- docs/source/c++/c++.rst | 10 ---------- docs/source/index.rst | 23 ++++++++++++++++++++--- docs/source/python/python.rst | 10 ---------- 3 files changed, 20 insertions(+), 23 deletions(-) delete mode 100644 docs/source/c++/c++.rst delete mode 100644 docs/source/python/python.rst diff --git a/docs/source/c++/c++.rst b/docs/source/c++/c++.rst deleted file mode 100644 index 2b1657e799..0000000000 --- a/docs/source/c++/c++.rst +++ /dev/null @@ -1,10 +0,0 @@ -C++ Interface -============= - - -.. toctree:: - :maxdepth: 1 - :caption: C++ Interface - - model_usage - model_creation \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index c15ecf1a94..e8757af817 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -104,8 +104,25 @@ Contents getting_started faq - c++/c++ - python/python - models/models + +.. toctree:: + :maxdepth: 2 + :caption: C++ Interface + + c++/model_usage + c++/model_creation + +.. toctree:: + :maxdepth: 2 + :caption: Python Interface + + python/model_usage + python/model_creation + +.. toctree:: + :maxdepth: 1 + :caption: Code API + + models/index pythonapi api/library_root \ No newline at end of file diff --git a/docs/source/python/python.rst b/docs/source/python/python.rst deleted file mode 100644 index 78326acd44..0000000000 --- a/docs/source/python/python.rst +++ /dev/null @@ -1,10 +0,0 @@ -Python Interface -================ - - -.. toctree:: - :maxdepth: 1 - :caption: Python Interface - - model_usage - model_creation \ No newline at end of file From a571edbe1bc1955c73471e3d34d62a8b5765913c Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 16:28:35 +0100 Subject: [PATCH 16/62] CHG: Move references to their own file --- docs/source/index.rst | 33 +-------------------------------- docs/source/references.rst | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 32 deletions(-) create mode 100644 docs/source/references.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index e8757af817..4d57558c8f 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -46,38 +46,6 @@ Some regularly used data for simulations of a pathogen's spread in Germany, like In `pycode`, different MEmilio Python packages are defined. Via our `memilio-simulation` package, you can run our C++ backend from Python; this package uses `pybind11` to bind our C++ model code. The `memilio-epidata` package provides tools to download and structure important data such as infection or mobility data. More about the Python packages can be found in the `Python README `_. -References -=========== - -Recently Submitted Publications --------------------------------------- - -- Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` -- Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` -- Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` -- Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` -- Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` - - -Peer-Reviewed Publications --------------------------- - -**2025** - -- Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` - -**2024** - -- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` - -**2022** - -- Kühn MJ, Abele D, Binder S, Rack K, Klitz M, et al. (2022). *Regional opening strategies with commuter testing and containment of new SARS-CoV-2 variants in Germany*. *BMC Infectious Diseases* 22(1): 333. `https://doi.org/10.1186/s12879-022-07302-9` -- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` - -**2021** - -- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` Development @@ -103,6 +71,7 @@ Contents :caption: Getting Started getting_started + references faq .. toctree:: diff --git a/docs/source/references.rst b/docs/source/references.rst new file mode 100644 index 0000000000..e614d9fed4 --- /dev/null +++ b/docs/source/references.rst @@ -0,0 +1,32 @@ +References +=========== + +Recently Submitted Publications +-------------------------------------- + +- Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` +- Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` +- Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` +- Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` +- Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` + + +Peer-Reviewed Publications +-------------------------- + +**2025** + +- Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` + +**2024** + +- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` + +**2022** + +- Kühn MJ, Abele D, Binder S, Rack K, Klitz M, et al. (2022). *Regional opening strategies with commuter testing and containment of new SARS-CoV-2 variants in Germany*. *BMC Infectious Diseases* 22(1): 333. `https://doi.org/10.1186/s12879-022-07302-9` +- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` + +**2021** + +- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` From 08af962b8525ab8c36753b51c20df99e7c00ccf7 Mon Sep 17 00:00:00 2001 From: HenrZu <69154294+HenrZu@users.noreply.github.com> Date: Mon, 17 Mar 2025 16:34:37 +0100 Subject: [PATCH 17/62] first draft mobility doc --- docs/source/c++/mobility.rst | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/docs/source/c++/mobility.rst b/docs/source/c++/mobility.rst index 2609f471dd..9fc7b1a230 100644 --- a/docs/source/c++/mobility.rst +++ b/docs/source/c++/mobility.rst @@ -1,2 +1,35 @@ Mobility -======== \ No newline at end of file +======== + +This directory contains a module to loosely couple multiple simulation instances and model the mobility between them. Each instance can represent a different geographical region. The regions are stored as nodes in a graph, with edges between them representing the mobility between the regions. Currently, only compartment models are supported as nodes, but support for other models will be extended in the future. + +Simulation Process +------------------ + +At each time step, the simulation executes the following two phases: + +1. **Advance the Simulation:** + - Each node (region) progresses independently according to its model. + +2. **Exchange of Population:** + - People are exchanged between nodes along the edges. + - The number of exchanged individuals is determined by coefficients. + - The coefficient :math:`a_i` of edge :math:`e_{xy}` represents the percentage of people in compartment :math:`i` moving from node :math:`x` to node :math:`y`. + - Coefficients may include dampings that vary over time, similar to contact matrices in compartment models. + - During the next time step, the exchanged population will stay at their destination and influence the simulation's evolution. Afterward, individuals return to their original node. + - The total number of people returning matches the number that left, but the compartments are adjusted to reflect changes due to the destination's epidemiological situation. For instance, some susceptible individuals may become exposed and will return in a different compartment. + +Graph-Based Mobility Model +-------------------------- + +To utilize the novel model, assume :math:`n` different geographic units (denoted as *regions*) are given. We integrate our novel mobility model extension into a simple ODE model with the graph approach proposed in Kühn et al. (2021). + +- Each region is represented by a node in the graph. +- The (multi-)edge :math:`\mathcal{E}_{ij}` between nodes :math:`\mathcal{N}_i` and :math:`\mathcal{N}_j` represents the (outgoing) mobility, with mobility-based exchange occurring twice a day (round trip). +- Each combination of sociodemographic group :math:`g_l`, where :math:`l = 1, \ldots, G`, and infection state :math:`z_l`, where :math:`l = 1, \ldots, Z`, is assigned a number of travelers. Therefore, the multi-edge consists of :math:`G \times Z` single edges. +- Return trips are mapped on the same edge, with the vector of weights on :math:`\mathcal{E}_{ij}` representing the number of outgoing travelers. + +For more information, we refer to: + +- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` +- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` From 742955dfa473732aad39eec27b47f843a38a079a Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 16:35:51 +0100 Subject: [PATCH 18/62] FIX: Fixed links to papers --- docs/source/references.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/source/references.rst b/docs/source/references.rst index e614d9fed4..e699e18b73 100644 --- a/docs/source/references.rst +++ b/docs/source/references.rst @@ -4,11 +4,11 @@ References Recently Submitted Publications -------------------------------------- -- Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` -- Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` -- Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` -- Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` -- Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` +- Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `arXiv:2502.14428 `_ +- Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `arXiv:2411.06500 `_ +- Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `arXiv:2408.12228 `_ +- Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `arXiv:2410.08050 `_ +- Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `DOI:10.48550/arXiv.2412.09140 `_ Peer-Reviewed Publications @@ -16,17 +16,17 @@ Peer-Reviewed Publications **2025** -- Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` +- Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `DOI:10.1016/j.idm.2024.12.015 `_ **2024** -- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` +- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `DOI:10.1371/journal.pcbi.1012630 `_ **2022** -- Kühn MJ, Abele D, Binder S, Rack K, Klitz M, et al. (2022). *Regional opening strategies with commuter testing and containment of new SARS-CoV-2 variants in Germany*. *BMC Infectious Diseases* 22(1): 333. `https://doi.org/10.1186/s12879-022-07302-9` -- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `https://doi.org/10.1371/journal.pcbi.1010054` +- Kühn MJ, Abele D, Binder S, Rack K, Klitz M, et al. (2022). *Regional opening strategies with commuter testing and containment of new SARS-CoV-2 variants in Germany*. *BMC Infectious Diseases* 22(1): 333. `DOI:10.1186/s12879-022-07302-9 `_ +- Koslow W, Kühn MJ, Binder S, Klitz M, Abele D, et al. (2022). *Appropriate relaxation of non-pharmaceutical interventions minimizes the risk of a resurgence in SARS-CoV-2 infections in spite of the Delta variant*. *PLOS Computational Biology* 18(5): e1010054. `DOI:10.1371/journal.pcbi.1010054 `_ **2021** -- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` +- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `DOI:10.1016/j.mbs.2021.108648 `_ From b4d15586ecf04e50376e79247fc45fefb6755ab8 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 16:40:39 +0100 Subject: [PATCH 19/62] FIX: Fix links to references in index.rst --- docs/source/index.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 4d57558c8f..0a557a9510 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -19,17 +19,17 @@ MEmilio implements various models for infectious disease dynamics, ranging from If you use MEmilio, please cite our work -- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `https://github.com/SciCompMod/memilio` and `https://elib.dlr.de/209739/`. +- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `GitHub Repository `_ and `DLR eLib `_. and, in particular, for -- **Ordinary differential equation-based (ODE) and Graph-ODE models**: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` -- **Integro-differential equation-based (IDE) models**: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `https://arxiv.org/abs/2408.12228` -- **Agent-based models (ABMs)**: Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `https://arxiv.org/abs/2410.08050` -- **Hybrid agent-metapopulation-based models**: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `https://doi.org/10.1016/j.idm.2024.12.015` -- **Graph Neural Networks**: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024). *Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `https://arxiv.org/abs/2411.06500` -- **ODE-based models with Linear Chain Trick**: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `https://doi.org/10.48550/arXiv.2412.09140` -- **Behavior-based ODE models**: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `https://arxiv.org/abs/2502.14428` +- **Ordinary differential equation-based (ODE) and Graph-ODE models**: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `DOI:10.1371/journal.pcbi.1012630 `_ +- **Integro-differential equation-based (IDE) models**: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `arXiv:2408.12228 `_ +- **Agent-based models (ABMs)**: Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `arXiv:2410.08050 `_ +- **Hybrid agent-metapopulation-based models**: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `DOI:10.1016/j.idm.2024.12.015 `_ +- **Graph Neural Networks**: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024).*Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `arXiv:2411.06500 `_ +- **ODE-based models with Linear Chain Trick**: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `DOI:10.48550/arXiv.2412.09140 `_ +- **Behavior-based ODE models**: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `arXiv:2502.14428 `_ Getting Started From d70a8a0546de4684b972b0302f124fa923cd95a8 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 17:11:31 +0100 Subject: [PATCH 20/62] CHG: Restructured index and added subfiles --- docs/source/citation.rst | 16 ++++++++++++ docs/source/development.rst | 6 +++++ docs/source/getting_started.rst | 27 +++++++++++++++++--- docs/source/index.rst | 45 +++------------------------------ 4 files changed, 50 insertions(+), 44 deletions(-) create mode 100644 docs/source/citation.rst create mode 100644 docs/source/development.rst diff --git a/docs/source/citation.rst b/docs/source/citation.rst new file mode 100644 index 0000000000..4f23d0c499 --- /dev/null +++ b/docs/source/citation.rst @@ -0,0 +1,16 @@ +Citing MEmilio +=============== + +If you use MEmilio, please cite our work + +- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `https://github.com/SciCompMod/memilio`_ and `https://elib.dlr.de/209739/`_. + +and, in particular, for + +- **Ordinary differential equation-based (ODE) and Graph-ODE models**: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `DOI:10.1371/journal.pcbi.1012630 `_ +- **Integro-differential equation-based (IDE) models**: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `arXiv:2408.12228 `_ +- **Agent-based models (ABMs)**: Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `arXiv:2410.08050 `_ +- **Hybrid agent-metapopulation-based models**: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `DOI:10.1016/j.idm.2024.12.015 `_ +- **Graph Neural Networks**: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024).*Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `arXiv:2411.06500 `_ +- **ODE-based models with Linear Chain Trick**: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `DOI:10.48550/arXiv.2412.09140 `_ +- **Behavior-based ODE models**: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `arXiv:2502.14428 `_ \ No newline at end of file diff --git a/docs/source/development.rst b/docs/source/development.rst new file mode 100644 index 0000000000..2425e97f1f --- /dev/null +++ b/docs/source/development.rst @@ -0,0 +1,6 @@ +Development +=========== + +- `Git workflow and change process `_ +- `Coding Guidelines `_ + diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 739d01e537..5e30328cf5 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -1,10 +1,31 @@ +Getting Started +=============== + +MEmilio supports various model types including equation-based, agent-based, and hybrid graph-ODE-based models. Among the equation-based models, we provide ordinary differential equation (ODE), linear chain trick (LCT), integro-differential equation (IDE) based models. + +- The C++ backend powers the model and simulation components for optimal efficiency. +- Data acquisition, plotting, and machine-learned models are handled via Python. + +For more details on the C++ implementation, see the `cpp directory README `_. + +Some regularly used data for simulations of a pathogen's spread in Germany, like contact and inter-county mobility, can be found in the `data directory README `_. + +In `pycode`, different MEmilio Python packages are defined. Via our `memilio-simulation` package, you can run our C++ backend from Python; this package uses `pybind11` to bind our C++ model code. The `memilio-epidata` package provides tools to download and structure important data such as infection or mobility data. More about the Python packages can be found in the `Python README `_. + + + +.. note:: + + This project is under active development. + + Usage -===== +__________ .. _installation: Installation ------------- +~~~~~~~~~~~~~ To use MEmilio, first install it using ... @@ -13,7 +34,7 @@ To use MEmilio, first install it using ... c++ init C++ Tutorial ----------------- +~~~~~~~~~~~~~~~~~~~~ TBD diff --git a/docs/source/index.rst b/docs/source/index.rst index 0a557a9510..7bfa81cbd9 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -17,62 +17,25 @@ MEmilio implements various models for infectious disease dynamics, ranging from .. image:: https://github.com/user-attachments/assets/65af6012-106e-43c6-9e0e-c96a73aa7b1e :alt: Memilio_overview -If you use MEmilio, please cite our work +If you use MEmilio, please :doc:`cite our work`. -- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `GitHub Repository `_ and `DLR eLib `_. - -and, in particular, for - -- **Ordinary differential equation-based (ODE) and Graph-ODE models**: Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `DOI:10.1371/journal.pcbi.1012630 `_ -- **Integro-differential equation-based (IDE) models**: Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `arXiv:2408.12228 `_ -- **Agent-based models (ABMs)**: Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `arXiv:2410.08050 `_ -- **Hybrid agent-metapopulation-based models**: Bicker J, Schmieding R, Meyer-Hermann M, Kühn MJ. (2025). *Hybrid metapopulation agent-based epidemiological models for efficient insight on the individual scale: A contribution to green computing*. *Infectious Disease Modelling* 10(2): 571-590. `DOI:10.1016/j.idm.2024.12.015 `_ -- **Graph Neural Networks**: Schmidt A, Zunker H, Heinlein A, Kühn MJ. (2024).*Towards Graph Neural Network Surrogates Leveraging Mechanistic Expert Knowledge for Pandemic Response*. arXiv. `arXiv:2411.06500 `_ -- **ODE-based models with Linear Chain Trick**: Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `DOI:10.48550/arXiv.2412.09140 `_ -- **Behavior-based ODE models**: Zunker H, Dönges P, Lenz P, Contreras S, Kühn MJ. (2025). *Risk-mediated dynamic regulation of effective contacts de-synchronizes outbreaks in metapopulation epidemic models*. arXiv. `arXiv:2502.14428 `_ - - -Getting Started -=============== - -MEmilio supports various model types including equation-based, agent-based, and hybrid graph-ODE-based models. Among the equation-based models, we provide ordinary differential equation (ODE), linear chain trick (LCT), integro-differential equation (IDE) based models. - -- The C++ backend powers the model and simulation components for optimal efficiency. -- Data acquisition, plotting, and machine-learned models are handled via Python. - -For more details on the C++ implementation, see the `cpp directory README `_. - -Some regularly used data for simulations of a pathogen's spread in Germany, like contact and inter-county mobility, can be found in the `data directory README `_. - -In `pycode`, different MEmilio Python packages are defined. Via our `memilio-simulation` package, you can run our C++ backend from Python; this package uses `pybind11` to bind our C++ model code. The `memilio-epidata` package provides tools to download and structure important data such as infection or mobility data. More about the Python packages can be found in the `Python README `_. - - - -Development -=========== - -- `Git workflow and change process `_ -- `Coding Guidelines `_ - -**MEmilio** is a framework that .. - -Check out the :doc:`getting_started` section for further information, including -how to :hoverxref:`installation` the project. .. note:: This project is under active development. Contents --------- +========= .. toctree:: :maxdepth: 1 :caption: Getting Started getting_started + citation references faq + development .. toctree:: :maxdepth: 2 From 1e748cfa4b07f382b5aef26b827a45bba46d823c Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Mon, 17 Mar 2025 17:19:13 +0100 Subject: [PATCH 21/62] CHG: Added content to FAQ --- docs/source/faq.rst | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 9a2bc461d8..161203945c 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -1,2 +1,13 @@ FAQ -==== \ No newline at end of file +==== + + +I found a bug. What should I do? +-------------------------------- + +Please open an issue on our `GitHub `_ page. Please try to describe the bug as detailed as possible, including the steps to reproduce it. + +I solved a bug. What should I do? +--------------------------------- + +Please open a pull request on our `GitHub `_ page. If there is not yet a bug report, please open an issue first and reference it in your pull request. \ No newline at end of file From 7710a19b0ee8a190d9da92f77a7d418f563f68a6 Mon Sep 17 00:00:00 2001 From: jubicker Date: Tue, 18 Mar 2025 08:31:52 +0100 Subject: [PATCH 22/62] rst diffusive ABM --- docs/source/c++/diffusive_abm.rst | 42 +++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/docs/source/c++/diffusive_abm.rst b/docs/source/c++/diffusive_abm.rst index 7eda6eaf7a..09866a3eca 100644 --- a/docs/source/c++/diffusive_abm.rst +++ b/docs/source/c++/diffusive_abm.rst @@ -6,14 +6,14 @@ The features of an agent are its position and its infection state. The evolution :math:`\partial_t p(X,Z;t) = G p(X,Z;t) + L p(X,Z;t)` -with :math:`X` the vector of all agents' positions and :math:`Z` the vector of all agents' infection states. The operator :math:`G` defines the infection state adoptions and only acts on :math:`Z`, while :math:`L` defines movement, i.e. location changes, only acting on :math:`X`. Infection state adoptions are modeled with independent Poisson processes given by adoption rate functions. Adoption rates always depend on the source infection state. If an adoption event requires interaction of agents (e.g. disease transmission), the corresponding rate depends not only on the source infection states, but also on other infection state, the `influences`. An adoption rate that only depends on the source compartment, e.g. recovery or worsening of disease symptoms, is called `first-order` adoption rate and an adoption rate that has influences is called `second-order` adoption rate. Movement is modeled with independent diffusion processes. A temporal Gillespie algorithm (a direct method without rejection sampling) is used for simulation. Therefore, :math:`G` and :math:`L` are not implemented explicitly, instead their effects are sampled via the `move` and `adoption_rate` functions, respectively. +with :math:`X` the vector of all agents' positions and :math:`Z` the vector of all agents' infection states. The operator :math:`G` defines the infection state adoptions and only acts on :math:`Z`, while :math:`L` defines movement, i.e. location changes, only acting on :math:`X`. Infection state adoptions are modeled with independent Poisson processes given by adoption rate functions. Adoption rates always depend on the source infection state. If an adoption event requires interaction of agents (e.g. disease transmission), the corresponding rate depends not only on the source infection state, but also on other infection states, the `influences`. An adoption rate that only depends on the source infection state, e.g. recovery or worsening of disease symptoms, is called `first-order` adoption rate and an adoption rate that has influences is called `second-order` adoption rate. Movement is modeled with independent diffusion processes. A temporal Gillespie algorithm (a direct method without rejection sampling) is used for simulation. Therefore, :math:`G` and :math:`L` are not implemented explicitly, instead their effects are sampled via the `move` and `adoption_rate` functions, respectively. The Model class needs an Implementation class as template argument which provides the domain agents move and interact in. A quadwell potential given in the class QuadWellModel is implemented, but any other suitable potential can be used as implementation. Simulation ----------- -The simulation runs in discrete time steps. In every step the model is advanced until the next infection state adoption event. Then the corresponding agent's infection state is adopted and a new waiting time until the next adoption event is srawn. If the waiting time until the next adoption event is bigger than the remaining time in the time step, we advance the model until the end of the time step. +The simulation runs in discrete time steps. In every step the model is advanced until the next infection state adoption event. Then the corresponding agent's infection state is adopted and a new waiting time until the next adoption event is drawn. If the waiting time until the next adoption event is bigger than the remaining time in the time step, we advance the model until the end of the time step. For a detailed description and application of the model, see: @@ -23,7 +23,7 @@ How to: Set up and run a simulation of the diffusive ABM --------------------------------------------------------- The infection states used need to be defined in an enum before initializing the model and are passed as template argument to the model. -Using the infection states Susceptible (S), Exposed (E), Carrier (C), Infected (I), Recovered (R) and Dead (D) this ca be done as follows: +Using the infection states Susceptible (S), Exposed (E), Carrier (C), Infected (I), Recovered (R) and Dead (D) this can be done as follows: .. code-block:: cpp @@ -48,11 +48,11 @@ To initialze the model using the quad well potential, the following inputs need - the interaction radius of agents, - the noise term for the diffusion process. -Agents have two attributes: A position on the domain and an infection states. The example below initializes 100 agents with an agent's position sampled uniformly from :math:`\left[-2,2\right]\times\left[-2,2\right]` and its infection state sampled from a discrete distribution with probabilities given by :math:`98\%` (S), :math:`1\%` (E), :math:`0.5\%` (C), :math:`0.5\%` (I), :math:`0\%` (R), :math:`0\%` (D). +Agents have two attributes: A position on the domain and an infection state. The example below initializes 100 agents with an agent's position sampled uniformly from :math:`\left[-2,2\right]\times\left[-2,2\right]` and its infection state sampled from a discrete distribution with probabilities given by :math:`98\%` (S), :math:`1\%` (E), :math:`0.5\%` (C), :math:`0.5\%` (I), :math:`0\%` (R), :math:`0\%` (D). .. code-block:: cpp - std::vector agents(1000); + std::vector agents(100); //Random variables for initialization of agents' position and infection state auto& pos_rng = mio::UniformDistribution::get_instance(); @@ -67,7 +67,7 @@ Agents have two attributes: A position on the domain and an infection states. Th a.status = static_cast(sta_rng(mio::thread_local_rng(), pop_dist)); } -As already mentioned above, infection state adoption rates can only depend on the source infection state (first-order) or they can be influenced by other infection states (second-order). An influence consists of an infection state and the corresponding multiplicative factor. Additionally, adoption rates are region-dependent with a region corresponding to the potential wells for the implemented quad well potential. That means the quad well potential has four regions given by :math:`\Omega_0=\left(-\infty,0\right)\times\left(0,\infty\right), \Omega_1=\left(0,\infty\right)\times\left(0,\infty\right), \Omega_2=\left(-\infty,0\right)\times\left(-\infty,0\right)` and :math:`\Omega_3=\left(0,\infty\right)\times\left(-\infty,0\right)`. +As already mentioned above, infection state adoption rates can only depend on the source infection state (first-order) or they can be influenced by other infection states (second-order). An influence consists of an infection state and the corresponding multiplicative factor. Additionally, adoption rates are region-dependent with the regions corresponding to the potential wells for the implemented quad well potential. That means the quad well potential has four regions given by :math:`\Omega_0=\left(-\infty,0\right)\times\left(0,\infty\right), \Omega_1=\left(0,\infty\right)\times\left(0,\infty\right), \Omega_2=\left(-\infty,0\right)\times\left(-\infty,0\right)` and :math:`\Omega_3=\left(0,\infty\right)\times\left(-\infty,0\right)`. In the example below, regions 0-2 have the same adoption rates while region 3 has a two times higher transmission rate (adoption from S to E): @@ -84,12 +84,12 @@ In the example below, regions 0-2 have the same adoption rates while region 3 ha adoption_rates.push_back({InfectionState::I, InfectionState::D, mio::regions::Region(region), 0.01 / 5., {}}); } - //Second-order adoption rate for region 0-2 + //Second-order adoption rate for regions 0-2 for (size_t region = 0; region < 3; ++region) { adoption_rates.push_back({InfectionState::S, InfectionState::E, mio::regions::Region(region), 0.1, {{InfectionState::C, 1}, {InfectionState::I, 0.5}}}); } - //Second order adoption rate for region 3 + //Second-order adoption rate for region 3 adoption_rates.push_back({InfectionState::S, InfectionState::E, mio::regions::Region(3), 0.2, {{InfectionState::C, 1}, {InfectionState::I, 0.5}}}); Choosing an interaction radius of 0.5 and a noise term of 0.4, the model is initialized by @@ -101,13 +101,13 @@ Choosing an interaction radius of 0.5 and a noise term of 0.4, the model is init Model model(agents, adoption_rates, interaction_radius, noise); -There is the option to pass a vector of non-moving state to the model. Defining that agents having infection state D do not move, the model initialization would be +There is the option to pass a vector of non-moving infection states to the model. Defining that agents in infection state D do not move, the model initialization would be .. code-block:: cpp Model model(agents, adoption_rates, interaction_radius, noise, {InfectionState::D}); -A to simulate the model from `t0` to `tmax` with given step size `dt`, a Simulation has to be created and the advanced until `tmax`, which is done as follows: +To simulate the model from `t0` to `tmax` with given step size `dt`, a Simulation has to be created and advanced until `tmax`, which is done as follows: .. code-block:: cpp @@ -120,3 +120,25 @@ A to simulate the model from `t0` to `tmax` with given step size `dt`, a Simulat //Advance the simulation until tmax sim.advance(tmax); + +The result vector containing all agents can be accessed via + +.. code-block:: cpp + + sim.get_model().populations + +Additionally, the agents are automatically aggregated by region and infection state in a `mio::TimeSeries` object which can be accessed and printed as follows: + +.. code-block:: cpp + + //Result object has size num_time_points x (num_infection_states * num_regions) + auto result = sim.get_result(); + + //Print result object to console. Infection state "Xi" with i=0,...,3 is the number of agents having infection state X in region i + result.print_table({"S0", "E0", "C0", "I0", "R0", "D0", "S1", "E1", "C1", "I1", "R1", "D1", "S2", "E2", "C2", "I2", "R2", "D2", "S3", "E3", "C3", "I3", "R3", "D3"}) + +If one wants to interpolate the aggregated results to a TimeSeries containing only full days, this can be done by + +.. code-block:: cpp + + auto interpolated_results = mio::interpolate_simulation_result(sim.get_result()); From a135d41a35e37a632586b465ef8a769fce6d3799 Mon Sep 17 00:00:00 2001 From: jubicker Date: Tue, 18 Mar 2025 08:43:17 +0100 Subject: [PATCH 23/62] Structure mobility metapop --- docs/source/c++/metapop.rst | 2 ++ docs/source/c++/mobility_metapop.rst | 10 ++++++++++ docs/source/c++/model_usage.rst | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 docs/source/c++/metapop.rst create mode 100644 docs/source/c++/mobility_metapop.rst diff --git a/docs/source/c++/metapop.rst b/docs/source/c++/metapop.rst new file mode 100644 index 0000000000..f4499fcc0e --- /dev/null +++ b/docs/source/c++/metapop.rst @@ -0,0 +1,2 @@ +Metapopulation Models +===================== diff --git a/docs/source/c++/mobility_metapop.rst b/docs/source/c++/mobility_metapop.rst new file mode 100644 index 0000000000..7effaf894b --- /dev/null +++ b/docs/source/c++/mobility_metapop.rst @@ -0,0 +1,10 @@ +Mobility and Metapopulation Models +================================== + + + +.. toctree:: + :maxdepth: 1 + + mobility + metapopulation diff --git a/docs/source/c++/model_usage.rst b/docs/source/c++/model_usage.rst index 8fa23d7778..efecba3004 100644 --- a/docs/source/c++/model_usage.rst +++ b/docs/source/c++/model_usage.rst @@ -8,6 +8,6 @@ Model Usage aggregated_models individual_models - mobility + mobility_metapop io - visualization \ No newline at end of file + visualization From 36f3b12f543cd0c260a217c1459eff1a61b2cc0d Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:55:25 +0100 Subject: [PATCH 24/62] CHG: Fix Links --- docs/source/citation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/citation.rst b/docs/source/citation.rst index 4f23d0c499..fcaa74e983 100644 --- a/docs/source/citation.rst +++ b/docs/source/citation.rst @@ -3,7 +3,7 @@ Citing MEmilio If you use MEmilio, please cite our work -- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `https://github.com/SciCompMod/memilio`_ and `https://elib.dlr.de/209739/`_. +- Kühn, Martin Joachim et al. (2024). *MEmilio - a High Performance Modular Epidemics Simulation Software (2022)*. Available at `https://github.com/SciCompMod/memilio `_ and `https://elib.dlr.de/209739/ `_. and, in particular, for From 6b774351de041ad5b29a502642a9510caead70f3 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Tue, 18 Mar 2025 10:56:41 +0100 Subject: [PATCH 25/62] CHG: Remove imported members --- docs/source/pythonapi.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/pythonapi.rst b/docs/source/pythonapi.rst index d3672dab48..df078081c7 100644 --- a/docs/source/pythonapi.rst +++ b/docs/source/pythonapi.rst @@ -7,7 +7,6 @@ Python API .. autosummary:: :toctree: generated :recursive: - :imported-members: :caption: Pyhton Module API memilio.generation From 83cd5c6cc6005d5756dad1eee33d4c14547ca9e1 Mon Sep 17 00:00:00 2001 From: jubicker Date: Tue, 18 Mar 2025 11:02:04 +0100 Subject: [PATCH 26/62] rst stochastic metapop model --- docs/source/c++/metapop.rst | 126 ++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/docs/source/c++/metapop.rst b/docs/source/c++/metapop.rst index f4499fcc0e..075af7a073 100644 --- a/docs/source/c++/metapop.rst +++ b/docs/source/c++/metapop.rst @@ -1,2 +1,128 @@ Metapopulation Models ===================== + +Stochastic Metapopulation Model +------------------------------- + +The stochastic metapopulation model uses a Markov process to simulate disease dynamics. Similar to the `Diffusive Agent-based Model` the Markov process is given by location and infection state changes. However, in contrast to the diffusive ABM, location changes are not given by agent-dependent diffusion processes, but by stochastic jumps between regions with the requirement that the domain is split into disjoint regions. Hence, there is no further spatial resolution within one region and locations or positions are only given by the region index. The evolution of the system state is determined by the following master equation + +:math:`\partial_t p(X,Z;t) = G p(X,Z;t) + L p(X,Z;t)`. + +The operator :math:`G` defines the infection state adoptions and only acts on :math:`Z` the vector containing all subpopulations stratified by infection state. :math:`L` defines location changes, only acting on :math:`X` the vector containing all subpopulations stratified by region. Infection state adoptions are modeled as stochastic jumps with independent Poisson processes given by adoption rate functions. Adoption rates always depend on the source infection state. If an adoption event requires interaction of agents (e.g. disease transmission), the corresponding rate depends not only on the source infection state, but also on other infection states, the `influences`. An adoption rate that only depends on the source infection state, e.g. recovery or worsening of disease symptoms, is called `first-order` adoption rate and an adoption rate that has influences is called `second-order` adoption rate. Similar to the infection state dynamics, spatial transitions between regions are also modeled as stochastic jumps with independent Poisson processes given by transition rate functions. Gillespie's direct methode (stochastic simulation algorithm) is used for simulation. + +How to: Set up and run a simulation of the stochastic metapopulation model +-------------------------------------------------------------------------- + +The infection states used need to be defined in an enum before initializing the model and are passed - together with the number of regions - as template arguments to the model. +Using four regions and the infection states Susceptible (S), Exposed (E), Carrier (C), Infected (I), Recovered (R) and Dead (D) this can be done as follows: + +.. code-block:: cpp + + enum class InfectionState + { + S, + E, + C, + I, + R, + D, + Count + + }; + + const size_t num_regions = 4; + + using Model = mio::smm::Model; + Model model; + +To initialize the model, the following parameters have to be set: + +- the initial subpopulations i.e. the number of agents per infection state for every region, +- the adoption rates for infection state adoptions, +- the spatial transition rates for location (region) changes. + +The example below initializes a population of size 1000 that is equally distributed to the four regions. In every region, :math:`0.1\%` of the population is Exposed, :math:`0.01\%` is Carrier, :math:`0.01\%` is Infected and the rest of the population is Susceptible. There are no Recovered or Dead agents in the beginning. + +.. code-block:: cpp + + double pop = 1000, numE = 0.001 * pop, numC = 0.0001 * pop, numI = 0.0001 * pop; + + //Population is distributed equally to the four regions + for (size_t r = 0; r < num_regions; ++r) { + model.populations[{mio::regions::Region(r), InfectionState::S}] = (pop - numE - numC - numI - numR - numD) / num_regions; + model.populations[{mio::regions::Region(r), InfectionState::E}] = numE / num_regions; + model.populations[{mio::regions::Region(r), InfectionState::C}] = numC / num_regions; + model.populations[{mio::regions::Region(r), InfectionState::I}] = numI / num_regions; + model.populations[{mio::regions::Region(r), InfectionState::R}] = 0; + model.populations[{mio::regions::Region(r), InfectionState::D}] = 0; + } + +As already mentioned above, infection state adoption rates can only depend on the source infection state (first-order) or they can be influenced by other infection states (second-order). An influence consists of an infection state and the corresponding multiplicative factor. Additionally, adoption rates are region-dependent. In the example below, all regions have the same adoption rates. + +.. code-block:: cpp + + //Set infection state adoption rates + std::vector> adoption_rates; + for (size_t r = 0; r < num_regions; ++r) { + //Second-order adoption rate + adoption_rates.push_back({InfectionState::S, InfectionState::E, mio::regions::Region(r), 0.1, {{InfectionState::C, 1}, {InfectionState::I, 0.5}}}); + //First-order adoption rate + adoption_rates.push_back({InfectionState::E, InfectionState::C, mio::regions::Region(r), 1.0 / 5., {}}); + adoption_rates.push_back({InfectionState::C, InfectionState::R, mio::regions::Region(r), 0.2 / 3., {}}); + adoption_rates.push_back({InfectionState::C, InfectionState::I, mio::regions::Region(r), 0.8 / 3., {}}); + adoption_rates.push_back({InfectionState::I, InfectionState::R, mio::regions::Region(r), 0.99 / 5., {}}); + adoption_rates.push_back({InfectionState::I, InfectionState::D, mio::regions::Region(r), 0.01 / 5., {}}); + } + + model.parameters.get>() = adoption_rates; + +The spatial transition rates are dependent on infection state such that location changes for specific infection states can be prevented. Below, symmetric spatial transition rates are set for every region: + +.. code-block:: cpp + + //Set spatial transition rates + std::vector> transition_rates; + //Agents in infection state D do not transition + for (size_t s = 0; s < static_cast(InfectionState::D); ++s) { + for (size_t i = 0; i < num_regions; ++i) { + for (size_t j = 0; j < num_regions; ++j) + if (i != j) { + transition_rates.push_back( + {InfectionState(s), mio::regions::Region(i), mio::regions::Region(j), 0.01}); + transition_rates.push_back( + {InfectionState(s), mio::regions::Region(j), mio::regions::Region(i), 0.01}); + } + } + } + + model.parameters.get>() = transition_rates; + +To simulate the model from `t0` to `tmax` with given step size `dt`, a Simulation has to be created. The step size is only used to regularly save the system state during the simulation. Advancing the simulation until `tmax` is done as follows: + +.. code-block:: cpp + + double t0 = 0.0; + double dt = 0.1; + double tmax = 30.; + + //Pass the model, t0 and dt to the Simulation + auto sim = mio::smm::Simulation(model, t0, dt); + + //Advance the simulation until tmax + sim.advance(tmax); + +Subpopulations stratified by region and infection state are saved in a `mio::TimeSeries` object which can be accessed and printed as follows: + +.. code-block:: cpp + + //Result object has size num_time_points x (num_infection_states * num_regions) + auto result = sim.get_result(); + + //Print result object to console. Infection state "Xi" with i=0,...,3 is the number of agents having infection state X in region i + result.print_table({"S0", "E0", "C0", "I0", "R0", "D0", "S1", "E1", "C1", "I1", "R1", "D1", "S2", "E2", "C2", "I2", "R2", "D2", "S3", "E3", "C3", "I3", "R3", "D3"}) + +If one wants to interpolate the aggregated results to a TimeSeries containing only full days, this can be done by + +.. code-block:: cpp + + auto interpolated_results = mio::interpolate_simulation_result(sim.get_result()); From 0d028ec3e757194bd7dc83339982f6d1b9180722 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Tue, 18 Mar 2025 11:07:10 +0100 Subject: [PATCH 27/62] FIX: Literature links repaired --- docs/source/c++/mobility.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/c++/mobility.rst b/docs/source/c++/mobility.rst index 9fc7b1a230..1decb237ec 100644 --- a/docs/source/c++/mobility.rst +++ b/docs/source/c++/mobility.rst @@ -31,5 +31,5 @@ To utilize the novel model, assume :math:`n` different geographic units (denoted For more information, we refer to: -- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630` -- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648` +- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630 `_ +- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648 `_ From 928b3750d94406bd395e75bab28507d0a358e56d Mon Sep 17 00:00:00 2001 From: HenrZu <69154294+HenrZu@users.noreply.github.com> Date: Tue, 18 Mar 2025 12:44:44 +0100 Subject: [PATCH 28/62] more detailed doc for mobility --- docs/source/c++/mobility.rst | 149 ++++++++++++++++++++++++++++++----- 1 file changed, 130 insertions(+), 19 deletions(-) diff --git a/docs/source/c++/mobility.rst b/docs/source/c++/mobility.rst index 1decb237ec..358316bec4 100644 --- a/docs/source/c++/mobility.rst +++ b/docs/source/c++/mobility.rst @@ -1,35 +1,146 @@ Mobility ======== -This directory contains a module to loosely couple multiple simulation instances and model the mobility between them. Each instance can represent a different geographical region. The regions are stored as nodes in a graph, with edges between them representing the mobility between the regions. Currently, only compartment models are supported as nodes, but support for other models will be extended in the future. +In order to extend the local models with spatial resolution, we provide a module to loosely couple multiple simulation instances and model the mobility between them. Each instance can represent a different geographical region. The regions are stored as nodes in a multi-edge graph as proposed in Kühn et al. (2021), with edges between them representing the mobility between the regions. +We assume that :math:`n` different geographic units (denoted as *regions*) are given. The mobility extension can contain a arbitrary number of regions. The number of edges is limited by the number of regions squared. +A pair of nodes is connected via multi edges, where each edge represents the mobility of a specific group of individuals. The number of edges between a pair of nodes is given as the product of the number of age groups and number of compartments in the (local) model. -Simulation Process + +Currently, only ODE models are supported as nodes; support for other models will be added soon. + +For further details, please refer to: + +- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. ``_ +- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. ``_ + +Simulation process ------------------ +The mobility can contain a different scale of complexity. One option is the "instant" mobility scheme, where we implement two daily exchanges of commuters that occur instantaneously, at the beginning of the day and after half a day. With this approach, +commuters can change their infection state during the half-day stay. Theres also another more "detailed" mobility scheme, where travel times and stay durations are considered; see Zunker et al. (2024) for more details. -At each time step, the simulation executes the following two phases: +Basicallly, the graph simulation consists of two phases: 1. **Advance the Simulation:** - - Each node (region) progresses independently according to its model. + + - Each node progresses independently according to its model. 2. **Exchange of Population:** - - People are exchanged between nodes along the edges. + + - Individuals are exchanged between nodes along the graph edges. - The number of exchanged individuals is determined by coefficients. - - The coefficient :math:`a_i` of edge :math:`e_{xy}` represents the percentage of people in compartment :math:`i` moving from node :math:`x` to node :math:`y`. - - Coefficients may include dampings that vary over time, similar to contact matrices in compartment models. - - During the next time step, the exchanged population will stay at their destination and influence the simulation's evolution. Afterward, individuals return to their original node. - - The total number of people returning matches the number that left, but the compartments are adjusted to reflect changes due to the destination's epidemiological situation. For instance, some susceptible individuals may become exposed and will return in a different compartment. + - Number of daily commuters may include time-dependent damping factors, similar to the dampings used in contact matrices. + - While located in another node, the individuals can change their infection state. Therefore, we need to estimate the infection state of the commuters at the time of the return. + +How to: Set up a graph and run a graph simulation +--------------------------------------------- + +The graph simulation couples multiple simulation instances representing different geographic regions via a graph-based approach. In this example, a compartment model based on ODEs (ODE-SECIR) is used for each region. The simulation proceeds by advancing each region independently and then exchanging portions of the population between regions along the graph edges. + +The following steps detail how to configure and execute a graph simulation: + +1. **Initialize the local compartment model:** + + First, set up the compartment model by initializing the populations and parameters. In this example, we use a single age group and start with 10,000 susceptible individuals. Additionally, the necessary epidemiological parameters (e.g. time periods, transmission probabilities) are set. + + .. code-block:: cpp + const size_t num_groups = 1; + mio::osecir::Model model(num_groups); + model.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}] = 10000; + model.parameters.set(0); + model.parameters.set>(0.2); + + model.parameters.get>() = 3.2; + model.parameters.get>() = 2.0; + model.parameters.get>() = 5.8; + model.parameters.get>() = 9.5; + model.parameters.get>() = 7.1; + + model.parameters.get>() = 0.1; + model.parameters.get>() = 0.7; + model.parameters.get>() = 0.09; + model.parameters.get>() = 0.25; + model.parameters.get>() = 0.45; + model.parameters.get>() = 35; + model.parameters.get>() = 0.2; + model.parameters.get>() = 0.25; + model.parameters.get>() = 0.3; + + mio::ContactMatrixGroup& contact_matrix = model.parameters.get>(); + contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 10)); + +2. **Create simulation groups and adjust contact patterns:** + + To represent different geographic regions, clone the base model into separate model groups. In this example, two model groups are created. The first group is modified by applying a contact damping to simulate contact restrictions. + + .. code-block:: cpp + + // Create two mostly identical groups + auto model_group1 = model; + auto model_group2 = model; + + // Apply contact restrictions to model_group1 + mio::ContactMatrixGroup& contact_matrix_m1 = + model_group1.parameters.get>(); + contact_matrix_m1[0].add_damping(0.7, mio::SimulationTime(15.)); + + // Initialize infection in group 1 + model_group1.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}] = 9990; + model_group1.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::Exposed}] = 100; + +3. **Define compartments to save from edges:** + + To extract the mobility results, define the compartments to save from the edges. In this example, the compartments for infected individuals with and without symptoms are saved for each region. + + .. code-block:: cpp + + // Get indices of INS and ISy compartments. + std::vector> indices_save_edges(2); + for (auto& vec : indices_save_edges) { + vec.reserve(2 * num_groups); + } + for (auto i = mio::AgeGroup(0); i < mio::AgeGroup(num_groups); ++i) { + indices_save_edges[0].emplace_back( + model.populations.get_flat_index({i, mio::osecir::InfectionState::InfectedNoSymptoms})); + indices_save_edges[0].emplace_back( + model.populations.get_flat_index({i, mio::osecir::InfectionState::InfectedNoSymptomsConfirmed})); + indices_save_edges[1].emplace_back( + model.populations.get_flat_index({i, mio::osecir::InfectionState::InfectedSymptoms})); + indices_save_edges[1].emplace_back( + model.populations.get_flat_index({i, mio::osecir::InfectionState::InfectedSymptomsConfirmed})); + } + +4. **Construct the Mobility Graph:** + + Build a graph where each node represents a simulation and each edge represents mobility between a pair of nodes. Mobility coefficients (here, 0.1 for all compartments) determine the fraction of the population exchanged between nodes. + + .. code-block:: cpp + const auto t0 = 0.; + mio::Graph>, mio::MobilityEdge> g; + g.add_node(1001, model_group1, t0); + g.add_node(1002, model_group2, t0); + g.add_edge(0, 1, Eigen::VectorXd::Constant((size_t)mio::osecir::InfectionState::Count, 0.1), indices_save_edges); + g.add_edge(1, 0, Eigen::VectorXd::Constant((size_t)mio::osecir::InfectionState::Count, 0.1), indices_save_edges); + +5. **Initialize and Advance the Mobility Simulation:** + + With the graph constructed, initialize the simulation with the starting time and time step. Then, advance the simulation until the final time :math:`t_{max}`. -Graph-Based Mobility Model --------------------------- + .. code-block:: cpp + + const auto tmax = 30.; + const auto dt = 0.5; // time step or Mobility (daily mobility occurs every second step) + auto sim = mio::make_mobility_sim(t0, dt, std::move(g)); + sim.advance(tmax); -To utilize the novel model, assume :math:`n` different geographic units (denoted as *regions*) are given. We integrate our novel mobility model extension into a simple ODE model with the graph approach proposed in Kühn et al. (2021). +6. **Access and Display Mobility Results:** -- Each region is represented by a node in the graph. -- The (multi-)edge :math:`\mathcal{E}_{ij}` between nodes :math:`\mathcal{N}_i` and :math:`\mathcal{N}_j` represents the (outgoing) mobility, with mobility-based exchange occurring twice a day (round trip). -- Each combination of sociodemographic group :math:`g_l`, where :math:`l = 1, \ldots, G`, and infection state :math:`z_l`, where :math:`l = 1, \ldots, Z`, is assigned a number of travelers. Therefore, the multi-edge consists of :math:`G \times Z` single edges. -- Return trips are mapped on the same edge, with the vector of weights on :math:`\mathcal{E}_{ij}` representing the number of outgoing travelers. + After the simulation, the mobility results can be extracted from a specific edge. In this example, the results for the edge from node 1 to node 0 are printed. -For more information, we refer to: + .. code-block:: cpp -- Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `https://doi.org/10.1371/journal.pcbi.1012630 `_ -- Kühn MJ, Abele D, Mitra T, Koslow W, Abedi M, et al. (2021). *Assessment of effective mitigation and prediction of the spread of SARS-CoV-2 in Germany using demographic information and spatial resolution*. *Mathematical Biosciences* 108648. `https://doi.org/10.1016/j.mbs.2021.108648 `_ + auto& edge_1_0 = sim.get_graph().edges()[1]; + auto& results = edge_1_0.property.get_mobility_results(); + results.print_table({"Commuter INS", "Commuter ISy", "Commuter Total"}); + + return 0; + } From d661d34d348467243eb83948aa46b4452df1ba35 Mon Sep 17 00:00:00 2001 From: jubicker Date: Tue, 18 Mar 2025 12:58:55 +0100 Subject: [PATCH 29/62] docu --- docs/source/c++/diffusive_abm.rst | 2 +- docs/source/c++/metapop.rst | 2 +- docs/source/c++/mobility_metapop.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/c++/diffusive_abm.rst b/docs/source/c++/diffusive_abm.rst index 09866a3eca..44d48bb254 100644 --- a/docs/source/c++/diffusive_abm.rst +++ b/docs/source/c++/diffusive_abm.rst @@ -127,7 +127,7 @@ The result vector containing all agents can be accessed via sim.get_model().populations -Additionally, the agents are automatically aggregated by region and infection state in a `mio::TimeSeries` object which can be accessed and printed as follows: +Additionally, the agents are automatically aggregated by region and infection state in a ``mio::TimeSeries`` object which can be accessed and printed as follows: .. code-block:: cpp diff --git a/docs/source/c++/metapop.rst b/docs/source/c++/metapop.rst index 075af7a073..ee56940df4 100644 --- a/docs/source/c++/metapop.rst +++ b/docs/source/c++/metapop.rst @@ -111,7 +111,7 @@ To simulate the model from `t0` to `tmax` with given step size `dt`, a Simulatio //Advance the simulation until tmax sim.advance(tmax); -Subpopulations stratified by region and infection state are saved in a `mio::TimeSeries` object which can be accessed and printed as follows: +Subpopulations stratified by region and infection state are saved in a ``mio::TimeSeries`` object which can be accessed and printed as follows: .. code-block:: cpp diff --git a/docs/source/c++/mobility_metapop.rst b/docs/source/c++/mobility_metapop.rst index 7effaf894b..1d7d0b03b0 100644 --- a/docs/source/c++/mobility_metapop.rst +++ b/docs/source/c++/mobility_metapop.rst @@ -7,4 +7,4 @@ Mobility and Metapopulation Models :maxdepth: 1 mobility - metapopulation + metapop From b0894e748fce3747ab253772555a4be2890cf1ee Mon Sep 17 00:00:00 2001 From: HenrZu <69154294+HenrZu@users.noreply.github.com> Date: Tue, 18 Mar 2025 13:00:28 +0100 Subject: [PATCH 30/62] add more references --- docs/source/references.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/references.rst b/docs/source/references.rst index e699e18b73..aeef0f97c7 100644 --- a/docs/source/references.rst +++ b/docs/source/references.rst @@ -9,6 +9,7 @@ Recently Submitted Publications - Wendler AC, Plötzke L, Tritzschak H, Kühn MJ. (2024). *A nonstandard numerical scheme for a novel SECIR integro differential equation-based model with nonexponentially distributed stay times*. Submitted for publication. `arXiv:2408.12228 `_ - Kerkmann D, Korf S, Nguyen K, Abele D, Schengen A, et al. (2024). *Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread*. arXiv. `arXiv:2410.08050 `_ - Plötzke L, Wendler A, Schmieding R, Kühn MJ. (2024). *Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions*. Submitted for publication. `DOI:10.48550/arXiv.2412.09140 `_ +- Schmid N, Bicker J, Hofmann AF, Wallrafen-Sam K, Kerkmann D, et al. (2024). *Integrative Modeling of the Spread of Serious Infectious Diseases and Corresponding Wastewater Dynamics*. medRxiv. `DOI:10.1101/2024.11.10.24317057 `_ Peer-Reviewed Publications @@ -21,6 +22,7 @@ Peer-Reviewed Publications **2024** - Zunker H, Schmieding R, Kerkmann D, Schengen A, Diexer S, et al. (2024). *Novel travel time aware metapopulation models and multi-layer waning immunity for late-phase epidemic and endemic scenarios*. *PLOS Computational Biology* 20(12): e1012630. `DOI:10.1371/journal.pcbi.1012630 `_ +- Memon S, Jadebeck JF, Osthege M, Wendler A, Kerkmann D, et al. (2024). *Automated Processing of Pipelines Managing Now- and Forecasting of Infectious Diseases*. In: 2024 47th MIPRO ICT and Electronics Convention (MIPRO), Opatija, Croatia. IEEE. pp. 1157-1162. `DOI:10.1109/MIPRO60963.2024.10569336 `_ **2022** From 3a92f7c116ca68e934d825655877e9c8e5d27c4d Mon Sep 17 00:00:00 2001 From: HenrZu <69154294+HenrZu@users.noreply.github.com> Date: Tue, 18 Mar 2025 13:01:24 +0100 Subject: [PATCH 31/62] more prints get_flows --- cpp/models/sde_seirvv/model.h | 89 +++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 14 deletions(-) diff --git a/cpp/models/sde_seirvv/model.h b/cpp/models/sde_seirvv/model.h index bf4b449702..c06ff941a8 100644 --- a/cpp/models/sde_seirvv/model.h +++ b/cpp/models/sde_seirvv/model.h @@ -59,51 +59,73 @@ class Model : public FlowModel> pop, Eigen::Ref> y, ScalarType t, Eigen::Ref> flows) const { + std::cout << "calc flows" << std::endl; auto& params = this->parameters; - params.get().get_matrix_at(t)(0, 0); - ScalarType coeffStoIV1 = params.get().get_matrix_at(t)(0, 0) * - params.get() / populations.get_total(); - ScalarType coeffStoIV2 = params.get().get_matrix_at(t)(0, 0) * - params.get() / populations.get_total(); - // Normal distributed values for the stochastic part of the flows, variables are encoded - // in the following way: x_y is the stochastic part for the flow from x to y. Variant - // specific compartments also get an addendum v1 or v2 denoting the relevant variant. + // Hole den Kontaktmuster-Wert aus der Matrix bei Zeit t + ScalarType cp_val = params.get().get_matrix_at(t)(0, 0); + std::cout << "ContactPatterns value: " << cp_val << std::endl; + // Berechne Koeffizienten für die Transmission + ScalarType coeffStoIV1 = cp_val * params.get() / populations.get_total(); + std::cout << "coeffStoIV1: " << coeffStoIV1 << std::endl; + + ScalarType coeffStoIV2 = cp_val * params.get() / populations.get_total(); + std::cout << "coeffStoIV2: " << coeffStoIV2 << std::endl; + + // Normalverteilte Zufallszahlen für den stochastischen Anteil der Flows ScalarType s_ev1 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "s_ev1: " << s_ev1 << std::endl; + ScalarType s_ev2 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "s_ev2: " << s_ev2 << std::endl; + ScalarType ev1_iv1 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "ev1_iv1: " << ev1_iv1 << std::endl; + ScalarType ev2_iv2 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "ev2_iv2: " << ev2_iv2 << std::endl; + ScalarType iv1_rv1 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "iv1_rv1: " << iv1_rv1 << std::endl; + ScalarType iv2_rv2 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "iv2_rv2: " << iv2_rv2 << std::endl; + ScalarType rv1_ev1v2 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "rv1_ev1v2: " << rv1_ev1v2 << std::endl; + ScalarType ev1v2_iv1v2 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "ev1v2_iv1v2: " << ev1v2_iv1v2 << std::endl; + ScalarType iv1v2_rv1v2 = mio::DistributionAdapter>::get_instance()(rng, 0.0, 1.0); + std::cout << "iv1v2_rv1v2: " << iv1v2_rv1v2 << std::endl; - // Assuming that no person can change its InfectionState twice in a single time step, - // take the minimum of the calculated flow and the source compartment, to ensure that - // no compartment attains negative values. + // Berechne Optimierungsgrößen + ScalarType inv_step_size = 1.0 / step_size; + std::cout << "inv_step_size: " << inv_step_size << std::endl; - // Calculate inv_step_size and inv_sqrt_step_size for optimization. - ScalarType inv_step_size = 1.0 / step_size; ScalarType inv_sqrt_step_size = 1.0 / sqrt(step_size); + std::cout << "inv_sqrt_step_size: " << inv_sqrt_step_size << std::endl; - // Two outgoing flows from S so will clamp their sum to S * inv_step_size to ensure non-negative S. + // Berechne den ersten Outflow aus S const ScalarType outflow1 = std::clamp( coeffStoIV1 * y[(size_t)InfectionState::Susceptible] * pop[(size_t)InfectionState::InfectedV1] + sqrt(coeffStoIV1 * y[(size_t)InfectionState::Susceptible] * pop[(size_t)InfectionState::InfectedV1]) * inv_sqrt_step_size * s_ev1, 0.0, y[(size_t)InfectionState::Susceptible] * inv_step_size); + std::cout << "outflow1: " << outflow1 << std::endl; + // Berechne den zweiten Outflow aus S const ScalarType outflow2 = std::clamp(coeffStoIV1 * y[(size_t)InfectionState::Susceptible] * (pop[(size_t)InfectionState::InfectedV1V2] + pop[(size_t)InfectionState::InfectedV2]) + @@ -111,43 +133,69 @@ class Model : public FlowModel 0) { const ScalarType scale = std::clamp(outflow_sum, 0.0, y[(size_t)InfectionState::Susceptible] * inv_step_size) / outflow_sum; + std::cout << "scale: " << scale << std::endl; flows[get_flat_flow_index()] = outflow1 * scale; + std::cout << "flow Sus -> ExpV1: " + << flows[get_flat_flow_index()] + << std::endl; flows[get_flat_flow_index()] = outflow2 * scale; + std::cout << "flow Sus -> ExpV2: " + << flows[get_flat_flow_index()] + << std::endl; } else { flows[get_flat_flow_index()] = 0; + std::cout << "flow Sus -> ExpV1 auf 0 gesetzt" << std::endl; flows[get_flat_flow_index()] = 0; + std::cout << "flow Sus -> ExpV2 auf 0 gesetzt" << std::endl; } + // Fluss von ExposedV1 zu InfectedV1 flows[get_flat_flow_index()] = std::clamp((1.0 / params.get()) * y[(size_t)InfectionState::ExposedV1] + sqrt((1.0 / params.get()) * y[(size_t)InfectionState::ExposedV1]) * inv_sqrt_step_size * ev1_iv1, 0.0, y[(size_t)InfectionState::ExposedV1] * inv_step_size); + std::cout << "flow ExpV1 -> InfV1: " + << flows[get_flat_flow_index()] << std::endl; + // Fluss von ExposedV2 zu InfectedV2 flows[get_flat_flow_index()] = std::clamp((1.0 / params.get()) * y[(size_t)InfectionState::ExposedV2] + sqrt((1.0 / params.get()) * y[(size_t)InfectionState::ExposedV2]) * inv_sqrt_step_size * ev2_iv2, 0.0, y[(size_t)InfectionState::ExposedV2] * inv_step_size); + std::cout << "flow ExpV2 -> InfV2: " + << flows[get_flat_flow_index()] << std::endl; + // Fluss von InfectedV1 zu RecoveredV1 flows[get_flat_flow_index()] = std::clamp((1.0 / params.get()) * y[(size_t)InfectionState::InfectedV1] + sqrt((1.0 / params.get()) * y[(size_t)InfectionState::InfectedV1]) * inv_sqrt_step_size * iv1_rv1, 0.0, y[(size_t)InfectionState::InfectedV1] * inv_step_size); + std::cout << "flow InfV1 -> RecV1: " + << flows[get_flat_flow_index()] << std::endl; + // Fluss von InfectedV2 zu RecoveredV2 flows[get_flat_flow_index()] = std::clamp((1.0 / params.get()) * y[(size_t)InfectionState::InfectedV2] + sqrt((1.0 / params.get()) * y[(size_t)InfectionState::InfectedV2]) * inv_sqrt_step_size * iv2_rv2, 0.0, y[(size_t)InfectionState::InfectedV2] * inv_step_size); + std::cout << "flow InfV2 -> RecV2: " + << flows[get_flat_flow_index()] << std::endl; + // Fluss von RecoveredV1 zu ExposedV1V2 flows[get_flat_flow_index()] = std::clamp(coeffStoIV2 * y[(size_t)InfectionState::RecoveredV1] * (pop[(size_t)InfectionState::InfectedV1V2] + pop[(size_t)InfectionState::InfectedV2]) + @@ -155,18 +203,31 @@ class Model : public FlowModel ExpV1V2: " + << flows[get_flat_flow_index()] + << std::endl; + // Fluss von ExposedV1V2 zu InfectedV1V2 flows[get_flat_flow_index()] = std::clamp((1.0 / params.get()) * y[(size_t)InfectionState::ExposedV1V2] + sqrt((1.0 / params.get()) * y[(size_t)InfectionState::ExposedV1V2]) / sqrt(step_size) * ev1v2_iv1v2, 0.0, y[(size_t)InfectionState::ExposedV1V2] * inv_step_size); + std::cout << "flow ExpV1V2 -> InfV1V2: " + << flows[get_flat_flow_index()] + << std::endl; + // Fluss von InfectedV1V2 zu RecoveredV1V2 flows[get_flat_flow_index()] = std::clamp((1.0 / params.get()) * y[(size_t)InfectionState::InfectedV1V2] + sqrt((1.0 / params.get()) * y[(size_t)InfectionState::InfectedV1V2]) / sqrt(step_size) * iv1v2_rv1v2, 0.0, y[(size_t)InfectionState::InfectedV1V2] * inv_step_size); + std::cout << "flow InfV1V2 -> RecV1V2: " + << flows[get_flat_flow_index()] + << std::endl; + + std::cout << "calc flows done" << std::endl; } ScalarType step_size; ///< A step size of the model with which the stochastic process is realized. From bda223eb96eef1fd91eea698365bcf97965990d0 Mon Sep 17 00:00:00 2001 From: Anna Wendler <106674756+annawendler@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:40:44 +0100 Subject: [PATCH 32/62] add docu for usage of ide secir model --- docs/source/c++/aggregated_models.rst | 11 +- docs/source/c++/{ide.rst => ide_creation.rst} | 0 docs/source/c++/ide_usage.rst | 176 ++++++++++++++++++ docs/source/c++/model_creation.rst | 2 +- docs/source/models/{isecir => isecir.rst} | 0 5 files changed, 187 insertions(+), 2 deletions(-) rename docs/source/c++/{ide.rst => ide_creation.rst} (100%) create mode 100644 docs/source/c++/ide_usage.rst rename docs/source/models/{isecir => isecir.rst} (100%) diff --git a/docs/source/c++/aggregated_models.rst b/docs/source/c++/aggregated_models.rst index 3902a4b97c..25a48af42c 100644 --- a/docs/source/c++/aggregated_models.rst +++ b/docs/source/c++/aggregated_models.rst @@ -1,2 +1,11 @@ Aggregated models -================= \ No newline at end of file +================= + +There are different equation-based models implemented in MEmilio that consider an aggregated population. + +.. toctree:: + :maxdepth: 1 + + ode + sde + ide_usage \ No newline at end of file diff --git a/docs/source/c++/ide.rst b/docs/source/c++/ide_creation.rst similarity index 100% rename from docs/source/c++/ide.rst rename to docs/source/c++/ide_creation.rst diff --git a/docs/source/c++/ide_usage.rst b/docs/source/c++/ide_usage.rst new file mode 100644 index 0000000000..1d5076bbe8 --- /dev/null +++ b/docs/source/c++/ide_usage.rst @@ -0,0 +1,176 @@ +IDE Models +========== + +Models based on integro-differential equations allow arbitrary stay time distributions... + +In MEmilio, two models based on integro-differential equations are implemented. They have different infection states and are solved with different numerical solvers. Their respective usage is described below. + + +IDE-SECIR model +---------------- + +This IDE-based model implements eight infection states and corresponding transition distributions can be set in a flexible way. The model is solved with a nonstandard finite difference scheme + +For a detailed description and application of the model, see: + +Wendler A, Plötzke L, Tritzschak H, Kühn MJ (2024) A nonstandard numerical scheme for a novel SECIR integro-differential equation-based model allowing nonexponentially distributed stay times. Under review. https://doi.org/10.48550/arXiv.2408.12228 + + +How to: Set up and run a simulation of the IDE-SECIR model +----------------------------------------------------------- + +The numerical solver requires a fixed time step size which we define by + +.. code-block:: cpp + ScalarType dt = 1.; + +To initialize the model, the following inputs need to be passed to the model constructor: + +- a time series containing the flows within a time step between the infection states for a large enough number of time points before the start of the simulation, +- a vector containing the population sizes for every age group, +- a vector containing the total number of deaths at time t0 for every age group, +- the number of age groups, +- optionally, a vector containing the total confirmed cases at time t0 and can be set if it should be used for initialization for every age group. + +The number of age groups, the population sizes and total number of deaths can be defined directly by + +.. code-block:: cpp + + size_t num_agegroups = 1; + + mio::CustomIndexArray N = + mio::CustomIndexArray(mio::AgeGroup(num_agegroups), 10000.); + mio::CustomIndexArray deaths = + mio::CustomIndexArray(mio::AgeGroup(num_agegroups), 13.10462213); + +In this example, we define the necessary flows before the simulation start by defining a time series at time points -10, ..., 0 that all contain the same vector of flows. The number of required time points before the simulation start depends on the chosen transition distributions that we can adapt later. +Note that the last time point in our initial flow TimeSeries determines the start time of the simulation. +.. code-block:: cpp + + int num_transitions = (int)mio::isecir::InfectionTransition::Count; + + // Create TimeSeries with num_transitions * num_agegroups elements where transitions needed for simulation will be + // stored. + mio::TimeSeries init(num_transitions * num_agegroups); + + // Define vector with flows. + Vec vec_init(num_transitions * num_agegroups); + vec_init[(int)mio::isecir::InfectionTransition::SusceptibleToExposed] = 25.0; + vec_init[(int)mio::isecir::InfectionTransition::ExposedToInfectedNoSymptoms] = 15.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedNoSymptomsToInfectedSymptoms] = 8.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedNoSymptomsToRecovered] = 4.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedSymptomsToInfectedSevere] = 1.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedSymptomsToRecovered] = 4.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedSevereToInfectedCritical] = 1.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedSevereToRecovered] = 1.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedCriticalToDead] = 1.0; + vec_init[(int)mio::isecir::InfectionTransition::InfectedCriticalToRecovered] = 1.0; + + vec_init = vec_init * dt; + + // Add initial time point to time series. + init.add_time_point(-10, vec_init); + // Add further time points until time 0. + while (init.get_last_time() < -dt / 2) { + init.add_time_point(init.get_last_time() + dt, vec_init); + } + +With this, we can construct our model: +.. code-block:: cpp + mio::isecir::Model model(std::move(init), N, deaths, num_agegroups); + + +TODO: Mention other init possibilities. + + +If we do not want to use the default parameters, we can adapt them as follows. + +An important feature of our IDE-based model is that we can choose the transition distributions in a flexible way. The default distribution is a smoother cosine function as it provides good testing qualities. For more realistic simulations, MEmilio provides the possibility to use exponential, gamma or lognormal distributions within the model. +Practically, one first needs to create an object of a class that is derived from the class StateAgeFunction, e.g. SmootherCosine. Any class that is derived from StateAgeFunction can be inserted into a StateAgeFunctionWrapper object that is then passed to the model. + +In this example, we start with creating a SmootherCosine object with parameter 2.0 that is then passed to the StateAgeFunctionWrapper object. Then we create a vector of type StateAgeFunctionWrapper. Within this vector we adapt the distribution parameter for the transition from InfectedNoSymptoms to InfectedSymptoms. Finally, this vector of StateAgeFunctionWrapper objects is passed to the model as demosntarted below. +.. code-block:: cpp + mio::SmootherCosine smoothcos(2.0); + mio::StateAgeFunctionWrapper delaydistribution(smoothcos); + std::vector vec_delaydistrib(num_transitions, delaydistribution); + vec_delaydistrib[(int)mio::isecir::InfectionTransition::InfectedNoSymptomsToInfectedSymptoms] + .set_distribution_parameter(4.0); + + model.parameters.get()[mio::AgeGroup(0)] = vec_delaydistrib; + +The transition probabilities can be set as follows +.. code-block:: cpp + std::vector vec_prob(num_transitions, 0.5); + // The following probabilities must be 1, as there is no other way to go. + vec_prob[Eigen::Index(mio::isecir::InfectionTransition::SusceptibleToExposed)] = 1; + vec_prob[Eigen::Index(mio::isecir::InfectionTransition::ExposedToInfectedNoSymptoms)] = 1; + model.parameters.get()[mio::AgeGroup(0)] = vec_prob; + +Here, we set the contact matrix used in the simulation. One can define multiple matrices for different locations. The size of each of these matrices is defined by tha number of age groups. +In our example below we use only one contact matrix. We only consider one age group and set the contact rate to 10. +.. code-block:: cpp + size_t num_matrices =1; + mio::ContactMatrixGroup contact_matrix = mio::ContactMatrixGroup(num_matrices, num_agegroups); + contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(num_agegroups, num_agegroups, 10.)); + model.parameters.get() = mio::UncertainContactMatrix(contact_matrix); + + +The parameters TransmissionProbabilityOnContact, RelativeTransmissionNoSymptoms and RiskOfInfectionFromSymptomatic can be made dependent on the time. This is why we use a StateAgeFunction that is passed to a StateAgeFunctionWrapper to set these parameters. Note that there is also a ConstantFunction availbale if we do not want to have any dependency on the time. +Here we use an ExponentialSurvivalFunction to set the mentioned parameters. +.. code-block:: cpp + mio::ExponentialSurvivalFunction exponential(0.5); + mio::StateAgeFunctionWrapper prob(exponential); + + model.parameters.get()[mio::AgeGroup(0)] = prob; + model.parameters.get()[mio::AgeGroup(0)] = prob; + model.parameters.get()[mio::AgeGroup(0)] = prob; + +Finally, we can also set the parameters Seasonality and StartDay directly as follows. +.. code-block:: cpp + model.parameters.set(0.1); + // Start the simulation on the 40th day of a year (i.e. in February). + model.parameters.set(40); + +Before the simulation, we check if all constraints of the model are satisfied so that the simulation can run as expected. +.. code-block:: cpp + model.check_constraints(dt); + +To simulate the model from `t0` (that is determined by the initial flows provided to the constructor) to `tmax` with given step size `dt`, a Simulation has to be created and advanced until `tmax`, which is done as follows: +.. code-block:: cpp + ScalarType tmax = 10.; + + mio::isecir::Simulation sim(model, dt); + sim.advance(tmax); + +We can access and print the computed compartments and flows as follows. +.. code-block:: cpp + auto compartments = sim.get_result(); + auto flows = sim.get_transitions(); + + compartments.print_table({"S", "E", "C", "I", "H", "U", "R", "D "}, 16, 8); + flows.print_table({"S->E 1", "E->C 1", "C->I 1", "C->R 1", "I->H 1", "I->R 1", "H->U 1", "H->R 1", "U->D 1", "U->R 1"}, 16, 8); + +If one wants to interpolate the results to a TimeSeries containing only full days, this can be done by +.. code-block:: cpp + auto interpolated_results = mio::interpolate_simulation_result(sim.get_result()); + + +TODO: +- different initialization possible + + + + +IDE-SEIR model +--------------- +This IDE-based model implements four infection states. + +For a detailed description and application of the model, see: + +Ploetzke ... BA + +Simulation +----------- + +How to: Set up and run a simulation of the IDE-SEIR model +---------------------------------------------------------- \ No newline at end of file diff --git a/docs/source/c++/model_creation.rst b/docs/source/c++/model_creation.rst index 7f07d88546..e162f10abe 100644 --- a/docs/source/c++/model_creation.rst +++ b/docs/source/c++/model_creation.rst @@ -9,5 +9,5 @@ Model Creation structure ode sde - ide + ide_creation \ No newline at end of file diff --git a/docs/source/models/isecir b/docs/source/models/isecir.rst similarity index 100% rename from docs/source/models/isecir rename to docs/source/models/isecir.rst From ec7b49817d81664e56508ec1ae51d582ed398c18 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Tue, 18 Mar 2025 16:23:57 +0100 Subject: [PATCH 33/62] FIX: code block formatting --- docs/source/c++/ide_usage.rst | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/docs/source/c++/ide_usage.rst b/docs/source/c++/ide_usage.rst index 1d5076bbe8..17da170a29 100644 --- a/docs/source/c++/ide_usage.rst +++ b/docs/source/c++/ide_usage.rst @@ -22,6 +22,7 @@ How to: Set up and run a simulation of the IDE-SECIR model The numerical solver requires a fixed time step size which we define by .. code-block:: cpp + ScalarType dt = 1.; To initialize the model, the following inputs need to be passed to the model constructor: @@ -45,6 +46,7 @@ The number of age groups, the population sizes and total number of deaths can be In this example, we define the necessary flows before the simulation start by defining a time series at time points -10, ..., 0 that all contain the same vector of flows. The number of required time points before the simulation start depends on the chosen transition distributions that we can adapt later. Note that the last time point in our initial flow TimeSeries determines the start time of the simulation. + .. code-block:: cpp int num_transitions = (int)mio::isecir::InfectionTransition::Count; @@ -76,6 +78,7 @@ Note that the last time point in our initial flow TimeSeries determines the star } With this, we can construct our model: + .. code-block:: cpp mio::isecir::Model model(std::move(init), N, deaths, num_agegroups); @@ -86,9 +89,10 @@ TODO: Mention other init possibilities. If we do not want to use the default parameters, we can adapt them as follows. An important feature of our IDE-based model is that we can choose the transition distributions in a flexible way. The default distribution is a smoother cosine function as it provides good testing qualities. For more realistic simulations, MEmilio provides the possibility to use exponential, gamma or lognormal distributions within the model. -Practically, one first needs to create an object of a class that is derived from the class StateAgeFunction, e.g. SmootherCosine. Any class that is derived from StateAgeFunction can be inserted into a StateAgeFunctionWrapper object that is then passed to the model. +Practically, one first needs to create an object of a class that is derived from the class ``StateAgeFunction``, e.g. ``SmootherCosine``. Any class that is derived from ``StateAgeFunction`` can be inserted into a ``StateAgeFunctionWrapper`` object that is then passed to the model. + +In this example, we start with creating a ``SmootherCosine`` object with parameter 2.0 that is then passed to the ``StateAgeFunctionWrapper`` object. Then we create a vector of type ``StateAgeFunctionWrapper``. Within this vector we adapt the distribution parameter for the transition from ``InfectedNoSymptoms`` to ``InfectedSymptoms``. Finally, this vector of ``StateAgeFunctionWrapper`` objects is passed to the model as demosntarted below. -In this example, we start with creating a SmootherCosine object with parameter 2.0 that is then passed to the StateAgeFunctionWrapper object. Then we create a vector of type StateAgeFunctionWrapper. Within this vector we adapt the distribution parameter for the transition from InfectedNoSymptoms to InfectedSymptoms. Finally, this vector of StateAgeFunctionWrapper objects is passed to the model as demosntarted below. .. code-block:: cpp mio::SmootherCosine smoothcos(2.0); mio::StateAgeFunctionWrapper delaydistribution(smoothcos); @@ -99,6 +103,7 @@ In this example, we start with creating a SmootherCosine object with parameter 2 model.parameters.get()[mio::AgeGroup(0)] = vec_delaydistrib; The transition probabilities can be set as follows + .. code-block:: cpp std::vector vec_prob(num_transitions, 0.5); // The following probabilities must be 1, as there is no other way to go. @@ -108,6 +113,7 @@ The transition probabilities can be set as follows Here, we set the contact matrix used in the simulation. One can define multiple matrices for different locations. The size of each of these matrices is defined by tha number of age groups. In our example below we use only one contact matrix. We only consider one age group and set the contact rate to 10. + .. code-block:: cpp size_t num_matrices =1; mio::ContactMatrixGroup contact_matrix = mio::ContactMatrixGroup(num_matrices, num_agegroups); @@ -115,8 +121,9 @@ In our example below we use only one contact matrix. We only consider one age gr model.parameters.get() = mio::UncertainContactMatrix(contact_matrix); -The parameters TransmissionProbabilityOnContact, RelativeTransmissionNoSymptoms and RiskOfInfectionFromSymptomatic can be made dependent on the time. This is why we use a StateAgeFunction that is passed to a StateAgeFunctionWrapper to set these parameters. Note that there is also a ConstantFunction availbale if we do not want to have any dependency on the time. -Here we use an ExponentialSurvivalFunction to set the mentioned parameters. +The parameters ``TransmissionProbabilityOnContact``, ``RelativeTransmissionNoSymptoms`` and ``RiskOfInfectionFromSymptomatic`` can be made dependent on the time. This is why we use a ``StateAgeFunction`` that is passed to a ``StateAgeFunctionWrapper`` to set these parameters. Note that there is also a ``ConstantFunction`` availbale if we do not want to have any dependency on the time. +Here we use an ``ExponentialSurvivalFunction`` to set the mentioned parameters. + .. code-block:: cpp mio::ExponentialSurvivalFunction exponential(0.5); mio::StateAgeFunctionWrapper prob(exponential); @@ -126,16 +133,19 @@ Here we use an ExponentialSurvivalFunction to set the mentioned parameters. model.parameters.get()[mio::AgeGroup(0)] = prob; Finally, we can also set the parameters Seasonality and StartDay directly as follows. + .. code-block:: cpp model.parameters.set(0.1); // Start the simulation on the 40th day of a year (i.e. in February). model.parameters.set(40); Before the simulation, we check if all constraints of the model are satisfied so that the simulation can run as expected. + .. code-block:: cpp model.check_constraints(dt); To simulate the model from `t0` (that is determined by the initial flows provided to the constructor) to `tmax` with given step size `dt`, a Simulation has to be created and advanced until `tmax`, which is done as follows: + .. code-block:: cpp ScalarType tmax = 10.; @@ -143,6 +153,7 @@ To simulate the model from `t0` (that is determined by the initial flows provide sim.advance(tmax); We can access and print the computed compartments and flows as follows. + .. code-block:: cpp auto compartments = sim.get_result(); auto flows = sim.get_transitions(); @@ -151,6 +162,7 @@ We can access and print the computed compartments and flows as follows. flows.print_table({"S->E 1", "E->C 1", "C->I 1", "C->R 1", "I->H 1", "I->R 1", "H->U 1", "H->R 1", "U->D 1", "U->R 1"}, 16, 8); If one wants to interpolate the results to a TimeSeries containing only full days, this can be done by + .. code-block:: cpp auto interpolated_results = mio::interpolate_simulation_result(sim.get_result()); From 5764abdde5c50209564b4321a60ccf8ca744e0a4 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Tue, 18 Mar 2025 16:29:03 +0100 Subject: [PATCH 34/62] CHG: ODE and SDE model creation files added --- docs/source/c++/model_creation.rst | 4 ++-- docs/source/c++/ode_creation.rst | 2 ++ docs/source/c++/sde_creation.rst | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) create mode 100644 docs/source/c++/ode_creation.rst create mode 100644 docs/source/c++/sde_creation.rst diff --git a/docs/source/c++/model_creation.rst b/docs/source/c++/model_creation.rst index e162f10abe..362c00a43b 100644 --- a/docs/source/c++/model_creation.rst +++ b/docs/source/c++/model_creation.rst @@ -7,7 +7,7 @@ Model Creation :maxdepth: 1 structure - ode - sde + ode_creation + sde_creation ide_creation \ No newline at end of file diff --git a/docs/source/c++/ode_creation.rst b/docs/source/c++/ode_creation.rst new file mode 100644 index 0000000000..b64978fa26 --- /dev/null +++ b/docs/source/c++/ode_creation.rst @@ -0,0 +1,2 @@ +ODE Model Creation +================== diff --git a/docs/source/c++/sde_creation.rst b/docs/source/c++/sde_creation.rst new file mode 100644 index 0000000000..53a0f1ea3c --- /dev/null +++ b/docs/source/c++/sde_creation.rst @@ -0,0 +1,2 @@ +SDE Model Creation +================== \ No newline at end of file From a8d08e4b80d2e74021ddf529905f78e2031c91ba Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Wed, 19 Mar 2025 09:46:35 +0100 Subject: [PATCH 35/62] FIX: Code blocks corrected --- docs/source/c++/ide_usage.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/source/c++/ide_usage.rst b/docs/source/c++/ide_usage.rst index 17da170a29..4ce950c5b1 100644 --- a/docs/source/c++/ide_usage.rst +++ b/docs/source/c++/ide_usage.rst @@ -80,6 +80,7 @@ Note that the last time point in our initial flow TimeSeries determines the star With this, we can construct our model: .. code-block:: cpp + mio::isecir::Model model(std::move(init), N, deaths, num_agegroups); @@ -94,6 +95,7 @@ Practically, one first needs to create an object of a class that is derived from In this example, we start with creating a ``SmootherCosine`` object with parameter 2.0 that is then passed to the ``StateAgeFunctionWrapper`` object. Then we create a vector of type ``StateAgeFunctionWrapper``. Within this vector we adapt the distribution parameter for the transition from ``InfectedNoSymptoms`` to ``InfectedSymptoms``. Finally, this vector of ``StateAgeFunctionWrapper`` objects is passed to the model as demosntarted below. .. code-block:: cpp + mio::SmootherCosine smoothcos(2.0); mio::StateAgeFunctionWrapper delaydistribution(smoothcos); std::vector vec_delaydistrib(num_transitions, delaydistribution); @@ -105,6 +107,7 @@ In this example, we start with creating a ``SmootherCosine`` object with paramet The transition probabilities can be set as follows .. code-block:: cpp + std::vector vec_prob(num_transitions, 0.5); // The following probabilities must be 1, as there is no other way to go. vec_prob[Eigen::Index(mio::isecir::InfectionTransition::SusceptibleToExposed)] = 1; @@ -115,6 +118,7 @@ Here, we set the contact matrix used in the simulation. One can define multiple In our example below we use only one contact matrix. We only consider one age group and set the contact rate to 10. .. code-block:: cpp + size_t num_matrices =1; mio::ContactMatrixGroup contact_matrix = mio::ContactMatrixGroup(num_matrices, num_agegroups); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(num_agegroups, num_agegroups, 10.)); @@ -125,6 +129,7 @@ The parameters ``TransmissionProbabilityOnContact``, ``RelativeTransmissionNoSym Here we use an ``ExponentialSurvivalFunction`` to set the mentioned parameters. .. code-block:: cpp + mio::ExponentialSurvivalFunction exponential(0.5); mio::StateAgeFunctionWrapper prob(exponential); @@ -135,6 +140,7 @@ Here we use an ``ExponentialSurvivalFunction`` to set the mentioned parameters. Finally, we can also set the parameters Seasonality and StartDay directly as follows. .. code-block:: cpp + model.parameters.set(0.1); // Start the simulation on the 40th day of a year (i.e. in February). model.parameters.set(40); @@ -142,11 +148,13 @@ Finally, we can also set the parameters Seasonality and StartDay directly as fol Before the simulation, we check if all constraints of the model are satisfied so that the simulation can run as expected. .. code-block:: cpp + model.check_constraints(dt); To simulate the model from `t0` (that is determined by the initial flows provided to the constructor) to `tmax` with given step size `dt`, a Simulation has to be created and advanced until `tmax`, which is done as follows: .. code-block:: cpp + ScalarType tmax = 10.; mio::isecir::Simulation sim(model, dt); @@ -155,6 +163,7 @@ To simulate the model from `t0` (that is determined by the initial flows provide We can access and print the computed compartments and flows as follows. .. code-block:: cpp + auto compartments = sim.get_result(); auto flows = sim.get_transitions(); @@ -164,6 +173,7 @@ We can access and print the computed compartments and flows as follows. If one wants to interpolate the results to a TimeSeries containing only full days, this can be done by .. code-block:: cpp + auto interpolated_results = mio::interpolate_simulation_result(sim.get_result()); From 5e859daa2aa00fef28ff008c782d3781000b106d Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Wed, 19 Mar 2025 09:51:09 +0100 Subject: [PATCH 36/62] FIX: Typos --- docs/source/c++/ide_usage.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/c++/ide_usage.rst b/docs/source/c++/ide_usage.rst index 4ce950c5b1..2041c6028a 100644 --- a/docs/source/c++/ide_usage.rst +++ b/docs/source/c++/ide_usage.rst @@ -92,7 +92,7 @@ If we do not want to use the default parameters, we can adapt them as follows. An important feature of our IDE-based model is that we can choose the transition distributions in a flexible way. The default distribution is a smoother cosine function as it provides good testing qualities. For more realistic simulations, MEmilio provides the possibility to use exponential, gamma or lognormal distributions within the model. Practically, one first needs to create an object of a class that is derived from the class ``StateAgeFunction``, e.g. ``SmootherCosine``. Any class that is derived from ``StateAgeFunction`` can be inserted into a ``StateAgeFunctionWrapper`` object that is then passed to the model. -In this example, we start with creating a ``SmootherCosine`` object with parameter 2.0 that is then passed to the ``StateAgeFunctionWrapper`` object. Then we create a vector of type ``StateAgeFunctionWrapper``. Within this vector we adapt the distribution parameter for the transition from ``InfectedNoSymptoms`` to ``InfectedSymptoms``. Finally, this vector of ``StateAgeFunctionWrapper`` objects is passed to the model as demosntarted below. +In this example, we start with creating a ``SmootherCosine`` object with parameter 2.0 that is then passed to the ``StateAgeFunctionWrapper`` object. Then we create a vector of type ``StateAgeFunctionWrapper``. Within this vector we adapt the distribution parameter for the transition from ``InfectedNoSymptoms`` to ``InfectedSymptoms``. Finally, this vector of ``StateAgeFunctionWrapper`` objects is passed to the model as demonstrated below. .. code-block:: cpp @@ -137,7 +137,7 @@ Here we use an ``ExponentialSurvivalFunction`` to set the mentioned parameters. model.parameters.get()[mio::AgeGroup(0)] = prob; model.parameters.get()[mio::AgeGroup(0)] = prob; -Finally, we can also set the parameters Seasonality and StartDay directly as follows. +Finally, we can also set the parameters ``Seasonality`` and ``StartDay`` directly as follows. .. code-block:: cpp @@ -170,10 +170,10 @@ We can access and print the computed compartments and flows as follows. compartments.print_table({"S", "E", "C", "I", "H", "U", "R", "D "}, 16, 8); flows.print_table({"S->E 1", "E->C 1", "C->I 1", "C->R 1", "I->H 1", "I->R 1", "H->U 1", "H->R 1", "U->D 1", "U->R 1"}, 16, 8); -If one wants to interpolate the results to a TimeSeries containing only full days, this can be done by +If one wants to interpolate the results to a ``TimeSeries`` containing only full days, this can be done by .. code-block:: cpp - + auto interpolated_results = mio::interpolate_simulation_result(sim.get_result()); From 53fed8db5e86557c8448d22ffcc1e91946cd4429 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Wed, 19 Mar 2025 09:53:26 +0100 Subject: [PATCH 37/62] FIX: Code block layout --- docs/source/c++/mobility.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/source/c++/mobility.rst b/docs/source/c++/mobility.rst index 358316bec4..786be186e6 100644 --- a/docs/source/c++/mobility.rst +++ b/docs/source/c++/mobility.rst @@ -42,7 +42,8 @@ The following steps detail how to configure and execute a graph simulation: First, set up the compartment model by initializing the populations and parameters. In this example, we use a single age group and start with 10,000 susceptible individuals. Additionally, the necessary epidemiological parameters (e.g. time periods, transmission probabilities) are set. - .. code-block:: cpp + .. code-block:: cpp + const size_t num_groups = 1; mio::osecir::Model model(num_groups); model.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}] = 10000; @@ -114,6 +115,7 @@ The following steps detail how to configure and execute a graph simulation: Build a graph where each node represents a simulation and each edge represents mobility between a pair of nodes. Mobility coefficients (here, 0.1 for all compartments) determine the fraction of the population exchanged between nodes. .. code-block:: cpp + const auto t0 = 0.; mio::Graph>, mio::MobilityEdge> g; g.add_node(1001, model_group1, t0); From c8d503f226696cd7ee9be6bacebc97301d974d38 Mon Sep 17 00:00:00 2001 From: Anna Wendler <106674756+annawendler@users.noreply.github.com> Date: Thu, 20 Mar 2025 08:37:26 +0100 Subject: [PATCH 38/62] more docu for ide secir --- docs/source/c++/ide_usage.rst | 92 ++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 17 deletions(-) diff --git a/docs/source/c++/ide_usage.rst b/docs/source/c++/ide_usage.rst index 1d5076bbe8..adfaf8a710 100644 --- a/docs/source/c++/ide_usage.rst +++ b/docs/source/c++/ide_usage.rst @@ -1,15 +1,26 @@ IDE Models ========== -Models based on integro-differential equations allow arbitrary stay time distributions... - In MEmilio, two models based on integro-differential equations are implemented. They have different infection states and are solved with different numerical solvers. Their respective usage is described below. IDE-SECIR model ---------------- -This IDE-based model implements eight infection states and corresponding transition distributions can be set in a flexible way. The model is solved with a nonstandard finite difference scheme +This model is based on integro-differential equations. +The eight compartments +- `Susceptible` ($S$), may become Exposed at any time +- `Exposed` ($E$), becomes InfectedNoSymptoms after some time +- `InfectedNoSymptoms` ($I_{NS}$), becomes InfectedSymptoms or Recovered after some time +- `InfectedSymptoms` ($I_{Sy}$), becomes InfectedSevere or Recovered after some time +- `InfectedSevere` ($I_{Sev}$), becomes InfectedCritical or Recovered after some time +- `InfectedCritical` ($I_{Cr}$), becomes Recovered or Dead after some time +- `Recovered` ($R$) +- `Dead` ($D$) + +are used to simulate the spread of the disease and corresponding transition distributions can be set in a flexible way. + +The simulation runs in discrete time steps using a non-standard numerical scheme. This approach is based on the paper ["A non-standard numerical scheme for an age-of infection epidemic model" by Messina et al., Journal of Computational Dynamics, 2022](https://doi.org/10.3934/jcd.2021029). For a detailed description and application of the model, see: @@ -75,13 +86,27 @@ Note that the last time point in our initial flow TimeSeries determines the star init.add_time_point(init.get_last_time() + dt, vec_init); } -With this, we can construct our model: -.. code-block:: cpp - mio::isecir::Model model(std::move(init), N, deaths, num_agegroups); +There are different options for initializing a fictional scenario. Regardless of the approach, you must provide a history of values for the transitions as demonstrated above and possibly additional information to compute the initial distribution of the population in the compartments. This information must be of the following type: + - You can state the number of total confirmed cases `total_confirmed_cases` at time $t_0$. The number of recovered people is set accordingly and the remaining values are derived in the model before starting the simulation. Then the model can be constructed by + .. code-block:: cpp + mio::CustomIndexArray total_confirmed_cases = + mio::CustomIndexArray(mio::AgeGroup(num_agegroups), 100.); + mio::isecir::Model model(std::move(init), N, deaths, num_agegroups, total_confirmed_cases); + - If you cannot provide this number of total confirmed cases, we can construct the model without this information. + .. code-block:: cpp + mio::isecir::Model model(std::move(init), N, deaths, num_agegroups); -TODO: Mention other init possibilities. + In that case, we have three possible options for initializing: + - You can set the number of people in the `Susceptible` compartment at time $t_0$ via `populations`. Initial values of the other compartments are derived in the model before starting the simulation. + .. code-block:: cpp + model.populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 1000.; + - You can set the number of people in the `Recovered` compartment at time $t_0$ via `populations`. Initial values of the other compartments are derived in the model before starting the simulation. + .. code-block:: cpp + model.populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 1000.; + - If none of the above is used, the force of infection formula and the values for the initial transitions are used consistently with the numerical scheme proposed in [Messina et al (2022)](https://doi.org/10.3934/jcd.2021029) to set the `Susceptible`s. +- The file [parameters_io](parameters_io.h) provides functionality to compute initial data for the IDE-SECIR model based on real data. An example for this initialization method can be found at [IDE initialization example](../../examples/ide_initialization.cpp). If we do not want to use the default parameters, we can adapt them as follows. @@ -155,12 +180,6 @@ If one wants to interpolate the results to a TimeSeries containing only full day auto interpolated_results = mio::interpolate_simulation_result(sim.get_result()); -TODO: -- different initialization possible - - - - IDE-SEIR model --------------- This IDE-based model implements four infection states. @@ -169,8 +188,47 @@ For a detailed description and application of the model, see: Ploetzke ... BA -Simulation ------------ - How to: Set up and run a simulation of the IDE-SEIR model ----------------------------------------------------------- \ No newline at end of file +---------------------------------------------------------- + +To initialize the model, the following inputs need to be passed to the model constructor: + +.. code-block:: cpp + using Vec = mio::TimeSeries::Vector; + + + int N = 810000; + double dt = 0.1; + mio::TimeSeries init(1); + + /** + * Construction of the initial TimeSeries with point of times and the corresponding number of susceptibles. + * The smallest time should be small enough. See the documentation of the IdeSeirModel constructor for + * detailed information. Initial data are chosen randomly. + */ + init.add_time_point(-15.0, Vec::Constant(1, N * 0.95)); + while (init.get_last_time() < 0) { + init.add_time_point(init.get_last_time() + dt, + Vec::Constant(1, (double)init.get_last_value()[0] + init.get_last_time())); + } + + // Initialize model. + mio::iseir::Model model(std::move(init), dt, N); + + // Set working parameters. + model.parameters.set(3.3); + model.parameters.set(8.2); + model.parameters.set(0.015); + mio::ContactMatrixGroup contact_matrix = mio::ContactMatrixGroup(1, 1); + contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 10.)); + // Add damping. + contact_matrix[0].add_damping(0.7, mio::SimulationTime(10.)); + model.parameters.get>() = mio::UncertainContactMatrix(contact_matrix); + + // Carry out simulation. + int tmax = 15; + model.simulate(tmax); + // Calculate values for compartments EIR. + auto result = model.calculate_EIR(); + //Print results. + result.print_table({"S", "E", "I", "R"}); \ No newline at end of file From 4dea91724bb0a38f60c992598306cd161be438df Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:28:50 +0100 Subject: [PATCH 39/62] FIX: markdown to rst layout --- docs/source/c++/ide_usage.rst | 51 ++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/docs/source/c++/ide_usage.rst b/docs/source/c++/ide_usage.rst index fdef5708f2..37300268b0 100644 --- a/docs/source/c++/ide_usage.rst +++ b/docs/source/c++/ide_usage.rst @@ -9,18 +9,19 @@ IDE-SECIR model This model is based on integro-differential equations. The eight compartments -- `Susceptible` ($S$), may become Exposed at any time -- `Exposed` ($E$), becomes InfectedNoSymptoms after some time -- `InfectedNoSymptoms` ($I_{NS}$), becomes InfectedSymptoms or Recovered after some time -- `InfectedSymptoms` ($I_{Sy}$), becomes InfectedSevere or Recovered after some time -- `InfectedSevere` ($I_{Sev}$), becomes InfectedCritical or Recovered after some time -- `InfectedCritical` ($I_{Cr}$), becomes Recovered or Dead after some time -- `Recovered` ($R$) -- `Dead` ($D$) + +- `Susceptible` (:math:`S`), may become Exposed at any time +- `Exposed` (:math:`E`), becomes InfectedNoSymptoms after some time +- `InfectedNoSymptoms` (:math:`I_{NS}`), becomes InfectedSymptoms or Recovered after some time +- `InfectedSymptoms` (:math:`I_{Sy}`), becomes InfectedSevere or Recovered after some time +- `InfectedSevere` (:math:`I_{Sev}`), becomes InfectedCritical or Recovered after some time +- `InfectedCritical` (:math:`I_{Cr}`), becomes Recovered or Dead after some time +- `Recovered` (:math:`R`) +- `Dead` (:math:`D`) are used to simulate the spread of the disease and corresponding transition distributions can be set in a flexible way. -The simulation runs in discrete time steps using a non-standard numerical scheme. This approach is based on the paper ["A non-standard numerical scheme for an age-of infection epidemic model" by Messina et al., Journal of Computational Dynamics, 2022](https://doi.org/10.3934/jcd.2021029). +The simulation runs in discrete time steps using a non-standard numerical scheme. This approach is based on the paper `"A non-standard numerical scheme for an age-of infection epidemic model" by Messina et al., Journal of Computational Dynamics, 2022 `_. For a detailed description and application of the model, see: @@ -40,9 +41,9 @@ To initialize the model, the following inputs need to be passed to the model con - a time series containing the flows within a time step between the infection states for a large enough number of time points before the start of the simulation, - a vector containing the population sizes for every age group, -- a vector containing the total number of deaths at time t0 for every age group, +- a vector containing the total number of deaths at time :math:`t0` for every age group, - the number of age groups, -- optionally, a vector containing the total confirmed cases at time t0 and can be set if it should be used for initialization for every age group. +- optionally, a vector containing the total confirmed cases at time :math:`t0` and can be set if it should be used for initialization for every age group. The number of age groups, the population sizes and total number of deaths can be defined directly by @@ -55,8 +56,8 @@ The number of age groups, the population sizes and total number of deaths can be mio::CustomIndexArray deaths = mio::CustomIndexArray(mio::AgeGroup(num_agegroups), 13.10462213); -In this example, we define the necessary flows before the simulation start by defining a time series at time points -10, ..., 0 that all contain the same vector of flows. The number of required time points before the simulation start depends on the chosen transition distributions that we can adapt later. -Note that the last time point in our initial flow TimeSeries determines the start time of the simulation. +In this example, we define the necessary flows before the simulation start by defining a time series at time points :math:`-10,\dots, 0` that all contain the same vector of flows. The number of required time points before the simulation start depends on the chosen transition distributions that we can adapt later. +Note that the last time point in our initial flow ``TimeSeries`` determines the start time of the simulation. .. code-block:: cpp @@ -90,25 +91,36 @@ Note that the last time point in our initial flow TimeSeries determines the star There are different options for initializing a fictional scenario. Regardless of the approach, you must provide a history of values for the transitions as demonstrated above and possibly additional information to compute the initial distribution of the population in the compartments. This information must be of the following type: - - You can state the number of total confirmed cases `total_confirmed_cases` at time $t_0$. The number of recovered people is set accordingly and the remaining values are derived in the model before starting the simulation. Then the model can be constructed by + - You can state the number of total confirmed cases `total_confirmed_cases` at time :math:`t_0`. The number of recovered people is set accordingly and the remaining values are derived in the model before starting the simulation. Then the model can be constructed by + .. code-block:: cpp + mio::CustomIndexArray total_confirmed_cases = mio::CustomIndexArray(mio::AgeGroup(num_agegroups), 100.); mio::isecir::Model model(std::move(init), N, deaths, num_agegroups, total_confirmed_cases); + - If you cannot provide this number of total confirmed cases, we can construct the model without this information. + .. code-block:: cpp + mio::isecir::Model model(std::move(init), N, deaths, num_agegroups); In that case, we have three possible options for initializing: - - You can set the number of people in the `Susceptible` compartment at time $t_0$ via `populations`. Initial values of the other compartments are derived in the model before starting the simulation. + - You can set the number of people in the `Susceptible` compartment at time :math:`t_0` via `populations`. Initial values of the other compartments are derived in the model before starting the simulation. + .. code-block:: cpp + model.populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Susceptible] = 1000.; - - You can set the number of people in the `Recovered` compartment at time $t_0$ via `populations`. Initial values of the other compartments are derived in the model before starting the simulation. + + - You can set the number of people in the `Recovered` compartment at time :math:`t_0` via `populations`. Initial values of the other compartments are derived in the model before starting the simulation. + .. code-block:: cpp + model.populations.get_last_value()[(Eigen::Index)mio::isecir::InfectionState::Recovered] = 1000.; - - If none of the above is used, the force of infection formula and the values for the initial transitions are used consistently with the numerical scheme proposed in [Messina et al (2022)](https://doi.org/10.3934/jcd.2021029) to set the `Susceptible`s. -- The file [parameters_io](parameters_io.h) provides functionality to compute initial data for the IDE-SECIR model based on real data. An example for this initialization method can be found at [IDE initialization example](../../examples/ide_initialization.cpp). + - If none of the above is used, the force of infection formula and the values for the initial transitions are used consistently with the numerical scheme proposed in `Messina et al (2022) `_ to set the ``Susceptible``s. + +- The file `parameters_io `_ provides functionality to compute initial data for the IDE-SECIR model based on real data. An example for this initialization method can be found at `IDE initialization example `_. If we do not want to use the default parameters, we can adapt them as follows. @@ -174,7 +186,7 @@ Before the simulation, we check if all constraints of the model are satisfied so model.check_constraints(dt); -To simulate the model from `t0` (that is determined by the initial flows provided to the constructor) to `tmax` with given step size `dt`, a Simulation has to be created and advanced until `tmax`, which is done as follows: +To simulate the model from :math:`t_0` (that is determined by the initial flows provided to the constructor) to :math:`t_{\max}` with given step size :math:`dt`, a Simulation has to be created and advanced until :math:`t_{\max}`, which is done as follows: .. code-block:: cpp @@ -214,6 +226,7 @@ How to: Set up and run a simulation of the IDE-SEIR model To initialize the model, the following inputs need to be passed to the model constructor: .. code-block:: cpp + using Vec = mio::TimeSeries::Vector; From cf1b1cf40583fecd5899a0ec3e6b02da3b9432f4 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:05:29 +0100 Subject: [PATCH 40/62] CHG: Development and FAQ improved --- docs/source/development.rst | 3 +++ docs/source/faq.rst | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/development.rst b/docs/source/development.rst index 2425e97f1f..2f559cd559 100644 --- a/docs/source/development.rst +++ b/docs/source/development.rst @@ -1,6 +1,9 @@ Development =========== +We are always happy about contributions to the project! If you want to contribute, please follow the guidelines below. + - `Git workflow and change process `_ - `Coding Guidelines `_ +For the documentation, please keep in mind that it is written in reStructuredText (RST) and uses a slightly different syntax than Markdown. A documentation can be found at ``_. \ No newline at end of file diff --git a/docs/source/faq.rst b/docs/source/faq.rst index 161203945c..a806aa7d11 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -10,4 +10,4 @@ Please open an issue on our `GitHub `_ page. If there is not yet a bug report, please open an issue first and reference it in your pull request. \ No newline at end of file +Please open a pull request on our `GitHub `_ page. If there is not yet a bug report, please open an issue first and reference it in your pull request. For more information, please refer to :doc:`development`. \ No newline at end of file From c916ce201ee597137d2087b447808b0085cb7f06 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:43:30 +0100 Subject: [PATCH 41/62] FIX: links to source code added --- docs/source/models/lsecir.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/models/lsecir.rst b/docs/source/models/lsecir.rst index e6e07540ba..7bd362a7cb 100644 --- a/docs/source/models/lsecir.rst +++ b/docs/source/models/lsecir.rst @@ -107,9 +107,9 @@ A simple example can be found at the Initialization -------------- -- The file ``parameters_io`` (``parameters_io.h``) provides functionality to compute an initial value vector for the LCT-SECIR model based on real data. +- The file `parameters_io `_ provides functionality to compute an initial value vector for the LCT-SECIR model based on real data. -- The file ``initializer_flows`` (``initializer_flows.h``) provides functionality to compute an initial value vector for the LCT-SECIR model based on initial data in the form of a TimeSeries of InfectionTransitions. For the concept of the InfectionTransitions or flows, see also the IDE-SECIR model. This method can be particularly useful if a comparison is to be made with an IDE model with matching initialization or if the real data is in the form of flows. +- The file `initializer_flows `_ provides functionality to compute an initial value vector for the LCT-SECIR model based on initial data in the form of a TimeSeries of InfectionTransitions. For the concept of the InfectionTransitions or flows, see also the IDE-SECIR model. This method can be particularly useful if a comparison is to be made with an IDE model with matching initialization or if the real data is in the form of flows. Overview of the ``lsecir`` namespace: ----------------------------------------- From f90822789364bbe52b2b83de6316a6cdc1d29053 Mon Sep 17 00:00:00 2001 From: Anna Wendler <106674756+annawendler@users.noreply.github.com> Date: Thu, 20 Mar 2025 13:51:24 +0100 Subject: [PATCH 42/62] add docu for ide seir --- docs/source/c++/{ide_usage.rst => ide.rst} | 62 +++++++++++++++++----- 1 file changed, 49 insertions(+), 13 deletions(-) rename docs/source/c++/{ide_usage.rst => ide.rst} (85%) diff --git a/docs/source/c++/ide_usage.rst b/docs/source/c++/ide.rst similarity index 85% rename from docs/source/c++/ide_usage.rst rename to docs/source/c++/ide.rst index 37300268b0..d07d8829c4 100644 --- a/docs/source/c++/ide_usage.rst +++ b/docs/source/c++/ide.rst @@ -149,7 +149,7 @@ The transition probabilities can be set as follows vec_prob[Eigen::Index(mio::isecir::InfectionTransition::ExposedToInfectedNoSymptoms)] = 1; model.parameters.get()[mio::AgeGroup(0)] = vec_prob; -Here, we set the contact matrix used in the simulation. One can define multiple matrices for different locations. The size of each of these matrices is defined by tha number of age groups. +Here, we set the contact matrix used in the simulation. One can define multiple matrices for different locations. The size of each of these matrices is defined by the number of age groups. In our example below we use only one contact matrix. We only consider one age group and set the contact rate to 10. .. code-block:: cpp @@ -214,16 +214,31 @@ If one wants to interpolate the results to a ``TimeSeries`` containing only full IDE-SEIR model --------------- -This IDE-based model implements four infection states. + +The four compartments +- `Susceptible` (:math:`S`), may become exposed at any time +- `Exposed` (:math:`E`), becomes infected after some time +- `Infected` (:math:`I`), will recover after some time +- `Recovered` (:math:`R`) + +are used to simulate the spread of the disease. + +The simulation runs in discrete time steps using a trapezoidal rule. The model and the numerical scheme is based on the paper `"Modeling infectious diseases using integro-differential equations: Optimal +control strategies for policy decisions and Applications in COVID-19" by Keimer and Pflug, 2020 `_. For a detailed description and application of the model, see: -Ploetzke ... BA +Plötzke L (2021) Modellierung epidemischer Infektionskrankheiten auf der Basis von gewöhnlichen und Integro-Differentialgleichungen. Bachelor thesis, University of Cologne. https://elib.dlr.de/143504/ How to: Set up and run a simulation of the IDE-SEIR model ---------------------------------------------------------- To initialize the model, the following inputs need to be passed to the model constructor: +- a time series containing the number of Susceptibles for a large enough number of time points before the start of the simulation, +- the time step size :math:`dt` used for numerical integration, +- the size of the population of the considered region :math:`N`. + +The initialization of the model can be done as follows where we set the Susceptibles from :math:`-15, \dots, 0` based on the total population and the time of the previous time point. .. code-block:: cpp @@ -234,11 +249,6 @@ To initialize the model, the following inputs need to be passed to the model con double dt = 0.1; mio::TimeSeries init(1); - /** - * Construction of the initial TimeSeries with point of times and the corresponding number of susceptibles. - * The smallest time should be small enough. See the documentation of the IdeSeirModel constructor for - * detailed information. Initial data are chosen randomly. - */ init.add_time_point(-15.0, Vec::Constant(1, N * 0.95)); while (init.get_last_time() < 0) { init.add_time_point(init.get_last_time() + dt, @@ -248,20 +258,46 @@ To initialize the model, the following inputs need to be passed to the model con // Initialize model. mio::iseir::Model model(std::move(init), dt, N); - // Set working parameters. +If we do not want to use the default parameters, we can adapt them as follows. + +The parameters ``LatencyTime``, ``InfectiousTime`` and ``TransmissionRisk`` can be set directly. + +.. code-block:: cpp + model.parameters.set(3.3); model.parameters.set(8.2); model.parameters.set(0.015); + +Here, we set the contact matrix used in the simulation. One can define multiple matrices for different locations. The size of each of these matrices is defined by the number of age groups. +In our example below we use only one contact matrix. Our model considers one age group and we set the contact rate to 10. + +.. code-block:: cpp + mio::ContactMatrixGroup contact_matrix = mio::ContactMatrixGroup(1, 1); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 10.)); - // Add damping. + +To simulate the implementation of nonpharmaceutical, we add dampings to the contact rate. Here, we apply a damping of :math:`0.7` after :math:`10`` days. + +.. code-block:: cpp + contact_matrix[0].add_damping(0.7, mio::SimulationTime(10.)); model.parameters.get>() = mio::UncertainContactMatrix(contact_matrix); - // Carry out simulation. +After defining :math:`t_{\max}``, we can simulate, which means that we calculate the value for the compartment :math:`S`. + +.. code-block:: cpp + int tmax = 15; model.simulate(tmax); - // Calculate values for compartments EIR. + +The values of the remaining compartments :math:`E`, :math:`I` and :math:`R` are calculated using the parameters ``LatencyTime`` and ``InfectiousTime`` and obtain a time series containing the values of all compartments. + +.. code-block:: cpp + auto result = model.calculate_EIR(); - //Print results. + +Finally, we ca print our results. + +.. code-block:: cpp + result.print_table({"S", "E", "I", "R"}); \ No newline at end of file From d4d0b9c9c23baa422791272ae54a1e2ba21ea943 Mon Sep 17 00:00:00 2001 From: Anna Wendler <106674756+annawendler@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:38:06 +0100 Subject: [PATCH 43/62] add files for lct --- docs/source/c++/aggregated_models.rst | 3 +- docs/source/c++/lct.rst | 44 +++++++++++++++++++++++++++ docs/source/c++/lct_creation.rst | 2 ++ docs/source/c++/model_creation.rst | 1 + 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 docs/source/c++/lct.rst create mode 100644 docs/source/c++/lct_creation.rst diff --git a/docs/source/c++/aggregated_models.rst b/docs/source/c++/aggregated_models.rst index 25a48af42c..6371f66726 100644 --- a/docs/source/c++/aggregated_models.rst +++ b/docs/source/c++/aggregated_models.rst @@ -7,5 +7,6 @@ There are different equation-based models implemented in MEmilio that consider a :maxdepth: 1 ode + lct sde - ide_usage \ No newline at end of file + ide \ No newline at end of file diff --git a/docs/source/c++/lct.rst b/docs/source/c++/lct.rst new file mode 100644 index 0000000000..12b61cf3b6 --- /dev/null +++ b/docs/source/c++/lct.rst @@ -0,0 +1,44 @@ +LCT Models +========== + +In MEmilio, two models based on Linear Chain Trick are implemented. Their respective usage is described below. + + +LCT-SECIR model +---------------- + +The Linear Chain Trick provides the option to use Erlang-distributed stay times in the compartments through the use of subcompartments. +The normal ODE models have (possibly unrealistic) exponentially distributed stay times. +The LCT model can still be described by an ordinary differential equation system. + +For the concept see +- Lena Plötzke, "Der Linear Chain Trick in der epidemiologischen Modellierung als Kompromiss zwischen gewöhnlichen und Integro-Differentialgleichungen", 2023. (https://elib.dlr.de/200381/, German only) +- P. J. Hurtado und A. S. Kirosingh, "Generalizations of the ‘Linear Chain Trick’: incorporating more flexible dwell time distributions into mean field ODE models“, 2019. (https://doi.org/10.1007/s00285-019-01412-w) + +The eight compartments +- `Susceptible` (:math:`S`), may become Exposed at any time +- `Exposed` (:math:`E`), becomes InfectedNoSymptoms after some time +- `InfectedNoSymptoms` (:math:`I_{NS}`), becomes InfectedSymptoms or Recovered after some time +- `InfectedSymptoms` (:math:`I_{Sy}`), becomes InfectedSevere or Recovered after some time +- `InfectedSevere` (:math:`I_{Sev}`), becomes InfectedCritical or Recovered after some time +- `InfectedCritical` (:math:`I_{Cr}`), becomes Recovered or Dead after some time +- `Recovered` (:math:`R`) +- `Dead` (:math:`D`) + +are used to simulate the spread of the disease. +It is possible to include subcompartments for the five compartments Exposed, InfectedNoSymptoms, InfectedSymptoms, InfectedSevere and InfectedCritical. +You can divide the population according to different groups, e.g. AgeGroups or gender and choose parameters according to groups. + + +How to: Set up and run a simulation of the LCT-SECIR model +----------------------------------------------------------- + + + + +GLCT-SECIR model +----------------- + + +How to: Set up and run a simulation of the GLCT-SECIR model +------------------------------------------------------------ diff --git a/docs/source/c++/lct_creation.rst b/docs/source/c++/lct_creation.rst new file mode 100644 index 0000000000..fcadda54b7 --- /dev/null +++ b/docs/source/c++/lct_creation.rst @@ -0,0 +1,2 @@ +LCT Models +========== \ No newline at end of file diff --git a/docs/source/c++/model_creation.rst b/docs/source/c++/model_creation.rst index 362c00a43b..9054e299c0 100644 --- a/docs/source/c++/model_creation.rst +++ b/docs/source/c++/model_creation.rst @@ -8,6 +8,7 @@ Model Creation structure ode_creation + lct_creation sde_creation ide_creation \ No newline at end of file From 07ba68452bef437742e5266f2d48ecc179cdb762 Mon Sep 17 00:00:00 2001 From: MaxBetzDLR Date: Thu, 20 Mar 2025 15:01:13 +0100 Subject: [PATCH 44/62] add first draft of the python packages --- docs/requirements.txt | 1 + docs/source/conf.py | 26 +-- docs/source/index.rst | 10 +- docs/source/python/memilio_epidata.rst | 175 ++++++++++++++++++ docs/source/python/memilio_generation.rst | 64 +++++++ docs/source/python/memilio_plot.rst | 79 ++++++++ docs/source/python/memilio_simulation.rst | 48 +++++ docs/source/python/memilio_surrogate.rst | 47 +++++ docs/source/python/model_creation.rst | 38 +++- docs/source/python/model_usage.rst | 109 ++++++++++- .../python/python_bindings_patterns.rst | 13 ++ docs/source/python/python_packages.rst | 122 ++++++++++++ .../pythonapi/memilio.simulation.abm.rst | 27 +++ .../pythonapi/memilio.simulation.osecir.rst | 26 +++ .../memilio.simulation.osecirvvs.rst | 27 +++ .../pythonapi/memilio.simulation.oseir.rst | 25 +++ .../pythonapi/memilio.simulation.osir.rst | 26 +++ docs/source/pythonapi/memilio.simulation.rst | 38 ++++ docs/source/{ => pythonapi}/pythonapi.rst | 12 +- 19 files changed, 884 insertions(+), 29 deletions(-) create mode 100644 docs/source/python/memilio_epidata.rst create mode 100644 docs/source/python/memilio_generation.rst create mode 100644 docs/source/python/memilio_plot.rst create mode 100644 docs/source/python/memilio_simulation.rst create mode 100644 docs/source/python/memilio_surrogate.rst mode change 100644 => 100755 docs/source/python/model_creation.rst mode change 100644 => 100755 docs/source/python/model_usage.rst create mode 100644 docs/source/python/python_bindings_patterns.rst create mode 100644 docs/source/python/python_packages.rst create mode 100644 docs/source/pythonapi/memilio.simulation.abm.rst create mode 100644 docs/source/pythonapi/memilio.simulation.osecir.rst create mode 100644 docs/source/pythonapi/memilio.simulation.osecirvvs.rst create mode 100644 docs/source/pythonapi/memilio.simulation.oseir.rst create mode 100644 docs/source/pythonapi/memilio.simulation.osir.rst create mode 100644 docs/source/pythonapi/memilio.simulation.rst rename docs/source/{ => pythonapi}/pythonapi.rst (50%) diff --git a/docs/requirements.txt b/docs/requirements.txt index 5c132004ec..e14edb7799 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,7 @@ sphinx==7.1.2 sphinx-rtd-theme==1.3.0rc1 sphinx-copybutton +sphinx_design breathe sphinx-hoverxref pycode/memilio-epidata diff --git a/docs/source/conf.py b/docs/source/conf.py index 8e5c4060dd..5c2c1545de 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -2,6 +2,10 @@ # -- Project information +import sys +import os +import subprocess +import memilio project = 'MEmilio' copyright = '2020-2025 MEmilio' author = '' @@ -9,15 +13,13 @@ release = '' version = '1.3.0' -import subprocess, os, sys read_the_docs_build = os.environ.get('READTHEDOCS', None) == 'True' if read_the_docs_build: - subprocess.call('cd ..; doxygen', shell=True) + subprocess.call('cd ..; doxygen', shell=True) -import memilio # sys.path.insert(0, os.path.abspath('../../pycode')) # -- General configuration @@ -30,10 +32,11 @@ 'sphinx.ext.intersphinx', 'sphinx.ext.napoleon', 'sphinx_copybutton', + 'sphinx_design', 'breathe', 'exhale', 'hoverxref.extension', -# 'sphinx_remove_toctrees' + # 'sphinx_remove_toctrees' ] intersphinx_mapping = { @@ -59,13 +62,13 @@ } exhale_args = { - "containmentFolder": "./api", - "rootFileName": "library_root.rst", - "doxygenStripFromPath": "..", - "rootFileTitle": "C++ API", - "createTreeView": True, - "treeViewIsBootstrap": False, - "contentsDirectives": False, + "containmentFolder": "./api", + "rootFileName": "library_root.rst", + "doxygenStripFromPath": "..", + "rootFileTitle": "C++ API", + "createTreeView": True, + "treeViewIsBootstrap": False, + "contentsDirectives": False, } breathe_projects = {"MEmilio": "../xml"} @@ -112,4 +115,3 @@ # -- Options for EPUB output epub_show_urls = 'footnote' - diff --git a/docs/source/index.rst b/docs/source/index.rst index 7bfa81cbd9..29e8ac4b11 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -48,13 +48,17 @@ Contents :maxdepth: 2 :caption: Python Interface - python/model_usage - python/model_creation + python/python_packages + python/memilio_simulation + python/memilio_epidata + python/memilio_surrogate + python/memilio_generation + python/memilio_plot .. toctree:: :maxdepth: 1 :caption: Code API models/index - pythonapi + pythonapi/pythonapi api/library_root \ No newline at end of file diff --git a/docs/source/python/memilio_epidata.rst b/docs/source/python/memilio_epidata.rst new file mode 100644 index 0000000000..4808e44933 --- /dev/null +++ b/docs/source/python/memilio_epidata.rst @@ -0,0 +1,175 @@ +MEmilio Epidata Package +======================= + + +This package provides modules and scripts to download epidemiological data from various official and inofficial sources. +The sources can be found in the `pycode/memilio-epidata `_. + +Installation +------------ + +Use the provided ``setup.py`` script to install the package and its dependencies. + +To install the package, use (from the directory that contains ``setup.py``) + +.. code-block:: console + + pip install . + +This copies everything required to your site-packages. + +For developement of code use the command + +.. code-block:: console + + pip install -e .[dev] + +This command allows you to work on the code without having to reinstall the package after a change. It also installs all additional dependencies required for development and maintenance. + +Dependencies +------------ + +Required python packages: + +* pandas>=2.0.0 +* matplotlib +* tables +* numpy>=1.22,<1.25 +* pyarrow +* openpyxl +* xlrd +* requests +* pyxlsb +* wget + +Running the scripts +------------------- + +After installation the scripts can be run via the following entry points. + * getcasedata (get case data from rki, see Results: RKI-C) + * getpopuldata (get population data, see Results: P) + * getjhdata (get case data from john hopkins university, see Results: JH) + * getdividata (get ICU data from DIVI, see Results: DIVI) + * getsimdata (get simulation data including case and vaccination data from rki, population data and ICU data, see Results: RKI-C, RKI-V, P, DIVI) + * cleandata (deletes written files) + * getcommutermobility (get data about commuter mobility, see Results: BAA) + * gettestingdata (get data about number of tests, see Results: RKI-T) + * gethospitalizationdata (get hospitalization data from RKI, see Results: RKI-H) + +For a detailed description of the run options and the resulting data files written +see the `epidata subfolder `_. + +Testing and Coverage +-------------------- + +The following packages are used by the tests: + +* pyfakefs (creates fake directory to test that expected folders are created and data is written) +* coverage + +See Installation on how to install all these dependencies automatically. + +To run the tests make + +.. code-block:: console + + python -m unittest + +To get the coverage report do + +.. code-block:: console + + python -m coverage run -m unittest + python -m coverage report + python -m coverage xml -o coverage_python.xml + python -m coverage html -d coverage_python + +Coverage report for actual master: + +:Coverage Report: https://scicompmod.github.io/memilio/coverage/python/ + +Inspection via pylint +--------------------- +The following packages have to be installed to run pylint: + +* pylint +* pylint-json2html + +See Installation on how to install all these dependencies automatically. + +Run pylint with the commands + +.. code-block:: console + + python setup.py pylint + pylint-json2html -f jsonextended -o build_pylint/pylint.html < build_pylint/pylint_extended.json + +Pylint report for actual master: + +:Pylint Report: https://dlr-sc.github.io/memilio/pylint/ + +Additional Tools +---------------- + +Some additional tools for processing or analysing data can be found in the `tools directory `_. + +Notes for developers +-------------------- + +If a new functionality shall be added please stick to the following instructions: + +When you start creating a new script: + +- have a look into getDataIntoPandasDataFrame.py there the main functionality which should be used is implemented. + - get_file is used to read in data. + - the Conf class sets relevant download options. + - use write_dataframe to write the pandas dataframe to file. + - use check_dir if you want to create a new folder to write data to +- use the dictionaries in defaultDict.py to rename the existing columns of your data + - add new column names to one of the existing language dictionaries; english, german and spanish translation exists at the moment. + - for non-english languages always use the EngEng dictionary as the key, thus we can easily change names with just changing one line. + - in defaultDict.py a dictionary with id, state and county name, respectively exists. Please use it. +- After renaming columns, you should not use pandas dataframe.column but instead use + dataframe[column] where column is given by the dictionaries in defaultDict.py. + Example: ID_County = dd.GerEng['IdLandkreis'] or dd.EngEng['idCounty']. +- For extensive operations use the progress indicator to give feedback for the user +- ALWAYS use Copy-on-Write for pandas DataFrames. +- use doxygen like comments in code as + - add description in the beginning of the file + - ## Header + - # @brief name descr + - # longer description + - add description in the beginning of every function directly after the definition + - start and end with """ + - add a short description to first line + - afterwards add a longer description + - # @param name of parameter + - # @return type description + +When you add a new script + +- add a executable to the setup.py in "pycode/memilio-epidata" +- add it to the cli_dict in getDataIntoPandasDataFrame.py + - add a meaningfull key for the new script + - as the value add a list in the form [comment to print when script is started, list of used parser arguments (optional)] + - if more than the default parser should be added, add these parser to the list of used parser +- add tests +- add an entry "executablename -h" to the .github/test-py/action.yml +- add an entry "executablename -o data_dl" to the .github/workflows/main.yml +- add generated data to cleanData + +Adding a new parser: + +- add default value to defaultDict in defaultDict.py +- add to cli_dict in getDataIntoPandasDataFrame.py which scripts use this parser +- add an if 'new parser' in what_list and add parser.add_argument() + +General +- Always add unittests +- Check test coverage report, if every new feature is covered. +- Check the pylint report just comments with "refactor" are allowed. + +Troubleshooting +--------------- + +- HDF5 errors during installation (mostly on Windows): one of the dependencies of the epidata package requires HDF5 to be installed on the system. If HDF5 is not discovered properly, this `stack overflow thread `_ may help resolve the issue. diff --git a/docs/source/python/memilio_generation.rst b/docs/source/python/memilio_generation.rst new file mode 100644 index 0000000000..922082826f --- /dev/null +++ b/docs/source/python/memilio_generation.rst @@ -0,0 +1,64 @@ +MEmilio Generation Package +========================== + + +This package provides an automatic code generator for python bindings of the MEmilio C++ library. +It enables the automatic generation of a part of the :doc:`Python Bindings ` that is common across multiple models. +For a particular example, see the SEIR model with its files `oseir.cpp` and `oseir.py`. + +This generating software was developed as a part of the Bachelor thesis `Automatische Codegenerierung für nutzerfreundliche mathematisch-epidemiologische Modelle `_. +The following figure from Chapter 5 outlines the workflow of the generator. Blue boxes represent parts of the code generator and orange ones the input and output. Rectangular boxes contain classes with logic, the rest represent data. + +.. image:: https://github.com/SciCompMod/memilio/main/blob/pycode/memilio-generation/generator_workflow.png + :alt: tikzGeneratorWorkflow + +Dependencies +------------ + +The package uses the `Clang C++ library `_ and the `LibClang Python library `_ to analyze the C++ code of a model. Both need to be installed and share the same version. + +Required python packages: + +Usage +----- + +During the installation the package creates a compilation database (compile_commands.json) for the models of the `C++ Library `_. + +The package provides an example script on how to use it in `memilio/tools`. The example uses the ode_seir model. + +Before running the example you have to do these steps of setup: +* Change `config.json.txt `_. +* Check if the parameters set in __post_init__() of the [ScannerConfig class](./memilio/generation/scanner_config.py) match with the cpp-class names. + +Example: +After processing as described in the previous paragraph, run the example with the command (path according to the current folder): + +.. code-block:: console + + python memilio/tools/example_oseir.py + + +When working on a new model you can copy the example script and add an additional segment to the config.json.txt. The setup works similar to the example. Additionaly you can print the AST of your model into a file (Usefull for development/debugging). + +Testing +------- + +The package provides a test suite in `memilio/generation_test `_. To run the tests, simply run the following command: + +.. code-block:: console + + python -m unittest + + +Development +----------- + +When implementing new model features you can follow these steps: +* Add necessary configurations to `config.json.txt `_ and add corresponding attributes to the ``ScannerConfig``. +* For the features you want to implement, find the nodes in the abstract syntax tree (AST) (use method Scanner.output_ast_file(); see the example in tools/). +* Add the extraction of those features. Therefore you need to change the "check_..."-methods corresponding to the ``CursorKind`` of your nodes in the ``Scanner``. If there is no corresponding "check_..."-method you need to write a new one and add it to the switch-method (scanner.switch_node_kind()). +* Extend the ``IntermediateRepresentation`` for the new model features. +* Adjust the `cpp-template `_ and the `string-template-methods `_. If needed, use new identifiers and write new string-template-methods for them. +* Adjust the substitution dictionaries in the ``Generator``. +* Write new/Adjust script in the `tool folder `_ for the model and try to run. +* Update tests. \ No newline at end of file diff --git a/docs/source/python/memilio_plot.rst b/docs/source/python/memilio_plot.rst new file mode 100644 index 0000000000..35b4747b8e --- /dev/null +++ b/docs/source/python/memilio_plot.rst @@ -0,0 +1,79 @@ +MEmilio Plot Package +======================= + +MEmilio Plot provides modules and scripts to plot epidemiological or simulation data as returned +by other packages of the MEmilio software. + +The package is contained inside the folder `pycode/memilio-plot `_. + + +Dependencies +------------ + +Required python packages: + +- pandas>=1.2.2 +- matplotlib +- numpy>=1.22,<1.25 +- openpyxl +- xlrd +- requests +- pyxlsb +- wget +- folium +- matplotlib +- mapclassify +- geopandas +- h5py +- imageio +- datetime + +Testing and Coverage +-------------------- + +The following packages are used by the tests: + +* pyfakefs (creates fake directory to test that expected folders are created and data is written) +* coverage + +See Installation on how to install all these dependencies automatically. + +To run the tests make + +.. code-block:: console + + python -m unittest + +To get the coverage report do + +.. code-block:: console + + python -m coverage run -m unittest + python -m coverage report + python -m coverage xml -o coverage_python.xml + python -m coverage html -d coverage_python + +Coverage report for actual master: + +`Coverage Report `_ + +Inspection via pylint +--------------------- +The following packages have to be installed to run pylint: + +* pylint +* pylint-json2html + +See Installation on how to install all these dependencies automatically. + +Run pylint with the commands + +.. code-block:: console + + python setup.py pylint + pylint-json2html -f jsonextended -o build_pylint/pylint.html < build_pylint/pylint_extended.json + +Pylint report for actual master: + +`Pylint Report `_ + diff --git a/docs/source/python/memilio_simulation.rst b/docs/source/python/memilio_simulation.rst new file mode 100644 index 0000000000..58447c0e72 --- /dev/null +++ b/docs/source/python/memilio_simulation.rst @@ -0,0 +1,48 @@ +MEmilio Simulation Package +========================== + +**Tutorials**: +:doc:`Model Usage ` | +:doc:`Model Creation ` | +:doc:`Common Patterns ` + +MEmilio Simulation contains Python bindings for the MEmilio C++ library. It enables setting up and running simulations from Python code. + +The package is contained inside the folder `pycode/memilio-simulation `_. + + +Dependencies +------------ + +Required python packages: + +- + +Stubs +----- + +A stub file contains a skeleton of the public interface of that Python +module including classes, variables, functions and their types. +They help by enabling autocompletes and type annotations. +mypy stubgen is used to generate the stub files for the MEmilio Python Bindings +and provide them as a separate stubs-only package. + + +For installing stubs you first need to install our package memilio.simulation +(not in editable mode -e) and the external dependency mypy for your python interpreter. +Then run generate_stubs.py to generate the stubs-only package and +install it as memilio-stubs, e.g. from the package folder + +.. code-block:: console + + python ./tools/generate_stubs.py + +\setcounter{tocdepth}{1} + +.. toctree:: + :maxdepth: 1 + :hidden: + + Model Usage + Model Creation + Common Patterns \ No newline at end of file diff --git a/docs/source/python/memilio_surrogate.rst b/docs/source/python/memilio_surrogate.rst new file mode 100644 index 0000000000..282a7110a1 --- /dev/null +++ b/docs/source/python/memilio_surrogate.rst @@ -0,0 +1,47 @@ +MEmilio Surrogate Model Package +=============================== + +MEmilio Surrogate Model contains machine learning based surrogate models that make predictions based on the MEmilio simulation models. +Currently there are only surrogate models for ODE models. These simulations of these equation-based models are used for data generation. +The goal is to create a powerful tool that predicts the dynamics faster than a simulation of an expert model, +e.g., a metapopulation or agent-based model while still having acceptable errors with respect to the original simulations. + +The package is contained inside the folder `pycode/memilio-surrogatemodel `_. + +Dependencies +------------ + +Required python packages: + + +Since we are running simulations to generate the data, the MEmilio :doc:`memilio-simulation ` package +also needs to be installed. + +Usage +----- + +The package currently provides the following modules: + +- `models`: models for different specific tasks + Currently we have the following models: + - `ode_secir_simple`: A simple model allowing for asymptomatic as well as symptomatic infection not stratified by age groups. + - `ode_secir_groups`: A model allowing for asymptomatic as well as symptomatic infection stratified by age groups and including one damping. + + Each model folder contains the following files: + - `data_generation`: data generated from expert model simulation. + - `model`: training and evaluation of the model. + - `network_architectures`: multiple network architectures are saved in this file. + + +- `tests`: this file contains all tests + +Testing +------- + +The package provides a test suite in `memilio/surrogatemodel_test `_. +To run the tests, simply use the following command. + +.. code-block:: console + + python -m unittest + diff --git a/docs/source/python/model_creation.rst b/docs/source/python/model_creation.rst old mode 100644 new mode 100755 index 1834ced0c2..9d6625c7c6 --- a/docs/source/python/model_creation.rst +++ b/docs/source/python/model_creation.rst @@ -1,8 +1,38 @@ -Model Creation -============== - +Tutorial: Expanding python bindings +=================================== .. toctree:: :maxdepth: 1 - \ No newline at end of file + +This tutorial is aimed at explaining the process of adding new functionalities to the simulation package +through writing new python bindings. It is advantagous to have knowledge on programming in C++ +as the bindings, as well as the functional source code we want to call from python, is written in C++. + +We will go over the common workflow of writing bindings for MEmilio, explaining the structure of the +bindings, providing a small step-by-step guide on adding a new model and showcasing common patterns you +may encounter with the C++ MEmilio library. + +Lets start by looking at the + +Adding a new model +------------------ + +If currently a model is not available in the python bindings or you added a new c++ model and want to bind it +then the following steps should give an overview of what needs to be done: + +#. Add new bindings including a model file in the [models](memilio/simulation/bindings/models/) folder that defines the new module +#. Add a python module file similar to the other models, e.g. [osir.py](memilio/simulation/osir.py) (needed for the structure of the python package) and modify getter function in [__init__.py](memilio/simulation/__init__.py) +#. Add the new module to the building process by modifying [CMakeLists.txt](CMakeLists.txt) +#. Write new tests and examples +#. (Add the package to the documentation and stubs generation) + +- talk about memilio generation :doc:`memilio-generation ` +Expanding the simulation packages +--------------------------------- + + +Pure python additions +--------------------- + +The bindings can also be expanded with pure Python code by expanding the existing python files or adding new ones underneath the [simulation](memilio/simulation/) folder. diff --git a/docs/source/python/model_usage.rst b/docs/source/python/model_usage.rst old mode 100644 new mode 100755 index 661aa96cd4..3b9b4053e9 --- a/docs/source/python/model_usage.rst +++ b/docs/source/python/model_usage.rst @@ -1,7 +1,108 @@ -Model Usage -=========== +Tutorial: Usage of python bindings +================================== +This tutorial should give an overview of how to use the +currently available functions and models of the python bindings. +For expanding the bindings with new models look into the section +:doc:`Model Creation `. -.. toctree:: - :maxdepth: 1 +Generally, the package is following the structure of the main C++ +library to make it easy to understand and comparable, while introducing +changes to create a more pythonic interface. We will follow the example of an +ODE SEIR model starting with a comparison of the model initialization between +Python and C++. + +.. grid:: 1 1 2 2 + + .. grid-item:: + + Python: + + .. code-block:: python + + import memilio.simulation.oseir as oseir + + num_groups = 1 + model = oseir.Model(num_groups) + + .. grid-item:: + + C++: + + .. code-block:: c++ + + + #include "ode_seir/model.h" + + mio::oseir::Model model(1); + + +Next, the parameters should be defined of the scenario you want to model. The model has the +possibility to incorporate age stratification, which leads to many of the parameters to have +values for each age group. The AgeGroup is used for indexing, which leads for the example model +with a single group defined by num_groups to the parameter definitions. + +.. code-block:: python + + A0 = AgeGroup(0) + + # Compartment transition duration + model.parameters.TimeExposed[A0] = 5.2 + model.parameters.TimeInfected[A0] = 6. + + # Compartment transition propabilities + model.parameters.TransmissionProbabilityOnContact[A0] = 1. + +AgeGroup(0) defines the first age group. For a model with more than one age group, +we could index the other groups with AgeGroup(1), AgeGroup(2), .... + +We also need to define the inital states of the population. As they are not only divided through an age group, +but also an infection state, we need to add an index of the enum InfectionState. + +.. code-block:: python + + total_population = 83_000 + + model.populations[A0, InfectionState.Exposed] = 100 + model.populations[A0, InfectionState.Infected] = 50 + model.populations[A0, InfectionState.Recovered] = 10 + model.populations.set_difference_from_total( + (A0, InfectionState.Susceptible), total_population) + +The function model.populations.set_difference_from_total hepls by setting the last compartment with +a total population size of the scenario and will take the difference to the combined other compartments +of the age group. + + +Now we could simulate with: + +.. code-block:: python + + result = simulate(0, days, dt, model) + +Similar to the MEmilio C++ library, the python interface provides the option of adjusting the solver. +Currently available: +- +- + +.. code-block:: python + + result = simulate(0, days, dt, model) + +parameter setting with spatial resolution + +simulation +redefining the solver + +Working with the output + +Expanding to graph model + +More examples: +- `examples/ode_secir.cpp `_ +- `examples/ode_secir_ageres.cpp `_ +- `examples/ode_secir_parameter_study.cpp `_ + + +Lastly Limitations with introduction of model creation diff --git a/docs/source/python/python_bindings_patterns.rst b/docs/source/python/python_bindings_patterns.rst new file mode 100644 index 0000000000..0ba4b134c3 --- /dev/null +++ b/docs/source/python/python_bindings_patterns.rst @@ -0,0 +1,13 @@ +Common patterns in python bindings +================================== + + +Template classes +---------------- + +IOResult as return +------------------ + +CustomIndexArray +---------------- + diff --git a/docs/source/python/python_packages.rst b/docs/source/python/python_packages.rst new file mode 100644 index 0000000000..22bbfd563e --- /dev/null +++ b/docs/source/python/python_packages.rst @@ -0,0 +1,122 @@ +Python Packages +=============== + +MEmilio contains a plethora of python modules containing tools to expand on the main C++. +Most of them serve their own use case, + +.. grid:: 1 1 2 2 + :gutter: 2 3 4 4 + + .. grid-item-card:: + :img-top: ../../memilio-small.png + :text-align: center + + MEmilio Python Bindings + ^^^ + + This module provides a python interface for parts of the C++ main library, + with the goal of exposing fast mathematical-epidemiological models to + a bigger user base. + + +++ + + .. button-ref:: memilio_simulation + :expand: + :color: secondary + :click-parent: + + To the python bindings + + .. grid-item-card:: + :img-top: ../../memilio-small.png + :text-align: center + + Epidata Tool + ^^^ + + The memilio-epidata package provides tools to download and structure important + data such as infection or mobility data. + + +++ + + .. button-ref:: memilio_epidata + :expand: + :color: secondary + :click-parent: + + To the data package + + +.. grid:: 1 1 1 1 + :gutter: 2 3 4 4 + + .. grid-item-card:: + :text-align: center + + Surrogate Models + ^^^ + + Expanding on AI + + +++ + + .. button-ref:: surrogate_models + :expand: + :color: secondary + :click-parent: + + To the intro of surrogate models + + .. grid-item-card:: + :text-align: center + + Visualization + ^^^ + + Plot of data + + +++ + + .. button-ref:: memilio_plot + :expand: + :color: secondary + :click-parent: + + To the visualization + + .. grid-item-card:: + :text-align: center + + Generating Bindings + ^^^ + + Easy to use tool for helping with the creation of new bindings of C++ models. + + +++ + + .. button-ref:: memilio_generation + :expand: + :color: secondary + :click-parent: + + To the generation package + + +Installation +------------ + +Each package provides a `setup.py` script that installs the packaga and its dependencies with which +the installation can be run with the command (from the directory containing `setup.py`) + +.. code-block:: console + + pip install . + + +For developement of code use + +.. code-block:: console + + pip install -e .[dev] + +The dependencies are denoted in documentation of each package. \ No newline at end of file diff --git a/docs/source/pythonapi/memilio.simulation.abm.rst b/docs/source/pythonapi/memilio.simulation.abm.rst new file mode 100644 index 0000000000..bd680971aa --- /dev/null +++ b/docs/source/pythonapi/memilio.simulation.abm.rst @@ -0,0 +1,27 @@ +memilio.simulation.abm +====================== + +.. automodule:: memilio.simulation._simulation_abm + :members: + :undoc-members: + :show-inheritance: + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/pythonapi/memilio.simulation.osecir.rst b/docs/source/pythonapi/memilio.simulation.osecir.rst new file mode 100644 index 0000000000..4fe3d42400 --- /dev/null +++ b/docs/source/pythonapi/memilio.simulation.osecir.rst @@ -0,0 +1,26 @@ +memilio.simulation.osecir +========================= + +.. automodule:: memilio.simulation._simulation_osecir + :members: + :undoc-members: + :show-inheritance: + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/pythonapi/memilio.simulation.osecirvvs.rst b/docs/source/pythonapi/memilio.simulation.osecirvvs.rst new file mode 100644 index 0000000000..e59ac55684 --- /dev/null +++ b/docs/source/pythonapi/memilio.simulation.osecirvvs.rst @@ -0,0 +1,27 @@ +memilio.simulation.osecirvvs +============================ + +.. automodule:: memilio.simulation._simulation_osecirvvs + :members: + :undoc-members: + :show-inheritance: + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/pythonapi/memilio.simulation.oseir.rst b/docs/source/pythonapi/memilio.simulation.oseir.rst new file mode 100644 index 0000000000..16a0b51615 --- /dev/null +++ b/docs/source/pythonapi/memilio.simulation.oseir.rst @@ -0,0 +1,25 @@ +memilio.simulation.oseir +======================== + +.. automodule:: memilio.simulation._simulation_oseir + :members: + :undoc-members: + :show-inheritance: + + + + + + + + + + + + + + + + + + diff --git a/docs/source/pythonapi/memilio.simulation.osir.rst b/docs/source/pythonapi/memilio.simulation.osir.rst new file mode 100644 index 0000000000..fcb6dcd78d --- /dev/null +++ b/docs/source/pythonapi/memilio.simulation.osir.rst @@ -0,0 +1,26 @@ +memilio.simulation.osir +======================= + +.. automodule:: memilio.simulation._simulation_osir + :members: + :undoc-members: + :show-inheritance: + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/pythonapi/memilio.simulation.rst b/docs/source/pythonapi/memilio.simulation.rst new file mode 100644 index 0000000000..d5e7bf0a42 --- /dev/null +++ b/docs/source/pythonapi/memilio.simulation.rst @@ -0,0 +1,38 @@ +memilio.simulation +================== + +.. rubric:: Modules + +.. toctree:: + :maxdepth: 1 + + memilio.simulation.abm + memilio.simulation.osir + memilio.simulation.oseir + memilio.simulation.osecir + memilio.simulation.osecirvvs + +.. automodule:: memilio.simulation._simulation + :members: + :undoc-members: + :show-inheritance: + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/pythonapi.rst b/docs/source/pythonapi/pythonapi.rst similarity index 50% rename from docs/source/pythonapi.rst rename to docs/source/pythonapi/pythonapi.rst index df078081c7..01d8b743c2 100644 --- a/docs/source/pythonapi.rst +++ b/docs/source/pythonapi/pythonapi.rst @@ -7,11 +7,11 @@ Python API .. autosummary:: :toctree: generated :recursive: - :caption: Pyhton Module API - - memilio.generation - memilio.epidata - memilio.simulation - memilio.surrogatemodel + memilio.plot + +.. toctree:: + :maxdepth: 1 + memilio.simulation + From fd4b6ecb6428bd9a43cf30b3735140709eea5ad2 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:05:18 +0100 Subject: [PATCH 45/62] add abm_mobility to doc --- docs/source/c++/mobility_based_abm.rst | 311 +++++++++++++++++++++++++ 1 file changed, 311 insertions(+) diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst index e69de29bb2..2cee6d0eb5 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/c++/mobility_based_abm.rst @@ -0,0 +1,311 @@ +Agent-Based Model +================= + +This module models and simulates the epidemic using an agent-based model (*ABM*) approach. Unlike the +:doc:`SECIR ` compartmental model that uses a system of ODEs, this model simulates +the spread of COVID-19 in a population with discrete persons (the agents) moving throughout locations in the +model and interacting with (infecting) each other. For a detailed overview of the ABM, see +- Kerkmann D, Korf S, et al. Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread. https://doi.org/10.48550/arXiv.2410.08050 + +Structure +--------- + +The model consists of the following major classes: + +1. **Person**: Represents an agent of the model. A person has an ID (i.e. a unique number), an age, a location, + and a list with their assigned locations (i.e. the locations they visit during the simulation). They can perform + tests and wear masks. Every person has lists with past and current infections and vaccinations. +2. **Infection**: Collection of all information about a person's infection, i.e. infectiousness, infection course, + virus variant. The infection course is drawn stochastically from the infection states that are similar to the + compartments of the SECIR model. +3. **Location**: Represents places in the model where people meet and interact, e.g. home, school, work, social event + sites. A location can be split into cells to model parts of a location, like classrooms in a school. Some infection + parameters are location-specific and one can activate NPIs like mandatory masks or tests to enter the location. +4. **Model**: Collection of all persons and locations. It also holds information about the testing strategy of the + simulation and holds the rules for the mobility phase. +5. **Simulation**: Runs the simulation and stores results. + + + +Simulation +---------- + +The simulation runs in discrete time steps. Each step has two phases, an **interaction phase** and a **mobility phase**. +After these two phases the disease can progress and the simulation time is increased by one step. + +Interaction Phase +~~~~~~~~~~~~~~~~~~~ + +In this phase, each person interacts with the other persons at the same location. This interaction determines the +transmission of the disease. A susceptible person can become infected by contact with an infected person. The probability +of infection depends on a multitude of factors, such as the viral load and infectiousness of the infected and the immunity +level of the susceptible person. + +Mobility Phase +~~~~~~~~~~~~~~~~~~ + +During the mobility phase, each person may change their location. Mobility follows complex +`rules `_, considering the current location, time of day, and properties of the person (e.g. age). +Some location changes are deterministic and regular (e.g. going to work), while others are random (e.g. going shopping or to a +social event in the evening/on the weekend). When agents are infected, they are quarantined and cannot change their location. +You can restrict some mobility rules by allowing only a proportion of people to enter specific locations. + +Another way of mobility we use in the `simulation of Braunschweig `_ is using trips. A trip +consists of the ID of the person that performs this trip, a time point when this trip is performed, and the destination. +At the beginning of the simulation, a list with all trips is initialized and followed during the simulation. There can be different +trips on the weekend than during the week, but other than that, the agents do the same trips every day. As before, agents that are +in quarantine or in the hospital cannot change their location. + + +Disease Progression +~~~~~~~~~~~~~~~~~~ + +The ABM implements a detailed disease progression model that captures the full course of an infection from exposure to resolution. The disease progression is modeled through the ``Infection`` class, which contains: + +1. **Infection States**: Similar to the SECIR model, an infected person progresses through states: + - **Susceptible**: Initial state before infection + - **Exposed**: Infected but not yet infectious + - **InfectedNoSymptoms**: Infectious but without symptoms + - **InfectedSymptoms**: Showing symptoms but not severe + - **InfectedSevere**: Severe infection requiring hospitalization + - **InfectedCritical**: Critical infection requiring ICU + - **Recovered**: Recovered from infection with immunity + - **Dead**: Deceased due to infection + +2. **Viral Load Dynamics**: The model implements realistic viral load curves based on scientific data: + - **Incline Phase**: Rapid increase in viral concentration + - **Peak**: Maximum viral load + - **Decline Phase**: Gradual decrease until clearance + +3. **Infectiousness**: The probability of transmitting the virus depends on viral load through an invlogit function: + +4. **Stochastic Transitions**: Progression between states is stochastic, with age-dependent probabilities: + - The duration in each state is drawn from distributions in the model parameters + - Prior immunity (from vaccination or previous infection) affects: + - Viral load (reduced peak) + - Severity progression (reduced probability of severe outcomes) + - Duration of infectious period + +5. **Infection Course**: The infection course is determined by: + - Age group of the person + - Virus variant + - Protection status (prior immunity) + - Random factors (individual variation) + + +Data Collection +~~~~~~~~~~~~~~~~~~ + +The ABM simulation can collect data through the ``History`` object, which allows for flexible data logging. This is particularly +useful for analyzing results after the simulation has completed. There are multiple types of data that can be collected: + +1. **Time Series Data**: Track how infection states change over time + +2. **Location-specific Data**: Monitor occupancy or infection rates at specific locations + +3. **Person-specific Data**: Follow individual movement patterns or infection trajectories + +The examples demonstrate two approaches: + +.. code-block:: cpp + + // Basic time series tracking of infection states + mio::History historyTimeSeries{ + Eigen::Index(mio::abm::InfectionState::Count)}; + + // More complex logging with multiple data types + mio::History history; + + // Run simulation with history object + sim.advance(tmax, history); + + +Interventions +~~~~~~~~~~~~~~~~~~ + +The ABM supports various interventions that can be applied at specific time points, such as: + +1. **Capacity Restrictions**: Limit the number of people at locations + +2. **Testing Regimes and Quarantines**: Implement regular testing at specific locations and resulting quarantines at home + +3. **Lockdowns**: Restrict movement between locations + +Get Started +----------- + +This section gives an introduction to how to use the ABM and set up your own simulation. For a quick overview, you can find a full +example in the `ABM minimal example `_ and a more detailed Doxygen documentation +`here `_. For a guide on installation and running the simulations and +examples, see this `README `_. + +Every person in the ABM belongs to an AgeGroup, which we can define as follows: + +.. code-block:: cpp + + size_t num_age_groups = 4; + const auto age_group_0_to_4 = mio::AgeGroup(0); + const auto age_group_5_to_14 = mio::AgeGroup(1); + ... = ... + +Note that every age group has to have values strictly smaller than the number of age groups ``num_age_groups``. +With this number we create an empty model: + +.. code-block:: cpp + + auto model = mio::abm::Model(num_age_groups); + +We can set several general parameters, which you can find `here `_. Here is an example where we set the +duration of the incubation period to 4 days: + +.. code-block:: cpp + + model.parameters.get() = 4.; + +Locations and Persons +~~~~~~~~~~~~~~~~~~~~~ + +To add a location to the model, we have to specify the kind of location: + +.. code-block:: cpp + + auto home = model.add_location(mio::abm::LocationType::Home); + +People are added with an age. Then we have to assign them, so the model knows they can travel to this location: + +.. code-block:: cpp + + auto person = model.add_person(home, age_group_0_to_4); + person.set_assigned_location(home); + +For more complex location configurations, the model allows setting location-specific parameters: + +.. code-block:: cpp + + // Add one social event with 5 maximum contacts + auto event = model.add_location(mio::abm::LocationType::SocialEvent); + model.get_location(event).get_infection_parameters().set(5); + + // Increase aerosol transmission for all locations + model.parameters.get() = 10.0; + + // Increase contact rate for specific age groups at work + model.get_location(work) + .get_infection_parameters() + .get()[{age_group_15_to_34, age_group_15_to_34}] = 10.0; + +Households +~~~~~~~~~~ + +For adding more people to the model, we can create households. A Household holds a vector of HouseholdMembers, which in turn +hold a weighted distribution, such that we can randomly draw the age of each Person belonging to the Household. To manage +multiple Households of the same type, we can use a HouseholdGroup. +In our example, we categorize individuals into two groups: children and parents. + +.. code-block:: cpp + + auto child = mio::abm::HouseholdMember(num_age_groups); + child.set_age_weight(age_group_0_to_4, 1); + child.set_age_weight(age_group_5_to_14, 1); + + auto parent = mio::abm::HouseholdMember(num_age_groups); + parent.set_age_weight(age_group_15_to_34, 1); + parent.set_age_weight(age_group_35_to_59, 1); + + // Two-person household with one parent and one child. + auto twoPersonHousehold_group = mio::abm::HouseholdGroup(); + auto twoPersonHousehold_full = mio::abm::Household(); + twoPersonHousehold_full.add_members(child, 1); + twoPersonHousehold_full.add_members(parent, 1); + twoPersonHousehold_group.add_households(twoPersonHousehold_full, n_households); + add_household_group_to_model(model, twoPersonHousehold_group); + +Testing Strategies +~~~~~~~~~~~~~~~~~ + +During the simulation, people can get tested, and we have to specify the scheme for that: + +.. code-block:: cpp + + auto validity_period = mio::abm::days(1); + 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::TestType::Antigen; + auto test_parameters = model.parameters.get()[test_type]; + auto testing_criteria_work = mio::abm::TestingCriteria(); + auto testing_scheme_work = mio::abm::TestingScheme(testing_criteria_work, validity_period, + start_date, end_date, + test_parameters, probability); + model.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); + +Initializing Infections +~~~~~~~~~~~~~~~~~~~~~~ + +For some infections to happen during the simulation, we have to initialize people with infections: + +.. code-block:: cpp + + // Assign infection state to each person randomly with specific distribution + std::vector infection_distribution{0.5, 0.3, 0.05, 0.05, 0.05, 0.05, 0.0, 0.0}; + for (auto& person : model.get_persons()) { + mio::abm::InfectionState infection_state = mio::abm::InfectionState( + mio::DiscreteDistribution::get_instance()(mio::thread_local_rng(), infection_distribution)); + auto rng = mio::abm::PersonalRandomNumberGenerator(person); + if (infection_state != mio::abm::InfectionState::Susceptible) { + person.add_new_infection(mio::abm::Infection(rng, mio::abm::VirusVariant::Wildtype, + person.get_age(), + model.parameters, start_date, infection_state)); + } + } + +Running the Simulation +~~~~~~~~~~~~~~~~~~~~~ + +Finally, we run the simulation: + +.. code-block:: cpp + + auto t0 = mio::abm::TimePoint(0); + auto tmax = t0 + mio::abm::days(30); + auto sim = mio::abm::Simulation(t0, std::move(model)); + + // Simple simulation without data collection + sim.advance(tmax); + +Alternatively, if we want to track things in the simulation, we need to set up a +`history `_, for example, to track all the Infection states of each simulation step. + +.. code-block:: cpp + + mio::History history{ + Eigen::Index(mio::abm::InfectionState::Count)}; + +Then we can run the simulation with the history object and access the data through ``get_log()``: + +.. code-block:: cpp + + sim.advance(tmax, history); + auto log = history.get_log(); + +Finally, we can print the data to a text file: + +.. code-block:: cpp + + std::ofstream outfile("abm_minimal.txt"); + std::get<0>(log).print_table({"S", "E", "I_NS", "I_Sy", "I_Sev", "I_Crit", "R", "D"}, 7, 4, outfile); + std::cout << "Results written to abm_minimal.txt" << std::endl; + +Current Limitations +------------------- + +Currently, a few things are not yet implemented, such as: + +- Different trips for each day. +- Trace functionality. + + +Overview of the ``abm`` namespace: +----------------------------------------- + +.. doxygennamespace:: mio::abm \ No newline at end of file From 25bbf2dd94c5f6ce9314457e15c10015d8eff0bc Mon Sep 17 00:00:00 2001 From: reneSchm <49305466+reneSchm@users.noreply.github.com> Date: Thu, 20 Mar 2025 14:34:32 +0100 Subject: [PATCH 46/62] add I/O documentation --- docs/source/c++/io.rst | 364 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 362 insertions(+), 2 deletions(-) diff --git a/docs/source/c++/io.rst b/docs/source/c++/io.rst index d3e4213ad6..30e12fd998 100644 --- a/docs/source/c++/io.rst +++ b/docs/source/c++/io.rst @@ -1,2 +1,362 @@ -Input/Output -============ \ No newline at end of file +MEmilio C++ IO +============== + +This document describes utilities for reading and writing data from and to files in different formats, in cases where +``TimeSeries::print_table()`` is not enough. The main sections are: + +- The serialization framework, that can be used to define the structure of data without using a specific file format. + There are implementations of the framework for different formats. The framework is described in detail below, also + see the `serialization example <../../examples/serialize.cpp>`__. + +- The command line interface, that can be used to set (and get) values of a ``ParameterSet``. + +- The History class for logging almost arbitrary information. It can be thought of as a generalization of a results + ``TimeSeries``, and is mainly used for the ABM. + + +The Serialization framework +=========================== + +Serialization is the process of converting a data structure or object into a different format that can be stored or +transmitted. In this section we will show you how to make use of and implement MEmilio's serialization feature, as +well as explaining concepts, error handling, and extension of the feature to new types and formats. +Our guiding example will be a humble struct ``Foo``: + +.. code-block:: cpp + + struct Foo { + int i; + }; + + +Using serialization +-------------------- + +In the next sections we will explain how to implement serialization (both for types and formats), here we quickly show +how to use it once it already is implemented for a type. In the following examples, we serialize (write) ``Foo`` to a +file in Json format, then deserialize (read) the Json again. + +.. code-block:: cpp + + Foo foo{5}; + mio::IOResult io_result = mio::write_json("path/to/foo.json", foo); + +.. code-block:: cpp + + mio::IOResult io_result = mio::read_json("path/to/foo.json", mio::Tag{}); + if (io_result) { + Foo foo = io_result.value(); + } + +There is also support for a binary format. If you want to use a format directly instead of writing to a file, use the +``serialize_json``/``deserialize_json`` and ``serialize_binary``/``deserialize_binary`` functions. + +Main functions and types +------------------------ + +- **functions serialize and deserialize**: + Main entry points to the framework to write and read values, respectively. The functions expect an IOContext + (see Concepts below) that stores the serialized data. (De-)serialization can be customized by providing a + (de-)serialize_internal overload or a (de-)serialize member function for the type. See the section "Implementing + serialization for a new type" or the documentation for ``serialize`` and ``deserialize``. +- **IOStatus and IOResult**: + Used for error handling, see section "Error Handling" below. + +Default serialization +---------------------- + +Before we get into the details of the framework, this feature provides an easy and convenient alternative to +implementing the serialize and deserialize functions. To give an example: + +.. code-block:: cpp + + struct Foo { + int i; + auto default_serialize() { + return Members("Foo").add("i", i); + } + }; + +Additional class members are added by repeated ``add`` calls, e.g. ``return Members("Foo").add("i", i).add("j", j)``, +where the first argument is a (descriptive) name and the second is a class member. + +The default serialization is intentionally less flexible than the serialize and deserialize functions +(which will be explained later) and has additional requirements: + +- The class must be default constructible. + + - If there is a default constructor that is *private*, it can still be used by marking the struct ``DefaultFactory`` + as a friend. For the example above, the line ``friend DefaultFactory;`` would be added to the struct + definition. + + - Alternatively, you may provide a specialization of the struct ``DefaultFactory``. For more details, view the + struct's documentation. + +- Every class member must be added to ``Members`` exactly once, and the provided names must be unique. + + - The members must be passed directly, like in the example. No copies, accessors, dereferencing, etc. + + - It is recommended, but not required, to add member variables to ``Members`` in the same order they are declared in + the class, using the variables' names or something very similar. + +- Every class member itself must be serializable, deserializable and assignable. + +This feature is primarily meant to make data classes easy to (de)serialize, avoiding some repitition that is necessary +when writing both a serialize and deserialize function. It can, however, be used for any class that should be +serialized in its entirety, and that does not need to make any decisions or computations while doing so. For example, +default serialization cannot be used if your class has optional members or values, or if one of its members is stored +as a pointer. + +As to the feature set, default-serialization only supports the ``add_element`` and ``expect_element`` operations defined +in the Concepts section below, where each operation's arguments are provided through the ``add`` function. Note that the +value provided to ``add`` is also used to assign a value during deserialization, hence the class members must be used +directly in the function (i.e. as a non-const lvalue reference). + +Concepts +-------- + +1. **IOContext** + + Stores data that describes serialized objects of any type in some unspecified format and provides structured + access to the data for deserialization. Implementations of this concept may store the data in any format + they want including binary. The data may also be written directly to disk. The context also keeps track + of errors. An IOContext object ``io`` allows the following operations: + + - ``io.create_object("Type")``: + Returns an IOObject for the type called ``"Type"``. The IOObject (see below) allows adding data that describes + the object to be serialized. The function must return something that can be assigned to a local + variable, e.g., a temporary or copyable function. IOObject may store references to the context internally, + so the lifetime of the local IOObject may not exceed the lifetime of the IOContext that created it. + - ``io.expect_object("Type")``: + Returns an IOObject for the type called ``"Type"``. The IOObject (see below) provides access to the data needed + for deserialization. + - ``io.flags()``: + Returns the flags that determine the behavior of serialization; see IOFlags. + - ``io.error()``: + Returns an IOStatus object to check if there were any errors during serialization. Usually it is not necessary to + check this manually but can be used to report the error faster and avoid expensive operations that would be + wasted anyway. + - ``io.set_error(s)`` with some IOStatus object: + Stores an error that was generated outside of the IOContext, e.g., if a value that was deserialized is outside an + allowed range. + +2. **IOObject** + + Gives structured access to serialized data. During serialization, data can be added with ``add_...`` operations. + During deserialization, data can be retrieved with ``expect_...`` operations. Data must be retrieved in the same + orderas it was added since, e.g., binary format does not allow lookup by key. The following operations are supported + for an IOObject ``obj``: + + - ``obj.add_element("Name", t)``: + Stores an object ``t`` in the IOObject under the key "Name". If ``t`` is of basic type (i.e., int, string), + IOObjectis expected to handle it directly. Otherwise, the object uses ``mio::serialize`` to get the data for ``t``. + - ``obj.add_list("Name", b, e)``: + Stores the elements in the range represented by iterators ``b`` and ``e`` under the key "Name". The individual + elements are not named. The elements are either handled directly by the IOObject or using ``mio::serialize`` just + like ``add_element``. + - ``obj.add_optional("Name", p)``: + Stores the element pointed to by pointer ``p`` under the key "Name". The pointer may be null. Otherwise identical + to add_element. + - ``obj.expect_element("Name", Tag{})``: + If an object of type T can be found under the key "Name" and can be deserialized, returns the object. Otherwise + returns an error. Analogously to serialization, the IOObject is expected to handle basic types directly and use + ``mio::deserialize`` otherwise. + - ``obj.expect_list("Name", Tag{})``: + If a list of objects of type T can be found under the key "Name" and can be deserialized, returns a range that can + be iterated over. Otherwise returns an error. + - ``obj.expect_optional("Name", Tag{})``: + Returns ``boost::optional`` if an optional value of type T can be found under the key "Name". The optional may + contain a value or it may be empty. Otherwise returns an error. Note that for some formats a wrong key is + indistinguishable from an empty optional, so make sure to provide the correct key. + +Error handling +-------------- + +Errors are handled by returning error codes. The type IOStatus contains an error code and an optional string with +additional information. The type IOResult contains either a value or an IOStatus that describes an error. Operations +that can fail return an ``IOResult`` where T is the type of the value that is produced by the operation if it is +successful. Except where necessary because of dependencies, the framework does not throw nor catch any exceptions. +IOContext and IOObject implementations are expected to store errors. During serialization, ``add_...`` operations fail +without returning errors, but the error is stored in the IOObject and subsequent calls are usually no-ops. During +deserialization, the values produced must usually be used or inspected, so ``expect_...`` operations return an IOResult. +The ``apply`` utility function provides a simple way to inspect the result of multiple ``expect_...`` operations and use +the values if all are successful. See the documentation of ``IOStatus``, ``IOResult`` and ``apply`` below for more +details. + +Adding a new data type to be serialized +--------------------------------------- + +Serialization of a new type T can be customized by providing *either* member functions ``serialize`` and ``deserialize`` +*or* free functions ``serialize_internal`` and ``deserialize_internal``. + +The ``void serialize(IOContext& io)`` member function takes an IO context and uses ``create_object`` and ``add_...`` +operations to add data. The static ``IOResult deserialize(IOContext& io)`` member function takes an IO context and +uses ``expect_...`` operations to retrieve the data. The ``apply`` utility function can be used to inspect the result of +the ``expect_...`` operations and construct the object of type T. +E.g.: + +.. code-block:: cpp + + struct Foo { + int i; + template + void serialize(IOContext& io) { + auto obj = io.create_object("Foo"); + obj.add_element("i", i); + } + template + static IOResult deserialize(IOContext& io) { + auto obj = io.expect_object("Foo"); + auto i_result = obj.expect_element("i", mio::Tag{}); + return mio::apply(io, [](auto&& i) { return Foo{i}; }, i_result); + } + }; + +The free functions ``serialize_internal`` and ``deserialize_internal`` must be found with argument-dependent lookup +(ADL). They can be used if no member function should or can be added to the type. See the code in ``memilio/io/io.h`` +for examples where this was done for, e.g., Eigen3 matrices and STL containers. + +Adding a new format +------------------- + +Implement concepts IOContext and IOObject that provide the operations listed above. Your implementation should handle +all built-in types as well as ``std::string``. It may handle other types (e.g., STL containers) as well if it can do so +more efficiently than the provided general free functions. + +Other IO modules +================ + +- HDF5 support classes for C++ +- Reading of mobility matrix files + +The command line interface +========================== + +We provide a function ``mio::command_line_interface`` in the header ``memilio/io/cli.h``, that can be used to write to +or read from a parameter set. It can take parameters from command line arguments (i.e. the content of ``argv`` in the +main function), and assign them to or get them from a ``mio::ParameterSet``. A small example can be seen in +``cpp/examples/cli.cpp``. + +The command line interface (CLI) provides some non-parameter options listed below. + +====================== ===================================== +Name (Alias) Description +====================== ===================================== +``--help`` (``-h``) Shows the basic usage of the CLI, and lists each parameter by name, as well as any alias and + description. Takes priority before all other options and exits the program. +``--print_option`` Can be used with a (space-separated) list of parameter names or aliases (both without dashes) to + print the current values of each parameter to the terminal. This shows the correct JSON format + used by the parameters. Exits after use. +``--read_from_json`` Allows reading parameters from a file instead of the command line. Both parameter names and + aliases can be used, for example: + + .. code-block:: json + + {"" : , "" : } + +``--write_to_json`` Writes *all* parameters with their current values to a specified file. +====================== ===================================== + +In general, an option is defined as a string, which consists either of two dashes followed by a name (e.g. ``--help``), +or a single dash followed by an alias (e.g. ``-h``). Apart from the built-in options, the names each refer to a +parameter that can be set. + +To set the value of a parameter from the command line, first type the corresponding parameter option (see ``--help``), +followed by the value that should be assigned (reference ``--print_option``). Values are given as a JSON value +corresponding to the Type of the parameter. Note that some characters may need to be escaped or quoted. For example, the +JSON string ``"some string"`` must be entered as ``\\"some string\\"`` or ``'"some string"'``. + +Working with the History object +=============================== + +The History object provides a way to save data throughout the simulation process. It offers an interface where users can +define the data to be saved from a given object using Loggers and the method of saving it using Writers. Afterward, the +user can access this data from the History object and manipulate it. For a basic Logger use case, refer to +`this example <../../examples/history.cpp>`__. For an example demonstrating using a Logger in the ABM, refer to +`this example <../../examples/abm_history_example.cpp>`__. + +Loggers +------- + +The ``Logger`` struct is a tool for logging data from a given object. Each user-implemented Logger must have a ``Type`` +and implement two functions: ``Type log(const T&)`` and ``bool should_log(const T&)``. The input ``T`` for these +functions is the same as the one given to the ``History`` member-function ``History::log``, e.g. ``Model&`` in the ABM. + +- ``Type``: Return Type of ``log``. + +- ``log``: This function determines which data from the input ``T`` is saved. It must have the same return Type ``Type`` + as the Loggers Type ``Type``. + +- ``should_log``: This function must return a boolean to determine if data should be logged and can use the input ``T`` + for this, e.g. if ``T`` fulfills some criteria. + +Users can derive their Loggers from ``LogOnce`` or ``LogAlways`` to use a predefined ``should_log`` function. +``LogOnce`` logs only at the first call of ``Logger::log()``, while ``LogAlways`` logs every time ``log`` is called. +All implemented Loggers must be default constructible/destructible. For user-defined examples in the ABM, refer to +`this file <../../models/abm/common_abm_loggers.h>`__. + +.. code-block:: cpp + + struct LoggerExample { /* : public LogOnce/LogAlways if one wants to derive the should_log from these. */ + using Type = /* type of the record */; + /* Below, T must be replaced by the type T from History::log(t). */ + Type log(const T& t) + { + return /* something of type Type */; + } + bool should_log(const T& t) + { + /* Determine whether log and add_record should be called by History::log(t). */ + return /* true or false */; + } + }; + +Writers +------- + +The ``Writer`` struct defines how to store the logged data from one or more implemented ``Loggers``. Each +user-implemented ``Writer`` must have a ``Data`` Type and implement the +``template static void add_record(const typename Logger::Type& t, Data& data)`` function. + +- ``Data``: This is some kind of container that stores the data returned by the Loggers. For example, this can be a + ``TimeSeries`` or depend on the Loggers (like ``std::tuple...>``). + +- ``add_record``: This manipulates the passed Data member of the ``History`` class to store the value ``t`` returned by + the Loggers. It is used whenever ``History::log`` is called and ``Logger::should_log`` is true. + +A predefined universal ``Writer`` called ``DataWriterToMemory`` is already implemented in `history.h `__. +This stores the data from the loggers in a tuple of vectors every time the Logger is called. Another ``Writer`` named +``TimeSeriesWriter`` can be found in `this file <../../models/abm/common_abm_loggers.h>`__, which saves data in a +Timeseries. The according Logger has to have a suitable return type. + +.. code-block:: cpp + + template + struct DataWriterExample { + using Data = /* Container for the stored data of the Loggers */; + template + static void add_record(const typename Logger::Type& t, Data& data) + { + /* Manipulation of data to store the value t returned by the Loggers */; + } + }; + +History +------- + +The ``History`` class manages the Writers and Loggers and provides an interface to log data. It is templated on one +``Writer`` and several suitable and unique ``Loggers``. To use the Writer to log something, the ``History`` provides the +function ``void log(const T& t)`` to call the ``add_record`` function of the ``Writer`` if the Logger function +``should_log`` returns true. + +To access the data from the ``History`` class after logging, we provide the function ``get_log`` to access all records. +For this, the lifetime of the ``History`` has to be as long as one wants to have access to the data, e.g., a history +should not be constructed in the function it is called in when data is needed later. + +To access data from a specific Logger, one can use ``std::get`` where x is the position of the Logger in the template +argument list of the ``History`` object. Refer to `this example <../../examples/history.cpp>`__ for a simple +implementation of a history object and `this full ABM example <../../simulation/abm.cpp>`__ for a more advanced use case +of the History object with several History objects in use. + +As mentioned, if multiple Writers have to be used simultaneously, a separate History object is needed for each Writer. +For a use case of this, refer to `the ABM Simulation advance function <../../models/abm/simulation.cpp>`__. From 7f81bac61b469d5f4c8699d0bcd1ef6198be08c1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:13:06 +0100 Subject: [PATCH 47/62] some enhancements --- docs/source/c++/mobility_based_abm.rst | 29 +++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst index 2cee6d0eb5..e7aca7fdda 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/c++/mobility_based_abm.rst @@ -1,10 +1,10 @@ Agent-Based Model ================= -This module models and simulates the epidemic using an agent-based model (*ABM*) approach. Unlike the -:doc:`SECIR ` compartmental model that uses a system of ODEs, this model simulates +This module models and simulates the epidemic using an agent-based model (*ABM*) approach. Unlike the compartmental models that use a system of ODEs, this model simulates the spread of COVID-19 in a population with discrete persons (the agents) moving throughout locations in the model and interacting with (infecting) each other. For a detailed overview of the ABM, see + - Kerkmann D, Korf S, et al. Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread. https://doi.org/10.48550/arXiv.2410.08050 Structure @@ -12,7 +12,7 @@ Structure The model consists of the following major classes: -1. **Person**: Represents an agent of the model. A person has an ID (i.e. a unique number), an age, a location, +1. **Person**: Represents an agent of the model. A person has an ID (i.e. and a list with their assigned locations (i.e. the locations they visit during the simulation). They can perform tests and wear masks. Every person has lists with past and current infections and vaccinations. 2. **Infection**: Collection of all information about a person's infection, i.e. infectiousness, infection course, @@ -44,14 +44,13 @@ level of the susceptible person. Mobility Phase ~~~~~~~~~~~~~~~~~~ -During the mobility phase, each person may change their location. Mobility follows complex +During the mobility phase, each person may change their location. Mobility follow `rules `_, considering the current location, time of day, and properties of the person (e.g. age). Some location changes are deterministic and regular (e.g. going to work), while others are random (e.g. going shopping or to a social event in the evening/on the weekend). When agents are infected, they are quarantined and cannot change their location. You can restrict some mobility rules by allowing only a proportion of people to enter specific locations. -Another way of mobility we use in the `simulation of Braunschweig `_ is using trips. A trip -consists of the ID of the person that performs this trip, a time point when this trip is performed, and the destination. +Another way of mobility is using trips. A trip consists of the ID of the person that performs this trip, a time point when this trip is performed, and the destination. At the beginning of the simulation, a list with all trips is initialized and followed during the simulation. There can be different trips on the weekend than during the week, but other than that, the agents do the same trips every day. As before, agents that are in quarantine or in the hospital cannot change their location. @@ -63,14 +62,14 @@ Disease Progression The ABM implements a detailed disease progression model that captures the full course of an infection from exposure to resolution. The disease progression is modeled through the ``Infection`` class, which contains: 1. **Infection States**: Similar to the SECIR model, an infected person progresses through states: - - **Susceptible**: Initial state before infection - - **Exposed**: Infected but not yet infectious - - **InfectedNoSymptoms**: Infectious but without symptoms - - **InfectedSymptoms**: Showing symptoms but not severe - - **InfectedSevere**: Severe infection requiring hospitalization - - **InfectedCritical**: Critical infection requiring ICU - - **Recovered**: Recovered from infection with immunity - - **Dead**: Deceased due to infection + - `**Susceptible**`: Initial state before infection + - `**Exposed**`: Infected but not yet infectious + - `**InfectedNoSymptoms**`: Infectious but without symptoms + - `**InfectedSymptoms**`: Showing symptoms but not severe + - `**InfectedSevere**`: Severe infection requiring hospitalization + - `**InfectedCritical**`: Critical infection requiring ICU + - `**Recovered**`: Recovered from infection with immunity + - `**Dead**`: Deceased due to infection 2. **Viral Load Dynamics**: The model implements realistic viral load curves based on scientific data: - **Incline Phase**: Rapid increase in viral concentration @@ -118,7 +117,7 @@ The examples demonstrate two approaches: // Run simulation with history object sim.advance(tmax, history); - + Interventions ~~~~~~~~~~~~~~~~~~ From 661dbab00f10517f1c52b11b9a4bf8066a73b7ab Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:25:44 +0100 Subject: [PATCH 48/62] list enhancement abm --- docs/source/c++/mobility_based_abm.rst | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst index e7aca7fdda..0518e2bdba 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/c++/mobility_based_abm.rst @@ -62,34 +62,34 @@ Disease Progression The ABM implements a detailed disease progression model that captures the full course of an infection from exposure to resolution. The disease progression is modeled through the ``Infection`` class, which contains: 1. **Infection States**: Similar to the SECIR model, an infected person progresses through states: - - `**Susceptible**`: Initial state before infection - - `**Exposed**`: Infected but not yet infectious - - `**InfectedNoSymptoms**`: Infectious but without symptoms - - `**InfectedSymptoms**`: Showing symptoms but not severe - - `**InfectedSevere**`: Severe infection requiring hospitalization - - `**InfectedCritical**`: Critical infection requiring ICU - - `**Recovered**`: Recovered from infection with immunity - - `**Dead**`: Deceased due to infection + * **Susceptible**: Initial state before infection + * **Exposed**: Infected but not yet infectious + * **InfectedNoSymptoms**: Infectious but without symptoms + * **InfectedSymptoms**: Showing symptoms but not severe + * **InfectedSevere**: Severe infection requiring hospitalization + * **InfectedCritical**: Critical infection requiring ICU + * **Recovered**: Recovered from infection with immunity + * **Dead**: Deceased due to infection 2. **Viral Load Dynamics**: The model implements realistic viral load curves based on scientific data: - - **Incline Phase**: Rapid increase in viral concentration - - **Peak**: Maximum viral load - - **Decline Phase**: Gradual decrease until clearance + * **Incline Phase**: Rapid increase in viral concentration + * **Peak**: Maximum viral load + * **Decline Phase**: Gradual decrease until clearance 3. **Infectiousness**: The probability of transmitting the virus depends on viral load through an invlogit function: 4. **Stochastic Transitions**: Progression between states is stochastic, with age-dependent probabilities: - - The duration in each state is drawn from distributions in the model parameters - - Prior immunity (from vaccination or previous infection) affects: - - Viral load (reduced peak) - - Severity progression (reduced probability of severe outcomes) - - Duration of infectious period + * The duration in each state is drawn from distributions in the model parameters + * Prior immunity (from vaccination or previous infection) affects: + * Viral load (reduced peak) + * Severity progression (reduced probability of severe outcomes) + * Duration of infectious period 5. **Infection Course**: The infection course is determined by: - - Age group of the person - - Virus variant - - Protection status (prior immunity) - - Random factors (individual variation) + * Age group of the person + * Virus variant + * Protection status (prior immunity) + * Random factors (individual variation) Data Collection From 1ae70a0482cf1402b8831eb506bef8ed9bf843b9 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:27:17 +0100 Subject: [PATCH 49/62] rechange --- docs/source/c++/mobility_based_abm.rst | 40 +++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst index 0518e2bdba..e00c5fe3d1 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/c++/mobility_based_abm.rst @@ -62,34 +62,34 @@ Disease Progression The ABM implements a detailed disease progression model that captures the full course of an infection from exposure to resolution. The disease progression is modeled through the ``Infection`` class, which contains: 1. **Infection States**: Similar to the SECIR model, an infected person progresses through states: - * **Susceptible**: Initial state before infection - * **Exposed**: Infected but not yet infectious - * **InfectedNoSymptoms**: Infectious but without symptoms - * **InfectedSymptoms**: Showing symptoms but not severe - * **InfectedSevere**: Severe infection requiring hospitalization - * **InfectedCritical**: Critical infection requiring ICU - * **Recovered**: Recovered from infection with immunity - * **Dead**: Deceased due to infection + - **Susceptible**: Initial state before infection + - **Exposed**: Infected but not yet infectious + - **InfectedNoSymptoms**: Infectious but without symptoms + - **InfectedSymptoms**: Showing symptoms but not severe + - **InfectedSevere**: Severe infection requiring hospitalization + - **InfectedCritical**: Critical infection requiring ICU + - **Recovered**: Recovered from infection with immunity + - **Dead**: Deceased due to infection 2. **Viral Load Dynamics**: The model implements realistic viral load curves based on scientific data: - * **Incline Phase**: Rapid increase in viral concentration - * **Peak**: Maximum viral load - * **Decline Phase**: Gradual decrease until clearance + - **Incline Phase**: Rapid increase in viral concentration + - **Peak**: Maximum viral load + - **Decline Phase**: Gradual decrease until clearance 3. **Infectiousness**: The probability of transmitting the virus depends on viral load through an invlogit function: 4. **Stochastic Transitions**: Progression between states is stochastic, with age-dependent probabilities: - * The duration in each state is drawn from distributions in the model parameters - * Prior immunity (from vaccination or previous infection) affects: - * Viral load (reduced peak) - * Severity progression (reduced probability of severe outcomes) - * Duration of infectious period + - The duration in each state is drawn from distributions in the model parameters + - Prior immunity (from vaccination or previous infection) affects: + - Viral load (reduced peak) + - Severity progression (reduced probability of severe outcomes) + - Duration of infectious period 5. **Infection Course**: The infection course is determined by: - * Age group of the person - * Virus variant - * Protection status (prior immunity) - * Random factors (individual variation) + - Age group of the person + - Virus variant + - Protection status (prior immunity) + - Random factors (individual variation) Data Collection From 902fe7bcb634de195971a2121097d5e2f178170c Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Thu, 20 Mar 2025 15:55:01 +0100 Subject: [PATCH 50/62] update ABM documentation --- docs/source/c++/mobility_based_abm.rst | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst index e00c5fe3d1..9b9546f443 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/c++/mobility_based_abm.rst @@ -1,4 +1,4 @@ -Agent-Based Model +Realistic Agent-Based Model ================= This module models and simulates the epidemic using an agent-based model (*ABM*) approach. Unlike the compartmental models that use a system of ODEs, this model simulates @@ -62,6 +62,7 @@ Disease Progression The ABM implements a detailed disease progression model that captures the full course of an infection from exposure to resolution. The disease progression is modeled through the ``Infection`` class, which contains: 1. **Infection States**: Similar to the SECIR model, an infected person progresses through states: + - **Susceptible**: Initial state before infection - **Exposed**: Infected but not yet infectious - **InfectedNoSymptoms**: Infectious but without symptoms @@ -302,9 +303,3 @@ Currently, a few things are not yet implemented, such as: - Different trips for each day. - Trace functionality. - - -Overview of the ``abm`` namespace: ------------------------------------------ - -.. doxygennamespace:: mio::abm \ No newline at end of file From 8f65c2718063f5e76d7969efc8b312425fbbf176 Mon Sep 17 00:00:00 2001 From: reneSchm <49305466+reneSchm@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:17:51 +0100 Subject: [PATCH 51/62] fix titles --- docs/source/c++/io.rst | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/source/c++/io.rst b/docs/source/c++/io.rst index 30e12fd998..325cac418a 100644 --- a/docs/source/c++/io.rst +++ b/docs/source/c++/io.rst @@ -1,4 +1,4 @@ -MEmilio C++ IO +Input / Output ============== This document describes utilities for reading and writing data from and to files in different formats, in cases where @@ -15,7 +15,7 @@ This document describes utilities for reading and writing data from and to files The Serialization framework -=========================== +--------------------------- Serialization is the process of converting a data structure or object into a different format that can be stored or transmitted. In this section we will show you how to make use of and implement MEmilio's serialization feature, as @@ -30,7 +30,7 @@ Our guiding example will be a humble struct ``Foo``: Using serialization --------------------- +~~~~~~~~~~~~~~~~~~~ In the next sections we will explain how to implement serialization (both for types and formats), here we quickly show how to use it once it already is implemented for a type. In the following examples, we serialize (write) ``Foo`` to a @@ -52,7 +52,7 @@ There is also support for a binary format. If you want to use a format directly ``serialize_json``/``deserialize_json`` and ``serialize_binary``/``deserialize_binary`` functions. Main functions and types ------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~ - **functions serialize and deserialize**: Main entry points to the framework to write and read values, respectively. The functions expect an IOContext @@ -63,7 +63,7 @@ Main functions and types Used for error handling, see section "Error Handling" below. Default serialization ----------------------- +~~~~~~~~~~~~~~~~~~~~~ Before we get into the details of the framework, this feature provides an easy and convenient alternative to implementing the serialize and deserialize functions. To give an example: @@ -113,7 +113,7 @@ value provided to ``add`` is also used to assign a value during deserialization, directly in the function (i.e. as a non-const lvalue reference). Concepts --------- +~~~~~~~~ 1. **IOContext** @@ -170,7 +170,7 @@ Concepts indistinguishable from an empty optional, so make sure to provide the correct key. Error handling --------------- +~~~~~~~~~~~~~~ Errors are handled by returning error codes. The type IOStatus contains an error code and an optional string with additional information. The type IOResult contains either a value or an IOStatus that describes an error. Operations @@ -184,7 +184,7 @@ the values if all are successful. See the documentation of ``IOStatus``, ``IORes details. Adding a new data type to be serialized ---------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Serialization of a new type T can be customized by providing *either* member functions ``serialize`` and ``deserialize`` *or* free functions ``serialize_internal`` and ``deserialize_internal``. @@ -217,20 +217,20 @@ The free functions ``serialize_internal`` and ``deserialize_internal`` must be f for examples where this was done for, e.g., Eigen3 matrices and STL containers. Adding a new format -------------------- +~~~~~~~~~~~~~~~~~~~ Implement concepts IOContext and IOObject that provide the operations listed above. Your implementation should handle all built-in types as well as ``std::string``. It may handle other types (e.g., STL containers) as well if it can do so more efficiently than the provided general free functions. Other IO modules -================ +---------------- - HDF5 support classes for C++ - Reading of mobility matrix files The command line interface -========================== +-------------------------- We provide a function ``mio::command_line_interface`` in the header ``memilio/io/cli.h``, that can be used to write to or read from a parameter set. It can take parameters from command line arguments (i.e. the content of ``argv`` in the @@ -250,7 +250,7 @@ Name (Alias) Description ``--read_from_json`` Allows reading parameters from a file instead of the command line. Both parameter names and aliases can be used, for example: - .. code-block:: json + .. code-block:: {"" : , "" : } @@ -267,7 +267,7 @@ corresponding to the Type of the parameter. Note that some characters may need t JSON string ``"some string"`` must be entered as ``\\"some string\\"`` or ``'"some string"'``. Working with the History object -=============================== +------------------------------- The History object provides a way to save data throughout the simulation process. It offers an interface where users can define the data to be saved from a given object using Loggers and the method of saving it using Writers. Afterward, the @@ -276,7 +276,7 @@ user can access this data from the History object and manipulate it. For a basic `this example <../../examples/abm_history_example.cpp>`__. Loggers -------- +~~~~~~~ The ``Logger`` struct is a tool for logging data from a given object. Each user-implemented Logger must have a ``Type`` and implement two functions: ``Type log(const T&)`` and ``bool should_log(const T&)``. The input ``T`` for these @@ -312,7 +312,7 @@ All implemented Loggers must be default constructible/destructible. For user-def }; Writers -------- +~~~~~~~ The ``Writer`` struct defines how to store the logged data from one or more implemented ``Loggers``. Each user-implemented ``Writer`` must have a ``Data`` Type and implement the @@ -342,7 +342,7 @@ Timeseries. The according Logger has to have a suitable return type. }; History -------- +~~~~~~~ The ``History`` class manages the Writers and Loggers and provides an interface to log data. It is templated on one ``Writer`` and several suitable and unique ``Loggers``. To use the Writer to log something, the ``History`` provides the From 416623fbbd42ebd742cd05821ba3b0e88449e11d Mon Sep 17 00:00:00 2001 From: reneSchm <49305466+reneSchm@users.noreply.github.com> Date: Thu, 20 Mar 2025 16:21:48 +0100 Subject: [PATCH 52/62] [wip] ode model creation --- docs/source/c++/ode_creation.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/source/c++/ode_creation.rst b/docs/source/c++/ode_creation.rst index b64978fa26..237fa7b0d7 100644 --- a/docs/source/c++/ode_creation.rst +++ b/docs/source/c++/ode_creation.rst @@ -1,2 +1,21 @@ ODE Model Creation ================== + +Model definition +---------------- + +Before implementing a model in MEmilio, we need to do a some math, in particular, define an initial value problem +given by a system of ordinary differential equations. For example we consider a SIRD model given by + +.. math:: + \begin{aligned} + S'(t) & = -\rho\phi\ \frac(S(t)*I(t))(N) \\ + I'(t) & = \rho\phi\ \frac(S(t)*I(t))(N) - \frac(\mu_R + \mu_D)(T_I)I(t) \\ + R'(t) & = \frac(\mu_R)(T_I)I(t) \\ + D'(t) & = \frac(\mu_R)(T_I)I(t) \\ + \end{aligned} + +and some initial values for :math:`t=0`. Here :math:`N := S(t) + I(t) + R(t)`. + +This type of model is called compartmental model, because the model population is represented by discrete infection +states**S**usceptible, **I**nfected, **R**ecovered, **D**ead, also called compartments. From 7dd18b3dbbd820462bdf71b8c5372e8bf5d762ff Mon Sep 17 00:00:00 2001 From: Anna Wendler <106674756+annawendler@users.noreply.github.com> Date: Fri, 21 Mar 2025 12:05:55 +0100 Subject: [PATCH 53/62] adjust structure --- docs/source/c++/aggregated_models.rst | 1 + docs/source/c++/glct.rst | 36 ++++++ docs/source/c++/ide.rst | 17 ++- docs/source/c++/lct.rst | 154 +++++++++++++++++++++++--- 4 files changed, 191 insertions(+), 17 deletions(-) create mode 100644 docs/source/c++/glct.rst diff --git a/docs/source/c++/aggregated_models.rst b/docs/source/c++/aggregated_models.rst index 6371f66726..86cc670167 100644 --- a/docs/source/c++/aggregated_models.rst +++ b/docs/source/c++/aggregated_models.rst @@ -8,5 +8,6 @@ There are different equation-based models implemented in MEmilio that consider a ode lct + glct sde ide \ No newline at end of file diff --git a/docs/source/c++/glct.rst b/docs/source/c++/glct.rst new file mode 100644 index 0000000000..637b118739 --- /dev/null +++ b/docs/source/c++/glct.rst @@ -0,0 +1,36 @@ +GLCT model +=========== + +Introduction +------------- + +This model is based on the Generalized Linear Chain Trick (GLCT). + +The GLCT provides the option to use phase-type distributed stay times in the compartments through the use of subcompartments. The Generalized Linear Chain Trick is an extension of the Linear Chain Trick (as the name already suggests). Phase-type distributions are dense in the field of all positive-valued distributions. Therefore, for any positive-valued distribution, a phase-type distribution of arbitrary precision can be identified. +The normal ODE models have (possibly unrealistic) exponentially distributed stay times. +The GLCT model can still be described by an ordinary differential equation system. + +For the concept see + +- Hurtado PJ and Kirosingh AS (2019) Generalizations of the ‘Linear Chain Trick’: incorporating more flexible dwell time distributions into mean field ODE models. Journal of Mathematical Biology. https://doi.org/10.1007/s00285-019-01412-w +- Hurtado PF and Richards C (2021) Building mean field ODE models using the generalized linear chain trick & Markov chain theory. Journal of Biological Dynamics. https://doi.org/10.1080/17513758.2021.1912418 + +Here, the eight compartments + +- `Susceptible` (:math:`S`), may become Exposed at any time +- `Exposed` (:math:`E`), becomes InfectedNoSymptoms after some time +- `InfectedNoSymptoms` (:math:`I_{NS}`), becomes InfectedSymptoms or Recovered after some time +- `InfectedSymptoms` (:math:`I_{Sy}`), becomes InfectedSevere or Recovered after some time +- `InfectedSevere` (:math:`I_{Sev}`), becomes InfectedCritical or Recovered after some time +- `InfectedCritical` (:math:`I_{Cr}`), becomes Recovered or Dead after some time +- `Recovered` (:math:`R`) +- `Dead` (:math:`D`) + +are used to simulate the spread of the disease. +It is possible to include phase-type distributed stay times for the five compartments Exposed, InfectedNoSymptoms, InfectedSymptoms, InfectedSevere and InfectedCritical. + +Simulation +----------- + +How to: Set up and run a simulation of the GLCT-SECIR model +------------------------------------------------------------ diff --git a/docs/source/c++/ide.rst b/docs/source/c++/ide.rst index d07d8829c4..119b816653 100644 --- a/docs/source/c++/ide.rst +++ b/docs/source/c++/ide.rst @@ -1,4 +1,4 @@ -IDE Models +IDE models ========== In MEmilio, two models based on integro-differential equations are implemented. They have different infection states and are solved with different numerical solvers. Their respective usage is described below. @@ -7,6 +7,9 @@ In MEmilio, two models based on integro-differential equations are implemented. IDE-SECIR model ---------------- +Introduction +~~~~~~~~~~~~~ + This model is based on integro-differential equations. The eight compartments @@ -21,6 +24,9 @@ The eight compartments are used to simulate the spread of the disease and corresponding transition distributions can be set in a flexible way. +Simulation +~~~~~~~~~~~ + The simulation runs in discrete time steps using a non-standard numerical scheme. This approach is based on the paper `"A non-standard numerical scheme for an age-of infection epidemic model" by Messina et al., Journal of Computational Dynamics, 2022 `_. For a detailed description and application of the model, see: @@ -29,7 +35,7 @@ Wendler A, Plötzke L, Tritzschak H, Kühn MJ (2024) A nonstandard numerical sch How to: Set up and run a simulation of the IDE-SECIR model ------------------------------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The numerical solver requires a fixed time step size which we define by @@ -215,6 +221,8 @@ If one wants to interpolate the results to a ``TimeSeries`` containing only full IDE-SEIR model --------------- +Introduction +~~~~~~~~~~~~~ The four compartments - `Susceptible` (:math:`S`), may become exposed at any time - `Exposed` (:math:`E`), becomes infected after some time @@ -223,6 +231,9 @@ The four compartments are used to simulate the spread of the disease. +Simulation +~~~~~~~~~~~ + The simulation runs in discrete time steps using a trapezoidal rule. The model and the numerical scheme is based on the paper `"Modeling infectious diseases using integro-differential equations: Optimal control strategies for policy decisions and Applications in COVID-19" by Keimer and Pflug, 2020 `_. @@ -231,7 +242,7 @@ For a detailed description and application of the model, see: Plötzke L (2021) Modellierung epidemischer Infektionskrankheiten auf der Basis von gewöhnlichen und Integro-Differentialgleichungen. Bachelor thesis, University of Cologne. https://elib.dlr.de/143504/ How to: Set up and run a simulation of the IDE-SEIR model ----------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To initialize the model, the following inputs need to be passed to the model constructor: - a time series containing the number of Susceptibles for a large enough number of time points before the start of the simulation, diff --git a/docs/source/c++/lct.rst b/docs/source/c++/lct.rst index 12b61cf3b6..f425463f3f 100644 --- a/docs/source/c++/lct.rst +++ b/docs/source/c++/lct.rst @@ -1,21 +1,20 @@ -LCT Models -========== +Linear Chain Trick model +========================= -In MEmilio, two models based on Linear Chain Trick are implemented. Their respective usage is described below. - - -LCT-SECIR model ----------------- +Introduction +------------- The Linear Chain Trick provides the option to use Erlang-distributed stay times in the compartments through the use of subcompartments. The normal ODE models have (possibly unrealistic) exponentially distributed stay times. The LCT model can still be described by an ordinary differential equation system. -For the concept see -- Lena Plötzke, "Der Linear Chain Trick in der epidemiologischen Modellierung als Kompromiss zwischen gewöhnlichen und Integro-Differentialgleichungen", 2023. (https://elib.dlr.de/200381/, German only) -- P. J. Hurtado und A. S. Kirosingh, "Generalizations of the ‘Linear Chain Trick’: incorporating more flexible dwell time distributions into mean field ODE models“, 2019. (https://doi.org/10.1007/s00285-019-01412-w) +For a detailed description and application of the model, see: + +- Plötzke L, Wendler A, Schmieding R, Kühn MJ (2024) Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions. Under review. https://doi.org/10.48550/arXiv.2412.09140 +- Hurtado PJ und Kirosingh AS (2019) Generalizations of the ‘Linear Chain Trick’: incorporating more flexible dwell time distributions into mean field ODE models. Journal of Mathematical Biology. https://doi.org/10.1007/s00285-019-01412-w The eight compartments + - `Susceptible` (:math:`S`), may become Exposed at any time - `Exposed` (:math:`E`), becomes InfectedNoSymptoms after some time - `InfectedNoSymptoms` (:math:`I_{NS}`), becomes InfectedSymptoms or Recovered after some time @@ -29,16 +28,143 @@ are used to simulate the spread of the disease. It is possible to include subcompartments for the five compartments Exposed, InfectedNoSymptoms, InfectedSymptoms, InfectedSevere and InfectedCritical. You can divide the population according to different groups, e.g. AgeGroups or gender and choose parameters according to groups. +Simulation +----------- How to: Set up and run a simulation of the LCT-SECIR model ----------------------------------------------------------- +We start by defining the number of subcompartments and constructing the model. + +.. code-block:: cpp + + // Simple example to demonstrate how to run a simulation using an LCT-SECIR 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. + constexpr size_t NumExposed = 2, NumInfectedNoSymptoms = 3, NumInfectedSymptoms = 1, NumInfectedSevere = 1, + NumInfectedCritical = 5; + using InfState = mio::lsecir::InfectionState; + using LctState = mio::LctInfectionState; + using Model = mio::lsecir::Model; + Model model; + + // Variable defines whether the class Initializer is used to define an initial vector from flows or whether a manually + // defined initial vector is used to initialize the LCT model. + bool use_initializer_flows = false; + + ScalarType tmax = 10; + + // Set Parameters. + model.parameters.get()[0] = 3.2; + model.parameters.get()[0] = 2.; + model.parameters.get()[0] = 5.8; + model.parameters.get()[0] = 9.5; + model.parameters.get()[0] = 7.1; + + model.parameters.get()[0] = 0.05; + + mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); + 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()[0] = 0.7; + model.parameters.get()[0] = 0.25; + model.parameters.get()[0] = 0.09; + model.parameters.get()[0] = 0.2; + model.parameters.get()[0] = 0.25; + model.parameters.get()[0] = 0.3; + + if (use_initializer_flows) { + // Example how to use the class Initializer for the definition of an initial vector for the LCT model. + + ScalarType dt = 0.001; + Eigen::VectorX total_population = Eigen::VectorX::Constant(1, 1000000.); + Eigen::VectorX deaths = Eigen::VectorX::Constant(1, 10.); + Eigen::VectorX total_confirmed_cases = Eigen::VectorX::Constant(1, 16000.); + + // Create TimeSeries with num_transitions elements. + int num_transitions = (int)mio::lsecir::InfectionTransition::Count; + mio::TimeSeries flows(num_transitions); + + mio::TimeSeries::Vector vec_flows(num_transitions); + vec_flows[(int)mio::lsecir::InfectionTransition::SusceptibleToExposed] = 2.0; + vec_flows[(int)mio::lsecir::InfectionTransition::ExposedToInfectedNoSymptoms] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedNoSymptomsToInfectedSymptoms] = 8.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedNoSymptomsToRecovered] = 4.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSymptomsToInfectedSevere] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSymptomsToRecovered] = 4.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSevereToInfectedCritical] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSevereToRecovered] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedCriticalToDead] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedCriticalToRecovered] = 1.0; + vec_flows = vec_flows * dt; + // Add initial time point to time series. + flows.add_time_point(-110, vec_flows); + // Add further time points until time 0. + while (flows.get_last_time() < -dt / 2) { + flows.add_time_point(flows.get_last_time() + dt, vec_flows); + } + + // Set initialization vector for the LCT model. + mio::lsecir::Initializer initializer(std::move(flows), model); + initializer.set_tol_for_support_max(1e-6); + auto status = initializer.compute_initialization_vector(total_population, deaths, total_confirmed_cases); + if (status) { + return 1; + } + } + else { + // 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> initial_populations = {{750}, {30, 20}, {20, 10, 10}, {50}, + {50}, {10, 10, 5, 3, 2}, {20}, {10}}; + + // 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()) || + (initial_populations[(size_t)InfState::Exposed].size() != NumExposed) || + (initial_populations[(size_t)InfState::InfectedNoSymptoms].size() != NumInfectedNoSymptoms) || + (initial_populations[(size_t)InfState::InfectedSymptoms].size() != NumInfectedSymptoms) || + (initial_populations[(size_t)InfState::InfectedSevere].size() != NumInfectedSevere) || + (initial_populations[(size_t)InfState::InfectedCritical].size() != NumInfectedCritical) || + (initial_populations[(size_t)InfState::Recovered].size() != + LctState::get_num_subcompartments()) || + (initial_populations[(size_t)InfState::Dead].size() != + LctState::get_num_subcompartments())) { + 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 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 result = mio::simulate(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 population_no_subcompartments = model.calculate_compartments(result); + auto interpolated_results = mio::interpolate_simulation_result(population_no_subcompartments); + interpolated_results.print_table({"S", "E", "C", "I", "H", "U", "R", "D "}, 12, 4); -GLCT-SECIR model ------------------ -How to: Set up and run a simulation of the GLCT-SECIR model ------------------------------------------------------------- From b81128c01985f79abd2f801006788de605258453 Mon Sep 17 00:00:00 2001 From: jubicker Date: Fri, 21 Mar 2025 12:31:12 +0100 Subject: [PATCH 54/62] inline code dabm smm --- docs/source/c++/diffusive_abm.rst | 4 ++-- docs/source/c++/metapop.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/c++/diffusive_abm.rst b/docs/source/c++/diffusive_abm.rst index 44d48bb254..f3cffbaa4b 100644 --- a/docs/source/c++/diffusive_abm.rst +++ b/docs/source/c++/diffusive_abm.rst @@ -8,7 +8,7 @@ The features of an agent are its position and its infection state. The evolution with :math:`X` the vector of all agents' positions and :math:`Z` the vector of all agents' infection states. The operator :math:`G` defines the infection state adoptions and only acts on :math:`Z`, while :math:`L` defines movement, i.e. location changes, only acting on :math:`X`. Infection state adoptions are modeled with independent Poisson processes given by adoption rate functions. Adoption rates always depend on the source infection state. If an adoption event requires interaction of agents (e.g. disease transmission), the corresponding rate depends not only on the source infection state, but also on other infection states, the `influences`. An adoption rate that only depends on the source infection state, e.g. recovery or worsening of disease symptoms, is called `first-order` adoption rate and an adoption rate that has influences is called `second-order` adoption rate. Movement is modeled with independent diffusion processes. A temporal Gillespie algorithm (a direct method without rejection sampling) is used for simulation. Therefore, :math:`G` and :math:`L` are not implemented explicitly, instead their effects are sampled via the `move` and `adoption_rate` functions, respectively. -The Model class needs an Implementation class as template argument which provides the domain agents move and interact in. A quadwell potential given in the class QuadWellModel is implemented, but any other suitable potential can be used as implementation. +The Model class needs an Implementation class as template argument which provides the domain agents move and interact in. A quadwell potential given in the class ``QuadWellModel`` is implemented, but any other suitable potential can be used as implementation. Simulation ----------- @@ -137,7 +137,7 @@ Additionally, the agents are automatically aggregated by region and infection st //Print result object to console. Infection state "Xi" with i=0,...,3 is the number of agents having infection state X in region i result.print_table({"S0", "E0", "C0", "I0", "R0", "D0", "S1", "E1", "C1", "I1", "R1", "D1", "S2", "E2", "C2", "I2", "R2", "D2", "S3", "E3", "C3", "I3", "R3", "D3"}) -If one wants to interpolate the aggregated results to a TimeSeries containing only full days, this can be done by +If one wants to interpolate the aggregated results to a ``mio::TimeSeries`` containing only full days, this can be done by .. code-block:: cpp diff --git a/docs/source/c++/metapop.rst b/docs/source/c++/metapop.rst index ee56940df4..362e6b2525 100644 --- a/docs/source/c++/metapop.rst +++ b/docs/source/c++/metapop.rst @@ -121,7 +121,7 @@ Subpopulations stratified by region and infection state are saved in a ``mio::Ti //Print result object to console. Infection state "Xi" with i=0,...,3 is the number of agents having infection state X in region i result.print_table({"S0", "E0", "C0", "I0", "R0", "D0", "S1", "E1", "C1", "I1", "R1", "D1", "S2", "E2", "C2", "I2", "R2", "D2", "S3", "E3", "C3", "I3", "R3", "D3"}) -If one wants to interpolate the aggregated results to a TimeSeries containing only full days, this can be done by +If one wants to interpolate the aggregated results to a ``mio::TimeSeries`` containing only full days, this can be done by .. code-block:: cpp From c44dc473c2a926dd9f3df16937ecc99b43a9ca81 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 21 Mar 2025 12:37:31 +0100 Subject: [PATCH 55/62] Push todos ABM --- docs/source/c++/mobility_based_abm.rst | 153 ++++++++++++++----------- 1 file changed, 83 insertions(+), 70 deletions(-) diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst index 9b9546f443..71dee33616 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/c++/mobility_based_abm.rst @@ -1,99 +1,83 @@ -Realistic Agent-Based Model +Agent-based model ================= This module models and simulates the epidemic using an agent-based model (*ABM*) approach. Unlike the compartmental models that use a system of ODEs, this model simulates the spread of COVID-19 in a population with discrete persons (the agents) moving throughout locations in the -model and interacting with (infecting) each other. For a detailed overview of the ABM, see +model and interacting with (infecting) each other. For a detailed overview of the ABM, see: - Kerkmann D, Korf S, et al. Agent-based modeling for realistic reproduction of human mobility and contact behavior to evaluate test and isolation strategies in epidemic infectious disease spread. https://doi.org/10.48550/arXiv.2410.08050 +Introduction +----------- + +The model is implemented in multiple classes and headers located in the ``/cpp/models/abm/`` directory. The core classes and their locations are: + +- ``Person`` (person.h): Represents individual agents in the simulation +- ``Infection`` (infection.h): Manages infection dynamics and disease progression +- ``Location`` (location.h): Defines places where agents interact +- ``Model`` (model.h): Coordinates all components of the simulation +- ``Simulation`` (simulation.h): Executes the simulation logic + +The following sections outline the major features of the agent-based model. + Structure ---------- +~~~~~~~~~ The model consists of the following major classes: -1. **Person**: Represents an agent of the model. A person has an ID (i.e. - and a list with their assigned locations (i.e. the locations they visit during the simulation). They can perform +1. **Person**: Represents an agent of the model. A person has an ID and a list with their assigned locations (i.e. the locations they visit during the simulation). They can perform tests and wear masks. Every person has lists with past and current infections and vaccinations. + 2. **Infection**: Collection of all information about a person's infection, i.e. infectiousness, infection course, virus variant. The infection course is drawn stochastically from the infection states that are similar to the compartments of the SECIR model. + 3. **Location**: Represents places in the model where people meet and interact, e.g. home, school, work, social event sites. A location can be split into cells to model parts of a location, like classrooms in a school. Some infection parameters are location-specific and one can activate NPIs like mandatory masks or tests to enter the location. + 4. **Model**: Collection of all persons and locations. It also holds information about the testing strategy of the simulation and holds the rules for the mobility phase. + 5. **Simulation**: Runs the simulation and stores results. - - -Simulation ----------- - -The simulation runs in discrete time steps. Each step has two phases, an **interaction phase** and a **mobility phase**. -After these two phases the disease can progress and the simulation time is increased by one step. - -Interaction Phase -~~~~~~~~~~~~~~~~~~~ - -In this phase, each person interacts with the other persons at the same location. This interaction determines the -transmission of the disease. A susceptible person can become infected by contact with an infected person. The probability -of infection depends on a multitude of factors, such as the viral load and infectiousness of the infected and the immunity -level of the susceptible person. - -Mobility Phase -~~~~~~~~~~~~~~~~~~ - -During the mobility phase, each person may change their location. Mobility follow -`rules `_, considering the current location, time of day, and properties of the person (e.g. age). -Some location changes are deterministic and regular (e.g. going to work), while others are random (e.g. going shopping or to a -social event in the evening/on the weekend). When agents are infected, they are quarantined and cannot change their location. -You can restrict some mobility rules by allowing only a proportion of people to enter specific locations. - -Another way of mobility is using trips. A trip consists of the ID of the person that performs this trip, a time point when this trip is performed, and the destination. -At the beginning of the simulation, a list with all trips is initialized and followed during the simulation. There can be different -trips on the weekend than during the week, but other than that, the agents do the same trips every day. As before, agents that are -in quarantine or in the hospital cannot change their location. - - -Disease Progression +Disease progression ~~~~~~~~~~~~~~~~~~ The ABM implements a detailed disease progression model that captures the full course of an infection from exposure to resolution. The disease progression is modeled through the ``Infection`` class, which contains: -1. **Infection States**: Similar to the SECIR model, an infected person progresses through states: +1. **Infection States**: Similar to the SECIR model, an infected person progresses through states defined in ``infection_state.h``: - - **Susceptible**: Initial state before infection - - **Exposed**: Infected but not yet infectious - - **InfectedNoSymptoms**: Infectious but without symptoms - - **InfectedSymptoms**: Showing symptoms but not severe - - **InfectedSevere**: Severe infection requiring hospitalization - - **InfectedCritical**: Critical infection requiring ICU - - **Recovered**: Recovered from infection with immunity - - **Dead**: Deceased due to infection + * **Susceptible**: Initial state before infection + * **Exposed**: Infected but not yet infectious + * **InfectedNoSymptoms**: Infectious but without symptoms + * **InfectedSymptoms**: Showing symptoms but not severe + * **InfectedSevere**: Severe infection requiring hospitalization + * **InfectedCritical**: Critical infection requiring ICU + * **Recovered**: Recovered from infection with immunity + * **Dead**: Deceased due to infection 2. **Viral Load Dynamics**: The model implements realistic viral load curves based on scientific data: - - **Incline Phase**: Rapid increase in viral concentration - - **Peak**: Maximum viral load - - **Decline Phase**: Gradual decrease until clearance + * **Incline Phase**: Rapid increase in viral concentration + * **Peak**: Maximum viral load + * **Decline Phase**: Gradual decrease until clearance -3. **Infectiousness**: The probability of transmitting the virus depends on viral load through an invlogit function: +3. **Infectiousness**: The probability of transmitting the virus depends on viral load through an invlogit function. 4. **Stochastic Transitions**: Progression between states is stochastic, with age-dependent probabilities: - - The duration in each state is drawn from distributions in the model parameters - - Prior immunity (from vaccination or previous infection) affects: - - Viral load (reduced peak) - - Severity progression (reduced probability of severe outcomes) - - Duration of infectious period + * The duration in each state is drawn from distributions in the model parameters + * Prior immunity (from vaccination or previous infection) affects: + * Viral load (reduced peak) + * Severity progression (reduced probability of severe outcomes) + * Duration of infectious period 5. **Infection Course**: The infection course is determined by: - - Age group of the person - - Virus variant - - Protection status (prior immunity) - - Random factors (individual variation) - + * Age group of the person + * Virus variant + * Protection status (prior immunity) + * Random factors (individual variation) -Data Collection +Data collection ~~~~~~~~~~~~~~~~~~ The ABM simulation can collect data through the ``History`` object, which allows for flexible data logging. This is particularly @@ -119,7 +103,6 @@ The examples demonstrate two approaches: // Run simulation with history object sim.advance(tmax, history); - Interventions ~~~~~~~~~~~~~~~~~~ @@ -131,7 +114,35 @@ The ABM supports various interventions that can be applied at specific time poin 3. **Lockdowns**: Restrict movement between locations -Get Started +Simulation +---------- + +The simulation runs in discrete time steps. Each step has two phases, an **interaction phase** and a **mobility phase**. +After these two phases the disease can progress and the simulation time is increased by one step. + +Interaction phase +~~~~~~~~~~~~~~~~~~~ + +In this phase, each person interacts with the other persons at the same location. This interaction determines the +transmission of the disease. A susceptible person can become infected by contact with an infected person. The probability +of infection depends on a multitude of factors, such as the viral load and infectiousness of the infected and the immunity +level of the susceptible person. + +Mobility phase +~~~~~~~~~~~~~~~~~~ + +During the mobility phase, each person may change their location. Mobility follow +`rules `_, considering the current location, time of day, and properties of the person (e.g. age). +Some location changes are deterministic and regular (e.g. going to work), while others are random (e.g. going shopping or to a +social event in the evening/on the weekend). When agents are infected, they are quarantined and cannot change their location. +You can restrict some mobility rules by allowing only a proportion of people to enter specific locations. + +Another way of mobility is using trips. A trip consists of the ID of the person that performs this trip, a time point when this trip is performed, and the destination. +At the beginning of the simulation, a list with all trips is initialized and followed during the simulation. There can be different +trips on the weekend than during the week, but other than that, the agents do the same trips every day. As before, agents that are +in quarantine or in the hospital cannot change their location. + +How to ----------- This section gives an introduction to how to use the ABM and set up your own simulation. For a quick overview, you can find a full @@ -162,7 +173,7 @@ duration of the incubation period to 4 days: model.parameters.get() = 4.; -Locations and Persons +Locations and persons ~~~~~~~~~~~~~~~~~~~~~ To add a location to the model, we have to specify the kind of location: @@ -220,7 +231,7 @@ In our example, we categorize individuals into two groups: children and parents. twoPersonHousehold_group.add_households(twoPersonHousehold_full, n_households); add_household_group_to_model(model, twoPersonHousehold_group); -Testing Strategies +Testing strategies ~~~~~~~~~~~~~~~~~ During the simulation, people can get tested, and we have to specify the scheme for that: @@ -239,7 +250,7 @@ During the simulation, people can get tested, and we have to specify the scheme test_parameters, probability); model.get_testing_strategy().add_testing_scheme(mio::abm::LocationType::Work, testing_scheme_work); -Initializing Infections +Initializing infections ~~~~~~~~~~~~~~~~~~~~~~ For some infections to happen during the simulation, we have to initialize people with infections: @@ -259,7 +270,7 @@ For some infections to happen during the simulation, we have to initialize peopl } } -Running the Simulation +Running the simulation ~~~~~~~~~~~~~~~~~~~~~ Finally, we run the simulation: @@ -296,10 +307,12 @@ Finally, we can print the data to a text file: std::get<0>(log).print_table({"S", "E", "I_NS", "I_Sy", "I_Sev", "I_Crit", "R", "D"}, 7, 4, outfile); std::cout << "Results written to abm_minimal.txt" << std::endl; -Current Limitations +[THIS SECTION NEEDS EXAMPLE OUTPUT IMAGES - Add two images showing model output] + +Current limitations ------------------- Currently, a few things are not yet implemented, such as: -- Different trips for each day. -- Trace functionality. +* Different trips for each day +* Trace functionality From bc7681e040a8297c2d1ec3eb277e6266e54e8df1 Mon Sep 17 00:00:00 2001 From: Sascha Korf <51127093+xsaschako@users.noreply.github.com> Date: Fri, 21 Mar 2025 12:39:14 +0100 Subject: [PATCH 56/62] Delete some abm things for clarity and uniformity --- docs/source/c++/mobility_based_abm.rst | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/c++/mobility_based_abm.rst index 71dee33616..69ef09ba14 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/c++/mobility_based_abm.rst @@ -307,12 +307,3 @@ Finally, we can print the data to a text file: std::get<0>(log).print_table({"S", "E", "I_NS", "I_Sy", "I_Sev", "I_Crit", "R", "D"}, 7, 4, outfile); std::cout << "Results written to abm_minimal.txt" << std::endl; -[THIS SECTION NEEDS EXAMPLE OUTPUT IMAGES - Add two images showing model output] - -Current limitations -------------------- - -Currently, a few things are not yet implemented, such as: - -* Different trips for each day -* Trace functionality From bbfa21aaf1f3396c50de84b309e306f6a0ad5f56 Mon Sep 17 00:00:00 2001 From: reneSchm <49305466+reneSchm@users.noreply.github.com> Date: Fri, 21 Mar 2025 12:46:02 +0100 Subject: [PATCH 57/62] Fix math --- docs/source/c++/ode_creation.rst | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/source/c++/ode_creation.rst b/docs/source/c++/ode_creation.rst index 237fa7b0d7..11bef1f879 100644 --- a/docs/source/c++/ode_creation.rst +++ b/docs/source/c++/ode_creation.rst @@ -1,4 +1,4 @@ -ODE Model Creation +ODE model creation ================== Model definition @@ -9,13 +9,16 @@ given by a system of ordinary differential equations. For example we consider a .. math:: \begin{aligned} - S'(t) & = -\rho\phi\ \frac(S(t)*I(t))(N) \\ - I'(t) & = \rho\phi\ \frac(S(t)*I(t))(N) - \frac(\mu_R + \mu_D)(T_I)I(t) \\ - R'(t) & = \frac(\mu_R)(T_I)I(t) \\ - D'(t) & = \frac(\mu_R)(T_I)I(t) \\ + S'(t) & = -\rho\phi\ \frac{S(t)*I(t)}{N_{\perp D}} \\ + I'(t) & = \rho\phi\ \frac{S(t)*I(t)}{N_{\perp D}} - \frac{\mu_R + \mu_D}{T_I}I(t) \\ + R'(t) & = \frac{\mu_R}{T_I}I(t) \\ + D'(t) & = \frac{\mu_D}{T_I}I(t) \\ \end{aligned} -and some initial values for :math:`t=0`. Here :math:`N := S(t) + I(t) + R(t)`. +and some initial values for :math:`t=0`. Here :math:`N_{\perp D} := S(t) + I(t) + R(t)`. This type of model is called compartmental model, because the model population is represented by discrete infection states**S**usceptible, **I**nfected, **R**ecovered, **D**ead, also called compartments. + +How to define an ODE model +-------------------------- From 238be0118328ed10281ffa3c1c8c040ad3688b19 Mon Sep 17 00:00:00 2001 From: Anna Wendler <106674756+annawendler@users.noreply.github.com> Date: Fri, 21 Mar 2025 14:15:30 +0100 Subject: [PATCH 58/62] add lct docu and some small corrections --- docs/source/c++/aggregated_models.rst | 2 +- docs/source/c++/ide.rst | 11 +- docs/source/c++/lct.rst | 192 +++++++++++++++++--------- 3 files changed, 133 insertions(+), 72 deletions(-) diff --git a/docs/source/c++/aggregated_models.rst b/docs/source/c++/aggregated_models.rst index 86cc670167..33260f0265 100644 --- a/docs/source/c++/aggregated_models.rst +++ b/docs/source/c++/aggregated_models.rst @@ -4,7 +4,7 @@ Aggregated models There are different equation-based models implemented in MEmilio that consider an aggregated population. .. toctree:: - :maxdepth: 1 + :maxdepth: 2 ode lct diff --git a/docs/source/c++/ide.rst b/docs/source/c++/ide.rst index 119b816653..4a73c5f740 100644 --- a/docs/source/c++/ide.rst +++ b/docs/source/c++/ide.rst @@ -47,9 +47,9 @@ To initialize the model, the following inputs need to be passed to the model con - a time series containing the flows within a time step between the infection states for a large enough number of time points before the start of the simulation, - a vector containing the population sizes for every age group, -- a vector containing the total number of deaths at time :math:`t0` for every age group, +- a vector containing the total number of deaths at time :math:`t_0` for every age group, - the number of age groups, -- optionally, a vector containing the total confirmed cases at time :math:`t0` and can be set if it should be used for initialization for every age group. +- optionally, a vector containing the total confirmed cases at time :math:`t_0` and can be set if it should be used for initialization for every age group. The number of age groups, the population sizes and total number of deaths can be defined directly by @@ -112,6 +112,7 @@ There are different options for initializing a fictional scenario. Regardless of mio::isecir::Model model(std::move(init), N, deaths, num_agegroups); In that case, we have three possible options for initializing: + - You can set the number of people in the `Susceptible` compartment at time :math:`t_0` via `populations`. Initial values of the other compartments are derived in the model before starting the simulation. .. code-block:: cpp @@ -165,7 +166,6 @@ In our example below we use only one contact matrix. We only consider one age gr contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(num_agegroups, num_agegroups, 10.)); model.parameters.get() = mio::UncertainContactMatrix(contact_matrix); - The parameters ``TransmissionProbabilityOnContact``, ``RelativeTransmissionNoSymptoms`` and ``RiskOfInfectionFromSymptomatic`` can be made dependent on the time. This is why we use a ``StateAgeFunction`` that is passed to a ``StateAgeFunctionWrapper`` to set these parameters. Note that there is also a ``ConstantFunction`` availbale if we do not want to have any dependency on the time. Here we use an ``ExponentialSurvivalFunction`` to set the mentioned parameters. @@ -224,6 +224,7 @@ IDE-SEIR model Introduction ~~~~~~~~~~~~~ The four compartments + - `Susceptible` (:math:`S`), may become exposed at any time - `Exposed` (:math:`E`), becomes infected after some time - `Infected` (:math:`I`), will recover after some time @@ -287,14 +288,14 @@ In our example below we use only one contact matrix. Our model considers one age mio::ContactMatrixGroup contact_matrix = mio::ContactMatrixGroup(1, 1); contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 10.)); -To simulate the implementation of nonpharmaceutical, we add dampings to the contact rate. Here, we apply a damping of :math:`0.7` after :math:`10`` days. +To simulate the implementation of nonpharmaceutical interventions, we add dampings to the contact rate. Here, we apply a damping of :math:`0.7` after :math:`10`` days, meaning that the contact rate is reduced to 30% of the initial value. .. code-block:: cpp contact_matrix[0].add_damping(0.7, mio::SimulationTime(10.)); model.parameters.get>() = mio::UncertainContactMatrix(contact_matrix); -After defining :math:`t_{\max}``, we can simulate, which means that we calculate the value for the compartment :math:`S`. +After defining :math:`t_{\max}`, we can simulate, which means that we calculate the value for the compartment :math:`S`. .. code-block:: cpp diff --git a/docs/source/c++/lct.rst b/docs/source/c++/lct.rst index f425463f3f..f0b26db925 100644 --- a/docs/source/c++/lct.rst +++ b/docs/source/c++/lct.rst @@ -8,11 +8,6 @@ The Linear Chain Trick provides the option to use Erlang-distributed stay times The normal ODE models have (possibly unrealistic) exponentially distributed stay times. The LCT model can still be described by an ordinary differential equation system. -For a detailed description and application of the model, see: - -- Plötzke L, Wendler A, Schmieding R, Kühn MJ (2024) Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions. Under review. https://doi.org/10.48550/arXiv.2412.09140 -- Hurtado PJ und Kirosingh AS (2019) Generalizations of the ‘Linear Chain Trick’: incorporating more flexible dwell time distributions into mean field ODE models. Journal of Mathematical Biology. https://doi.org/10.1007/s00285-019-01412-w - The eight compartments - `Susceptible` (:math:`S`), may become Exposed at any time @@ -31,16 +26,22 @@ You can divide the population according to different groups, e.g. AgeGroups or g Simulation ----------- +The simulation runs in discrete time steps. Different ODE solvers are available, some of them use an adaptive time step size. + +For a detailed description and application of the model, see: + +- Plötzke L, Wendler A, Schmieding R, Kühn MJ (2024) Revisiting the Linear Chain Trick in epidemiological models: Implications of underlying assumptions for numerical solutions. Under review. https://doi.org/10.48550/arXiv.2412.09140 +- Hurtado PJ und Kirosingh AS (2019) Generalizations of the ‘Linear Chain Trick’: incorporating more flexible dwell time distributions into mean field ODE models. Journal of Mathematical Biology. https://doi.org/10.1007/s00285-019-01412-w + How to: Set up and run a simulation of the LCT-SECIR model ----------------------------------------------------------- -We start by defining the number of subcompartments and constructing the model. +In the following, we will use an example with one age group/category. + +We start by defining the number of subcompartments and constructing the model. We can choose the number of subcompartments individually for the compartments Exposed, InfectedNoSymptoms, InfectedSymptoms, InfectedSevere and InfectedCritical. .. code-block:: cpp - // Simple example to demonstrate how to run a simulation using an LCT-SECIR 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. constexpr size_t NumExposed = 2, NumInfectedNoSymptoms = 3, NumInfectedSymptoms = 1, NumInfectedSevere = 1, NumInfectedCritical = 5; using InfState = mio::lsecir::InfectionState; @@ -49,13 +50,10 @@ We start by defining the number of subcompartments and constructing the model. using Model = mio::lsecir::Model; Model model; - // Variable defines whether the class Initializer is used to define an initial vector from flows or whether a manually - // defined initial vector is used to initialize the LCT model. - bool use_initializer_flows = false; +If we do not want to use the default parameters, they can be set as follows. - ScalarType tmax = 10; +.. code-block:: cpp - // Set Parameters. model.parameters.get()[0] = 3.2; model.parameters.get()[0] = 2.; model.parameters.get()[0] = 5.8; @@ -64,11 +62,6 @@ We start by defining the number of subcompartments and constructing the model. model.parameters.get()[0] = 0.05; - mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); - 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()[0] = 0.7; model.parameters.get()[0] = 0.25; model.parameters.get()[0] = 0.09; @@ -76,55 +69,33 @@ We start by defining the number of subcompartments and constructing the model. model.parameters.get()[0] = 0.25; model.parameters.get()[0] = 0.3; - if (use_initializer_flows) { - // Example how to use the class Initializer for the definition of an initial vector for the LCT model. +Here, we set the contact matrix used in the simulation. One can define multiple matrices for different locations. The size of each of these matrices is defined by the number of age groups. +In our example below we use only one contact matrix. We only consider one age group and set the contact rate to 10. - ScalarType dt = 0.001; - Eigen::VectorX total_population = Eigen::VectorX::Constant(1, 1000000.); - Eigen::VectorX deaths = Eigen::VectorX::Constant(1, 10.); - Eigen::VectorX total_confirmed_cases = Eigen::VectorX::Constant(1, 16000.); +.. code-block:: cpp - // Create TimeSeries with num_transitions elements. - int num_transitions = (int)mio::lsecir::InfectionTransition::Count; - mio::TimeSeries flows(num_transitions); + mio::ContactMatrixGroup& contact_matrix = model.parameters.get(); + contact_matrix[0] = mio::ContactMatrix(Eigen::MatrixXd::Constant(1, 1, 10)); - mio::TimeSeries::Vector vec_flows(num_transitions); - vec_flows[(int)mio::lsecir::InfectionTransition::SusceptibleToExposed] = 2.0; - vec_flows[(int)mio::lsecir::InfectionTransition::ExposedToInfectedNoSymptoms] = 1.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedNoSymptomsToInfectedSymptoms] = 8.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedNoSymptomsToRecovered] = 4.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSymptomsToInfectedSevere] = 1.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSymptomsToRecovered] = 4.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSevereToInfectedCritical] = 1.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSevereToRecovered] = 1.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedCriticalToDead] = 1.0; - vec_flows[(int)mio::lsecir::InfectionTransition::InfectedCriticalToRecovered] = 1.0; - vec_flows = vec_flows * dt; - // Add initial time point to time series. - flows.add_time_point(-110, vec_flows); - // Add further time points until time 0. - while (flows.get_last_time() < -dt / 2) { - flows.add_time_point(flows.get_last_time() + dt, vec_flows); - } +To simulate the implementation of nonpharmaceutical interventions, we add dampings to the contact rate. Here, we apply a damping of :math:`0.7` after :math:`5`` days, meaning that the contact rate is reduced to 30% of the initial value. + +.. code-block:: cpp + + contact_matrix[0].add_damping(0.7, mio::SimulationTime(5.)); + +For the simulation, we need initial values for all (sub)compartments. If we do not set the initial values manually, these are internally set to :math:`0`. + +We start with constructing a vector ``initial_populations`` that we will pass on to the model. It contains vectors for each compartment, that contains a vector with initial values for the respective subcompartments. + +.. code-block:: cpp - // Set initialization vector for the LCT model. - mio::lsecir::Initializer initializer(std::move(flows), model); - initializer.set_tol_for_support_max(1e-6); - auto status = initializer.compute_initialization_vector(total_population, deaths, total_confirmed_cases); - if (status) { - return 1; - } - } - else { - // 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> initial_populations = {{750}, {30, 20}, {20, 10, 10}, {50}, {50}, {10, 10, 5, 3, 2}, {20}, {10}}; - // Assert that initial_populations has the right shape. +We assert that vector has the correct size by checking that the number of ``InfectionStates`` and the number of subcomaprtments are correct. + +.. code-block:: cpp + 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."); @@ -147,7 +118,10 @@ We start by defining the number of subcompartments and constructing the model. return 1; } - // Transfer the initial values in initial_populations to the model. +Now, we transfer the vector ``initial_populations`` to the model. + +.. code-block:: cpp + std::vector flat_initial_populations; for (auto&& vec : initial_populations) { flat_initial_populations.insert(flat_initial_populations.end(), vec.begin(), vec.end()); @@ -157,14 +131,100 @@ We start by defining the number of subcompartments and constructing the model. } } - // Perform a simulation. - mio::TimeSeries result = mio::simulate(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. +We can simulate the model from :math:`t_0` to :math:`t_{\max}` with initial step size :math:`dt` as follows: + +.. code-block:: cpp + + ScalarType t0 = 0; + ScalarType tmax = 10; + ScalarType dt = 0.5; + mio::TimeSeries result = mio::simulate(t0, tmax, dt, model); + +The simulation result is divided by subcompartments. We can call the function calculate_compartments to get a result according to the InfectionStates. + +.. code-block:: cpp + mio::TimeSeries population_no_subcompartments = model.calculate_compartments(result); + +We can interpolate the simulation results to a ``TimeSeries`` containing only full days and print the results to the terminal. + +.. code-block:: cpp + auto interpolated_results = mio::interpolate_simulation_result(population_no_subcompartments); interpolated_results.print_table({"S", "E", "C", "I", "H", "U", "R", "D "}, 12, 4); +Remarks +~~~~~~~~ + +Above, we have defined the vector of initial values ``initial_populations`` directly. There also exists a function, that computes an intial value vector for the compartments based on a ``TimeSeries`` with flows that are given for a big enough time window before the simulation start. We will demonstarte this below. +Here, we assume that a model was already constructedas above. + +We start with defining the vectors ``total_population``, ``deaths`` and ``total_confirmed_cases``that contain the respective values per age group. + +.. code-block:: cpp + + Eigen::VectorX total_population = Eigen::VectorX::Constant(1, 1000000.); + Eigen::VectorX deaths = Eigen::VectorX::Constant(1, 10.); + Eigen::VectorX total_confirmed_cases = Eigen::VectorX::Constant(1, 16000.); + + + +Now, we will define a time series containing flows for some time before the simulation start that will later be used to compute the initial values for the compartments. + +We start by defining the time step size :math:`dt` that determines the distance between the time points that will be added to the time series. + +.. code-block:: cpp + + ScalarType dt = 0.001; + +We proceed by creating a time series ``flows`` that contains a vector with the size of the number of transitions that the model allows. + +.. code-block:: cpp + + int num_transitions = (int)mio::lsecir::InfectionTransition::Count; + mio::TimeSeries flows(num_transitions); + +Here, we define the vector that will be added to the time series for each time point. + +.. code-block:: cpp + + mio::TimeSeries::Vector vec_flows(num_transitions); + vec_flows[(int)mio::lsecir::InfectionTransition::SusceptibleToExposed] = 2.0; + vec_flows[(int)mio::lsecir::InfectionTransition::ExposedToInfectedNoSymptoms] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedNoSymptomsToInfectedSymptoms] = 8.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedNoSymptomsToRecovered] = 4.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSymptomsToInfectedSevere] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSymptomsToRecovered] = 4.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSevereToInfectedCritical] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedSevereToRecovered] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedCriticalToDead] = 1.0; + vec_flows[(int)mio::lsecir::InfectionTransition::InfectedCriticalToRecovered] = 1.0; + vec_flows = vec_flows * dt; + + +We add the first time point at :math:`-110` and add time points until time :math:`0` where the time step size :math:`dt`determines the distance between the time points. + +.. code-block:: cpp + + flows.add_time_point(-110, vec_flows); + while (flows.get_last_time() < -dt / 2) { + flows.add_time_point(flows.get_last_time() + dt, vec_flows); + } + +Now, we can construct an object of type ``Initializer`` where the computations for the initial value vector will be performed. + +.. code-block:: cpp + + mio::lsecir::Initializer initializer(std::move(flows), model); + +Finally, we can compute the initialization vector. This is based on the knowledge of the flows as well as the Erlang-distributed stay times in the respective compartments. For further details, see the documentation of the function. + +.. code-block:: cpp + + auto status = initializer.compute_initialization_vector(total_population, deaths, total_confirmed_cases); + + + From c7bad2450eb48b4276a83c948ae76a2dda326938 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Fri, 21 Mar 2025 16:58:35 +0100 Subject: [PATCH 59/62] CHG: Copied wiki into development --- docs/source/development.rst | 388 +++++++++++++++++++++++++++++++++++- 1 file changed, 385 insertions(+), 3 deletions(-) diff --git a/docs/source/development.rst b/docs/source/development.rst index 2f559cd559..0a99930147 100644 --- a/docs/source/development.rst +++ b/docs/source/development.rst @@ -1,9 +1,391 @@ Development =========== -We are always happy about contributions to the project! If you want to contribute, please follow the guidelines below. +We are always happy about contributions to the project! Here you can find more information on our coding guidelines, our git workflow, benchmarking our models and writing documentation. + +Coding guidelines +--------------------- + +All software is built in modules, unit tests have to be added for each module/functionality. + +The CI pipeline also automates some code style enforcement via a ``pre-commit``. +We recommend to configure it locally such that it runs automatically on every commit: + +.. code:: bash + + pip install pre-commit + pre-commit install + + +For more information about ``pre-commit`` check `here `_ and this short video series: https://calmcode.io/pre-commit/the-problem.html + +Please be aware that the ``isort`` pre-commit hook accidentally sorts our own code with third party libraries, also see: https://github.com/PyCQA/isort/issues/2068 Be therefore sure to not commit python code from a worktree. + +C++ Coding guidelines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +C++ Standard: + + - C++ 17, higher standards are currently not allowed + +Namespaces: + + - Use the ``mio`` namespace. + +Naming rules: + + - Classes begin with large Letters , e.g. ``class MyClass`` + - functions, methods, variables use small letters + underscore, e.g. ``my_awesome_function`` + - member variables should be generally private (we allow exceptions from this rule) and should be named with a leading "m_", e.g. ``m_my_member``. + +Return Values: + + - If only one object is output, use return, for multiple objects, pass by reference (we still have to check ``std::expected``) + - The semantics of return value arguments have to make clear, how the ownership is handled + + - If the function creates an object (allocates), pass it as ``std::unique_ptr&`` + - If the function simply changes an object, pass is as ``T&`` + + - Avoid producing unnecessarily long outputs. Ensure that all output is concise and limited to relevant information. + +Exceptions: + + - In order to avoid MPI deadlocks, do not use exceptions. Use logging or return codes. + +Logging: + + - Do not use printfs + - Use the logging functions from ``logging.h`` + - For debug logs, use ``mio::log_debug(msg)`` + +Includes: + + - Please use include guards with capitalized name of the header file (``test.h -> #ifndefine TEST_H``) + - Sort includes according to + + 1. own header + 2. headers from the same library + 3. specific third party library (e.g., hdf5, and eigen) + 4. general third party/standard library + + +Code Documentation: + + - Use doxygen docstrings. In particular + - Write an explicit `@brief` for method documentations. Continue the detailed description in the next line. + - Always start a line with a capital letter and end with a dot. + - The plural of classes, objects etc. should be denoted with a `%` sign between class name and plural s, e.g., `Household%s`. This is in order to visualize it correctly and provide a link on the doxygen page. + - Use `[in]`, `[out]`, or `[in, out]` after `@param` in order to clarify if parameters are used as input, output or in- and output parameters. + - To reference to enums put a # sign before the name. + - Plase also provide a description for member variables; use ``///< DESCRIPTION` or `/**< DESCRIPTION */`` for two lines. Keep it short. + + +Mandatory C++ Style Guidelines +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The style guidelines are adopted from `TiGL `_. + + +**Tabs and Indentation** + + - Use 4 spaces indentation. **Don't use tabs!** + - Exceptions: + + - public/protected/private keywords in class definitions + - namespaces + +.. code:: cpp + + namespace mio + { + namespace foo + { + namespace bar + { + /*some code*/ + } // namespace bar + } // namespace foo + } // namespace mio + +**Definitions and Declarations** + + - Braces in new lines: + +.. code:: cpp + + class Secir + { + + private: + double m_member; + }; + +If you use several lines for a functions definition/declaration, align the function arguments horizontally: + +.. code:: cpp + + ReturnCode compute_something(Arg1 arg1, + Arg2 arg2, + Arg3 arg3) + + +**Loops, If and Switch Statements** + + - space before and after condition + - Braces in the same line + +.. code:: cpp + + if (psi.size()<=2) { + psi.clear(); + } + else { + double psimax = psi[psi.size()-1]; + } + + + for (size_t i = 0; i < psi.size(); i++) { + some code + } + + + switch (GetSymmetryAxis()) { + case TIGL_X_Y_PLANE: + return zmax - zmin; + case TIGL_X_Z_PLANE: + return ymax - ymin; + } + + +**Automatic code formatting with clang-format** + +The Clang-Format Tool can also be used to reformat the code to our style. Here are the settings that should comply to our style. + +.. code:: + + BasedOnStyle: LLVM + IndentWidth: 4 + SortIncludes: false + ColumnLimit: 120 + AlignTrailingComments: false + AccessModifierOffset: -4 + AlignConsecutiveAssignments: true + ReflowComments: false + BraceWrapping: + AfterClass: true + AfterFunction: true + BeforeElse: true + BeforeCatch: true + AfterNamespace: true + AfterEnum: true + BreakBeforeBraces: "Custom" + PointerAlignment: Left + AllowShortFunctionsOnASingleLine: false + NamespaceIndentation: None + BreakConstructorInitializersBeforeComma: true + AlwaysBreakTemplateDeclarations: Yes + AllowShortLambdasOnASingleLine: Empty + + +These settings are set in the file ``.clang-format`` in the root directory of the repository. + +**Using clang-format with either Qt, Visual Studio Code, or VSCodium** + +The Beautifier plugin shipped with QtCreator supports clang-format (help could also be provided by https://www.vikingsoftware.com/using-clang-format-with-qtcreator/ ), so you will be able to automatically format your code. For Visual Studio Code, install the Clang-format extension and add the lines: + +.. code:: + + "editor.formatOnSave": true, + "clang-format.executable": "...path...to...clang-format-executable", + +to your settings.json and store the above code formatting rules in a file named ``.clang-format`` in the working directory of VSCode. + +Note: The clang-format provided by default in Debian/Ubuntu is quite old and with our style file the issue + +.. code:: bash + + YAML:21:34: error: invalid boolean + AlwaysBreakTemplateDeclarations: Yes + ^~~ + Error reading PATH/.clang-format: Invalid argument + + +might appear. In that case, update ``clang-format`` or install a newer version (e.g. ``clang-format-10``) manually and point to its executable. + + +Python coding guidelines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Please follow the `PEP 8 -- Style Guide for Python. `_ + + +**Note on maximum line length** + +If using autopep8, e.g., of the Python plugin for Visual Studio Code or VSCodium, maximum length might not be correctly applied. In this case, add + +.. code:: + + "python.formatting.autopep8Args": ["--max-line-length", "79", "--experimental"] + +to your corresponding ``settings.json``. + + +Git workflow +---------------------- + +General +~~~~~~~~~~~~ + +- There is a main but no release or develop branch. The main branch is always stable and the latest release can be found as a tagged commit on the main branch. Stable means that all tests pass. +- All actual work is done in task branches, regardless of whether it's a feature, a bugfix, or a performance analysis. +- Task branches are generally created from the main branch. +- Please **never rebase** your branches, **always use merging** (with the main or other changes) such that committed changes can be followed in the history. There will be a squashed commit when the changes are added to the main branch. +- The name of a task branch satisfies the following template: ``issueId-issueName``. +- Each commit must have a meaningful commit message. +- In general, we should try to keep the branches working. However, if you need to commit a non-working change, please begin the commit message with ``[ci skip] non-working`` for the following reasons: + + - Nobody attempts to checkout this commit with the assumption it would work. + - ``[ci skip]`` prevents the CI from running. + +- If we release a new version of the software, we create a tag for the version on the main branch. +- Please keep all issue-related communication within the issue or pull request. + +Software Development in Sprints +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The software development process is inspired by `Scrum `_ and the development of the core developers is organized in sprints. The rules below only partially apply to external (non-core) contributors. + +**General** + + +- A sprint is a temporally limited cycle of a fixed time, in our case **three** weeks. +- The scope of work will be defined in a sprint meeting where work is related to issues. +- MEmilio-related issues are categorized in three different classes: agent-based modeling, equation-based modeling and MEmilio: data, tools and more. If a clear categorization is not possible, issues may be assigned to more than one class. +- Sprints are organized via the new GitHub Project boards: https://github.com/DLR-SC/memilio/projects + +**Procedure** + +- At the latest in the morning *before* every sprint meeting, all developers are encouraged to think about which issues should be processed in the upcoming sprint, regardless of whether those issues are tasks for oneself or someone else. Therefore, those issues are marked with the upcoming project. Every developer should put the issues they want to work on or request others to work on in the "SprintBacklog" and attribute them with the next sprint number. +- Shortly before the meeting, **every** developer should already look at the project issues and think about the time needed for realization. +- In the meeting, we go through the different issues and clarify questions and comments. + +**New Tasks** + +- For every single programming task, bug report, discussion item etc., open a new issue. +- Every issue should contain a detailed description of the task and subtasks understandable for all developers in the project. +- A new issue has no status label. Additional labels should be appended, see the label list below. At this point, it is not necessary to assign it to someone. +- Every issue should be tagged with at least one of the projects, if possible. +- Tasks (issues) which are attributed to a sprint are tracked in an `issue board `_ found under "Projects". + +**Working on an Issue** + + +- When you start working on an issue, make sure it is attributed to the current sprint. +- Then, assign it to yourself and move it into the column "In Progress" or change the label to ``status::in progress``. If code changes are involved, create a branch. If you are working with a partner, mention the partner in the issue description. The assignee is responsible for the ticket. +- You should only work on one ticket at a time. It shouldn't happen that two tickets are "In Progress" at the same time. +- If you completed the issue, set the pull request to "Ready for Review". Check that all coding requirements of the author (automatically added as checkboxes) are met. Assign the pull request to the person who should review your work and move the issue into the column "in review" or change the status to ``status::in review``. + +**Review** + + +- The task of the reviewer is to check the code for correctness, compliance with the coding guidelines, completeness, quality, etc. +- If the review has finished and there are complaints, the issue is moved to ``status::in progress`` again, reassigned to the original assignee, and the threads must be resolved. Add the ``WIP`` tag to the merge request again. +- If the reviewer approves the work, the new code can be merged and the issue is automatically "Closed". +- The reviewer is allowed to make small changes in the comments or documentation, e.g., remove typos. Also, small changes such as adding/deleting spaces or empty lines can be made directly by the reviewer to speed up the process. +- For all other changes concerning the code and its functionality, the reviewer has to write a comment or make a suggestion which then goes back to the developer (see above). + +**Authors and Contributions** + + +To honor original authors as well as reviewers and their suggestions, reviewers should be added as co-authors when merging a pull request. To do so, add the following line(s) at the end of the commit message: + +.. code-block:: text + + COMMIT_MSG + + Co-authored-by: NAME + +**Label List** + + +The full list of labels that should be used to identify issues can be found at: https://github.com/DLR-SC/memilio/labels + + +Agent-based model development +------------------------------------------------ + +Benchmarks +~~~~~~~~~~~~~~~~~~~~~ + +There is a suite of benchmarks for the ABM that can be used to check performance. The suite contains setups of different sizes. If you added a new feature (i.e., you didn't just fix a bug in an existing feature), make sure the feature is actually used by the benchmark. Add it to the benchmark if necessary, then run the benchmark to see if the cost for the new feature is acceptable and as expected. + +Most new features will add some overhead, but this needs to be limited and in proportion to the added value of the feature so runtime doesn't grow out of control. Optional features that can be disabled should only incur minimal overhead. If you did not add any new feature, just run the benchmark before and after your changes to make sure there are no performance regressions. This process will hopefully be automated soon by running benchmarks in the CI. + +Build the benchmarks by defining the CMake variable ``MEMILIO_BUILD_BENCHMARKS=ON`` in the build. Make sure to use a **Release** build to test performance. + +.. code-block:: bash + + cmake .. -DMEMILIO_BUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release + cmake --build . + +Run the benchmark executable: + +.. code-block:: bash + + ./build/bin/abm_benchmark + +Each benchmark is run for a number of iterations and the average time is reported. + +.. code-block:: text + + Benchmark Time CPU Iterations + --------------------------------------------------------------------------- + abm_benchmark/abm_benchmark_50k 7583 ms 7583 ms 1 + abm_benchmark/abm_benchmark_100k 18216 ms 18214 ms 1 + abm_benchmark/abm_benchmark_200k 41492 ms 41489 ms 1 + +You may get a warning: + +.. code-block:: text + + ***WARNING*** CPU scaling is enabled, the benchmark real time measurements may be noisy and will incur extra overhead. + +If possible, disable CPU scaling to improve the consistency of results. See the Google Benchmark documentation here: +https://google.github.io/benchmark/reducing_variance.html + +Also, try to reduce other system load during the benchmark run. + +If it is not possible to disable frequency scaling, increase the runtime of the benchmark using the commands below. Constant CPU frequency is necessary to get the most reliable results and to measure small differences. + +**REMINDER:** Don't forget to re-enable CPU scaling after you ran the benchmarks to save energy. Rebooting may restore the settings as well. + +The benchmark executable has a number of command line arguments that customize execution. Use ``--help`` to list them all. + +Two important options for consistency and stability: + +- ``--benchmark_min_time=``: Iterate each benchmark so that the total runtime is at least ``T`` seconds. + Default is 1 second, which may not be enough. + Try 60 seconds for better stability (you may need to experiment). + +- ``--benchmark_repetitions=``: Repeat each benchmark ``N`` times and report mean, median, and variance. + (Repetitions are **not** iterations; a benchmark can be repeated 10 times with 5 iterations each. Each repetition runs for at least the minimum time.) + +``benchmark_repetitions`` is useful to check timing consistency, as it reports variance. +However, it can be expensive because long-running benchmarks are repeated. +``benchmark_min_time`` increases iterations only for fast-running benchmarks, which tend to be less stable. + +**Suggested workflow:** + +1. Run with 5–10 repetitions to check variance. +2. Increase ``benchmark_min_time`` until variance is acceptable. +3. Continue benchmarking with 1 repetition and the adjusted minimum time. + + + +Documentation +-------------------- -- `Git workflow and change process `_ -- `Coding Guidelines `_ For the documentation, please keep in mind that it is written in reStructuredText (RST) and uses a slightly different syntax than Markdown. A documentation can be found at ``_. \ No newline at end of file From f4ea00ddca55479d87406dacc1f44aaa6d60f7ab Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Fri, 21 Mar 2025 16:58:47 +0100 Subject: [PATCH 60/62] CHG: Improved getting started --- docs/source/getting_started.rst | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/docs/source/getting_started.rst b/docs/source/getting_started.rst index 5e30328cf5..497639e9e0 100644 --- a/docs/source/getting_started.rst +++ b/docs/source/getting_started.rst @@ -1,17 +1,24 @@ Getting Started =============== -MEmilio supports various model types including equation-based, agent-based, and hybrid graph-ODE-based models. Among the equation-based models, we provide ordinary differential equation (ODE), linear chain trick (LCT), integro-differential equation (IDE) based models. +Overview +------------- + +MEmilio supports various model types including equation-based, agent-based, and hybrid graph-ODE-based models. Among the equation-based models, we provide models based on :doc:`ordinary differential equations `, :doc:`the linear chain trick, ` and its :doc:`generalisation `, :doc:`integro-differential equations `, as well as :doc:`stochastic differential equations `. - The C++ backend powers the model and simulation components for optimal efficiency. - Data acquisition, plotting, and machine-learned models are handled via Python. -For more details on the C++ implementation, see the `cpp directory README `_. +For more details on the C++ implementation, see the sections on :doc:`model usage ` and :doc:`model creation ` in the documentation for the C++-interface. + +We also provide several MEmilio Python packages. Via our :doc:`memilio-simulation ` package, you can run our C++ backend from Python; this package uses ``pybind11`` to bind our C++ model code. The :doc:`memilio-epidata ` package provides tools to download and structure important data such as infection or mobility data. More about the Python packages can be found in the :doc:`Python Interface Section ` of this documentation. -Some regularly used data for simulations of a pathogen's spread in Germany, like contact and inter-county mobility, can be found in the `data directory README `_. +A few things are not represented in this documentation, but part of the `github repository `_. In the ``data`` folder you can find some regularly used data for simulations of a pathogen's spread, currently mostly for Germany. -In `pycode`, different MEmilio Python packages are defined. Via our `memilio-simulation` package, you can run our C++ backend from Python; this package uses `pybind11` to bind our C++ model code. The `memilio-epidata` package provides tools to download and structure important data such as infection or mobility data. More about the Python packages can be found in the `Python README `_. +Visualizations +----------------- +For visualizations we first of all recommend our :doc:`python package `. Apart from that we have collected some scripts that we used for visualizations in the `tools folder in our github repository `_. .. note:: @@ -33,17 +40,4 @@ To use MEmilio, first install it using ... c++ init -C++ Tutorial -~~~~~~~~~~~~~~~~~~~~ - -TBD - - -For example: - ->>> import memilio.epidata import progress_indicator - - -Other examples can be found in the :doc:`models/index` page. - From 2ae3d83678e030a72bb470040b54792a8eca9201 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Fri, 21 Mar 2025 17:00:14 +0100 Subject: [PATCH 61/62] CHG: Changed overall structure for nicer links (c++ -> cpp) --- docs/source/c++/aggregated_models.rst | 13 ------------- docs/source/c++/model_creation.rst | 14 -------------- docs/source/c++/visualization.rst | 2 -- docs/source/cpp/aggregated_models.rst | 13 +++++++++++++ docs/source/{c++ => cpp}/diffusive_abm.rst | 0 docs/source/{c++ => cpp}/glct.rst | 0 docs/source/{c++ => cpp}/ide.rst | 0 docs/source/{c++ => cpp}/ide_creation.rst | 0 docs/source/{c++ => cpp}/individual_models.rst | 0 docs/source/cpp/installation.rst | 4 ++++ docs/source/{c++ => cpp}/io.rst | 0 docs/source/{c++ => cpp}/lct.rst | 0 docs/source/{c++ => cpp}/lct_creation.rst | 0 docs/source/{c++ => cpp}/metapop.rst | 0 docs/source/{c++ => cpp}/mobility.rst | 0 docs/source/{c++ => cpp}/mobility_based_abm.rst | 4 ++++ docs/source/{c++ => cpp}/mobility_metapop.rst | 0 docs/source/cpp/model_creation.rst | 14 ++++++++++++++ docs/source/{c++ => cpp}/model_usage.rst | 1 - docs/source/{c++ => cpp}/ode.rst | 0 docs/source/{c++ => cpp}/ode_creation.rst | 2 +- docs/source/cpp/overview.rst | 2 ++ docs/source/{c++ => cpp}/sde.rst | 0 docs/source/{c++ => cpp}/sde_creation.rst | 0 docs/source/{c++ => cpp}/structure.rst | 0 docs/source/index.rst | 11 +++++++++-- docs/source/python/model_usage.rst | 2 +- 27 files changed, 48 insertions(+), 34 deletions(-) delete mode 100644 docs/source/c++/aggregated_models.rst delete mode 100644 docs/source/c++/model_creation.rst delete mode 100644 docs/source/c++/visualization.rst create mode 100644 docs/source/cpp/aggregated_models.rst rename docs/source/{c++ => cpp}/diffusive_abm.rst (100%) rename docs/source/{c++ => cpp}/glct.rst (100%) rename docs/source/{c++ => cpp}/ide.rst (100%) rename docs/source/{c++ => cpp}/ide_creation.rst (100%) rename docs/source/{c++ => cpp}/individual_models.rst (100%) create mode 100644 docs/source/cpp/installation.rst rename docs/source/{c++ => cpp}/io.rst (100%) rename docs/source/{c++ => cpp}/lct.rst (100%) rename docs/source/{c++ => cpp}/lct_creation.rst (100%) rename docs/source/{c++ => cpp}/metapop.rst (100%) rename docs/source/{c++ => cpp}/mobility.rst (100%) rename docs/source/{c++ => cpp}/mobility_based_abm.rst (99%) rename docs/source/{c++ => cpp}/mobility_metapop.rst (100%) create mode 100644 docs/source/cpp/model_creation.rst rename docs/source/{c++ => cpp}/model_usage.rst (88%) rename docs/source/{c++ => cpp}/ode.rst (100%) rename docs/source/{c++ => cpp}/ode_creation.rst (90%) create mode 100644 docs/source/cpp/overview.rst rename docs/source/{c++ => cpp}/sde.rst (100%) rename docs/source/{c++ => cpp}/sde_creation.rst (100%) rename docs/source/{c++ => cpp}/structure.rst (100%) diff --git a/docs/source/c++/aggregated_models.rst b/docs/source/c++/aggregated_models.rst deleted file mode 100644 index 33260f0265..0000000000 --- a/docs/source/c++/aggregated_models.rst +++ /dev/null @@ -1,13 +0,0 @@ -Aggregated models -================= - -There are different equation-based models implemented in MEmilio that consider an aggregated population. - -.. toctree:: - :maxdepth: 2 - - ode - lct - glct - sde - ide \ No newline at end of file diff --git a/docs/source/c++/model_creation.rst b/docs/source/c++/model_creation.rst deleted file mode 100644 index 9054e299c0..0000000000 --- a/docs/source/c++/model_creation.rst +++ /dev/null @@ -1,14 +0,0 @@ -Model Creation -============== - - - -.. toctree:: - :maxdepth: 1 - - structure - ode_creation - lct_creation - sde_creation - ide_creation - \ No newline at end of file diff --git a/docs/source/c++/visualization.rst b/docs/source/c++/visualization.rst deleted file mode 100644 index 27e80a1334..0000000000 --- a/docs/source/c++/visualization.rst +++ /dev/null @@ -1,2 +0,0 @@ -Visualizations -============== \ No newline at end of file diff --git a/docs/source/cpp/aggregated_models.rst b/docs/source/cpp/aggregated_models.rst new file mode 100644 index 0000000000..808ef39641 --- /dev/null +++ b/docs/source/cpp/aggregated_models.rst @@ -0,0 +1,13 @@ +Aggregated models +================= + +There are different equation-based models implemented in MEmilio that consider an aggregated population. + +.. toctree:: + :maxdepth: 2 + + Ordinary differential equations + Linear Chain Trick + Generalized Linear Chain Trick + Stochastic-differential equations + Integro-differential equations \ No newline at end of file diff --git a/docs/source/c++/diffusive_abm.rst b/docs/source/cpp/diffusive_abm.rst similarity index 100% rename from docs/source/c++/diffusive_abm.rst rename to docs/source/cpp/diffusive_abm.rst diff --git a/docs/source/c++/glct.rst b/docs/source/cpp/glct.rst similarity index 100% rename from docs/source/c++/glct.rst rename to docs/source/cpp/glct.rst diff --git a/docs/source/c++/ide.rst b/docs/source/cpp/ide.rst similarity index 100% rename from docs/source/c++/ide.rst rename to docs/source/cpp/ide.rst diff --git a/docs/source/c++/ide_creation.rst b/docs/source/cpp/ide_creation.rst similarity index 100% rename from docs/source/c++/ide_creation.rst rename to docs/source/cpp/ide_creation.rst diff --git a/docs/source/c++/individual_models.rst b/docs/source/cpp/individual_models.rst similarity index 100% rename from docs/source/c++/individual_models.rst rename to docs/source/cpp/individual_models.rst diff --git a/docs/source/cpp/installation.rst b/docs/source/cpp/installation.rst new file mode 100644 index 0000000000..97a9eb4699 --- /dev/null +++ b/docs/source/cpp/installation.rst @@ -0,0 +1,4 @@ +Installation +================ + +Fow now, we refer to our `github repository `_ . \ No newline at end of file diff --git a/docs/source/c++/io.rst b/docs/source/cpp/io.rst similarity index 100% rename from docs/source/c++/io.rst rename to docs/source/cpp/io.rst diff --git a/docs/source/c++/lct.rst b/docs/source/cpp/lct.rst similarity index 100% rename from docs/source/c++/lct.rst rename to docs/source/cpp/lct.rst diff --git a/docs/source/c++/lct_creation.rst b/docs/source/cpp/lct_creation.rst similarity index 100% rename from docs/source/c++/lct_creation.rst rename to docs/source/cpp/lct_creation.rst diff --git a/docs/source/c++/metapop.rst b/docs/source/cpp/metapop.rst similarity index 100% rename from docs/source/c++/metapop.rst rename to docs/source/cpp/metapop.rst diff --git a/docs/source/c++/mobility.rst b/docs/source/cpp/mobility.rst similarity index 100% rename from docs/source/c++/mobility.rst rename to docs/source/cpp/mobility.rst diff --git a/docs/source/c++/mobility_based_abm.rst b/docs/source/cpp/mobility_based_abm.rst similarity index 99% rename from docs/source/c++/mobility_based_abm.rst rename to docs/source/cpp/mobility_based_abm.rst index 69ef09ba14..23e21e734f 100644 --- a/docs/source/c++/mobility_based_abm.rst +++ b/docs/source/cpp/mobility_based_abm.rst @@ -58,6 +58,7 @@ The ABM implements a detailed disease progression model that captures the full c * **Dead**: Deceased due to infection 2. **Viral Load Dynamics**: The model implements realistic viral load curves based on scientific data: + * **Incline Phase**: Rapid increase in viral concentration * **Peak**: Maximum viral load * **Decline Phase**: Gradual decrease until clearance @@ -65,13 +66,16 @@ The ABM implements a detailed disease progression model that captures the full c 3. **Infectiousness**: The probability of transmitting the virus depends on viral load through an invlogit function. 4. **Stochastic Transitions**: Progression between states is stochastic, with age-dependent probabilities: + * The duration in each state is drawn from distributions in the model parameters * Prior immunity (from vaccination or previous infection) affects: + * Viral load (reduced peak) * Severity progression (reduced probability of severe outcomes) * Duration of infectious period 5. **Infection Course**: The infection course is determined by: + * Age group of the person * Virus variant * Protection status (prior immunity) diff --git a/docs/source/c++/mobility_metapop.rst b/docs/source/cpp/mobility_metapop.rst similarity index 100% rename from docs/source/c++/mobility_metapop.rst rename to docs/source/cpp/mobility_metapop.rst diff --git a/docs/source/cpp/model_creation.rst b/docs/source/cpp/model_creation.rst new file mode 100644 index 0000000000..bd62d14e59 --- /dev/null +++ b/docs/source/cpp/model_creation.rst @@ -0,0 +1,14 @@ +Model Creation +============== + +Here we collect information on how to create models. + +.. toctree:: + :maxdepth: 1 + + Common structure + Ordinary differential equations + Linear Chain Trick + stochastic-differential equations + integro-differenatial equations + \ No newline at end of file diff --git a/docs/source/c++/model_usage.rst b/docs/source/cpp/model_usage.rst similarity index 88% rename from docs/source/c++/model_usage.rst rename to docs/source/cpp/model_usage.rst index efecba3004..b2cd499a21 100644 --- a/docs/source/c++/model_usage.rst +++ b/docs/source/cpp/model_usage.rst @@ -10,4 +10,3 @@ Model Usage individual_models mobility_metapop io - visualization diff --git a/docs/source/c++/ode.rst b/docs/source/cpp/ode.rst similarity index 100% rename from docs/source/c++/ode.rst rename to docs/source/cpp/ode.rst diff --git a/docs/source/c++/ode_creation.rst b/docs/source/cpp/ode_creation.rst similarity index 90% rename from docs/source/c++/ode_creation.rst rename to docs/source/cpp/ode_creation.rst index 11bef1f879..ef489bab9a 100644 --- a/docs/source/c++/ode_creation.rst +++ b/docs/source/cpp/ode_creation.rst @@ -18,7 +18,7 @@ given by a system of ordinary differential equations. For example we consider a and some initial values for :math:`t=0`. Here :math:`N_{\perp D} := S(t) + I(t) + R(t)`. This type of model is called compartmental model, because the model population is represented by discrete infection -states**S**usceptible, **I**nfected, **R**ecovered, **D**ead, also called compartments. +states **S** usceptible, **I** nfected, **R** ecovered, **D** ead, also called compartments. How to define an ODE model -------------------------- diff --git a/docs/source/cpp/overview.rst b/docs/source/cpp/overview.rst new file mode 100644 index 0000000000..8a41ec726f --- /dev/null +++ b/docs/source/cpp/overview.rst @@ -0,0 +1,2 @@ +Overview +============ \ No newline at end of file diff --git a/docs/source/c++/sde.rst b/docs/source/cpp/sde.rst similarity index 100% rename from docs/source/c++/sde.rst rename to docs/source/cpp/sde.rst diff --git a/docs/source/c++/sde_creation.rst b/docs/source/cpp/sde_creation.rst similarity index 100% rename from docs/source/c++/sde_creation.rst rename to docs/source/cpp/sde_creation.rst diff --git a/docs/source/c++/structure.rst b/docs/source/cpp/structure.rst similarity index 100% rename from docs/source/c++/structure.rst rename to docs/source/cpp/structure.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index 29e8ac4b11..4643219f58 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -12,6 +12,11 @@ Welcome =============== +.. attention:: + + This documentation is a work in progress. Some areas are already quite detailed, others are still missing completely. + + MEmilio implements various models for infectious disease dynamics, ranging from simple compartmental models to complex Integro-Differential and agent-based models. Its modular design enables the combination of different models with distinct mobility patterns. Through efficient implementation and parallelization, MEmilio delivers cutting-edge and compute-intensive epidemiological models at a large scale, providing precise and high-resolution spatiotemporal infectious disease dynamics. MEmilio is continuously extended and is available open-source for community use. .. image:: https://github.com/user-attachments/assets/65af6012-106e-43c6-9e0e-c96a73aa7b1e @@ -41,8 +46,10 @@ Contents :maxdepth: 2 :caption: C++ Interface - c++/model_usage - c++/model_creation + cpp/overview + cpp/installation + cpp/model_usage + cpp/model_creation .. toctree:: :maxdepth: 2 diff --git a/docs/source/python/model_usage.rst b/docs/source/python/model_usage.rst index 3b9b4053e9..094fb689ab 100755 --- a/docs/source/python/model_usage.rst +++ b/docs/source/python/model_usage.rst @@ -29,7 +29,7 @@ Python and C++. C++: - .. code-block:: c++ + .. code-block:: cpp #include "ode_seir/model.h" From 826fe64acb3b8b156f1ad310c64199a9606acf20 Mon Sep 17 00:00:00 2001 From: Kilian Volmer <13285635+kilianvolmer@users.noreply.github.com> Date: Fri, 21 Mar 2025 17:06:32 +0100 Subject: [PATCH 62/62] CHG: Add comment on python docstring keywords to python coding guidelines --- docs/source/development.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/source/development.rst b/docs/source/development.rst index 0a99930147..095f7bf826 100644 --- a/docs/source/development.rst +++ b/docs/source/development.rst @@ -19,7 +19,7 @@ We recommend to configure it locally such that it runs automatically on every co For more information about ``pre-commit`` check `here `_ and this short video series: https://calmcode.io/pre-commit/the-problem.html -Please be aware that the ``isort`` pre-commit hook accidentally sorts our own code with third party libraries, also see: https://github.com/PyCQA/isort/issues/2068 Be therefore sure to not commit python code from a worktree. +Please be aware that the ``isort`` pre-commit hook accidentally sorts our own code with third party libraries, also see: https://github.com/PyCQA/isort/issues/2068 . Be therefore sure to not commit python code from a worktree. C++ Coding guidelines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -232,6 +232,11 @@ If using autopep8, e.g., of the Python plugin for Visual Studio Code or VSCodium to your corresponding ``settings.json``. +**Docstrings** + +Docstrings in Python should be added for every function, as detailed in the C++ coding guidelines. However, the syntax is slightly different than for C++ code. An overview and examples can be found at https://sphinx-rtd-tutorial.readthedocs.io/en/latest/docstrings.html . + + Git workflow ----------------------