├── .coveragerc ├── .editorconfig ├── .flake8 ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── coverage-test.yml │ ├── cpp-coverage.yml │ ├── cpp-unit-tests-ubuntu.yml │ ├── doc-tests.yml │ ├── func-tests.yml │ ├── os-tests.yml │ ├── style-test.yml │ └── unit-tests.yml ├── .gitignore ├── .gitmodules ├── CITATION.cff ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── cEpiabm ├── CMakeLists.txt ├── README.rst ├── cmake │ ├── Catch.cmake │ ├── CatchAddTests.cmake │ ├── CompilerWarnings.cmake │ ├── FindSphinx.cmake │ ├── ProjectSettings.cmake │ ├── Sanitisers.cmake │ ├── StaticAnalysers.cmake │ └── epiabm-config.cmake ├── docs │ ├── .readthedocs.yaml │ ├── CMakeLists.txt │ ├── Doxyfile │ ├── Doxyfile.in │ ├── Makefile │ ├── conf.py │ ├── configuration.rst │ ├── dataclasses.rst │ ├── index.rst │ ├── make.bat │ ├── reporters.rst │ ├── requirements.txt │ ├── simulations.rst │ ├── sweeps.rst │ └── utilities.rst ├── examples │ ├── CMakeLists.txt │ └── basic_example │ │ ├── CMakeLists.txt │ │ └── main.cpp ├── src │ ├── CMakeLists.txt │ ├── configuration │ │ ├── config_factory_interface.hpp │ │ ├── host_progression_config.hpp │ │ ├── infection_config.hpp │ │ ├── json.hpp │ │ ├── json_factory.cpp │ │ ├── json_factory.hpp │ │ ├── population_config.hpp │ │ └── simulation_config.hpp │ ├── covidsim.cpp │ ├── covidsim.hpp │ ├── dataclasses │ │ ├── cell.cpp │ │ ├── cell.hpp │ │ ├── compartment_counter.cpp │ │ ├── compartment_counter.hpp │ │ ├── household.cpp │ │ ├── household.hpp │ │ ├── infection_status.hpp │ │ ├── microcell.cpp │ │ ├── microcell.hpp │ │ ├── person.cpp │ │ ├── person.hpp │ │ ├── place.cpp │ │ ├── place.hpp │ │ ├── population.cpp │ │ └── population.hpp │ ├── household_linker.cpp │ ├── household_linker.hpp │ ├── logfile.cpp │ ├── logfile.hpp │ ├── output_folder_handler.cpp │ ├── output_folder_handler.hpp │ ├── population_factory.cpp │ ├── population_factory.hpp │ ├── python_bindings │ │ ├── bind_configuration.hpp │ │ ├── bind_dataclasses.hpp │ │ ├── bind_logfile.hpp │ │ ├── bind_reporters.hpp │ │ ├── bind_simulation.hpp │ │ ├── bind_sweeps.hpp │ │ ├── bind_utilities.hpp │ │ └── bindings.cpp │ ├── reporters │ │ ├── age_stratified_new_cases_reporter.cpp │ │ ├── age_stratified_new_cases_reporter.hpp │ │ ├── age_stratified_population_reporter.cpp │ │ ├── age_stratified_population_reporter.hpp │ │ ├── cell_compartment_reporter.cpp │ │ ├── cell_compartment_reporter.hpp │ │ ├── new_cases_reporter.cpp │ │ ├── new_cases_reporter.hpp │ │ ├── percell_compartment_reporter.cpp │ │ ├── percell_compartment_reporter.hpp │ │ ├── population_compartment_reporter.cpp │ │ ├── population_compartment_reporter.hpp │ │ ├── timestep_reporter_interface.cpp │ │ └── timestep_reporter_interface.hpp │ ├── simulations │ │ ├── basic_simulation.cpp │ │ ├── basic_simulation.hpp │ │ ├── covid_sim.hpp │ │ ├── threaded_simulation.cpp │ │ └── threaded_simulation.hpp │ ├── sweeps │ │ ├── basic_host_progression_sweep.cpp │ │ ├── basic_host_progression_sweep.hpp │ │ ├── host_progression_sweep.cpp │ │ ├── host_progression_sweep.hpp │ │ ├── household_sweep.cpp │ │ ├── household_sweep.hpp │ │ ├── new_infection_sweep.cpp │ │ ├── new_infection_sweep.hpp │ │ ├── place_sweep.cpp │ │ ├── place_sweep.hpp │ │ ├── random_seed_sweep.cpp │ │ ├── random_seed_sweep.hpp │ │ ├── spatial_sweep.cpp │ │ ├── spatial_sweep.hpp │ │ ├── sweep_interface.cpp │ │ └── sweep_interface.hpp │ ├── toy_population_factory.cpp │ ├── toy_population_factory.hpp │ └── utilities │ │ ├── distance_metrics.cpp │ │ ├── distance_metrics.hpp │ │ ├── inverse_cdf.cpp │ │ ├── inverse_cdf.hpp │ │ ├── random_generator.hpp │ │ ├── random_manager.cpp │ │ ├── random_manager.hpp │ │ └── thread_pool.hpp └── test │ ├── CMakeLists.txt │ ├── catch │ └── catch.hpp │ ├── catch_main.cpp │ ├── configuration │ ├── helpers.hpp │ ├── test_host_progression_config.cpp │ ├── test_infection_config.cpp │ ├── test_json_factory.cpp │ ├── test_population_config.cpp │ └── test_simulation_config.cpp │ ├── dataclasses │ ├── test_cell.cpp │ ├── test_compartment_counter.cpp │ ├── test_distance_metrics.cpp │ ├── test_household.cpp │ ├── test_infection_status.cpp │ ├── test_microcell.cpp │ ├── test_person.cpp │ ├── test_place.cpp │ └── test_population.cpp │ ├── reporters │ ├── test_age_stratified_new_cases_reporter.cpp │ ├── test_age_stratified_population_reporter.cpp │ ├── test_cell_compartment_reporter.cpp │ ├── test_new_cases_reporter.cpp │ ├── test_percell_compartment_reporter.cpp │ └── test_population_compartment_reporter.cpp │ ├── sweeps │ ├── helpers.hpp │ ├── test_basic_host_progression_sweep.cpp │ ├── test_household_sweep.cpp │ ├── test_new_infection_sweep.cpp │ ├── test_place_sweep.cpp │ ├── test_random_seed_sweep.cpp │ └── test_spatial_sweep.cpp │ ├── test_basic_simulation.cpp │ ├── test_covidsim.cpp │ ├── test_log_file.cpp │ ├── test_output_file_handler.cpp │ ├── test_population_factory.cpp │ ├── test_toy_population_factory.cpp │ ├── testdata │ └── test_config.json │ └── utilities │ ├── test_distance_metrics.cpp │ ├── test_inverse_cdf.cpp │ ├── test_random_generator.cpp │ └── test_random_manager.cpp ├── images ├── Histograms │ ├── Withoutsim.png │ └── Withsim.png ├── covidsim_schema.png ├── diagram_covid_transition.jpg ├── distribution_covid_sim_rand.png ├── distribution_random_number.png ├── epiabm_waning_immunity_diagram.png ├── infectiousness_dist_gamma11.png ├── infectiousness_dist_gamma251.png ├── infectiousness_progression │ ├── infectiousness_prog.png │ ├── infectiousness_prog_diff.png │ ├── infectiousness_prog_timestep1.png │ └── infectiousness_prog_timestep2.png ├── power_law_eqn.svg ├── transition_times_dist │ ├── asympt_to_recov_time.png │ ├── gp_to_dead_time.png │ ├── gp_to_hosp_time.png │ ├── gp_to_recov_time.png │ ├── hosp_to_dead_time.png │ ├── hosp_to_icu_time.png │ ├── hosp_to_recov_tume.png │ ├── icu_to_dead_time.png │ ├── icu_to_icurecov_time.png │ ├── icurecov_to_recov_time.png │ ├── latent_time.png │ ├── latent_time_exp.png │ ├── latent_time_noexp.png │ └── mild_to_recov_time.png └── workplace_dist.svg ├── pyEpiabm ├── README.rst ├── docs │ ├── .readthedocs.yaml │ ├── Makefile │ ├── make.bat │ └── source │ │ ├── conf.py │ │ ├── core.rst │ │ ├── index.rst │ │ ├── interventions.rst │ │ ├── outputs.rst │ │ ├── properties.rst │ │ ├── py2c.rst │ │ ├── routines.rst │ │ ├── sweeps.rst │ │ └── utility.rst ├── pyEpiabm │ ├── __init__.py │ ├── core │ │ ├── __init__.py │ │ ├── _compartment_counter.py │ │ ├── cell.py │ │ ├── household.py │ │ ├── microcell.py │ │ ├── parameters.py │ │ ├── person.py │ │ ├── place.py │ │ └── population.py │ ├── intervention │ │ ├── __init__.py │ │ ├── abstract_intervention.py │ │ ├── case_isolation.py │ │ ├── disease_testing.py │ │ ├── household_quarantine.py │ │ ├── place_closure.py │ │ ├── social_distancing.py │ │ ├── travel_isolation.py │ │ └── vaccination.py │ ├── output │ │ ├── __init__.py │ │ ├── _csv_dict_writer.py │ │ ├── _csv_writer.py │ │ ├── abstract_reporter.py │ │ ├── age_stratified_new_cases_writer.py │ │ └── new_cases_writer.py │ ├── property │ │ ├── __init__.py │ │ ├── household_foi.py │ │ ├── infection_status.py │ │ ├── personal_foi.py │ │ ├── place_foi.py │ │ ├── place_type.py │ │ └── spatial_foi.py │ ├── py2c │ │ ├── __init__.py │ │ └── py2c_population.py │ ├── routine │ │ ├── __init__.py │ │ ├── abstract_population_config.py │ │ ├── file_population_config.py │ │ ├── simulation.py │ │ └── toy_population_config.py │ ├── sweep │ │ ├── __init__.py │ │ ├── abstract_sweep.py │ │ ├── host_progression_sweep.py │ │ ├── household_sweep.py │ │ ├── initial_demographics_sweep.py │ │ ├── initial_household_sweep.py │ │ ├── initial_infected_sweep.py │ │ ├── initial_place_sweep.py │ │ ├── initial_vaccine_sweep.py │ │ ├── intervention_sweep.py │ │ ├── place_sweep.py │ │ ├── queue_sweep.py │ │ ├── spatial_sweep.py │ │ ├── transition_matrices.py │ │ ├── travel_sweep.py │ │ └── update_place_sweep.py │ ├── tests │ │ ├── __init__.py │ │ ├── test_func │ │ │ ├── __init__.py │ │ │ ├── functional_testing_class.py │ │ │ ├── helper_func.py │ │ │ ├── spatial_input.csv │ │ │ ├── test_closure_functional.py │ │ │ ├── test_distancing_functional.py │ │ │ ├── test_integration.py │ │ │ ├── test_isolation_functional.py │ │ │ ├── test_quarantine_functional.py │ │ │ ├── test_random_seeds.py │ │ │ └── test_sim_functional.py │ │ ├── test_unit │ │ │ ├── __init__.py │ │ │ ├── mocked_logging_tests.py │ │ │ ├── parameter_config_tests.py │ │ │ ├── test_core │ │ │ │ ├── __init__.py │ │ │ │ ├── test_cell.py │ │ │ │ ├── test_compartment_counter.py │ │ │ │ ├── test_household.py │ │ │ │ ├── test_microcell.py │ │ │ │ ├── test_parameters.py │ │ │ │ ├── test_person.py │ │ │ │ ├── test_place.py │ │ │ │ └── test_population.py │ │ │ ├── test_intervention │ │ │ │ ├── __init__.py │ │ │ │ ├── test_abstract_intervention.py │ │ │ │ ├── test_case_isolation.py │ │ │ │ ├── test_household_quarantine.py │ │ │ │ ├── test_place_closure.py │ │ │ │ ├── test_social_distancing.py │ │ │ │ ├── test_testing.py │ │ │ │ ├── test_travel_isolation.py │ │ │ │ └── test_vaccination.py │ │ │ ├── test_output │ │ │ │ ├── __init__.py │ │ │ │ ├── test_abstract_reporter.py │ │ │ │ ├── test_age_stratified_new_cases_writer.py │ │ │ │ ├── test_csv_dict_writer.py │ │ │ │ ├── test_csv_writer.py │ │ │ │ └── test_new_cases_writer.py │ │ │ ├── test_property │ │ │ │ ├── __init__.py │ │ │ │ ├── test_household_foi.py │ │ │ │ ├── test_infection_status.py │ │ │ │ ├── test_personal_foi.py │ │ │ │ ├── test_place_foi.py │ │ │ │ ├── test_place_type.py │ │ │ │ └── test_spatial_foi.py │ │ │ ├── test_py2c │ │ │ │ ├── __init__.py │ │ │ │ ├── test_py2c_population.py │ │ │ │ └── test_timer.py │ │ │ ├── test_routine │ │ │ │ ├── __init__.py │ │ │ │ ├── test_abstract_population_config.py │ │ │ │ ├── test_file_population_config.py │ │ │ │ ├── test_simulation.py │ │ │ │ └── test_toy_population_config.py │ │ │ ├── test_sweep │ │ │ │ ├── __init__.py │ │ │ │ ├── test_abstract_sweep.py │ │ │ │ ├── test_host_progression_sweep.py │ │ │ │ ├── test_household_sweep.py │ │ │ │ ├── test_initial_demographics_sweep.py │ │ │ │ ├── test_initial_household_sweep.py │ │ │ │ ├── test_initial_infected_sweep.py │ │ │ │ ├── test_initial_vaccine_sweep.py │ │ │ │ ├── test_initialise_place_sweep.py │ │ │ │ ├── test_intervention_sweep.py │ │ │ │ ├── test_place_sweep.py │ │ │ │ ├── test_queue_sweep.py │ │ │ │ ├── test_spatial_sweep.py │ │ │ │ ├── test_state_transition_matrix.py │ │ │ │ ├── test_transition_time_matrix.py │ │ │ │ ├── test_travel_sweep.py │ │ │ │ └── test_update_place_sweep.py │ │ │ └── test_utility │ │ │ │ ├── __init__.py │ │ │ │ ├── test_antibody_multiplier.py │ │ │ │ ├── test_covidsim_kernel.py │ │ │ │ ├── test_distance_metrics.py │ │ │ │ ├── test_exception_logger.py │ │ │ │ ├── test_inverse_cdf.py │ │ │ │ ├── test_random_methods.py │ │ │ │ └── test_rate_multiplier.py │ │ └── testing_parameters.json │ ├── utility │ │ ├── __init__.py │ │ ├── antibody_multiplier.py │ │ ├── covidsim_kernel.py │ │ ├── distance_metrics.py │ │ ├── exception_logger.py │ │ ├── inverse_cdf.py │ │ ├── random_methods.py │ │ └── rate_multiplier.py │ └── version_info.py ├── requirements.txt ├── run_tests.py └── setup.py └── python_examples ├── NI_example ├── NI_flow.py └── NI_parameters.json ├── NZ_example ├── NZ_flow.py ├── NewZealand_noInt_parameters.json ├── NewZealand_parameters.json └── NewZealand_parameters_relaxed.json ├── R0_inference ├── learn_R.ipynb └── si-covid.csv ├── README.md ├── age_stratified_example ├── age_hist │ ├── age_hist.py │ └── simulation_outputs │ │ └── output_gibraltar.csv ├── age_stratified_plot.py ├── simple_parameters_with_age.json ├── simulation_flow_with_age.py └── simulation_outputs │ ├── age_stratify.png │ ├── daily_cases.csv │ ├── gibraltar_cases.csv │ ├── output_with_age.csv │ └── simulation_flow_SIR_plot.png ├── antibody_igG_test ├── IgG_validation_graphs.png ├── Lumley_paper_igG_levels_graph.png └── antibody_igG_test_graph.py ├── basic_infection_history_simulation ├── simple_parameters.json ├── simulation_flow.py └── simulation_outputs │ ├── demographics.csv │ ├── inf_status_history.csv │ ├── infectiousness_history.csv │ └── output.csv ├── basic_simulation ├── simple_parameters.json ├── simulation_flow.py └── simulation_outputs │ ├── output.csv │ └── simulation_flow_SIR_plot.png ├── cEpiabm_example ├── icdf.ipynb ├── output │ └── population_results.csv ├── parameters.json ├── parameters_live.json ├── python_parameters.json ├── python_to_cpp_population_converter.ipynb ├── simulation.ipynb ├── threaded_output │ └── population_results.csv └── threaded_simulation.ipynb ├── gibraltar_example ├── README.md ├── covidsim_results │ ├── WeeklyIncidenceCasesbyAgeGroup.png │ ├── covidsim_daily_cases.csv │ ├── modified_age_severity.csv │ ├── plot_covidsim.py │ └── severity_age.csv ├── gibraltar_flow.py ├── gibraltar_inputs │ ├── gib_input.csv │ ├── microcell_conversion.py │ └── wpop_gib.txt ├── gibraltar_parameters.json ├── gibraltar_parameters_without_intervention.json └── simulation_outputs │ ├── with_intervention │ ├── age_stratify.png │ ├── gibraltar_weeky_cases.csv │ └── simulation_flow_SIR_plot.png │ └── without_intervention │ ├── age_stratify.png │ ├── gibraltar_weeky_cases.csv │ └── simulation_flow_SIR_plot.png ├── gibraltar_example_cpp ├── gibraltar_parameters_cpp.json ├── gibraltar_parameters_py.json ├── gibraltar_simulation_flow_cpp.py ├── output │ ├── age_stratified_new_cases.csv │ ├── age_stratified_population_results.csv │ ├── new_cases.csv │ └── population_results.csv └── plot.ipynb ├── intervention_example ├── README.md ├── case_isolation_parameters.json ├── case_isolation_simulation_flow.py ├── disease_testing_parameters.json ├── disease_testing_simulation_flow.py ├── household_quarantine_parameters.json ├── household_quarantine_simulation_flow.py ├── input.csv ├── intervention_outputs │ ├── case_isolation_Icurve_plot.png │ ├── case_isolation_via_testing_plot.png │ ├── household_quarantine_Icurve_plot.png │ ├── place_closure_closure_place_type_Icurve_plot.png │ ├── social_distancing_distancing_enhanced_prob_Icurve_plot.png │ ├── travel_isolation_Icurve_plot.png │ └── vaccination_Icurve_plot.png ├── place_closure_parameters.json ├── place_closure_simulation_flow.py ├── social_distancing_parameters.json ├── social_distancing_simulation_flow.py ├── travel_isolation_parameters.json ├── travel_isolation_simulation_flow.py ├── vaccination_flow.py └── vaccination_parameters.json ├── luxembourg_example ├── animation │ ├── population_output_intervention_simulation_1.gif │ ├── population_output_simulation_1.gif │ ├── population_output_simulation_1_grid.png │ └── pre_population_output_simulation_1.gif ├── luxembourg_flow.py ├── luxembourg_inputs │ ├── luxembourg_adapted_5_in_cell_input.csv │ ├── luxembourg_initial_infect.py │ └── luxembourg_input_file.csv ├── luxembourg_intervention_parameters.json ├── luxembourg_parameters.json ├── paper_plots │ ├── incidence_rural_vs_urban.png │ ├── post_day_40.png │ ├── pre_day_40.png │ ├── pre_post_raw.png │ └── pre_post_rural_vs_urban.png ├── rural_v_urban.ipynb └── simulation_outputs │ ├── all_post_summary.csv │ ├── all_pre_summary.csv │ ├── urban_rural_post_summary.csv │ ├── urban_rural_pre_summary.csv │ ├── urban_rural_summary.csv │ └── urban_rural_summary_interventions.csv ├── model_population_example ├── IntCI_params.json ├── IntMult_params.json ├── model_interventions.ipynb ├── model_population.ipynb ├── noInt_params.json ├── simulation_outputs │ ├── combined_summary.csv │ └── multi_interventions │ │ ├── summary_4x4_av5_CI+HQ+PC.csv │ │ ├── summary_4x4_av5_CI+HQ.csv │ │ ├── summary_4x4_av5_CI.csv │ │ └── summary_4x4_av5_No intervention.csv ├── toy_plotter.py └── uniform_inputs │ ├── input_12x12_av5_places.csv │ ├── input_15x15_av5_places.csv │ ├── input_4x4_av5_places.csv │ ├── input_6x6_av5_places.csv │ └── input_8x8_av5_places.csv ├── sim_speeds ├── Readme.md ├── Sim_Speeds.txt ├── basic_speed_plot.py ├── old_intervention_basic_speeds.csv ├── old_intervention_spatial_speeds.csv ├── sim_runner.py ├── sim_runner_spatial.py ├── sim_speeds.ipynb ├── sim_speeds_plots │ └── basic_sim_speed_from_file.png ├── simple_parameters.json └── spatial_parameters.json ├── spatial_example ├── input.csv ├── spatial_outputs │ ├── output.csv │ ├── spatial_flow_Icurve_plot.png │ ├── voronoi_animation.gif │ └── voronoi_grid_img.png ├── spatial_parameters.json ├── spatial_simulation_flow.py └── voronoi_plotting_example.py └── travel_example ├── input.csv ├── travel_simulation_flow.py ├── travelling_outputs ├── travelling_constant_introduce_cases_Icurve_plot.png └── travelling_ratio_introduce_cases_Icurve_plot.png └── travelling_parameters.json /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = pyEpiabm 3 | omit = 4 | pyEpiabm/pyEpiabm/tests/* 5 | pyEpiabm/pyEpiabm/version_info.py 6 | pyEpiabm/run_tests.py 7 | pyEpiabm/setup.py 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org/#file-format-details 2 | root = true 3 | 4 | # Always use Unix style new lines with new line ending on every file and trim whitespace 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | # Python: PEP8 defines 4 spaces for indentation 12 | [*.py] 13 | indent_style = space 14 | indent_size = 4 15 | 16 | # Allow new paragraph from two trailing whitespaces in markdown 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 79 3 | exclude = 4 | .git 5 | .vscode 6 | .pytest_cache 7 | .venv 8 | .env 9 | per-file-ignores = 10 | */__init__.py: F401 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | cEpiabm/test/catch/catch.hpp linguist-vendored 2 | *.ipynb linguist-vendored 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | Include file/line locations if you believe it pertains to a particular class/function. 13 | 14 | **To Reproduce** 15 | Steps to reproduce the behaviour: 16 | 1. Set Parameters to... 17 | 2. Run with the configuration... 18 | 19 | **Expected behaviour** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Log Files** 23 | If applicable, add log files to explain what happened 24 | 25 | **Desktop (please complete the following information):** 26 | - OS: 27 | - Python/ C++ Version: 28 | 29 | **Additional context** 30 | Add any other context about the problem here. 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | If it is a new feature, where should it be added? 16 | 17 | **Describe alternatives you've considered** 18 | A clear and concise description of any alternative solutions or implementations you've considered. 19 | 20 | **Comparison to CovidSim** 21 | Give any relevant comparison to the CovidSim code, and describe any deviations from their functionality 22 | 23 | **Additional context** 24 | Add any other context or screenshots about the feature request here. 25 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | 3 | Describe the issue, and what you have done to solve it 4 | 5 | ## Further work 6 | 7 | If relevant, add in what needs to be done next on this area (and whether you will do it!) 8 | 9 | ## Checklist 10 | 11 | - [ ] All new functions have docstrings in the correct style 12 | - [ ] I've verified the complete docs build locally without errors 13 | - [ ] I've maintained 100% coverage (please mention any 'no cover' annotations explicitly) 14 | - [ ] I've unit-tested all new methods directly 15 | 16 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 17 | - [ ] I have read the **CONTRIBUTING** document. 18 | - [ ] My code follows the code style of this project. 19 | - [ ] I have updated the wiki with new parameters/model functionality 20 | 21 | ## Closing issues 22 | 23 | Put `closes #XXXX` in your comment to auto-close the issue that your PR fixes (if such). 24 | -------------------------------------------------------------------------------- /.github/workflows/coverage-test.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: coverage 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Set up Python 3.11 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: '3.11' 24 | architecture: x64 25 | 26 | - name: install pyEpiabm 27 | run: | 28 | python --version 29 | python -m pip install --upgrade pip setuptools wheel 30 | python -m pip install pyEpiabm/. 31 | python -m pip install coverage codecov 32 | - name: run coverage 33 | run: | 34 | coverage run pyEpiabm/run_tests.py --unit 35 | - name: codecov 36 | if: success() 37 | env: 38 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 39 | run: | 40 | codecov 41 | -------------------------------------------------------------------------------- /.github/workflows/cpp-coverage.yml: -------------------------------------------------------------------------------- 1 | name: CPP Coverage Report 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | runs-on: ubuntu-20.04 15 | env: 16 | CC: gcc-10 17 | CXX: g++-10 18 | 19 | steps: 20 | - name: checkout repo & submodules 21 | uses: actions/checkout@v2 22 | with: 23 | submodules: true 24 | 25 | - name: install tools 26 | run: sudo apt install lcov 27 | 28 | - name: make build directory 29 | run: mkdir build_dir 30 | 31 | - name: run unit tests with coverage 32 | run: | 33 | cmake ../cEpiabm/. -DCMAKE_BUILD_TYPE=Debug -DENABLE_COVERAGE=ON 34 | cmake --build . --parallel $(nproc) --target unit_tests 35 | ctest -j2 --output-on-failure 36 | working-directory: build_dir 37 | 38 | - name: upload coverage results 39 | run: | 40 | lcov --directory . --capture --output-file coverage.info 41 | lcov --remove coverage.info '/usr/*' '*/test/*' '*/examples/*' '*/src/configuration/json.hpp' --output-file coverage.info 42 | lcov --list coverage.info 43 | bash <(curl https://codecov.io/bash) -f coverage.info 44 | env: 45 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 46 | working-directory: build_dir -------------------------------------------------------------------------------- /.github/workflows/cpp-unit-tests-ubuntu.yml: -------------------------------------------------------------------------------- 1 | name: Unit tests (cEpiabm) 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | runs-on: ubuntu-20.04 15 | env: 16 | CC: gcc-9 17 | CXX: g++-9 18 | 19 | steps: 20 | - name: checkout repo & submodules 21 | uses: actions/checkout@v2 22 | with: 23 | submodules: true 24 | 25 | - name: make build directory 26 | run: mkdir build_dir 27 | 28 | - name: cmake configure 29 | run: cmake ../cEpiabm/. -DCMAKE_BUILD_TYPE=Debug 30 | working-directory: build_dir 31 | 32 | - name: cmake build 33 | run: cmake --build . --parallel $(nproc) --target unit_tests 34 | working-directory: build_dir 35 | 36 | - name: run unit tests 37 | run: ctest -j2 --output-on-failure 38 | working-directory: build_dir 39 | -------------------------------------------------------------------------------- /.github/workflows/doc-tests.yml: -------------------------------------------------------------------------------- 1 | name: Doctest 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: doctest 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Set up Python '3.11' 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: '3.11' 24 | architecture: x64 25 | 26 | - name: install pyEpiabm 27 | run: | 28 | python --version 29 | python -m pip install --upgrade pip setuptools wheel 30 | python -m pip install pyEpiabm/. 31 | python -m pip install pyEpiabm/.[docs] 32 | - name: run doctest 33 | run: | 34 | cd pyEpiabm 35 | python run_tests.py --docs 36 | 37 | Validate-CITATION-cff: 38 | name: Validate CITATION.cff 39 | runs-on: ubuntu-latest 40 | 41 | steps: 42 | - name: Checkout 43 | uses: actions/checkout@v4 44 | 45 | - name: Validate CITATION.cff 46 | uses: dieghernan/cff-validator@v3 47 | -------------------------------------------------------------------------------- /.github/workflows/func-tests.yml: -------------------------------------------------------------------------------- 1 | name: Functional tests (pyEpiabm) 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: func test 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Set up Python 3.11 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: '3.11' 24 | architecture: x64 25 | 26 | - name: install pyEpiabm 27 | run: | 28 | python --version 29 | python -m pip install --upgrade pip setuptools wheel 30 | python -m pip install pyEpiabm/. 31 | - name: run func tests 32 | run: | 33 | python pyEpiabm/run_tests.py --func 34 | -------------------------------------------------------------------------------- /.github/workflows/os-tests.yml: -------------------------------------------------------------------------------- 1 | name: Unit tests (pyEpiabm - OS versions) 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, windows-latest] 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: Set up Python 3.11 23 | uses: actions/setup-python@v4 24 | with: 25 | python-version: '3.11' 26 | architecture: x64 27 | 28 | - name: install pyEpiabm 29 | run: | 30 | python --version 31 | python -m pip install --upgrade pip setuptools wheel 32 | python -m pip install pyEpiabm/. 33 | - name: run unit tests 34 | run: | 35 | python pyEpiabm/run_tests.py --unit 36 | -------------------------------------------------------------------------------- /.github/workflows/style-test.yml: -------------------------------------------------------------------------------- 1 | name: Style tests (flake8) 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | name: style test 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Set up Python 3.11 21 | uses: actions/setup-python@v4 22 | with: 23 | python-version: '3.11' 24 | architecture: x64 25 | 26 | - name: install pyEpiabm 27 | run: | 28 | python --version 29 | python -m pip install --upgrade pip setuptools wheel 30 | python -m pip install pyEpiabm/. 31 | python -m pip install pyEpiabm/.[dev] 32 | - name: run style tests 33 | run: | 34 | python -m flake8 35 | -------------------------------------------------------------------------------- /.github/workflows/unit-tests.yml: -------------------------------------------------------------------------------- 1 | name: Unit tests (pyEpiabm) 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | jobs: 12 | 13 | build-and-test: 14 | runs-on: ubuntu-latest 15 | strategy: 16 | matrix: 17 | python-version: ['3.7', '3.8', '3.9', '3.10', '3.11'] 18 | 19 | steps: 20 | - uses: actions/checkout@v4 21 | 22 | - name: Set up Python ${{ matrix.python-version }} 23 | uses: actions/setup-python@v4 24 | with: 25 | python-version: ${{ matrix.python-version }} 26 | architecture: x64 27 | 28 | - name: install pyEpiabm 29 | run: | 30 | python --version 31 | python -m pip install --upgrade pip setuptools wheel 32 | python -m pip install pyEpiabm/. 33 | - name: run unit tests 34 | run: | 35 | python pyEpiabm/run_tests.py --unit 36 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "cEpiabm/pybind11"] 2 | path = cEpiabm/pybind11 3 | url = https://github.com/pybind/pybind11 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, SABS-R3-Epidemiology 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /cEpiabm/README.rst: -------------------------------------------------------------------------------- 1 | cEpiabm 2 | ======= 3 | 4 | We provide an efficient and scalable backend in C++, which can run 5 | simulations for populations comparable to the UK in a reasonable 6 | timeframe. This code may be harder than pyEpiabm for new users to 7 | understand, but the parallels with the python code should be 8 | sufficiently informative for those who wish to look deeper into the 9 | code. 10 | 11 | Set up 12 | ------ 13 | 14 | Installation of cEpiabm 15 | ~~~~~~~~~~~~~~~~~~~~~~~ 16 | 17 | Cmake is used for installation of the cEpiabm software. The following 18 | procedure will compile the code and run all unit tests: 19 | 20 | .. code:: console 21 | 22 | mkdir build_dir 23 | cd build_dir 24 | cmake ../cEpiabm/. -DCMAKE_BUILD_TYPE=Debug 25 | cmake --build . --parallel 2 --target unit_tests 26 | ctest -j2 --output-on-failure 27 | 28 | Note that cmake must be installed on your system. The following command 29 | can be used on ubuntu systems: 30 | 31 | .. code:: console 32 | 33 | sudo apt-get install cmake cmake-data 34 | 35 | We recommend the use of the G++ compiler (version 9 or higher) with 36 | cEpiabm. If other compilers are used, users should ensure they include 37 | the filesystem library, or include this explicitly by inserting 38 | ``link_libraries(stdc++fs)`` in the ``cEpiabm/CMakeLists.txt`` file. 39 | 40 | Compiling cEpiabm Python Bindings 41 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 42 | 43 | Pybind11 is required for compiling cEpiabm with Python bindings. 44 | Pybind11 is added as a git submodule, make sure this submodule is cloned 45 | along with the main epiabm repository. 46 | 47 | Compiling Python bindings follows similar procedure to compiling the 48 | cEpiabm tests: 49 | 50 | .. code:: console 51 | 52 | mkdir build_dir 53 | cd build_dir 54 | cmake ../cEpiabm/. -DCMAKE_BUILD_TYPE=Release -DENABLE_COVERAGE=OFF 55 | cmake --build . --parallel 6 --target epiabm 56 | 57 | cEpiabm’s python bindings will be compiled to a python module named 58 | epiabm, located in ``build_dir/src/epiabm.cpython-(version info).so``. 59 | -------------------------------------------------------------------------------- /cEpiabm/cmake/FindSphinx.cmake: -------------------------------------------------------------------------------- 1 | # Based on https://devblogs.microsoft.com/cppblog/clear-functional-c-documentation-with-sphinx-breathe-doxygen-cmake/ 2 | # https://github.com/TartanLlama/cpp-documentation-example 3 | 4 | #Look for an executable called sphinx-build 5 | find_program(SPHINX_EXECUTABLE 6 | NAMES sphinx-build 7 | HINTS ${PROJECT_SOURCE_DIR}/venv/bin 8 | DOC "Path to sphinx-build executable") 9 | 10 | include(FindPackageHandleStandardArgs) 11 | 12 | #Handle standard arguments to find_package like REQUIRED and QUIET 13 | find_package_handle_standard_args(Sphinx 14 | "Failed to find sphinx-build executable" 15 | SPHINX_EXECUTABLE) -------------------------------------------------------------------------------- /cEpiabm/cmake/ProjectSettings.cmake: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Based on https://github.com/lefticus/cpp_starter_project 4 | 5 | # Set a default build type if none was specified 6 | if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) 7 | message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.") 8 | set(CMAKE_BUILD_TYPE 9 | RelWithDebInfo 10 | CACHE STRING "Choose the type of build." FORCE) 11 | # Set the possible values of build type for cmake-gui, ccmake 12 | set_property( 13 | CACHE CMAKE_BUILD_TYPE 14 | PROPERTY STRINGS 15 | "Debug" 16 | "Release" 17 | "MinSizeRel" 18 | "RelWithDebInfo") 19 | endif () 20 | 21 | # Generate compile_commands.json to make it easier to work with clang based tools 22 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 23 | 24 | if (CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") 25 | option(ENABLE_BUILD_WITH_TIME_TRACE "Enable -ftime-trace to generate time tracing .json files on clang" OFF) 26 | if (ENABLE_BUILD_WITH_TIME_TRACE) 27 | add_compile_definitions(project_settings INTERFACE -ftime-trace) 28 | endif () 29 | endif () 30 | -------------------------------------------------------------------------------- /cEpiabm/cmake/StaticAnalysers.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Based on https://github.com/lefticus/cpp_starter_project 3 | 4 | option(ENABLE_CPPCHECK "Enable static analysis with cppcheck" OFF) 5 | option(ENABLE_CLANG_TIDY "Enable static analysis with clang-tidy" OFF) 6 | 7 | if (ENABLE_CPPCHECK) 8 | find_program(CPPCHECK cppcheck) 9 | if (CPPCHECK) 10 | set(CMAKE_CXX_CPPCHECK 11 | ${CPPCHECK} 12 | --suppress=missingInclude 13 | --suppress=unusedFunction 14 | --suppress=unmatchedSuppression 15 | --enable=all 16 | --inconclusive) 17 | message(STATUS "Using cppcheck ${CPPCHECK}") 18 | else () 19 | message(SEND_ERROR "cppcheck requested but executable not found") 20 | endif () 21 | endif () 22 | 23 | if (ENABLE_CLANG_TIDY) 24 | find_program(CLANGTIDY NAMES clang-tidy-11 clang-tidy-10 clang-tidy-9 clang-tidy-8 clang-tidy) 25 | if (CLANGTIDY) 26 | set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY} -extra-arg=-Wno-unknown-warning-option) 27 | message(STATUS "Using clang-tidy ${CLANGTIDY}") 28 | else () 29 | message(SEND_ERROR "clang-tidy requested but executable not found") 30 | endif () 31 | endif () 32 | -------------------------------------------------------------------------------- /cEpiabm/cmake/epiabm-config.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeFindDependencyMacro) 2 | 3 | 4 | include(${CMAKE_CURRENT_LIST_DIR}/epiabm-runtime.cmake) 5 | -------------------------------------------------------------------------------- /cEpiabm/docs/.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the required OS and Python version 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.10" 13 | 14 | # Build documentation in the docs/ directory with Sphinx 15 | sphinx: 16 | configuration: cEpiabm/docs/conf.py 17 | 18 | python: 19 | install: 20 | - requirements: cEpiabm/docs/requirements.txt 21 | -------------------------------------------------------------------------------- /cEpiabm/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /cEpiabm/docs/configuration.rst: -------------------------------------------------------------------------------- 1 | ************* 2 | CONFIGURATION 3 | ************* 4 | 5 | .. currentmodule:: cEpiabm 6 | 7 | Configure a cEpiabm simulation. 8 | 9 | Overview: 10 | 11 | - :class:`SimulationConfig` 12 | - :class:`PopulationConfig` 13 | - :class:`InfectionConfig` 14 | - :class:`HostProgressionConfig` 15 | - :class:`ConfigurationFactoryInterface` 16 | - :class:`JsonFactory` 17 | 18 | 19 | CONFIGURATION 20 | ************* 21 | 22 | .. doxygenclass:: epiabm::SimulationConfig 23 | :members: 24 | :undoc-members: 25 | 26 | .. doxygenclass:: epiabm::PopulationConfig 27 | :members: 28 | :undoc-members: 29 | 30 | .. doxygenclass:: epiabm::InfectionConfig 31 | :members: 32 | :undoc-members: 33 | 34 | .. doxygenclass:: epiabm::HostProgressionConfig 35 | :members: 36 | :undoc-members: 37 | 38 | .. doxygenclass:: epiabm::ConfigurationFactoryInterface 39 | :members: 40 | :undoc-members: 41 | 42 | .. doxygenclass:: epiabm::JsonFactory 43 | :members: 44 | :undoc-members: 45 | -------------------------------------------------------------------------------- /cEpiabm/docs/dataclasses.rst: -------------------------------------------------------------------------------- 1 | *********** 2 | DATACLASSES 3 | *********** 4 | 5 | .. currentmodule:: cEpiabm 6 | 7 | Dataclasses provides the basic class framework to build a population 8 | 9 | Overview: 10 | 11 | - :class:`Population` 12 | - :class:`Cell` 13 | - :class:`Microcell` 14 | - :class:`Household` 15 | - :class:`Place` 16 | - :class:`Person` 17 | - :enum:`InfectionStatus` 18 | 19 | 20 | DATACLASSES 21 | *********** 22 | 23 | .. doxygenclass:: epiabm::Population 24 | :members: 25 | :undoc-members: 26 | 27 | .. doxygenclass:: epiabm::Cell 28 | :members: 29 | :undoc-members: 30 | 31 | .. doxygenclass:: epiabm::Microcell 32 | :members: 33 | :undoc-members: 34 | 35 | .. doxygenclass:: epiabm::Household 36 | :members: 37 | :undoc-members: 38 | 39 | .. doxygenstruct:: epiabm::HouseholdParams 40 | :members: 41 | :undoc-members: 42 | 43 | .. doxygenclass:: epiabm::Place 44 | :members: 45 | :undoc-members: 46 | 47 | .. doxygenclass:: epiabm::Person 48 | :members: 49 | :undoc-members: 50 | 51 | .. doxygenstruct:: epiabm::PersonParams 52 | :members: 53 | :undoc-members: 54 | 55 | .. doxygenenum:: epiabm::InfectionStatus 56 | -------------------------------------------------------------------------------- /cEpiabm/docs/index.rst: -------------------------------------------------------------------------------- 1 | .. C++ Epiabm documentation master file, created by 2 | sphinx-quickstart on Wed Dec 8 15:19:55 2021. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to C++ Epiabm's documentation! 7 | ====================================== 8 | 9 | .. include:: ../README.rst 10 | 11 | Contents 12 | ======== 13 | 14 | .. module:: cEpiabm 15 | 16 | .. toctree:: 17 | 18 | simulations 19 | dataclasses 20 | sweeps 21 | configuration 22 | reporters 23 | utilities 24 | 25 | 26 | 27 | Indices and tables 28 | ================== 29 | 30 | * :ref:`genindex` 31 | * :ref:`modindex` 32 | * :ref:`search` 33 | 34 | -------------------------------------------------------------------------------- /cEpiabm/docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.https://www.sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /cEpiabm/docs/reporters.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | REPORTERS 3 | ********* 4 | 5 | .. currentmodule:: cEpiabm 6 | 7 | Class framework for outputting simulation data 8 | 9 | Overview: 10 | 11 | - :class:`TimestepReporterInterface` 12 | - :class:`PopulationCompartmentReporter` 13 | - :class:`CellCompartmentReporter` 14 | - :class:`PerCellCompartmentReporter` 15 | 16 | 17 | REPORTERS 18 | ********* 19 | 20 | .. doxygenclass:: epiabm::TimestepReporterInterface 21 | :members: 22 | :undoc-members: 23 | 24 | .. doxygenclass:: epiabm::PopulationCompartmentReporter 25 | :members: 26 | :undoc-members: 27 | 28 | .. doxygenclass:: epiabm::CellCompartmentReporter 29 | :members: 30 | :undoc-members: 31 | 32 | .. doxygenclass:: epiabm::PerCellCompartmentReporter 33 | :members: 34 | :undoc-members: 35 | -------------------------------------------------------------------------------- /cEpiabm/docs/requirements.txt: -------------------------------------------------------------------------------- 1 | breathe 2 | -------------------------------------------------------------------------------- /cEpiabm/docs/simulations.rst: -------------------------------------------------------------------------------- 1 | *********** 2 | SIMULATIONS 3 | *********** 4 | 5 | .. currentmodule:: cEpiabm 6 | 7 | Overall simulation management class. 8 | 9 | Overview: 10 | 11 | - :class:`BasicSimulation` 12 | - :class:`ThreadedSimulation` 13 | 14 | 15 | SIMULATIONS 16 | *********** 17 | 18 | .. doxygenclass:: epiabm::BasicSimulation 19 | :members: 20 | :undoc-members: 21 | 22 | .. doxygenclass:: epiabm::ThreadedSimulation 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /cEpiabm/docs/sweeps.rst: -------------------------------------------------------------------------------- 1 | ****** 2 | SWEEPS 3 | ****** 4 | 5 | .. currentmodule:: cEpiabm 6 | 7 | Sweeps implements classes which manage infection propagation mechanisms. Class sweeps through the population to decide infection transmission. 8 | 9 | Overview: 10 | 11 | - :class:`SweepInterface` 12 | - :class:`HouseholdSweep` 13 | - :class:`SpatialSweep` 14 | - :class:`PlaceSweep` 15 | - :class:`BasicHostProgressionSweep` 16 | - :class:`HostProgressionSweep` 17 | - :class:`NewInfectionSweep` 18 | - :class:`RandomSeedSweep` 19 | 20 | SWEEPS 21 | ****** 22 | 23 | .. doxygenclass:: epiabm::SweepInterface 24 | :members: 25 | :undoc-members: 26 | 27 | .. doxygenclass:: epiabm::HouseholdSweep 28 | :members: 29 | :undoc-members: 30 | 31 | .. doxygenclass:: epiabm::SpatialSweep 32 | :members: 33 | :undoc-members: 34 | 35 | .. doxygenclass:: epiabm::PlaceSweep 36 | :members: 37 | :undoc-members: 38 | 39 | .. doxygenclass:: epiabm::BasicHostProgressionSweep 40 | :members: 41 | :undoc-members: 42 | 43 | .. doxygenclass:: epiabm::HostProgressionSweep 44 | :members: 45 | :undoc-members: 46 | 47 | .. doxygenclass:: epiabm::NewInfectionSweep 48 | :members: 49 | :undoc-members: 50 | 51 | .. doxygenclass:: epiabm::RandomSeedSweep 52 | :members: 53 | :undoc-members: 54 | -------------------------------------------------------------------------------- /cEpiabm/docs/utilities.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | UTILITIES 3 | ********* 4 | 5 | .. currentmodule:: cEpiabm 6 | 7 | Utility classes 8 | 9 | Overview: 10 | 11 | - :class:`Logfile` 12 | - :class:`OutputFolderHandler` 13 | - :class:`PopulationFactory` 14 | - :class:`ToyPopulationFactory` 15 | - :class:`HouseholdLinker` 16 | - :class:`thread_pool` 17 | - :class:`RandomManager` 18 | - :class:`RandomGenerator` 19 | - :class:`InverseCDF` 20 | - :class:`DistanceMetrics` 21 | 22 | 23 | UTILITIES 24 | ********* 25 | 26 | .. doxygenclass:: epiabm::LogFile 27 | :members: 28 | :undoc-members: 29 | 30 | .. doxygenclass:: epiabm::OutputFolderHandler 31 | :members: 32 | :undoc-members: 33 | 34 | .. doxygenclass:: epiabm::PopulationFactory 35 | :members: 36 | :undoc-members: 37 | 38 | .. doxygenclass:: epiabm::ToyPopulationFactory 39 | :members: 40 | :undoc-members: 41 | 42 | .. doxygenclass:: epiabm::HouseholdLinker 43 | :members: 44 | :undoc-members: 45 | 46 | .. doxygenclass:: epiabm::thread_pool 47 | :members: 48 | :undoc-members: 49 | 50 | .. doxygenclass:: epiabm::RandomManager 51 | :members: 52 | :undoc-members: 53 | 54 | .. doxygenclass:: epiabm::RandomGenerator 55 | :members: 56 | :undoc-members: 57 | 58 | .. doxygenclass:: epiabm::InverseCDF 59 | :members: 60 | :undoc-members: 61 | 62 | .. doxygenclass:: epiabm::DistanceMetrics 63 | :members: 64 | :undoc-members: 65 | -------------------------------------------------------------------------------- /cEpiabm/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | add_subdirectory(basic_example) 4 | -------------------------------------------------------------------------------- /cEpiabm/examples/basic_example/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | add_executable(main main.cpp) 4 | target_link_libraries(main PRIVATE epiabm_lib project_warnings project_settings) 5 | 6 | -------------------------------------------------------------------------------- /cEpiabm/src/configuration/config_factory_interface.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_CONFIGURATION_JSON_CONFIGURATION_HELPER_HPP 2 | #define EPIABM_CONFIGURATION_JSON_CONFIGURATION_HELPER_HPP 3 | 4 | #include "json.hpp" 5 | #include "simulation_config.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace epiabm 11 | { 12 | 13 | /** 14 | * @brief Interface class for configuration factories 15 | * 16 | * Factory pattern for configuration classes 17 | * Must have loadConfig method which takes a filepath input and returns a SimulationConfig class 18 | */ 19 | class ConfigurationFactoryInterface 20 | { 21 | private: 22 | public: 23 | /** 24 | * @brief Construct a new Configuration Factory Interface object 25 | * 26 | */ 27 | ConfigurationFactoryInterface() {}; 28 | /** 29 | * @brief Destroy the Configuration Factory Interface object 30 | * 31 | */ 32 | virtual ~ConfigurationFactoryInterface() = default; 33 | 34 | /** 35 | * @brief Load Config from File 36 | * 37 | * Reads input file and creates SimulationConfig object 38 | */ 39 | virtual SimulationConfigPtr loadConfig( 40 | const std::filesystem::path& /*configFile*/){ return std::shared_ptr(); }; 41 | 42 | protected: 43 | }; 44 | 45 | typedef std::shared_ptr ConfigurationFactoryPtr; 46 | 47 | } 48 | 49 | #endif // EPIABM_CONFIGURATION_JSON_CONFIGURATION_HELPER_HPP -------------------------------------------------------------------------------- /cEpiabm/src/configuration/host_progression_config.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_CONFIGURATION_INFECTION_PROGRESSION_CONFIGURATION_HPP 2 | #define EPIABM_CONFIGURATION_INFECTION_PROGRESSION_CONFIGURATION_HPP 3 | 4 | #include "../utilities/inverse_cdf.hpp" 5 | #include "../dataclasses/population.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace epiabm 11 | { 12 | 13 | /** 14 | * @brief Configuration subclass for configuring an infection's within host progression dynamics 15 | * 16 | */ 17 | class HostProgressionConfig 18 | { 19 | private: 20 | public: 21 | InverseCDF latentPeriodICDF; 22 | InverseCDF asymptToRecovICDF; 23 | InverseCDF mildToRecovICDF; 24 | InverseCDF gpToRecovICDF; 25 | InverseCDF gpToHospICDF; 26 | InverseCDF gpToDeathICDF; 27 | InverseCDF hospToRecovICDF; 28 | InverseCDF hospToICUICDF; 29 | InverseCDF hospToDeathICDF; 30 | InverseCDF icuToICURecovICDF; 31 | InverseCDF icuToDeathICDF; 32 | InverseCDF icuRecovToRecovICDF; 33 | 34 | bool use_ages; 35 | std::array prob_gp_to_hosp; 36 | std::array prob_gp_to_recov; 37 | std::array prob_exposed_to_asympt; 38 | std::array prob_exposed_to_gp; 39 | std::array prob_exposed_to_mild; 40 | std::array prob_hosp_to_death; 41 | std::array prob_hosp_to_recov; 42 | std::array prob_hosp_to_icu; 43 | std::array prob_icu_to_death; 44 | std::array prob_icu_to_icurecov; 45 | 46 | std::vector infectiousness_profile; 47 | 48 | private: 49 | }; // class InfectionProgressionConfig 50 | 51 | typedef std::shared_ptr HostProgressionConfigPtr; 52 | 53 | } // namespace epiabm 54 | 55 | #endif // EPIABM_CONFIGURATION_INFECTION_PROGRESSION_CONFIGURATION_HPP -------------------------------------------------------------------------------- /cEpiabm/src/configuration/infection_config.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_CONFIGURATION_INFECTION_CONFIGURATION_HPP 2 | #define EPIABM_CONFIGURATION_INFECTION_CONFIGURATION_HPP 3 | 4 | #include "host_progression_config.hpp" 5 | #include "../dataclasses/place.hpp" 6 | 7 | #include 8 | 9 | namespace epiabm 10 | { 11 | 12 | /** 13 | * @brief Configuration subclass for infection configuration options 14 | * 15 | */ 16 | class InfectionConfig 17 | { 18 | private: 19 | public: 20 | HostProgressionConfigPtr hostProgressionConfig; 21 | 22 | double basicReproductionNum; 23 | double infectionRadius; 24 | double probSymptomatic; 25 | double symptInfectiousness; 26 | double asymptInfectiousness; 27 | double latentToSymptDelay; 28 | 29 | double falsePositiveRate; 30 | 31 | double householdTransmission; 32 | double placeTransmission; 33 | 34 | std::array meanPlaceGroupSize; 35 | 36 | std::string spatial_distance_metric; 37 | 38 | /** 39 | * @brief Construct a new Infection Config object 40 | * 41 | */ 42 | InfectionConfig() 43 | { 44 | hostProgressionConfig = std::make_shared(); 45 | } 46 | private: 47 | }; 48 | 49 | typedef std::shared_ptr InfectionConfigPtr; 50 | 51 | } // namespace epiabm 52 | 53 | 54 | #endif // EPIABM_CONFIGURATION_INFECTION_CONFIGURATION_HPP -------------------------------------------------------------------------------- /cEpiabm/src/configuration/population_config.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_CONFIGURATION_POPULATION_CONFIGURATION_HPP 2 | #define EPIABM_CONFIGURATION_POPULATION_CONFIGURATION_HPP 3 | 4 | #include "../dataclasses/population.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace epiabm 10 | { 11 | 12 | class PopulationConfig 13 | { 14 | private: 15 | public: 16 | std::array age_proportions; 17 | std::array age_contacts; 18 | 19 | private: 20 | }; // class PopulationConfigPtr 21 | 22 | typedef std::shared_ptr PopulationConfigPtr; 23 | 24 | } // namespace epiabm 25 | 26 | #endif // EPIABM_CONFIGURATION_POPULATION_CONFIGURATION_HPP -------------------------------------------------------------------------------- /cEpiabm/src/configuration/simulation_config.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_CONFIGURATION_SIMULATION_CONFIGURATION_HPP 2 | #define EPIABM_CONFIGURATION_SIMULATION_CONFIGURATION_HPP 3 | 4 | #include "infection_config.hpp" 5 | #include "population_config.hpp" 6 | #include "../utilities/random_manager.hpp" 7 | 8 | #include 9 | #include 10 | 11 | namespace epiabm 12 | { 13 | 14 | /** 15 | * @brief Highest level master configuration class 16 | * 17 | * Class to contain configuration information on entire simulation. 18 | */ 19 | class SimulationConfig 20 | { 21 | private: 22 | public: 23 | InfectionConfigPtr infectionConfig; 24 | PopulationConfigPtr populationConfig; 25 | 26 | unsigned short timestepsPerDay; 27 | RandomManagerPtr randomManager; 28 | 29 | /** 30 | * @brief Construct a new Simulation Config object 31 | * 32 | */ 33 | SimulationConfig() 34 | { 35 | infectionConfig = std::make_shared(); 36 | populationConfig = std::make_shared(); 37 | randomManager = std::make_shared(0); 38 | } 39 | 40 | private: 41 | }; 42 | 43 | typedef std::shared_ptr SimulationConfigPtr; 44 | 45 | } // epiabm 46 | 47 | #endif // EPIABM_CONFIGURATION_SIMULATION_CONFIGURATION_HPP 48 | -------------------------------------------------------------------------------- /cEpiabm/src/covidsim.cpp: -------------------------------------------------------------------------------- 1 | #include "covidsim.hpp" 2 | 3 | 4 | namespace epiabm 5 | { 6 | double Covidsim::CalcHouseInf( 7 | Person* /*infector*/, 8 | unsigned short int ) 9 | { 10 | return 1.0; 11 | } 12 | 13 | double Covidsim::CalcCellInf( 14 | Cell* cell, 15 | unsigned short int ) 16 | { 17 | const int R_value = 2; 18 | return static_cast(R_value * cell->numInfectious()); 19 | } 20 | 21 | double Covidsim::CalcSpaceInf( 22 | Cell* /*cell*/, 23 | Person* /*infector*/, 24 | unsigned short int ) 25 | { 26 | return 0.5; 27 | } 28 | 29 | double Covidsim::CalcHouseSusc( 30 | Person* infector, 31 | Person* infectee, 32 | unsigned short int timestep) 33 | { 34 | return CalcPersonSusc(infector, infectee, timestep); 35 | } 36 | 37 | double Covidsim::CalcPersonSusc( 38 | Person* /*infector*/, 39 | Person* /*infectee*/, 40 | unsigned short int ) 41 | { 42 | return 1.0; 43 | } 44 | 45 | double Covidsim::CalcSpaceSusc( 46 | Cell* /*cell*/, 47 | Person* /*infectee*/, 48 | unsigned short int ) 49 | { 50 | return 0.2; 51 | } 52 | 53 | 54 | } // namespace epiabm 55 | -------------------------------------------------------------------------------- /cEpiabm/src/covidsim.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_COVIDSIM_HPP 2 | #define EPIABM_COVIDSIM_HPP 3 | 4 | #include "dataclasses/person.hpp" 5 | #include "dataclasses/cell.hpp" 6 | 7 | namespace epiabm 8 | { 9 | 10 | class Covidsim 11 | { 12 | public: 13 | // Calculate Infectiousness Helpers 14 | static double CalcHouseInf( 15 | Person* infector, 16 | unsigned short int timestep); 17 | static double CalcCellInf( 18 | Cell* cell, 19 | unsigned short int timestep); 20 | static double CalcSpaceInf( 21 | Cell* inf_cell, 22 | Person* infector, 23 | unsigned short int timestep); 24 | 25 | // Calculate Susceptibilities Helpers 26 | static double CalcHouseSusc( 27 | Person* infector, 28 | Person* infectee, 29 | unsigned short int timestep); 30 | static double CalcPersonSusc( 31 | Person* infector, 32 | Person* infectee, 33 | unsigned short int timestep); 34 | static double CalcSpaceSusc( 35 | Cell* cell, 36 | Person* infectee, 37 | unsigned short int timestep); 38 | }; 39 | 40 | } // namespace epiabm 41 | 42 | #endif // EPIABM_COVIDSIM_HPP -------------------------------------------------------------------------------- /cEpiabm/src/dataclasses/compartment_counter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_DATACLASSES_COMPARTMENT_COUNTER_HPP 2 | #define EPIABM_DATACLASSES_COMPARTMENT_COUNTER_HPP 3 | 4 | #include "infection_status.hpp" 5 | #include "person.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace epiabm 12 | { 13 | class Cell; 14 | 15 | /** 16 | * @brief Class to keep count of number of people in each compartment 17 | * 18 | */ 19 | class CompartmentCounter 20 | { 21 | private: 22 | std::unordered_map m_counts; 23 | 24 | public: 25 | CompartmentCounter(); 26 | ~CompartmentCounter(); 27 | 28 | void clear(); 29 | 30 | unsigned int operator()(InfectionStatus status) const; 31 | 32 | void notify(InfectionStatus oldStatus, InfectionStatus newStatus); 33 | 34 | void initialize(Cell* cell, const std::vector& people); 35 | 36 | void initialize(const std::vector& people); 37 | 38 | private: 39 | friend class Cell; 40 | friend class Microcell; 41 | }; 42 | 43 | 44 | } // namespace epiabm 45 | 46 | #endif // EPIABM_DATACLASSES_COMPARTMENT_COUNTER_HPP 47 | -------------------------------------------------------------------------------- /cEpiabm/src/dataclasses/household.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_DATACLASSES_HOUSEHOLD_HPP 2 | #define EPIABM_DATACLASSES_HOUSEHOLD_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace epiabm 10 | { 11 | class Cell; 12 | class Microcell; 13 | class Person; 14 | /** 15 | * @brief Structure for household parameters 16 | * For parameters which are independent to individual households 17 | */ 18 | struct HouseholdParams 19 | { 20 | double susceptibility = 0, infectiousness = 0; 21 | std::pair location = {0, 0}; 22 | }; 23 | 24 | /** 25 | * @brief Class representing a household 26 | * 27 | */ 28 | class Household 29 | { 30 | private: 31 | HouseholdParams m_params; 32 | 33 | size_t m_mcellPos; // Position within Microcell::m_households vector 34 | 35 | std::set m_members; // Indices of people in Microcell::m_people vector 36 | 37 | public: 38 | Household(size_t mcellPos); 39 | ~Household() = default; 40 | 41 | size_t microcellPos() const; 42 | 43 | HouseholdParams& params(); 44 | 45 | void forEachMember(Cell &cell, Microcell µcell, 46 | std::function callback); 47 | bool isMember(size_t person) const; 48 | 49 | bool addMember(size_t person); // Maybe should make this private 50 | 51 | std::set &members(); 52 | private: 53 | 54 | friend class PopulationFactory; 55 | }; 56 | 57 | typedef std::shared_ptr HouseholdPtr; 58 | 59 | } // namespace epiabm 60 | 61 | #endif // EPIABM_DATACLASSES_HOUSEHOLD_HPP 62 | -------------------------------------------------------------------------------- /cEpiabm/src/dataclasses/infection_status.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_DATACLASSES_INFECTION_STATUS_HPP 2 | #define EPIABM_DATACLASSES_INFECTION_STATUS_HPP 3 | 4 | #include 5 | 6 | namespace epiabm 7 | { 8 | const size_t N_INFECTION_STATES = 10; 9 | 10 | enum class InfectionStatus 11 | { 12 | Susceptible = 0, 13 | Exposed = 1, 14 | InfectASympt = 2, 15 | InfectMild = 3, 16 | InfectGP = 4, 17 | InfectHosp = 5, 18 | InfectICU = 6, 19 | InfectICURecov = 7, 20 | Recovered = 8, 21 | Dead = 9 22 | }; 23 | 24 | /** 25 | * @brief Convert InfectionStatus Enum into a String Representation 26 | * 27 | * @param status InfectionStatus Enum to convert 28 | * @return constexpr const char* String representation of the status 29 | */ 30 | constexpr const char* status_string(InfectionStatus status) 31 | { 32 | switch (status) 33 | { 34 | case InfectionStatus::Susceptible: return "Susceptible"; 35 | case InfectionStatus::Exposed: return "Exposed"; 36 | case InfectionStatus::InfectASympt: return "InfectASympt"; 37 | case InfectionStatus::InfectMild: return "InfectMild"; 38 | case InfectionStatus::InfectGP: return "InfectGP"; 39 | case InfectionStatus::InfectHosp: return "InfectHosp"; 40 | case InfectionStatus::InfectICU: return "InfectICU"; 41 | case InfectionStatus::InfectICURecov: return "InfectICURecov"; 42 | case InfectionStatus::Recovered: return "Recovered"; 43 | case InfectionStatus::Dead: return "Dead"; 44 | default: return "Unknown"; 45 | } 46 | } 47 | } 48 | 49 | 50 | #endif // EPIABM_DATACLASSES_INFECTION_STATUS_HPP 51 | -------------------------------------------------------------------------------- /cEpiabm/src/dataclasses/microcell.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_DATACLASSES_MICROCELL_HPP 2 | #define EPIABM_DATACLASSES_MICROCELL_HPP 3 | 4 | #include "person.hpp" 5 | #include "place.hpp" 6 | #include "household.hpp" 7 | #include "compartment_counter.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace epiabm 16 | { 17 | class Cell; 18 | 19 | /** 20 | * @brief Class representing a microcell 21 | * 22 | */ 23 | class Microcell 24 | { 25 | private: 26 | std::vector m_people; 27 | std::vector m_households; 28 | 29 | size_t m_cellPos; // index of this microcell in parent cell's m_microcells 30 | 31 | CompartmentCounter m_compartmentCounter; 32 | 33 | public: 34 | Microcell(size_t cellPos); 35 | ~Microcell(); 36 | Microcell(const Microcell&); 37 | Microcell(Microcell&&); 38 | 39 | size_t cellPos() const; 40 | 41 | void forEachPerson(Cell& cell, std::function callback); 42 | 43 | Person& getPerson(Cell& cell, size_t i); 44 | HouseholdPtr getHousehold(size_t i); 45 | 46 | std::vector& people(); 47 | std::vector& households(); 48 | 49 | void initialize(Cell* cell); 50 | 51 | unsigned int compartmentCount(InfectionStatus status); 52 | 53 | void personStatusChange(Person* person, InfectionStatus newStatus, unsigned short timestep); 54 | 55 | 56 | private: 57 | friend class Place; 58 | }; 59 | 60 | typedef std::shared_ptr MicrocellPtr; 61 | 62 | } // namespace epiabm 63 | 64 | #endif // EPIABM_DATACLASSES_MICROCELL_HPP -------------------------------------------------------------------------------- /cEpiabm/src/dataclasses/population.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_DATACLASSES_POPULATION_HPP 2 | #define EPIABM_DATACLASSES_POPULATION_HPP 3 | 4 | #include "cell.hpp" 5 | #include "place.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace epiabm 12 | { 13 | const size_t N_AGE_GROUPS = 17; // Each age group is 5 years 14 | 15 | /** 16 | * @brief Class representing a population 17 | * 18 | */ 19 | class Population 20 | { 21 | private: 22 | std::vector m_cells; 23 | std::vector m_places; 24 | 25 | public: 26 | Population(); 27 | ~Population(); 28 | 29 | void forEachCell(std::function callback); 30 | void forEachPlace(std::function callback); 31 | 32 | std::vector& cells(); 33 | std::vector& places(); 34 | 35 | void initialize(); 36 | 37 | private: 38 | }; 39 | 40 | typedef std::shared_ptr PopulationPtr; 41 | 42 | } // namespace epiabm 43 | 44 | #endif // EPIABM_DATACLASSES_POPULATION_HPP 45 | -------------------------------------------------------------------------------- /cEpiabm/src/household_linker.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "household_linker.hpp" 3 | #include "dataclasses/household.hpp" 4 | 5 | #include 6 | 7 | namespace epiabm 8 | { 9 | 10 | void HouseholdLinker::linkHouseholds(PopulationPtr population, size_t n_households, int percInHousehold, std::optional seed) 11 | { 12 | std::mt19937_64 g(seed.value_or(0)); 13 | population->forEachCell([&](Cell* cell) 14 | { 15 | cell->forEachMicrocell([&](Microcell* microcell) 16 | { 17 | // Add Households 18 | for (size_t h = 0; h < n_households; h++) 19 | { 20 | microcell->households().push_back( 21 | std::make_shared(microcell->households().size())); 22 | } 23 | 24 | // Assign each person to a household 25 | microcell->forEachPerson(*cell, [&](Person* person) 26 | { 27 | if (static_cast(g()) % 100 > percInHousehold) return true; 28 | size_t hh = static_cast(g()) % n_households; 29 | cell->getMicrocell(person->microcell()).households()[hh]->addMember(person->microcellPos()); 30 | person->setHousehold(hh); 31 | return true; 32 | }); 33 | return true; 34 | }); 35 | return true; 36 | }); 37 | } 38 | 39 | } // namespace epiabm 40 | -------------------------------------------------------------------------------- /cEpiabm/src/household_linker.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SRC_HOUSEHOLD_LINKER_HPP 2 | #define EPIABM_SRC_HOUSEHOLD_LINKER_HPP 3 | 4 | 5 | #include "dataclasses/population.hpp" 6 | 7 | 8 | namespace epiabm 9 | { 10 | 11 | 12 | class HouseholdLinker 13 | { 14 | private: 15 | public: 16 | 17 | /** 18 | * @brief Link households 19 | * Create n_households per microcell. 20 | * Person has percInHousehold to be in a household. 21 | * People who should be in a household are randomly assigned to a household in their microcell. 22 | * @param population 23 | * @param n_households 24 | * @param percInHousehold 25 | */ 26 | void linkHouseholds( 27 | PopulationPtr population, 28 | size_t n_households, 29 | int percInHousehold, 30 | std::optional seed); 31 | 32 | private: 33 | }; // class HouseholdLinker 34 | 35 | 36 | } // namespace epiabm 37 | 38 | #endif // EPIABM_SRC_HOUSEHOLD_LINKER_HPP 39 | -------------------------------------------------------------------------------- /cEpiabm/src/output_folder_handler.cpp: -------------------------------------------------------------------------------- 1 | #include "output_folder_handler.hpp" 2 | 3 | 4 | namespace epiabm 5 | { 6 | 7 | OutputFolderHandler::OutputFolderHandler( 8 | const std::filesystem::path& directory_path, 9 | bool cleanOutputDirectory) : 10 | m_path(directory_path) 11 | { 12 | // Create directory 13 | std::filesystem::create_directories(directory_path); 14 | if (cleanOutputDirectory) // If should clear directory 15 | { 16 | std::filesystem::remove_all(directory_path); // Clear directory 17 | std::filesystem::create_directory(directory_path); // Recreate top directory 18 | } 19 | } 20 | 21 | ofstreamPtr OutputFolderHandler::OpenOutputFile( 22 | const std::string& filename, 23 | std::ios_base::openmode mode) const 24 | { 25 | return std::make_shared(m_path / filename, mode); 26 | } 27 | 28 | } // namespace epiabm 29 | -------------------------------------------------------------------------------- /cEpiabm/src/output_folder_handler.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_OUTPUT_FOLDER_HANDLER_HPP 2 | #define EPIABM_OUTPUT_FOLDER_HANDLER_HPP 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | namespace epiabm 11 | { 12 | typedef std::shared_ptr ofstreamPtr; 13 | 14 | /** 15 | * @brief Output Folder Handling Class 16 | * Class which handles opening a folder 17 | * Creates folder if it doesn't exist 18 | * Can clear the folder after opening 19 | * Public method which allows opening a file within this folder for writing 20 | */ 21 | class OutputFolderHandler 22 | { 23 | private: 24 | const std::filesystem::path m_path; 25 | 26 | public: 27 | /** 28 | * @brief Construct a new Output File Handler object 29 | * 30 | * @param directory_path Path to output directory 31 | * @param cleanOutputDirectory Flag whether to clear contents of output directory 32 | */ 33 | OutputFolderHandler( 34 | const std::filesystem::path& directory_path, 35 | bool cleanOutputDirectory = true); 36 | 37 | /** 38 | * @brief Make outputfile and return ofstream for the file 39 | * Construct a new file inside of the OutputFolderHandler's directory. 40 | * @param rFileName New filename 41 | * @param mode std::ios_base::openmode Mode with which to open file 42 | * @return ofstreamPtr 43 | */ 44 | ofstreamPtr OpenOutputFile( 45 | const std::string& rFileName, 46 | std::ios_base::openmode mode = std::ios::out | std::ios::trunc) const; 47 | 48 | }; 49 | } 50 | 51 | 52 | #endif // EPIABM_OUTPUT_FOLDER_HANDLER_HPP -------------------------------------------------------------------------------- /cEpiabm/src/population_factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_POPULATION_FACTORY_HPP 2 | #define EPIABM_POPULATION_FACTORY_HPP 3 | 4 | #include "dataclasses/population.hpp" 5 | #include "dataclasses/cell.hpp" 6 | #include "dataclasses/microcell.hpp" 7 | #include "dataclasses/place.hpp" 8 | #include "dataclasses/person.hpp" 9 | 10 | namespace epiabm 11 | { 12 | 13 | class PopulationFactory 14 | { 15 | private: 16 | public: 17 | PopulationPtr makePopulation(); 18 | 19 | /** 20 | * @brief Create a Basic Population 21 | * 22 | * Create a Population with n_cells, n_microcells :class:`Microcell` in each cell, and n_people :class:`People` in each microcell. 23 | * 24 | * @param n_cells 25 | * @param n_microcells 26 | * @param n_people 27 | * @return PopulationPtr 28 | */ 29 | PopulationPtr makePopulation( 30 | size_t n_cells, // n cells in population 31 | size_t n_microcells, // n microcels per cell 32 | size_t n_people); // n people per microcell 33 | 34 | void addCell(PopulationPtr population); 35 | void addMicrocell(Cell* cell); 36 | void addPerson(Cell* cell, size_t microcell_index); 37 | 38 | void addCells(PopulationPtr population, size_t n); 39 | void addMicrocells(Cell* cell, size_t n); 40 | void addPeople(Cell* cell, size_t microcell_index, size_t n); 41 | 42 | void addHousehold(Microcell* microcell); 43 | void addHouseholds(Microcell* microcell, size_t n); 44 | 45 | void addPlace(PopulationPtr population); 46 | void addPlaces(PopulationPtr population, size_t n); 47 | 48 | private: 49 | }; 50 | 51 | } // namespace epiabm 52 | 53 | #endif // EPIABM_POPULATION_FACTORY_HPP 54 | -------------------------------------------------------------------------------- /cEpiabm/src/python_bindings/bind_logfile.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "logfile.hpp" 7 | 8 | 9 | namespace py = pybind11; 10 | 11 | void bind_logfile(py::module &m) 12 | { 13 | using namespace epiabm; 14 | 15 | py::class_(m, "LogFile") 16 | .def_static("Instance", &LogFile::Instance, py::return_value_policy::reference) 17 | .def("configure", &LogFile::configure) 18 | .def("set_level", &LogFile::setLevel); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /cEpiabm/src/python_bindings/bind_simulation.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "simulations/basic_simulation.hpp" 5 | #include "simulations/threaded_simulation.hpp" 6 | 7 | 8 | namespace py = pybind11; 9 | 10 | void bind_simulation(py::module &m) 11 | { 12 | using namespace epiabm; 13 | 14 | py::class_(m, "BasicSimulation") 15 | .def(py::init()) 16 | .def("add_sweep", &BasicSimulation::addSweep) 17 | .def("add_timestep_reporter", &BasicSimulation::addTimestepReporter) 18 | .def("simulate", &BasicSimulation::simulate); 19 | 20 | py::class_(m, "ThreadedSimulation") 21 | .def(py::init>()) 22 | .def("add_sweep", &ThreadedSimulation::addSweep) 23 | .def("add_timestep_reporter", &ThreadedSimulation::addTimestepReporter) 24 | .def("simulate", &ThreadedSimulation::simulate); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /cEpiabm/src/python_bindings/bind_sweeps.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sweeps/sweep_interface.hpp" 5 | #include "sweeps/household_sweep.hpp" 6 | #include "sweeps/basic_host_progression_sweep.hpp" 7 | #include "sweeps/host_progression_sweep.hpp" 8 | #include "sweeps/new_infection_sweep.hpp" 9 | #include "sweeps/random_seed_sweep.hpp" 10 | #include "sweeps/spatial_sweep.hpp" 11 | #include "sweeps/place_sweep.hpp" 12 | 13 | 14 | namespace py = pybind11; 15 | 16 | void bind_sweeps(py::module &m) 17 | { 18 | using namespace epiabm; 19 | 20 | py::class_(m, "SweepInterface") 21 | .def("bind_population", &SweepInterface::bind_population) 22 | .def("__call__", &SweepInterface::operator()); 23 | 24 | py::class_(m, "HouseholdSweep", 25 | py::base()) 26 | .def(py::init()); 27 | 28 | py::class_(m, "BasicHostProgressionSweep", 29 | py::base()) 30 | .def(py::init()); 31 | 32 | py::class_(m, "HostProgressionSweep", 33 | py::base()) 34 | .def(py::init()); 35 | 36 | py::class_(m, "NewInfectionSweep", 37 | py::base()) 38 | .def(py::init()); 39 | 40 | py::class_(m, "RandomSeedSweep", 41 | py::base()) 42 | .def(py::init()); 43 | 44 | py::class_(m, "SpatialSweep", 45 | py::base()) 46 | .def(py::init()); 47 | 48 | py::class_(m, "PlaceSweep", 49 | py::base()) 50 | .def(py::init()); 51 | } 52 | 53 | -------------------------------------------------------------------------------- /cEpiabm/src/python_bindings/bind_utilities.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "utilities/inverse_cdf.hpp" 5 | #include "utilities/random_generator.hpp" 6 | #include "utilities/random_manager.hpp" 7 | 8 | namespace py = pybind11; 9 | 10 | void bind_utilities(py::module &m) 11 | { 12 | using namespace epiabm; 13 | 14 | py::class_(m, "InverseCDF") 15 | .def(py::init()) 16 | .def("choose", &InverseCDF::choose, "Generate random number from iCDF", 17 | py::arg("timesteps_per_day")=1, py::arg("generator")) 18 | .def("values", &InverseCDF::getValues, "Get iCDF values", 19 | py::return_value_policy::reference) 20 | .def("mean", &InverseCDF::mean, "Get iCDF mean", 21 | py::return_value_policy::copy); 22 | 23 | py::class_(m, "RandomManager") 24 | .def("generator", &RandomManager::g, "Get RandomGenerator", 25 | py::return_value_policy::reference); 26 | py::class_(m, "RandomGenerator") 27 | .def("randi", py::overload_cast(&RandomGenerator::randi), "Generate Random Long", 28 | py::return_value_policy::copy) 29 | .def("randf", &RandomGenerator::randf, "Generate Random Double", 30 | py::return_value_policy::copy) 31 | .def("generator", &RandomGenerator::generator, "Underlying mersenne twister generator", 32 | py::return_value_policy::reference); 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /cEpiabm/src/python_bindings/bindings.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "bind_dataclasses.hpp" 5 | #include "bind_sweeps.hpp" 6 | #include "bind_reporters.hpp" 7 | #include "bind_simulation.hpp" 8 | #include "bind_configuration.hpp" 9 | #include "bind_utilities.hpp" 10 | #include "bind_logfile.hpp" 11 | 12 | namespace py = pybind11; 13 | 14 | PYBIND11_MODULE(epiabm, m) 15 | { 16 | using namespace epiabm; 17 | bind_dataclasses(m); 18 | bind_sweeps(m); 19 | bind_reporters(m); 20 | bind_simulation(m); 21 | bind_configuration(m); 22 | bind_utilities(m); 23 | bind_logfile(m); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /cEpiabm/src/reporters/age_stratified_new_cases_reporter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_REPORTERS_AGE_STRATIFIED_NEW_CASES_REPORTER_HPP 2 | #define EPIABM_REPORTERS_AGE_STRATIFIED_NEW_CASES_REPORTER_HPP 3 | 4 | #include "timestep_reporter_interface.hpp" 5 | 6 | #include 7 | 8 | namespace epiabm 9 | { 10 | 11 | /** 12 | * @brief Report Compartment Counts each Iteration for Each Cell 13 | * Outputs to a folder with one file per cell with compartment counts over time 14 | */ 15 | class AgeStratifiedNewCasesReporter : public TimestepReporterInterface 16 | { 17 | private: 18 | ofstreamPtr m_os; 19 | 20 | public: 21 | AgeStratifiedNewCasesReporter(const std::string file); 22 | ~AgeStratifiedNewCasesReporter(); 23 | 24 | void setup(const PopulationPtr pop) override; 25 | 26 | void report(const PopulationPtr pop, const unsigned short timestep) override; 27 | 28 | void teardown() override; 29 | 30 | private: 31 | }; 32 | 33 | typedef std::shared_ptr AgeStratifiedNewCasesReporterPtr; 34 | 35 | } // namespace epiabm 36 | 37 | #endif // EPIABM_REPORTERS_AGE_STRATIFIED_NEW_CASES_REPORTER_HPP 38 | -------------------------------------------------------------------------------- /cEpiabm/src/reporters/age_stratified_population_reporter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_REPORTERS_AGE_STRATIFIED_POPULATION_REPORTER_HPP 2 | #define EPIABM_REPORTERS_AGE_STRATIFIED_POPULATION_REPORTER_HPP 3 | 4 | #include "timestep_reporter_interface.hpp" 5 | 6 | namespace epiabm 7 | { 8 | 9 | /** 10 | * @brief Report total compartment counts each iteration for the entire population 11 | * Outputs a single file which contains the compartment counts over time 12 | */ 13 | class AgeStratifiedPopulationReporter : public TimestepReporterInterface 14 | { 15 | private: 16 | std::set m_compartments; 17 | ofstreamPtr m_os; 18 | 19 | public: 20 | AgeStratifiedPopulationReporter(const std::string file); 21 | ~AgeStratifiedPopulationReporter(); 22 | 23 | void setup(const PopulationPtr population) override; 24 | 25 | void report(const PopulationPtr population, const unsigned short timestep) override; 26 | 27 | std::set &compartments(); 28 | 29 | private: 30 | }; 31 | 32 | typedef std::shared_ptr AgeStratifiedPopulationReporterPtr; 33 | 34 | } // namespace epiabm 35 | 36 | #endif // EPIABM_REPORTERS_AGE_STRATIFIED_POPULATION_REPORTER_HPP -------------------------------------------------------------------------------- /cEpiabm/src/reporters/cell_compartment_reporter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_REPORTERS_CELL_COMPARTMENT_REPORTER 2 | #define EPIABM_REPORTERS_CELL_COMPARTMENT_REPORTER 3 | 4 | #include "timestep_reporter_interface.hpp" 5 | 6 | namespace epiabm 7 | { 8 | 9 | /** 10 | * @brief Report Comportment Counts each iteration for each cell 11 | * Outputs to a folder with one csv each timestep with the compartment counts for each cell 12 | */ 13 | class CellCompartmentReporter : public TimestepReporterInterface 14 | { 15 | private: 16 | std::set m_compartments; 17 | 18 | public: 19 | CellCompartmentReporter(const std::string folder); 20 | ~CellCompartmentReporter(); 21 | 22 | void report(const PopulationPtr pop, const unsigned short timestep) override; 23 | 24 | std::set &compartments(); 25 | 26 | private: 27 | }; 28 | 29 | typedef std::shared_ptr CellCompartmentReporterPtr; 30 | 31 | } // namespace epiabm 32 | 33 | #endif // EPIABM_REPORTERS_CELL_COMPARTMENT_REPORTER 34 | -------------------------------------------------------------------------------- /cEpiabm/src/reporters/new_cases_reporter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_REPORTERS_NEW_CASES_REPORTER_HPP 2 | #define EPIABM_REPORTERS_NEW_CASES_REPORTER_HPP 3 | 4 | #include "timestep_reporter_interface.hpp" 5 | 6 | #include 7 | 8 | namespace epiabm 9 | { 10 | 11 | /** 12 | * @brief Report Compartment Counts each Iteration for Each Cell 13 | * Outputs to a folder with one file per cell with compartment counts over time 14 | */ 15 | class NewCasesReporter : public TimestepReporterInterface 16 | { 17 | private: 18 | ofstreamPtr m_os; 19 | 20 | public: 21 | NewCasesReporter(const std::string folder); 22 | ~NewCasesReporter(); 23 | 24 | void setup(const PopulationPtr pop) override; 25 | 26 | void report(const PopulationPtr pop, const unsigned short timestep) override; 27 | 28 | void teardown() override; 29 | 30 | private: 31 | }; 32 | 33 | typedef std::shared_ptr NewCasesReporterPtr; 34 | 35 | } // namespace epiabm 36 | 37 | #endif // EPIABM_REPORTERS_NEW_CASES_REPORTER_HPP 38 | -------------------------------------------------------------------------------- /cEpiabm/src/reporters/percell_compartment_reporter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_REPORTERS_PERCELL_COMPARTMENT_REPORTER 2 | #define EPIABM_REPORTERS_PERCELL_COMPARTMENT_REPORTER 3 | 4 | #include "timestep_reporter_interface.hpp" 5 | 6 | #include 7 | 8 | namespace epiabm 9 | { 10 | 11 | /** 12 | * @brief Report Compartment Counts each Iteration for Each Cell 13 | * Outputs to a folder with one file per cell with compartment counts over time 14 | */ 15 | class PerCellCompartmentReporter : public TimestepReporterInterface 16 | { 17 | private: 18 | std::set m_compartments; 19 | std::map m_cellFileMap; 20 | 21 | public: 22 | PerCellCompartmentReporter(const std::string folder); 23 | ~PerCellCompartmentReporter(); 24 | 25 | void setup(const PopulationPtr pop) override; 26 | 27 | void report(const PopulationPtr pop, const unsigned short timestep) override; 28 | 29 | void teardown() override; 30 | 31 | std::set &compartments(); 32 | 33 | private: 34 | }; 35 | 36 | typedef std::shared_ptr PerCellCompartmentReporterPtr; 37 | 38 | } // namespace epiabm 39 | 40 | #endif // EPIABM_REPORTERS_PERCELL_COMPARTMENT_REPORTER 41 | -------------------------------------------------------------------------------- /cEpiabm/src/reporters/population_compartment_reporter.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_REPORTERS_POPULATION_COMPARTMENT_REPORTER_HPP 2 | #define EPIABM_REPORTERS_POPULATION_COMPARTMENT_REPORTER_HPP 3 | 4 | #include "timestep_reporter_interface.hpp" 5 | 6 | namespace epiabm 7 | { 8 | 9 | /** 10 | * @brief Report total compartment counts each iteration for the entire population 11 | * Outputs a single file which contains the compartment counts over time 12 | */ 13 | class PopulationCompartmentReporter : public TimestepReporterInterface 14 | { 15 | private: 16 | std::set m_compartments; 17 | ofstreamPtr m_os; 18 | 19 | public: 20 | PopulationCompartmentReporter(const std::string file); 21 | ~PopulationCompartmentReporter(); 22 | 23 | void setup(const PopulationPtr population) override; 24 | 25 | void report(const PopulationPtr population, const unsigned short timestep) override; 26 | 27 | std::set &compartments(); 28 | 29 | private: 30 | }; 31 | 32 | typedef std::shared_ptr PopulationCompartmentReporterPtr; 33 | 34 | } // namespace epiabm 35 | 36 | #endif // EPIABM_REPORTERS_POPULATION_COMPARTMENT_REPORTER_HPP -------------------------------------------------------------------------------- /cEpiabm/src/reporters/timestep_reporter_interface.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "timestep_reporter_interface.hpp" 3 | 4 | 5 | namespace epiabm 6 | { 7 | 8 | /** 9 | * @brief Constructor 10 | * 11 | * @param folder Folder to output to 12 | * @param clearfolder whether folder should be emptied at the start of the simulation 13 | */ 14 | TimestepReporterInterface::TimestepReporterInterface( 15 | const std::string folder, 16 | bool clearfolder) : 17 | m_folder(std::filesystem::path(folder), clearfolder) 18 | {} 19 | 20 | /** 21 | * @brief Constructor 22 | * 23 | * @param folder Folder to output to 24 | * @param clearfolder whether folder should be emptied at the start of the simulation 25 | */ 26 | TimestepReporterInterface::TimestepReporterInterface( 27 | const std::filesystem::path folder, 28 | bool clearfolder) : 29 | m_folder(folder, clearfolder) 30 | {} 31 | 32 | /** 33 | * @brief Destroy the Timestep Reporter Interface:: Timestep Reporter Interface object 34 | * 35 | */ 36 | TimestepReporterInterface::~TimestepReporterInterface(){} 37 | 38 | /** 39 | * @brief Setup method run immediately before iterations begin 40 | * Used for initializing required files 41 | * @param population Initialized population 42 | */ 43 | void TimestepReporterInterface::setup(const PopulationPtr /*population*/) {} 44 | 45 | /** 46 | * @brief Report the population state at a timestep 47 | * 48 | * @param pop Population to report 49 | * @param timestep Timestep of report 50 | */ 51 | void TimestepReporterInterface::report(const PopulationPtr /*population*/, unsigned short /*timestep*/) {} 52 | 53 | /** 54 | * @brief Clean up method 55 | * Called after the simulation has completed to finalise the output files 56 | */ 57 | void TimestepReporterInterface::teardown() {} 58 | 59 | } // namespace epiabm 60 | -------------------------------------------------------------------------------- /cEpiabm/src/reporters/timestep_reporter_interface.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_REPORTERS_TIMESTEP_REPORTER_INTERFACE 2 | #define EPIABM_REPORTERS_TIMESTEP_REPORTER_INTERFACE 3 | 4 | #include "../dataclasses/population.hpp" 5 | #include "../output_folder_handler.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace epiabm 11 | { 12 | /** 13 | * @brief Interface for classes reporting on a population each iteration 14 | * 15 | */ 16 | class TimestepReporterInterface 17 | { 18 | protected: 19 | OutputFolderHandler m_folder; 20 | 21 | public: 22 | TimestepReporterInterface(const std::string folder, bool clearfolder = false); 23 | TimestepReporterInterface(const std::filesystem::path folder, bool clearfolder = false); 24 | virtual ~TimestepReporterInterface(); 25 | 26 | virtual void setup(const PopulationPtr population); 27 | 28 | virtual void report(const PopulationPtr population, const unsigned short timestep); 29 | 30 | virtual void teardown(); 31 | 32 | private: 33 | }; // class TimestepReporterInterface 34 | 35 | typedef std::shared_ptr TimestepReporterInterfacePtr; 36 | 37 | } // namespace epiabm 38 | 39 | #endif // EPIABM_REPORTERS_TIMESTEP_REPORTER_INTERFACE 40 | -------------------------------------------------------------------------------- /cEpiabm/src/simulations/basic_simulation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SIMULATINS_BASIC_SIMULATION_HPP 2 | #define EPIABM_SIMULATINS_BASIC_SIMULATION_HPP 3 | 4 | 5 | #include "../sweeps/sweep_interface.hpp" 6 | #include "../reporters/timestep_reporter_interface.hpp" 7 | 8 | #include "../dataclasses/population.hpp" 9 | 10 | #include 11 | #include 12 | 13 | 14 | namespace epiabm 15 | { 16 | /** 17 | * @brief Master Simulation Controlling Class 18 | * Links population with sweeps, and runs the sweeps to perform simulation 19 | * Reporters can be attached to extract information about the simulation 20 | */ 21 | class BasicSimulation 22 | { 23 | private: 24 | PopulationPtr m_population; 25 | std::vector m_sweeps; 26 | std::vector m_timestepReporters; 27 | 28 | 29 | public: 30 | BasicSimulation(PopulationPtr population); 31 | ~BasicSimulation(); 32 | 33 | void addSweep(SweepInterfacePtr sweep); 34 | 35 | void addTimestepReporter(TimestepReporterInterfacePtr reporter); 36 | 37 | void simulate(unsigned short timesteps); 38 | 39 | private: 40 | void setup(); 41 | void teardown(); 42 | }; 43 | 44 | typedef std::shared_ptr BasicSimulationPtr; 45 | 46 | } 47 | 48 | 49 | #endif // EPIABM_SIMULATIONS_BASIC_SIMULATION_HPP 50 | -------------------------------------------------------------------------------- /cEpiabm/src/simulations/covid_sim.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SIMULATINS_BASIC_SIMULATION_HPP 2 | #define EPIABM_SIMULATINS_BASIC_SIMULATION_HPP 3 | 4 | 5 | #include "../sweeps/sweep_interface.hpp" 6 | #include "../reporters/timestep_reporter_interface.hpp" 7 | 8 | #include "../dataclasses/population.hpp" 9 | 10 | #include 11 | #include 12 | 13 | 14 | namespace epiabm 15 | { 16 | 17 | /** 18 | * @brief Class to setup simulation closely matching Covid-Sim 19 | * 20 | */ 21 | class CovidSim 22 | { 23 | private: 24 | PopulationPtr m_population; 25 | std::vector m_sweeps; 26 | std::vector m_timestepReporters; 27 | 28 | 29 | public: 30 | CovidSim(PopulationPtr population); 31 | ~CovidSim() = default; 32 | 33 | void addSweep(SweepInterfacePtr sweep); 34 | 35 | void addTimestepReporter(TimestepReporterInterfacePtr reporter); 36 | 37 | void simulate(unsigned short timesteps); 38 | 39 | private: 40 | void setup(); 41 | void teardown(); 42 | }; 43 | 44 | typedef std::shared_ptr BasicSimulationPtr; 45 | 46 | } 47 | 48 | 49 | #endif // EPIABM_SIMULATINS_BASIC_SIMULATION_HPP 50 | -------------------------------------------------------------------------------- /cEpiabm/src/simulations/threaded_simulation.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SIMULATINS_Threaded_SIMULATION_HPP 2 | #define EPIABM_SIMULATINS_Threaded_SIMULATION_HPP 3 | 4 | 5 | #include "../sweeps/sweep_interface.hpp" 6 | #include "../reporters/timestep_reporter_interface.hpp" 7 | 8 | #include "../dataclasses/population.hpp" 9 | #include "../utilities/thread_pool.hpp" 10 | 11 | #include 12 | #include 13 | 14 | 15 | namespace epiabm 16 | { 17 | /** 18 | * @brief Master Simulation Controlling Class with Multithreading 19 | * Links population with sweeps, and runs the sweeps to perform simulation 20 | * Reporters can be attached to extract information about the simulation 21 | */ 22 | class ThreadedSimulation 23 | { 24 | private: 25 | PopulationPtr m_population; 26 | std::map> m_sweeps; 27 | std::vector m_timestepReporters; 28 | 29 | thread_pool m_pool; 30 | 31 | public: 32 | ThreadedSimulation(PopulationPtr population, std::optional nThreads); 33 | ~ThreadedSimulation(); 34 | 35 | void addSweep(SweepInterfacePtr sweep, size_t group); 36 | 37 | void addTimestepReporter(TimestepReporterInterfacePtr reporter); 38 | 39 | void simulate(unsigned short timesteps); 40 | 41 | private: 42 | void setup(); 43 | void teardown(); 44 | }; 45 | 46 | typedef std::shared_ptr ThreadedSimulationPtr; 47 | 48 | } 49 | 50 | 51 | #endif // EPIABM_SIMULATINS_BASIC_SIMULATION_HPP 52 | -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/basic_host_progression_sweep.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SWEEPS_BASIC_HOST_PROGRESSION_SWEEP_HPP 2 | #define EPIABM_SWEEPS_BASIC_HOST_PROGRESSION_SWEEP_HPP 3 | 4 | #include "sweep_interface.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | namespace epiabm 11 | { 12 | 13 | /** 14 | * @brief Replication of Covid-sim's host progression sweep without Severity 15 | * Checks Person's time to next state. 16 | * If the time is past, choose next state and update person. 17 | * Also decides duration to remain in next state. 18 | */ 19 | class BasicHostProgressionSweep : public SweepInterface 20 | { 21 | private: 22 | public: 23 | BasicHostProgressionSweep(SimulationConfigPtr cfg); 24 | ~BasicHostProgressionSweep(); 25 | 26 | void operator()(const unsigned short timestep) override; 27 | 28 | bool cellCallback( 29 | const unsigned short timestep, 30 | Cell* cell) override; 31 | 32 | /* For each Exposed Person */ 33 | bool cellExposedCallback( 34 | const unsigned short timestep, 35 | Cell* cell, 36 | Person* person); 37 | 38 | /* For each Infectious Person */ 39 | bool cellInfectiousCallback( 40 | const unsigned short timestep, 41 | Cell* cell, 42 | Person* person); 43 | 44 | private: 45 | unsigned short time_to_next_status( 46 | Person* person, 47 | InfectionStatus status); 48 | 49 | InfectionStatus first_infectious_status( 50 | Person* person); 51 | 52 | InfectionStatus next_status( 53 | Person* person); 54 | 55 | private: 56 | }; 57 | 58 | typedef std::shared_ptr BasicHostProgressionSweepPtr; 59 | 60 | } // namespace epiabm 61 | 62 | 63 | #endif // EPIABM_SWEEPS_BASIC_HOST_PROGRESSION_SWEEP_HPP -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/household_sweep.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SWEEPS_HOUSEHOLD_SWEEP_HPP 2 | #define EPIABM_SWEEPS_HOUSEHOLD_SWEEP_HPP 3 | 4 | #include "sweep_interface.hpp" 5 | 6 | #include 7 | 8 | 9 | namespace epiabm 10 | { 11 | 12 | /** 13 | * @brief Spread Infection within Households 14 | * Process each infected person and try to infect all susceptibles in their household. 15 | * People to be newly infected get queued in their cell's people queue. 16 | */ 17 | class HouseholdSweep : public SweepInterface 18 | { 19 | private: 20 | unsigned long m_counter; 21 | 22 | public: 23 | HouseholdSweep(SimulationConfigPtr cfg); 24 | ~HouseholdSweep() = default; 25 | 26 | /** 27 | * @brief Perform Household Sweep 28 | * 29 | * @param timestep 30 | */ 31 | void operator()(const unsigned short timestep) override; 32 | 33 | bool cellCallback( 34 | const unsigned short timestep, 35 | Cell* cell) override; 36 | 37 | bool cellInfectiousCallback( 38 | const unsigned short timestep, 39 | Cell* cell, 40 | Person* infectious); 41 | 42 | private: 43 | bool infectAttempt( 44 | const unsigned short timestep, 45 | Cell* cell, HouseholdPtr household, 46 | Person* infector, Person* infectee); 47 | 48 | double calcHouseInf( 49 | Person* infector, 50 | unsigned short int timestep); 51 | 52 | double calcHouseSusc( 53 | Person* infector, 54 | Person* infectee, 55 | unsigned short int timestep); 56 | 57 | double calcPersonSusc( 58 | Person* infector, 59 | Person* infectee, 60 | unsigned short int timestep); 61 | 62 | }; // class HouseholdSweep 63 | 64 | typedef std::shared_ptr HouseholdSweepPtr; 65 | 66 | 67 | } // namespace epiabm 68 | 69 | 70 | #endif // EPIABM_SWEEPS_HOUSEHOLD_SWEEP_HPP -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/new_infection_sweep.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SWEEPS_NEW_INFECTION_SWEEP_HPP 2 | #define EPIABM_SWEEPS_NEW_INFECTION_SWEEP_HPP 3 | 4 | #include "sweep_interface.hpp" 5 | #include "../dataclasses/person.hpp" 6 | #include "../configuration/simulation_config.hpp" 7 | 8 | #include 9 | 10 | 11 | namespace epiabm 12 | { 13 | 14 | /** 15 | * @brief Process New Infections 16 | * Processes the people queued into each cell, and changes their status from Susceptible to Exposed. 17 | * This sweep should be called after each of the infection spreading sweeps, which queue people to be infected. 18 | * Dequeus people as they are moved to exposed. 19 | * Also marks people as exposed in the Cell for fast looping through subsets. 20 | */ 21 | class NewInfectionSweep : public SweepInterface 22 | { 23 | private: 24 | unsigned long m_counter; 25 | 26 | public: 27 | NewInfectionSweep(SimulationConfigPtr cfg); 28 | ~NewInfectionSweep() = default; 29 | 30 | /** 31 | * @brief Perform New Infection Processing Sweep 32 | * 33 | * @param timestep 34 | */ 35 | void operator()(const unsigned short timestep) override; 36 | 37 | bool cellCallback( 38 | const unsigned short timestep, 39 | Cell* cell) override; 40 | 41 | void cellPersonQueueCallback( 42 | unsigned short timestep, 43 | Cell* cell, 44 | size_t personIndex); 45 | 46 | private: 47 | unsigned short latent_time(Person* person); 48 | 49 | }; // class NewInfectionSweep 50 | 51 | typedef std::shared_ptr NewInfectionSweepPtr; 52 | 53 | } // namespace epiabm 54 | 55 | 56 | #endif // EPIABM_SWEEPS_NEW_INFECTION_SWEEP_HPP -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/place_sweep.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SWEEPS_PLACE_SWEEP_HPP 2 | #define EPIABM_SWEEPS_PLACE_SWEEP_HPP 3 | 4 | #include "sweep_interface.hpp" 5 | 6 | #include 7 | 8 | 9 | namespace epiabm 10 | { 11 | 12 | /** 13 | * @brief Spread Infection within Places 14 | * Process each infected person and try to infect all susceptibles in their place. 15 | * People to be newly infected get queued in their cell's people queue. 16 | */ 17 | class PlaceSweep : public SweepInterface 18 | { 19 | private: 20 | unsigned long m_counter; 21 | 22 | public: 23 | PlaceSweep(SimulationConfigPtr cfg); 24 | ~PlaceSweep() = default; 25 | 26 | /** 27 | * @brief Perform Place Sweep 28 | * 29 | * @param timestep 30 | */ 31 | void operator()(const unsigned short timestep) override; 32 | 33 | bool cellCallback( 34 | const unsigned short timestep, 35 | Cell* cell) override; 36 | 37 | bool cellInfectiousCallback( 38 | const unsigned short timestep, 39 | Cell* infectorCell, Person* infector); 40 | 41 | private: 42 | bool placeCallback( 43 | const unsigned short timestep, 44 | Cell* infectorCell, Person* infector, 45 | Place* place, size_t group); 46 | 47 | bool doInfect( 48 | const unsigned short timestep, 49 | Cell* cell, Person* infector, 50 | Cell* infecteeCell, Person* infectee, 51 | Place* place, size_t group); 52 | 53 | double calcPlaceInf( 54 | Place* place, 55 | Person* infector, 56 | const unsigned short int timestep, 57 | size_t place_group); 58 | 59 | double calcPlaceFoi( 60 | Place* place, 61 | Person* infector, 62 | Person* infectee, 63 | const unsigned short int timestep, 64 | size_t place_group); 65 | 66 | }; // class PlaceSweep 67 | 68 | typedef std::shared_ptr PlaceSweepPtr; 69 | 70 | 71 | } // namespace epiabm 72 | 73 | 74 | #endif // EPIABM_SWEEPS_PLACE_SWEEP_HPP -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/random_seed_sweep.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "random_seed_sweep.hpp" 3 | #include "../logfile.hpp" 4 | 5 | namespace epiabm 6 | { 7 | 8 | 9 | RandomSeedSweep::RandomSeedSweep(SimulationConfigPtr simulationConfig, int per_n_people) : 10 | SweepInterface(simulationConfig), 11 | m_infectRate(per_n_people), 12 | m_infected(0) 13 | {} 14 | 15 | void RandomSeedSweep::operator()(const unsigned short timestep) 16 | { 17 | m_infected = 0; 18 | m_population->forEachCell(std::bind( 19 | &RandomSeedSweep::cellCallback, this, 20 | timestep, std::placeholders::_1)); 21 | LOG << LOG_LEVEL_INFO << "Randomly seeded " << m_infected << " people at timestep " << timestep; 22 | } 23 | 24 | bool RandomSeedSweep::cellCallback( 25 | const unsigned short timestep, 26 | Cell* cell) 27 | { 28 | cell->forEachPerson(std::bind( 29 | &RandomSeedSweep::cellPersonCallback, this, 30 | timestep, cell, std::placeholders::_1)); 31 | return true; 32 | } 33 | 34 | bool RandomSeedSweep::cellPersonCallback( 35 | unsigned short timestep, 36 | Cell* cell, 37 | Person* person) 38 | { 39 | if (m_cfg->randomManager->g().randi(INT32_MAX)%m_infectRate < 1) 40 | { 41 | person->updateStatus(cell, InfectionStatus::Exposed, timestep); 42 | person->params().next_status_time = static_cast(timestep); 43 | cell->markExposed(person->cellPos()); 44 | m_infected++; 45 | } 46 | return true; 47 | } 48 | } 49 | 50 | 51 | -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/random_seed_sweep.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SWEEPS_RANDOM_SEED_SWEEP_HPP 2 | #define EPIABM_SWEEPS_RANDOM_SEED_SWEEP_HPP 3 | 4 | #include "sweep_interface.hpp" 5 | 6 | namespace epiabm 7 | { 8 | 9 | class RandomSeedSweep : public SweepInterface 10 | { 11 | private: 12 | int m_infectRate; 13 | unsigned long m_infected; 14 | 15 | public: 16 | /** 17 | * @brief Construct a new Random Seed Sweep object 18 | * One in every per_n_people is updated to infectious 19 | * @param infection_rate 20 | */ 21 | RandomSeedSweep(SimulationConfigPtr simulationConfig, int per_n_people); 22 | ~RandomSeedSweep() = default; 23 | 24 | /** 25 | * @brief Sweep through population and infect people 26 | * 27 | * @param timestep 28 | */ 29 | void operator()(const unsigned short timestep) override; 30 | 31 | bool cellCallback( 32 | const unsigned short timestep, 33 | Cell* cell) override; 34 | 35 | bool cellPersonCallback( 36 | unsigned short timestep, 37 | Cell* cell, 38 | Person* person); 39 | 40 | private: 41 | }; // class RandomSeedSweep 42 | 43 | typedef std::shared_ptr RandomSeedSweepPtr; 44 | 45 | } // namespace epiabm 46 | 47 | 48 | #endif // EPIABM_SWEEPS_RANDOM_SEED_SWEEP_HPP -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/sweep_interface.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "sweep_interface.hpp" 3 | 4 | namespace epiabm 5 | { 6 | SweepInterface::SweepInterface() {} 7 | SweepInterface::SweepInterface(SimulationConfigPtr cfg) : 8 | m_cfg(cfg) 9 | {} 10 | 11 | void SweepInterface::bind_population(PopulationPtr population) 12 | { 13 | m_population = population; 14 | } 15 | 16 | } // namespace epiabm 17 | -------------------------------------------------------------------------------- /cEpiabm/src/sweeps/sweep_interface.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_SWEEPS_SWEEP_INTERFACE_HPP 2 | #define EPIABM_SWEEPS_SWEEP_INTERFACE_HPP 3 | 4 | #include "../dataclasses/population.hpp" 5 | #include "../configuration/simulation_config.hpp" 6 | 7 | #include 8 | #include 9 | 10 | namespace epiabm 11 | { 12 | 13 | /** 14 | * @brief Interface class for sweeps 15 | * Sweeps can have population bound, and then operate upon the bound populations each timestep. 16 | */ 17 | class SweepInterface 18 | { 19 | protected: 20 | PopulationPtr m_population; 21 | SimulationConfigPtr m_cfg; 22 | 23 | public: 24 | SweepInterface(); 25 | SweepInterface(SimulationConfigPtr cfg); 26 | virtual ~SweepInterface() = default; 27 | 28 | /** 29 | * @brief Bind Population 30 | * Attach population to the sweep 31 | * @param population 32 | */ 33 | void bind_population(PopulationPtr population); 34 | 35 | /** 36 | * @brief Apply sweep 37 | * Act on the population. Called by Simulation class each iteration timestep. 38 | */ 39 | virtual void operator()(const unsigned short /*timestep*/){}; 40 | 41 | /** 42 | * @brief Callback to apply sweep to each cell 43 | * 44 | * @param timestep Current Timestep 45 | * @param cell Cell to act on 46 | * @return true Returns true to continue and callback on next cell 47 | * @return false Terminate Callbacks 48 | */ 49 | virtual bool cellCallback( 50 | const unsigned short /*timestep*/, 51 | Cell* /*cell*/) { return true; } 52 | 53 | 54 | }; // class SweepInterface 55 | 56 | typedef std::shared_ptr SweepInterfacePtr; 57 | 58 | } // namespace epiabm 59 | 60 | 61 | #endif // EPIABM_SWEEPS_SWEEP_INTERFACE_HPP -------------------------------------------------------------------------------- /cEpiabm/src/toy_population_factory.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_TOY_POPULATION_FACTORY_HPP 2 | #define EPIABM_TOY_POPULATION_FACTORY_HPP 3 | 4 | #include "dataclasses/population.hpp" 5 | #include "dataclasses/cell.hpp" 6 | #include "dataclasses/microcell.hpp" 7 | #include "dataclasses/place.hpp" 8 | #include "dataclasses/person.hpp" 9 | 10 | 11 | namespace epiabm 12 | { 13 | 14 | class ToyPopulationFactory 15 | { 16 | private: 17 | public: 18 | PopulationPtr makePopulation( 19 | size_t populationSize, size_t nCells, size_t nMicrocells, 20 | size_t nHouseholds, size_t nPlaces, std::optional seed); 21 | 22 | private: 23 | }; 24 | 25 | } 26 | 27 | 28 | #endif // EPIABM_TOY_POPULATION_FACTORY_HPP -------------------------------------------------------------------------------- /cEpiabm/src/utilities/distance_metrics.cpp: -------------------------------------------------------------------------------- 1 | #include "distance_metrics.hpp" 2 | #include 3 | 4 | 5 | namespace epiabm 6 | { 7 | 8 | 9 | DistanceMetrics::DistanceMetrics() 10 | {} 11 | 12 | double DistanceMetrics::Dist(location loc1, location loc2) 13 | { 14 | return DistEuclid(loc1, loc2); 15 | } 16 | 17 | double DistanceMetrics::DistEuclid(location loc1, location loc2) 18 | { 19 | return pow(pow(loc1.first-loc2.first, 2) + pow(loc1.second-loc2.second, 2), 0.5); 20 | } 21 | 22 | double DistanceMetrics::DistCovidsim(location /*loc1*/, location /*loc2*/) 23 | { 24 | return 2; 25 | } 26 | 27 | } // namespace epiabm 28 | 29 | -------------------------------------------------------------------------------- /cEpiabm/src/utilities/distance_metrics.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_UTILITY_DISTANCE_METRICS_HPP 2 | #define EPIABM_UTILITY_DISTANCE_METRICS_HPP 3 | 4 | 5 | #include 6 | 7 | 8 | namespace epiabm 9 | { 10 | typedef std::pair location; 11 | 12 | class DistanceMetrics 13 | { 14 | public: 15 | DistanceMetrics(); 16 | ~DistanceMetrics() = default; 17 | 18 | static double Dist(location loc1, location loc2); 19 | static double DistEuclid(location loc1, location loc2); 20 | static double DistCovidsim(location loc1, location loc2); 21 | }; 22 | } // namespace epiabm 23 | 24 | #endif // EPIABM_UTILITY_DISTANCE_METRICS_HPP -------------------------------------------------------------------------------- /cEpiabm/src/utilities/inverse_cdf.cpp: -------------------------------------------------------------------------------- 1 | #include "inverse_cdf.hpp" 2 | 3 | #include 4 | 5 | namespace epiabm 6 | { 7 | 8 | InverseCDF::InverseCDF() : 9 | m_mean(0) 10 | {} 11 | InverseCDF::InverseCDF(double mean) : 12 | m_mean(mean) 13 | {} 14 | 15 | void InverseCDF::setNegLog(double startValue) 16 | { 17 | m_values[InverseCDF::RES] = startValue; 18 | for (size_t i = 0; i < InverseCDF::RES; i++) 19 | { 20 | m_values[i] = -log(1 - static_cast(i) / InverseCDF::RES); 21 | } 22 | } 23 | 24 | void InverseCDF::assignExponent() 25 | { 26 | for (size_t i = 0; i < InverseCDF::RES; i++) 27 | { 28 | m_values[i] = exp(-m_values[i]); 29 | } 30 | } 31 | 32 | void InverseCDF::assignExponent(double value) 33 | { 34 | for (size_t i = 0; i < InverseCDF::RES; i++) 35 | { 36 | m_values[i] = exp(value); 37 | } 38 | } 39 | 40 | unsigned short InverseCDF::choose(double timestepsPerDay, RandomGenerator& generator) 41 | { 42 | double q; 43 | size_t i = static_cast(floor(q = generator.randf()*static_cast(InverseCDF::RES))); 44 | q -= static_cast(i); 45 | 46 | double ti = m_mean * (q * m_values[i+1] + (1.0-q)*m_values[i]); 47 | return static_cast(floor(0.5 + (ti * timestepsPerDay))); 48 | } 49 | 50 | std::array& InverseCDF::getValues() 51 | { 52 | return m_values; 53 | } 54 | 55 | double& InverseCDF::operator[](size_t i) 56 | { 57 | return m_values[i]; 58 | } 59 | 60 | double InverseCDF::mean() 61 | { 62 | return m_mean; 63 | } 64 | 65 | 66 | } // namespace epiabm 67 | -------------------------------------------------------------------------------- /cEpiabm/src/utilities/inverse_cdf.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_UTILITIES_INVERSE_CDF_HPP 2 | #define EPIABM_UTILITIES_INVERSE_CDF_HPP 3 | 4 | #include "random_generator.hpp" 5 | 6 | #include 7 | #include 8 | 9 | namespace epiabm 10 | { 11 | class InverseCDF 12 | { 13 | public: 14 | static const size_t RES = 20; 15 | private: 16 | std::array m_values; 17 | double m_mean; 18 | 19 | public: 20 | InverseCDF(); 21 | InverseCDF(double mean); 22 | 23 | void setNegLog(double startValue); 24 | void assignExponent(); 25 | void assignExponent(double value); 26 | 27 | unsigned short choose(double timestepsPerDay, RandomGenerator& generator); 28 | 29 | std::array& getValues(); 30 | double& operator[](size_t i); 31 | 32 | double mean(); 33 | 34 | private: 35 | }; 36 | 37 | } // namespace epiabm 38 | 39 | #endif // EPIABM_UTILITIES_INVERSE_CDF_HPP 40 | -------------------------------------------------------------------------------- /cEpiabm/src/utilities/random_manager.cpp: -------------------------------------------------------------------------------- 1 | #include "random_manager.hpp" 2 | 3 | 4 | namespace epiabm 5 | { 6 | 7 | RandomManager::RandomManager(unsigned int seed) : 8 | m_generators(), 9 | m_seed(seed) 10 | {} 11 | 12 | RandomManager::~RandomManager() = default; 13 | 14 | RandomGenerator& RandomManager::g() 15 | { 16 | std::thread::id tid = std::this_thread::get_id(); 17 | if (m_generators.find(tid) == m_generators.end()) 18 | { 19 | std::lock_guard l(m_mutex); 20 | m_generators[tid] = std::make_shared( 21 | m_seed + m_nThreads, m_nThreads, tid); 22 | } 23 | return *m_generators.at(tid); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /cEpiabm/src/utilities/random_manager.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_UTILITIES_RANDOM_MANAGER_HPP 2 | #define EPIABM_UTILITIES_RANDOM_MANAGER_HPP 3 | 4 | 5 | #include "random_generator.hpp" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | namespace epiabm 13 | { 14 | 15 | class RandomManager 16 | { 17 | private: 18 | std::map m_generators; 19 | unsigned int m_nThreads; 20 | unsigned int m_seed; 21 | std::mutex m_mutex; 22 | 23 | public: 24 | RandomManager(unsigned int seed); 25 | ~RandomManager(); 26 | 27 | RandomGenerator& g(); 28 | 29 | private: 30 | }; 31 | 32 | typedef std::shared_ptr RandomManagerPtr; 33 | 34 | } // namespace epiabm 35 | 36 | 37 | #endif // EPIABM_UTILITIES_RANDOM_MANAGER_HPP -------------------------------------------------------------------------------- /cEpiabm/test/catch_main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #define CATCH_CONFIG_MAIN 3 | 4 | #include "catch/catch.hpp" 5 | 6 | // This file just tells Catch2 to provide a main function. The tests are located in other cpp files in this directory. 7 | -------------------------------------------------------------------------------- /cEpiabm/test/configuration/helpers.hpp: -------------------------------------------------------------------------------- 1 | #ifndef EPIABM_TEST_CONFIGURATION_HELPERS_HPP 2 | #define EPIABM_TEST_CONFIGURATION_HELPERS_HPP 3 | 4 | #include "utilities/inverse_cdf.hpp" 5 | 6 | #include 7 | 8 | #include "../catch/catch.hpp" 9 | 10 | namespace detail 11 | { 12 | const char alphanum[] = 13 | "0123456789" 14 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 15 | "abcdefghijklmnopqrstuvwxyz"; 16 | 17 | template 18 | inline T generate() 19 | { 20 | return static_cast(std::rand()); 21 | } 22 | 23 | inline std::string generate(size_t n = 10) 24 | { 25 | std::string s; 26 | s.reserve(n); 27 | for (size_t i = 0; i < n; i++) 28 | { 29 | s += alphanum[static_cast(std::rand()) % (sizeof(alphanum)-1)]; 30 | } 31 | return s; 32 | } 33 | 34 | } 35 | 36 | 37 | template 38 | inline void checkParameter(T& var, size_t reps = 1) 39 | { 40 | for (size_t r = 0; r < reps; r++) 41 | { 42 | const T value = detail::generate(); 43 | var = value; 44 | REQUIRE(var == value); 45 | } 46 | } 47 | 48 | template 49 | inline void checkParameter(std::array& var, size_t reps = 1) 50 | { 51 | for (size_t r = 0; r < reps; r++) 52 | { 53 | std::array value; 54 | for (size_t i = 0; i < N; i++) 55 | { 56 | value[i] = detail::generate(); 57 | var[i] = value[i]; 58 | } 59 | 60 | for (size_t i = 0; i < N; i++) 61 | { 62 | REQUIRE(var[i] == value[i]); 63 | } 64 | } 65 | } 66 | 67 | template <> 68 | inline void checkParameter(epiabm::InverseCDF& var, size_t reps) 69 | { 70 | checkParameter(var.getValues(), reps); 71 | } 72 | 73 | #endif // EPIABM_TEST_CONFIGURATION_HELPERS_HPP 74 | -------------------------------------------------------------------------------- /cEpiabm/test/configuration/test_host_progression_config.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "configuration/host_progression_config.hpp" 3 | #include "configuration/json.hpp" 4 | #include "logfile.hpp" 5 | 6 | #include "helpers.hpp" 7 | #include "../catch/catch.hpp" 8 | 9 | #include 10 | #include 11 | 12 | using namespace epiabm; 13 | 14 | TEST_CASE("host_progression_config: test constructor", "[HostProgressionConfig]") 15 | { 16 | HostProgressionConfigPtr subject = std::make_shared(); 17 | 18 | checkParameter(subject->latentPeriodICDF, 10); 19 | checkParameter(subject->asymptToRecovICDF, 10); 20 | checkParameter(subject->mildToRecovICDF, 10); 21 | checkParameter(subject->gpToRecovICDF, 10); 22 | checkParameter(subject->gpToHospICDF, 10); 23 | checkParameter(subject->gpToDeathICDF, 10); 24 | checkParameter(subject->hospToRecovICDF, 10); 25 | checkParameter(subject->hospToICUICDF, 10); 26 | checkParameter(subject->hospToDeathICDF, 10); 27 | checkParameter(subject->icuToICURecovICDF, 10); 28 | checkParameter(subject->icuToDeathICDF, 10); 29 | checkParameter(subject->icuRecovToRecovICDF, 10); 30 | 31 | checkParameter(subject->use_ages, 10); 32 | checkParameter(subject->prob_gp_to_hosp, 10); 33 | checkParameter(subject->prob_gp_to_recov, 10); 34 | checkParameter(subject->prob_exposed_to_asympt, 10); 35 | checkParameter(subject->prob_exposed_to_gp, 10); 36 | checkParameter(subject->prob_exposed_to_mild, 10); 37 | checkParameter(subject->prob_hosp_to_death, 10); 38 | checkParameter(subject->prob_hosp_to_recov, 10); 39 | checkParameter(subject->prob_hosp_to_icu, 10); 40 | checkParameter(subject->prob_icu_to_death, 10); 41 | checkParameter(subject->prob_icu_to_icurecov, 10); 42 | 43 | REQUIRE(subject->infectiousness_profile.size() == 0); 44 | } 45 | -------------------------------------------------------------------------------- /cEpiabm/test/configuration/test_infection_config.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "configuration/infection_config.hpp" 3 | #include "configuration/json.hpp" 4 | #include "logfile.hpp" 5 | 6 | #include "helpers.hpp" 7 | #include "../catch/catch.hpp" 8 | 9 | #include 10 | #include 11 | 12 | using namespace epiabm; 13 | 14 | TEST_CASE("infection_config: test constructor", "[InfectionConfig]") 15 | { 16 | InfectionConfigPtr subject = std::make_shared(); 17 | REQUIRE(subject->hostProgressionConfig != nullptr); 18 | 19 | checkParameter(subject->basicReproductionNum, 10); 20 | checkParameter(subject->infectionRadius, 10); 21 | checkParameter(subject->probSymptomatic, 10); 22 | checkParameter(subject->symptInfectiousness, 10); 23 | checkParameter(subject->asymptInfectiousness, 10); 24 | checkParameter(subject->latentToSymptDelay, 10); 25 | 26 | checkParameter(subject->falsePositiveRate, 10); 27 | 28 | checkParameter(subject->householdTransmission, 10); 29 | checkParameter(subject->placeTransmission, 10); 30 | } 31 | -------------------------------------------------------------------------------- /cEpiabm/test/configuration/test_population_config.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "configuration/population_config.hpp" 3 | #include "configuration/json.hpp" 4 | #include "logfile.hpp" 5 | 6 | #include "helpers.hpp" 7 | #include "../catch/catch.hpp" 8 | 9 | #include 10 | #include 11 | 12 | using namespace epiabm; 13 | 14 | TEST_CASE("population_config: test constructor", "[PopulationConfig]") 15 | { 16 | PopulationConfigPtr subject = std::make_shared(); 17 | 18 | checkParameter(subject->age_contacts, 10); 19 | checkParameter(subject->age_proportions, 10); 20 | } 21 | -------------------------------------------------------------------------------- /cEpiabm/test/configuration/test_simulation_config.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "configuration/simulation_config.hpp" 3 | #include "configuration/json.hpp" 4 | #include "logfile.hpp" 5 | 6 | #include "helpers.hpp" 7 | #include "../catch/catch.hpp" 8 | 9 | #include 10 | #include 11 | 12 | using namespace epiabm; 13 | 14 | TEST_CASE("simulation_config: test constructor", "[SimulationConfig]") 15 | { 16 | SimulationConfigPtr subject = std::make_shared(); 17 | REQUIRE(subject->infectionConfig != nullptr); 18 | REQUIRE(subject->populationConfig != nullptr); 19 | 20 | checkParameter(subject->timestepsPerDay); 21 | } 22 | -------------------------------------------------------------------------------- /cEpiabm/test/dataclasses/test_compartment_counter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "dataclasses/cell.hpp" 3 | 4 | #include "../catch/catch.hpp" 5 | 6 | #include 7 | 8 | using namespace epiabm; 9 | 10 | inline CompartmentCounter makeSubject(size_t n_people) 11 | { 12 | std::vector people = std::vector(); 13 | people.reserve(n_people); 14 | for (size_t i = 0; i < n_people; i++) people.push_back(Person(0, i, i)); 15 | CompartmentCounter subject = CompartmentCounter(); 16 | subject.initialize(people); 17 | return subject; 18 | } 19 | 20 | TEST_CASE("dataclasses/compartment_counter: test initialize", "[CompartmentCounter]") 21 | { 22 | CompartmentCounter subject = CompartmentCounter(); 23 | REQUIRE(subject(InfectionStatus::Susceptible) == 0); 24 | } 25 | 26 | TEST_CASE("dataclasses/compartment_counter: test initialize compartment counting", "[CompartmentCounter]") 27 | { 28 | CompartmentCounter subject = makeSubject(100); 29 | REQUIRE(subject(InfectionStatus::Susceptible) == 100); 30 | REQUIRE(subject(InfectionStatus::Exposed) == 0); 31 | } 32 | 33 | TEST_CASE("dataclasses/compartment_counter: test notify", "[CompartmentCounter]") 34 | { 35 | CompartmentCounter subject = makeSubject(100); 36 | REQUIRE(subject(InfectionStatus::Susceptible) == 100); 37 | REQUIRE(subject(InfectionStatus::Exposed) == 0); 38 | 39 | size_t n_exposed = static_cast(std::rand()) % 90 + 10; 40 | for (size_t i = 0; i < n_exposed; i++) 41 | subject.notify(InfectionStatus::Susceptible, InfectionStatus::Exposed); 42 | 43 | REQUIRE(subject(InfectionStatus::Susceptible) == 100 - n_exposed); 44 | REQUIRE(subject(InfectionStatus::Exposed) == n_exposed); 45 | } 46 | 47 | TEST_CASE("dataclasses/compartment_counter: test initialize cell", "[CompartmentCounter]") 48 | { 49 | Cell cell = Cell(0); 50 | for (size_t i = 0; i < 100; i++) cell.people().push_back(Person(0, i, i)); 51 | 52 | CompartmentCounter subject = CompartmentCounter(); 53 | subject.initialize(&cell, {1, 2, 3, 4, 5}); 54 | 55 | REQUIRE(subject(InfectionStatus::Susceptible) == 5); 56 | REQUIRE(subject(InfectionStatus::Exposed) == 0); 57 | } 58 | -------------------------------------------------------------------------------- /cEpiabm/test/dataclasses/test_distance_metrics.cpp: -------------------------------------------------------------------------------- 1 | #include "utility/distance_metrics.hpp" 2 | 3 | #include "../catch/catch.hpp" 4 | 5 | using namespace epiabm; 6 | 7 | TEST_CASE("utility/distance_metrics: test distance metric", "[DistanceMetrics]") 8 | { // tests the Dist function returns the same as the DistEuclid 9 | auto loc = std::make_pair(1.0, 1.0); 10 | double subject = DistanceMetrics::Dist(loc, loc); 11 | double euclid = DistanceMetrics::DistEuclid(loc, loc); 12 | REQUIRE(subject == euclid); 13 | 14 | auto loc2 = std::make_pair(1.0, 0.0); 15 | double subject = DistanceMetrics::Dist(loc, loc2); 16 | double euclid = DistanceMetrics::DistEuclid(loc, loc2); 17 | REQUIRE(subject == euclid); 18 | } 19 | 20 | TEST_CASE("utility/distance_metrics: test Euclidean distance metric", "[DistanceMetrics]") 21 | { 22 | auto loc = std::make_pair(1.0, 1.0); 23 | auto loc2 = loc; 24 | loc2.first = 0.0; 25 | double subject = DistanceMetrics::DistEuclid(loc, loc); 26 | REQUIRE(subject == 0); 27 | double subject = DistanceMetrics::DistEuclid(loc, loc2); 28 | REQUIRE(subject == 1); 29 | loc2.second = -1.0; 30 | double subject = DistanceMetrics::DistEuclid(loc, loc2); 31 | REQUIRE(subject == 1); 32 | } 33 | 34 | TEST_CASE("utility/distance_metrics: test Covidsim distance metric", "[DistanceMetrics]") 35 | { //these are all curretnly 2 which is helpful 36 | auto loc = std::make_pair(1.0, 1.0); 37 | auto loc2 = loc; 38 | loc2.first = 0.0; 39 | double subject = DistanceMetrics::DistCovidsim(loc, loc); 40 | REQUIRE(subject == 2); 41 | double subject = DistanceMetrics::DistCovidsim(loc, loc2); 42 | REQUIRE(subject == 2); 43 | loc2.second = -1.0; 44 | double subject = DistanceMetrics::DistCovidsim(loc, loc2); 45 | REQUIRE(subject == 2); 46 | } 47 | -------------------------------------------------------------------------------- /cEpiabm/test/dataclasses/test_infection_status.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "dataclasses/cell.hpp" 3 | 4 | #include "../catch/catch.hpp" 5 | 6 | #include 7 | 8 | using namespace epiabm; 9 | 10 | TEST_CASE("dataclasses/infection_status: test status_string", "[InfectionStatus]") 11 | { 12 | REQUIRE_NOTHROW(status_string(InfectionStatus::Susceptible)); 13 | REQUIRE_NOTHROW(status_string(InfectionStatus::Exposed)); 14 | REQUIRE_NOTHROW(status_string(InfectionStatus::InfectASympt)); 15 | REQUIRE_NOTHROW(status_string(InfectionStatus::InfectMild)); 16 | REQUIRE_NOTHROW(status_string(InfectionStatus::InfectGP)); 17 | REQUIRE_NOTHROW(status_string(InfectionStatus::InfectHosp)); 18 | REQUIRE_NOTHROW(status_string(InfectionStatus::InfectICU)); 19 | REQUIRE_NOTHROW(status_string(InfectionStatus::InfectICURecov)); 20 | REQUIRE_NOTHROW(status_string(InfectionStatus::Recovered)); 21 | REQUIRE_NOTHROW(status_string(InfectionStatus::Dead)); 22 | REQUIRE_NOTHROW(status_string(static_cast(20))); 23 | } 24 | -------------------------------------------------------------------------------- /cEpiabm/test/reporters/test_age_stratified_new_cases_reporter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "population_factory.hpp" 3 | #include "household_linker.hpp" 4 | #include "reporters/age_stratified_new_cases_reporter.hpp" 5 | 6 | #include "../catch/catch.hpp" 7 | 8 | #include 9 | 10 | using namespace epiabm; 11 | 12 | TEST_CASE("reporters/age_stratified_new_cases_reporter: test initialize", "[AgeStratifiedNewCasesReporter]") 13 | { 14 | PopulationPtr population = PopulationFactory().makePopulation(10, 10, 1000); 15 | population->cells()[0]->people()[0].setStatus(InfectionStatus::InfectASympt); 16 | HouseholdLinker().linkHouseholds(population, 1, 100, std::optional()); 17 | population->initialize(); 18 | 19 | AgeStratifiedNewCasesReporter subject = AgeStratifiedNewCasesReporter("test_output/test_population_compartment_reporter.csv"); 20 | REQUIRE_NOTHROW(subject.setup(population)); 21 | REQUIRE_NOTHROW(subject.report(population, 0)); 22 | REQUIRE_NOTHROW(subject.teardown()); 23 | } 24 | 25 | TEST_CASE("reporters/age_stratified_new_cases_reporter: test destructor", "[AgeStratifiedNewCasesReporter]") 26 | { 27 | { 28 | TimestepReporterInterface* i = new AgeStratifiedNewCasesReporter("test_output/test_destructor.csv"); 29 | [[maybe_unused]] AgeStratifiedNewCasesReporter* subject = dynamic_cast(i); 30 | delete i; 31 | i = nullptr; 32 | subject = nullptr; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cEpiabm/test/reporters/test_age_stratified_population_reporter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "population_factory.hpp" 3 | #include "household_linker.hpp" 4 | #include "reporters/age_stratified_population_reporter.hpp" 5 | 6 | #include "../catch/catch.hpp" 7 | 8 | #include 9 | 10 | using namespace epiabm; 11 | 12 | TEST_CASE("reporters/age_stratified_population_reporter: test initialize", "[AgeStratifiedPopulationReporter]") 13 | { 14 | PopulationPtr population = PopulationFactory().makePopulation(10, 10, 1000); 15 | population->cells()[0]->people()[0].setStatus(InfectionStatus::InfectASympt); 16 | HouseholdLinker().linkHouseholds(population, 1, 100, std::optional()); 17 | population->initialize(); 18 | 19 | AgeStratifiedPopulationReporter subject = AgeStratifiedPopulationReporter("test_output/test_population_compartment_reporter.csv"); 20 | REQUIRE_NOTHROW(subject.setup(population)); 21 | REQUIRE_NOTHROW(subject.compartments()); 22 | REQUIRE_NOTHROW(subject.report(population, 0)); 23 | REQUIRE_NOTHROW(subject.teardown()); 24 | } 25 | 26 | TEST_CASE("reporters/age_stratified_population_reporter: test destructor", "[AgeStratifiedPopulationReporter]") 27 | { 28 | { 29 | TimestepReporterInterface* i = new AgeStratifiedPopulationReporter("test_output/test_destructor.csv"); 30 | [[maybe_unused]] AgeStratifiedPopulationReporter* subject = dynamic_cast(i); 31 | delete i; 32 | i = nullptr; 33 | subject = nullptr; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /cEpiabm/test/reporters/test_cell_compartment_reporter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "population_factory.hpp" 3 | #include "household_linker.hpp" 4 | #include "reporters/cell_compartment_reporter.hpp" 5 | #include "logfile.hpp" 6 | 7 | #include "../catch/catch.hpp" 8 | 9 | #include 10 | 11 | using namespace epiabm; 12 | 13 | TEST_CASE("reporters/cell_compartment_reporter: test initialize", "[CellCompartmentReporter]") 14 | { 15 | PopulationPtr population = PopulationFactory().makePopulation(10, 10, 1000); 16 | HouseholdLinker().linkHouseholds(population, 1, 100, std::optional()); 17 | population->initialize(); 18 | 19 | CellCompartmentReporter subject = CellCompartmentReporter("test_output"); 20 | REQUIRE_NOTHROW(subject.setup(population)); 21 | REQUIRE_NOTHROW(subject.compartments()); 22 | REQUIRE_NOTHROW(subject.report(population, 0)); 23 | REQUIRE_NOTHROW(subject.teardown()); 24 | } 25 | 26 | TEST_CASE("reporters/cell_compartment_reporter: test destructor", "[CellCompartmentReporter]") 27 | { 28 | { 29 | TimestepReporterInterface* i = new CellCompartmentReporter("test_output"); 30 | [[maybe_unused]] CellCompartmentReporter* subject = dynamic_cast(i); 31 | delete i; 32 | i = nullptr; 33 | subject = nullptr; 34 | } 35 | { 36 | TimestepReporterInterface* i = new TimestepReporterInterface( 37 | std::filesystem::path("test_output/test.csv")); 38 | i->report(PopulationPtr(), 0); 39 | delete i; 40 | i = nullptr; 41 | } 42 | { 43 | std::string tmp = "test_output/test.csv"; 44 | [[maybe_unused]] TimestepReporterInterface* i = new TimestepReporterInterface(tmp); 45 | delete i; 46 | i = nullptr; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cEpiabm/test/reporters/test_new_cases_reporter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "population_factory.hpp" 3 | #include "household_linker.hpp" 4 | #include "reporters/new_cases_reporter.hpp" 5 | 6 | #include "../catch/catch.hpp" 7 | 8 | #include 9 | 10 | using namespace epiabm; 11 | 12 | TEST_CASE("reporters/new_cases_reporter: test initialize", "[NewCasesReporter]") 13 | { 14 | PopulationPtr population = PopulationFactory().makePopulation(10, 10, 1000); 15 | population->cells()[0]->people()[0].setStatus(InfectionStatus::InfectASympt); 16 | HouseholdLinker().linkHouseholds(population, 1, 100, std::optional()); 17 | population->initialize(); 18 | 19 | NewCasesReporter subject = NewCasesReporter("test_output/test_population_compartment_reporter.csv"); 20 | REQUIRE_NOTHROW(subject.setup(population)); 21 | REQUIRE_NOTHROW(subject.report(population, 0)); 22 | REQUIRE_NOTHROW(subject.teardown()); 23 | } 24 | 25 | TEST_CASE("reporters/new_cases_reporter: test destructor", "[NewCasesReporter]") 26 | { 27 | { 28 | TimestepReporterInterface* i = new NewCasesReporter("test_output/test_destructor.csv"); 29 | [[maybe_unused]] NewCasesReporter* subject = dynamic_cast(i); 30 | delete i; 31 | i = nullptr; 32 | subject = nullptr; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cEpiabm/test/reporters/test_percell_compartment_reporter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "population_factory.hpp" 3 | #include "household_linker.hpp" 4 | #include "reporters/percell_compartment_reporter.hpp" 5 | 6 | #include "../catch/catch.hpp" 7 | 8 | #include 9 | 10 | using namespace epiabm; 11 | 12 | TEST_CASE("reporters/percell_compartment_reporter: test initialize", "[PerCellCompartmentReporter]") 13 | { 14 | PopulationPtr population = PopulationFactory().makePopulation(10, 10, 1000); 15 | HouseholdLinker().linkHouseholds(population, 1, 100, std::optional()); 16 | population->initialize(); 17 | 18 | PerCellCompartmentReporter subject = PerCellCompartmentReporter("test_output"); 19 | REQUIRE_NOTHROW(subject.setup(population)); 20 | REQUIRE_NOTHROW(subject.compartments()); 21 | REQUIRE_NOTHROW(subject.report(population, 0)); 22 | REQUIRE_NOTHROW(subject.teardown()); 23 | } 24 | 25 | TEST_CASE("reporters/percell_compartment_reporter: test destructor", "[PerCellCompartmentReporter]") 26 | { 27 | { 28 | TimestepReporterInterface* i = new PerCellCompartmentReporter("test_output"); 29 | [[maybe_unused]] PerCellCompartmentReporter* subject = dynamic_cast(i); 30 | delete i; 31 | i = nullptr; 32 | subject = nullptr; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cEpiabm/test/reporters/test_population_compartment_reporter.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "population_factory.hpp" 3 | #include "household_linker.hpp" 4 | #include "reporters/population_compartment_reporter.hpp" 5 | 6 | #include "../catch/catch.hpp" 7 | 8 | #include 9 | 10 | using namespace epiabm; 11 | 12 | TEST_CASE("reporters/population_compartment_reporter: test initialize", "[PopulationCompartmentReporter]") 13 | { 14 | PopulationPtr population = PopulationFactory().makePopulation(10, 10, 1000); 15 | HouseholdLinker().linkHouseholds(population, 1, 100, std::optional()); 16 | population->initialize(); 17 | 18 | PopulationCompartmentReporter subject = PopulationCompartmentReporter("test_output/test_population_compartment_reporter.csv"); 19 | REQUIRE_NOTHROW(subject.setup(population)); 20 | REQUIRE_NOTHROW(subject.compartments()); 21 | REQUIRE_NOTHROW(subject.report(population, 0)); 22 | REQUIRE_NOTHROW(subject.teardown()); 23 | } 24 | 25 | TEST_CASE("reporters/population_compartment_reporter: test destructor", "[PopulationCompartmentReporter]") 26 | { 27 | { 28 | TimestepReporterInterface* i = new PopulationCompartmentReporter("test_output/test_destructor.csv"); 29 | [[maybe_unused]] PopulationCompartmentReporter* subject = dynamic_cast(i); 30 | delete i; 31 | i = nullptr; 32 | subject = nullptr; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cEpiabm/test/sweeps/test_random_seed_sweep.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "sweeps/random_seed_sweep.hpp" 4 | #include "population_factory.hpp" 5 | #include "configuration/json_factory.hpp" 6 | 7 | #include "../catch/catch.hpp" 8 | #include "helpers.hpp" 9 | 10 | #include 11 | 12 | using namespace epiabm; 13 | 14 | TEST_CASE("sweeps/random_seed_sweep: test initialize random_seed_sweep", "[RandomSeedSweep]") 15 | { 16 | RandomSeedSweepPtr subject = std::make_shared( 17 | std::make_shared(), 1000); 18 | } 19 | 20 | TEST_CASE("sweeps/random_seed_sweep: test random_seed_sweep bind_population", "[RandomSeedSweep]") 21 | { 22 | RandomSeedSweepPtr subject = std::make_shared( 23 | std::make_shared(), 1000); 24 | PopulationPtr population = PopulationFactory().makePopulation(5, 5, 1000); 25 | population->initialize(); 26 | REQUIRE_NOTHROW(subject->bind_population(population)); 27 | } 28 | 29 | TEST_CASE("sweeps/random_seed_sweep: test random_seed_sweep run sweep", "[RandomSeedSweep]") 30 | { 31 | RandomSeedSweepPtr subject = std::make_shared( 32 | JsonFactory().loadConfig(std::filesystem::path("../testdata/test_config.json")), 1000); 33 | PopulationPtr population = PopulationFactory().makePopulation(5, 5, 1000); 34 | random_seed(population, 10, InfectionStatus::InfectASympt, 5); 35 | random_seed(population, 10, InfectionStatus::Exposed, 2); 36 | population->initialize(); 37 | REQUIRE_NOTHROW(subject->bind_population(population)); 38 | for (int i = 0; i < 10; i++) 39 | REQUIRE_NOTHROW((*subject)(static_cast(i))); 40 | } 41 | 42 | TEST_CASE("sweeps/random_seed_sweep: test destructor", "[RandomSeedSweep]") 43 | { 44 | { 45 | SweepInterface* i = new RandomSeedSweep( 46 | std::make_shared(), 1000); 47 | [[maybe_unused]] RandomSeedSweep* subject = dynamic_cast(i); 48 | delete i; 49 | i = nullptr; 50 | subject = nullptr; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cEpiabm/test/utilities/test_distance_metrics.cpp: -------------------------------------------------------------------------------- 1 | #include "utilities/distance_metrics.hpp" 2 | 3 | #include "../catch/catch.hpp" 4 | 5 | using namespace epiabm; 6 | 7 | TEST_CASE("utilities/distance_metrics: test distance metric init", "[DistanceMetrics]") 8 | { // tests the Dist function returns the same as the DistEuclid 9 | DistanceMetrics subject = DistanceMetrics(); 10 | } 11 | 12 | TEST_CASE("utilities/distance_metrics: test distance metric", "[DistanceMetrics]") 13 | { // tests the Dist function returns the same as the DistEuclid 14 | auto loc = std::make_pair(1.0, 1.0); 15 | double subject = DistanceMetrics::Dist(loc, loc); 16 | double euclid = DistanceMetrics::DistEuclid(loc, loc); 17 | REQUIRE(subject == euclid); 18 | 19 | auto loc2 = std::make_pair(1.0, 0.0); 20 | subject = DistanceMetrics::Dist(loc, loc2); 21 | euclid = DistanceMetrics::DistEuclid(loc, loc2); 22 | REQUIRE(subject == euclid); 23 | } 24 | 25 | TEST_CASE("utilities/distance_metrics: test Euclidean distance metric", "[DistanceMetrics]") 26 | { 27 | auto loc = std::make_pair(1.0, 1.0); 28 | auto loc2 = std::make_pair(0.0, 1.0); 29 | double subject = DistanceMetrics::DistEuclid(loc, loc); 30 | REQUIRE(subject == 0); 31 | subject = DistanceMetrics::DistEuclid(loc, loc2); 32 | REQUIRE(subject == 1.0); 33 | loc2.first = -1.0; 34 | subject = DistanceMetrics::DistEuclid(loc, loc2); 35 | REQUIRE(subject == 2.0); 36 | } 37 | 38 | TEST_CASE("utilities/distance_metrics: test Covidsim distance metric", "[DistanceMetrics]") 39 | { //these are all curretnly 2 which is helpful 40 | auto loc = std::make_pair(1.0, 1.0); 41 | auto loc2 = loc; 42 | loc2.first = 0.0; 43 | double subject = DistanceMetrics::DistCovidsim(loc, loc); 44 | REQUIRE(subject == 2); 45 | subject = DistanceMetrics::DistCovidsim(loc, loc2); 46 | REQUIRE(subject == 2); 47 | loc2.second = -1.0; 48 | subject = DistanceMetrics::DistCovidsim(loc, loc2); 49 | REQUIRE(subject == 2); 50 | } 51 | -------------------------------------------------------------------------------- /cEpiabm/test/utilities/test_inverse_cdf.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "utilities/inverse_cdf.hpp" 4 | 5 | #include "../catch/catch.hpp" 6 | 7 | #include 8 | 9 | using namespace epiabm; 10 | 11 | TEST_CASE("utilities/inverse_cdf: test initialize inverse cdf", "[InverseCDF]") 12 | { 13 | InverseCDF subject = InverseCDF(); 14 | REQUIRE(subject.mean() == 0); 15 | InverseCDF subject2(1.0); 16 | REQUIRE(subject2.mean() == 1.0); 17 | } 18 | 19 | TEST_CASE("utilities/inverse_cdf: test setNegLog", "[InverseCDF]") 20 | { 21 | InverseCDF subject = InverseCDF(); 22 | REQUIRE_NOTHROW(subject.setNegLog(1.0)); 23 | } 24 | 25 | TEST_CASE("utilities/inverse_cdf: test assignExponent", "[InverseCDF]") 26 | { 27 | InverseCDF subject = InverseCDF(); 28 | REQUIRE_NOTHROW(subject.assignExponent()); 29 | REQUIRE_NOTHROW(subject.assignExponent(1.0)); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /images/Histograms/Withoutsim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/Histograms/Withoutsim.png -------------------------------------------------------------------------------- /images/Histograms/Withsim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/Histograms/Withsim.png -------------------------------------------------------------------------------- /images/covidsim_schema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/covidsim_schema.png -------------------------------------------------------------------------------- /images/diagram_covid_transition.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/diagram_covid_transition.jpg -------------------------------------------------------------------------------- /images/distribution_covid_sim_rand.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/distribution_covid_sim_rand.png -------------------------------------------------------------------------------- /images/distribution_random_number.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/distribution_random_number.png -------------------------------------------------------------------------------- /images/epiabm_waning_immunity_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/epiabm_waning_immunity_diagram.png -------------------------------------------------------------------------------- /images/infectiousness_dist_gamma11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/infectiousness_dist_gamma11.png -------------------------------------------------------------------------------- /images/infectiousness_dist_gamma251.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/infectiousness_dist_gamma251.png -------------------------------------------------------------------------------- /images/infectiousness_progression/infectiousness_prog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/infectiousness_progression/infectiousness_prog.png -------------------------------------------------------------------------------- /images/infectiousness_progression/infectiousness_prog_diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/infectiousness_progression/infectiousness_prog_diff.png -------------------------------------------------------------------------------- /images/infectiousness_progression/infectiousness_prog_timestep1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/infectiousness_progression/infectiousness_prog_timestep1.png -------------------------------------------------------------------------------- /images/infectiousness_progression/infectiousness_prog_timestep2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/infectiousness_progression/infectiousness_prog_timestep2.png -------------------------------------------------------------------------------- /images/transition_times_dist/asympt_to_recov_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/asympt_to_recov_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/gp_to_dead_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/gp_to_dead_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/gp_to_hosp_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/gp_to_hosp_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/gp_to_recov_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/gp_to_recov_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/hosp_to_dead_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/hosp_to_dead_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/hosp_to_icu_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/hosp_to_icu_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/hosp_to_recov_tume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/hosp_to_recov_tume.png -------------------------------------------------------------------------------- /images/transition_times_dist/icu_to_dead_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/icu_to_dead_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/icu_to_icurecov_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/icu_to_icurecov_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/icurecov_to_recov_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/icurecov_to_recov_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/latent_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/latent_time.png -------------------------------------------------------------------------------- /images/transition_times_dist/latent_time_exp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/latent_time_exp.png -------------------------------------------------------------------------------- /images/transition_times_dist/latent_time_noexp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/latent_time_noexp.png -------------------------------------------------------------------------------- /images/transition_times_dist/mild_to_recov_time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/images/transition_times_dist/mild_to_recov_time.png -------------------------------------------------------------------------------- /pyEpiabm/docs/.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.10" 13 | 14 | # Build documentation in the docs/ directory with Sphinx 15 | sphinx: 16 | configuration: pyEpiabm/docs/source/conf.py 17 | 18 | # We recommend specifying your dependencies to enable reproducible builds: 19 | # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 20 | python: 21 | install: 22 | - requirements: pyEpiabm/requirements.txt -------------------------------------------------------------------------------- /pyEpiabm/docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /pyEpiabm/docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/core.rst: -------------------------------------------------------------------------------- 1 | **** 2 | Core 3 | **** 4 | 5 | .. currentmodule:: pyEpiabm 6 | 7 | Core provides the basic class framework to build a population 8 | 9 | Overview: 10 | 11 | - :class:`Cell` 12 | - :class:`_CompartmentCounter` 13 | - :class:`Household` 14 | - :class:`Microcell` 15 | - :class:`Parameters` 16 | - :class:`Person` 17 | - :class:`Place` 18 | - :class:`Population` 19 | 20 | 21 | .. autoclass:: Cell 22 | :members: 23 | 24 | .. autoclass:: _CompartmentCounter 25 | :members: 26 | 27 | .. autoclass:: Household 28 | :members: 29 | 30 | .. autoclass:: Microcell 31 | :members: 32 | 33 | .. autoclass:: Parameters 34 | :members: 35 | 36 | .. autoclass:: Person 37 | :members: 38 | 39 | .. autoclass:: Place 40 | :members: 41 | 42 | .. autoclass:: Population 43 | :members: 44 | 45 | 46 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. pyEpiabm documentation master file, created by 2 | sphinx-quickstart on Wed Oct 28 05:13:22 2020. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to pyEpiabm's documentation! 7 | ==================================== 8 | 9 | .. include:: ../../README.rst 10 | 11 | Contents 12 | ======== 13 | 14 | .. module:: pyEpiabm 15 | 16 | .. toctree:: 17 | core 18 | interventions 19 | outputs 20 | properties 21 | routines 22 | sweeps 23 | utility 24 | py2c 25 | 26 | 27 | Search 28 | ====== 29 | * :ref:`genindex` 30 | * :ref:`search` 31 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/interventions.rst: -------------------------------------------------------------------------------- 1 | ************* 2 | Interventions 3 | ************* 4 | 5 | .. currentmodule:: pyEpiabm.intervention 6 | 7 | Interventions provides the basic class framework to interact with different interventions 8 | 9 | Overview: 10 | 11 | - :class:`AbstractIntervention` 12 | - :class:`CaseIsolation` 13 | - :class:`DiseaseTesting` 14 | - :class:`HouseholdQuarantine` 15 | - :class:`PlaceClosure` 16 | - :class:`SocialDistancing` 17 | - :class:`Vaccination` 18 | - :class:`TravelIsolation` 19 | 20 | .. autoclass:: AbstractIntervention 21 | :members: 22 | :special-members: __init__, __call__ 23 | 24 | .. autoclass:: CaseIsolation 25 | :members: 26 | :special-members: __init__, __call__ 27 | 28 | .. autoclass:: DiseaseTesting 29 | :members: 30 | :special-members: __init__, __call__ 31 | 32 | .. autoclass:: HouseholdQuarantine 33 | :members: 34 | :special-members: __init__, __call__ 35 | 36 | .. autoclass:: PlaceClosure 37 | :members: 38 | :special-members: __init__, __call__ 39 | 40 | .. autoclass:: SocialDistancing 41 | :members: 42 | :special-members: __init__, __call__ 43 | 44 | .. autoclass:: Vaccination 45 | :members: 46 | :special-members: __init__, __call__ 47 | 48 | .. autoclass:: TravelIsolation 49 | :members: 50 | :special-members: __init__, __call__ 51 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/outputs.rst: -------------------------------------------------------------------------------- 1 | ******** 2 | Outputs 3 | ******** 4 | 5 | .. currentmodule:: pyEpiabm.output 6 | 7 | Output provides various methods to record the outputs of any simulation or methods. 8 | 9 | Overview: 10 | 11 | - :class:`AbstractReporter` 12 | - :class:`_CsvDictWriter` 13 | - :class:`_CsvWriter` 14 | - :class:`NewCasesWriter` 15 | - :class:`AgeStratifiedNewCasesWriter` 16 | 17 | .. autoclass:: AbstractReporter 18 | :members: 19 | :special-members: __init__, __call__ 20 | 21 | .. autoclass:: _CsvDictWriter 22 | :members: 23 | :special-members: __init__, __del__ 24 | 25 | .. autoclass:: _CsvWriter 26 | :members: 27 | :special-members: __init__, __del__ 28 | 29 | .. autoclass:: NewCasesWriter 30 | :members: write 31 | :special-members: __init__ 32 | 33 | .. autoclass:: AgeStratifiedNewCasesWriter 34 | :members: write 35 | :special-members: __init__ 36 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/properties.rst: -------------------------------------------------------------------------------- 1 | ********** 2 | Properties 3 | ********** 4 | 5 | .. currentmodule:: pyEpiabm.property 6 | 7 | Property provides various methods to get information from the population. 8 | 9 | It includes many infection methods for houses, places and other spatial cells, 10 | characterised by a force of infection exerted by each infected person. 11 | This includes infectiousness and susceptibility components. 12 | 13 | Infectiousness is (broadly) a function of 1 person (their age, places, 14 | number of people in their household etc). 15 | Susceptibility is (broadly) a function of 2 people (a person's susceptibility 16 | to another person / potential infector). 17 | 18 | Overview: 19 | 20 | - :class:`InfectionStatus` 21 | - :class:`PlaceType` 22 | - :class:`PersonalInfection` 23 | - :class:`HouseholdInfection` 24 | - :class:`PlaceInfection` 25 | - :class:`SpatialInfection` 26 | 27 | .. autoclass:: InfectionStatus 28 | :members: 29 | 30 | .. autoclass:: PlaceType 31 | :members: 32 | 33 | .. autoclass:: PersonalInfection 34 | :members: 35 | 36 | .. autoclass:: HouseholdInfection 37 | :members: 38 | 39 | .. autoclass:: PlaceInfection 40 | :members: 41 | 42 | .. autoclass:: SpatialInfection 43 | :members: 44 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/py2c.rst: -------------------------------------------------------------------------------- 1 | **** 2 | py2c 3 | **** 4 | 5 | .. currentmodule:: pyEpiabm.py2c 6 | 7 | py2c provides a method for converting python populations to c population for speeding up code. 8 | 9 | Overview: 10 | 11 | .. autofunction:: py2c_convert_population 12 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/routines.rst: -------------------------------------------------------------------------------- 1 | ******** 2 | Routines 3 | ******** 4 | 5 | .. currentmodule:: pyEpiabm.routine 6 | 7 | Routine provides various methods to act upon or create a population, or members of it. 8 | 9 | Overview: 10 | 11 | - :class:`AbstractPopulationFactory` 12 | - :class:`FilePopulationFactory` 13 | - :class:`ToyPopulationFactory` 14 | - :class:`Simulation` 15 | 16 | .. autoclass:: AbstractPopulationFactory 17 | :members: 18 | 19 | .. autoclass:: FilePopulationFactory 20 | :members: 21 | 22 | .. autoclass:: ToyPopulationFactory 23 | :members: 24 | 25 | .. autoclass:: Simulation 26 | :members: 27 | -------------------------------------------------------------------------------- /pyEpiabm/docs/source/utility.rst: -------------------------------------------------------------------------------- 1 | ********* 2 | Utilities 3 | ********* 4 | 5 | .. currentmodule:: pyEpiabm.utility 6 | 7 | Utility provides various methods that don't act on a population directly. 8 | 9 | Overview: 10 | 11 | - :class:`AntibodyMultiplier` 12 | - :class:`DistanceFunctions` 13 | - :class:`InverseCdf` 14 | - :class:`RandomMethods` 15 | - :class:`RateMultiplier` 16 | - :class:`SpatialKernel` 17 | 18 | .. autoclass:: AntibodyMultiplier 19 | :members: 20 | :special-members: __call__ 21 | 22 | .. autoclass:: DistanceFunctions 23 | :members: 24 | 25 | .. autoclass:: InverseCdf 26 | :members: 27 | 28 | .. autoclass:: RandomMethods 29 | :members: 30 | 31 | .. autoclass:: RateMultiplier 32 | :members: 33 | :special-members: __call__ 34 | 35 | .. autoclass:: SpatialKernel 36 | :members: 37 | 38 | .. autofunction:: log_exceptions 39 | 40 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Root of the pyEpiabm module. 3 | # Provides access to all shared functionality (classes, simulation, etc.). 4 | # 5 | 6 | """pyEpiabm is the python backend for epiabm - an Epidemiological 7 | Agent Based Modelling software package. 8 | It contains functionality for setting up a population, and tracking the 9 | evolution of a virus across it, with various visualisation methods. 10 | """ 11 | 12 | 13 | from . import core 14 | from . import output 15 | from . import property 16 | from . import routine 17 | from . import sweep 18 | from . import utility 19 | 20 | # Expose modules in core within pyEpiabm namespace 21 | 22 | from .core._compartment_counter import _CompartmentCounter 23 | from .core.cell import Cell 24 | from .core.household import Household 25 | from .core.microcell import Microcell 26 | from .core.parameters import Parameters 27 | from .core.person import Person 28 | from .core.place import Place 29 | from .core.population import Population 30 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/core/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Core subpackage of the pyEpiabm module. 3 | # 4 | 5 | """ pyEpiabm.core provides the basic class framework to build a population. 6 | 7 | """ 8 | 9 | from .parameters import Parameters 10 | from .person import Person 11 | from .cell import Cell 12 | from .household import Household 13 | from .microcell import Microcell 14 | from .place import Place 15 | from .population import Population 16 | from ._compartment_counter import _CompartmentCounter 17 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/core/parameters.py: -------------------------------------------------------------------------------- 1 | # 2 | # Parameters 3 | # 4 | 5 | import json 6 | import numpy as np 7 | 8 | 9 | class Parameters: 10 | """Class for global parameters. 11 | 12 | Following a singleton Pattern. 13 | 14 | """ 15 | class __Parameters: 16 | """Singleton Parameters Object. 17 | 18 | """ 19 | def __init__(self, config_file_path): 20 | """Detailed description of parameters is given 21 | in github wiki: 22 | https://github.com/SABS-R3-Epidemiology/epiabm/wiki 23 | 24 | """ 25 | with open(config_file_path, "r") as parameters_file: 26 | parameters_str = parameters_file.read() 27 | parameters = json.loads(parameters_str) 28 | for key, value in parameters.items(): 29 | if isinstance(value, list): 30 | value = np.array(value) 31 | setattr(self, key, value) 32 | 33 | _instance = None # Singleton instance 34 | 35 | @staticmethod 36 | def instance(): 37 | """Creates singleton instance of __Parameters under 38 | _instance if one doesn't already exist. 39 | 40 | Returns 41 | ------- 42 | __Parameters 43 | An instance of the __Parameters class 44 | 45 | """ 46 | if not Parameters._instance: 47 | raise RuntimeError("Config file hasn't been set") 48 | return Parameters._instance 49 | 50 | @staticmethod 51 | def set_file(file_path): 52 | """Loads file""" 53 | Parameters._instance = Parameters.__Parameters(file_path) 54 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/intervention/__init__.py: -------------------------------------------------------------------------------- 1 | from .abstract_intervention import AbstractIntervention 2 | from .case_isolation import CaseIsolation 3 | from .disease_testing import DiseaseTesting 4 | from .place_closure import PlaceClosure 5 | from .household_quarantine import HouseholdQuarantine 6 | from .social_distancing import SocialDistancing 7 | from .vaccination import Vaccination 8 | from .travel_isolation import TravelIsolation 9 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/intervention/abstract_intervention.py: -------------------------------------------------------------------------------- 1 | # 2 | # AbstractIntervention Class 3 | # 4 | 5 | 6 | class AbstractIntervention: 7 | """Abstract class for Interventions. 8 | Detailed description of interventions can be found in github wiki: 9 | https://github.com/SABS-R3-Epidemiology/epiabm/wiki/Interventions. 10 | """ 11 | def __init__(self, start_time, policy_duration, population, 12 | case_threshold=0, **kwargs): 13 | """Set the parameters of the interventions. 14 | 15 | Parameters 16 | ---------- 17 | start_time : float 18 | Start time of intervention 19 | policy_duration : float 20 | Duration of the intervention 21 | case_threshold : float 22 | Number of cases required to trigger the intervention 23 | population : Population 24 | Population: :class:`Population` to bind 25 | 26 | """ 27 | self.start_time = start_time 28 | self.policy_duration = policy_duration 29 | self.case_threshold = case_threshold 30 | self._population = population 31 | 32 | def is_active(self, time, num_cases): 33 | """Query if the intervention is currently active. 34 | 35 | Parameters 36 | ---------- 37 | time : float 38 | Current simulation time 39 | num_cases : int 40 | Number of cases 41 | 42 | Returns 43 | ------- 44 | bool 45 | Whether the intervention is currently active 46 | 47 | """ 48 | 49 | return ( 50 | self.start_time <= time and 51 | self.start_time + self.policy_duration >= time and 52 | self.case_threshold <= num_cases 53 | ) 54 | 55 | def __call__(self, time: float): 56 | """Run intervention. 57 | 58 | Parameters 59 | ---------- 60 | time : float 61 | Current simulation time 62 | 63 | """ 64 | raise NotImplementedError 65 | 66 | def turn_off(self): 67 | """Turn off intervention after intervention stops being active. 68 | 69 | """ 70 | raise NotImplementedError 71 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/intervention/vaccination.py: -------------------------------------------------------------------------------- 1 | # 2 | # Vaccination Class 3 | # 4 | 5 | from pyEpiabm.intervention import AbstractIntervention 6 | 7 | 8 | class Vaccination(AbstractIntervention): 9 | """Vaccination intervention to vaccinate people in the vaccination queue 10 | according to the per day national vaccination capacity. 11 | For a description of this intervention see 12 | https://github.com/SABS-R3-Epidemiology/epiabm/wiki/Interventions#vaccination 13 | 14 | """ 15 | 16 | def __init__( 17 | self, 18 | daily_doses, 19 | population, 20 | **kwargs 21 | ): 22 | """Set the parameters for vaccinations. 23 | 24 | Parameters 25 | ---------- 26 | daily_doses : int 27 | Number of vaccine doses administered per day nationwide 28 | 29 | """ 30 | self.daily_doses = daily_doses 31 | self.name = 'vaccine_params' 32 | 33 | # kwargs read in by this method are: start_time, policy_duration, 34 | # and case_threshold 35 | super(Vaccination, self).__init__(**kwargs, population=population) 36 | 37 | def __call__(self, time): 38 | """Move down the priority queue removing people and 39 | vaccinating them. 40 | 41 | Parameters 42 | ---------- 43 | time : float 44 | Current simulation time 45 | 46 | """ 47 | number_vaccinated = 0 48 | while (number_vaccinated < self.daily_doses 49 | and not self._population.vaccine_queue.empty()): 50 | person = self._population.vaccine_queue.get()[2] 51 | person.vaccinate(time) 52 | number_vaccinated += 1 53 | 54 | def turn_off(self): 55 | # empty function since, unlike non-pharmaceutical interventions, if 56 | # mass vaccination ends already vaccinated individuals remain 57 | # vaccinated. 58 | return 59 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/output/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Output subpackage of the pyEpiabm module. 3 | # 4 | 5 | """ pyEpiabm.output provides various methods to record the outputs of any 6 | simulation. 7 | 8 | """ 9 | 10 | from .abstract_reporter import AbstractReporter 11 | from ._csv_dict_writer import _CsvDictWriter 12 | from ._csv_writer import _CsvWriter 13 | from .new_cases_writer import NewCasesWriter 14 | from .age_stratified_new_cases_writer import AgeStratifiedNewCasesWriter 15 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/output/_csv_writer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Write data in a list to a csv file 3 | # 4 | 5 | import csv 6 | import typing 7 | import os 8 | 9 | from pyEpiabm.output.abstract_reporter import AbstractReporter 10 | 11 | 12 | class _CsvWriter(AbstractReporter): 13 | def __init__(self, folder: str, filename: str, fieldnames: typing.List, 14 | clear_folder: bool = False): 15 | """Initialises a file to store output in, and which categories 16 | to record. 17 | 18 | Parameters 19 | ---------- 20 | folder : str 21 | Output folder path 22 | filename : str 23 | Output file name 24 | fieldnames : typing.List 25 | List of categories to be saved 26 | clear_folder : bool 27 | Whether to empty the folder before saving results 28 | 29 | """ 30 | super().__init__(folder, clear_folder) 31 | 32 | self.f = open(os.path.join(folder, filename), 'w') 33 | self.writer = csv.writer( 34 | self.f, delimiter=',') 35 | self.writer.writerow(fieldnames) 36 | 37 | def __del__(self): 38 | """Closes the file when the simulation is finished. 39 | Required for file data to be further used. 40 | 41 | """ 42 | if self.f: 43 | self.f.close() 44 | 45 | def write(self, row: typing.List): 46 | """Writes data to file. 47 | 48 | Parameters 49 | ---------- 50 | row : typing.List 51 | List of data to be saved 52 | 53 | """ 54 | self.writer.writerow(row) 55 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/output/abstract_reporter.py: -------------------------------------------------------------------------------- 1 | # 2 | # AbstractReporter Class 3 | # 4 | 5 | import os 6 | import logging 7 | 8 | 9 | class AbstractReporter: 10 | """Abstract class for Data Reporters. 11 | """ 12 | 13 | def __init__(self, folder: str, clear_folder: bool = False): 14 | """Constructor method for reporter. Makes a new folder 15 | in specified location if one does not already exist. 16 | Also clears contents of an existing folder if 17 | clear_folder is true. 18 | 19 | Parameters 20 | ---------- 21 | folder : str 22 | Absolute path to folder to store results 23 | clear_folder : bool 24 | Whether to empty the folder before saving results 25 | 26 | """ 27 | self.folder = folder 28 | if os.path.exists(folder): 29 | if clear_folder: 30 | try: 31 | for file in os.scandir(folder): 32 | os.remove(file.path) 33 | except IsADirectoryError as e: 34 | logging.exception(f"{type(e).__name__}: cannot delete" 35 | + f" folder {folder} as it contains" 36 | + " subfolders") 37 | 38 | else: 39 | os.makedirs(folder) 40 | 41 | def write(self): 42 | """Write data to .csv files in target folder. 43 | 44 | """ 45 | raise NotImplementedError 46 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/output/age_stratified_new_cases_writer.py: -------------------------------------------------------------------------------- 1 | from pyEpiabm.output._csv_writer import _CsvWriter 2 | from pyEpiabm.core import Population 3 | 4 | 5 | class AgeStratifiedNewCasesWriter(_CsvWriter): 6 | """ Writer for collecting number of daily new cases 7 | and splitting them between age groups. 8 | 9 | """ 10 | 11 | def __init__(self, folder: str): 12 | """ Constructor method. 13 | 14 | Parameters 15 | ---------- 16 | folder : str 17 | Absolute path to folder to store results 18 | """ 19 | super().__init__( 20 | folder, 'age_stratified_new_cases.csv', 21 | ['t', 'cell', 'age_group', 'new_cases'], False) 22 | 23 | def write(self, t: float, population: Population): 24 | """ Write method - write daily new cases split 25 | by age group in population to file. 26 | 27 | Parameters 28 | ---------- 29 | t : float 30 | Current simulation time 31 | population : Population 32 | Population to record 33 | """ 34 | for cell in population.cells: 35 | new_cases = {} 36 | for person in cell.persons: 37 | if (person.infection_start_times != [] 38 | and person.infection_start_times[-1] > (t-1)): 39 | if person.age_group in new_cases: 40 | new_cases[person.age_group] += 1 41 | else: 42 | new_cases[person.age_group] = 1 43 | for age_group, cases in new_cases.items(): 44 | super().write([t, cell.id, age_group, cases]) 45 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/output/new_cases_writer.py: -------------------------------------------------------------------------------- 1 | from pyEpiabm.output._csv_writer import _CsvWriter 2 | from pyEpiabm.core import Population 3 | 4 | 5 | class NewCasesWriter(_CsvWriter): 6 | """ Writer for collecting number of daily new cases 7 | """ 8 | 9 | def __init__(self, folder: str): 10 | """ Constructor method 11 | 12 | Parameters 13 | ---------- 14 | folder : str 15 | Absolute path to folder to store results 16 | """ 17 | super().__init__( 18 | folder, 'new_cases.csv', 19 | ['t', 'cell', 'new_cases'], False) 20 | 21 | def write(self, t: float, population: Population): 22 | """ Write method 23 | Write daily new cases from population to file 24 | 25 | Parameters 26 | ---------- 27 | t : float 28 | Current simulation time 29 | population : Population 30 | Population to record 31 | """ 32 | for cell in population.cells: 33 | new_cases = 0 34 | for person in cell.persons: 35 | if person.infection_start_times != [] and \ 36 | person.infection_start_times[-1] > (t-1): 37 | new_cases += 1 38 | super().write([t, cell.id, new_cases]) 39 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/property/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Property subpackage of the pyEpiabm module. 3 | # 4 | 5 | """ pyEpiabm.property provides various methods to get 6 | information from the population. 7 | 8 | It includes many infection methods for houses, places and other spatial cells, 9 | characterised by a force of infection exerted by each infected person. 10 | This includes infectiousness and susceptibility components. 11 | 12 | Infectiousness is (broadly) a function of 1 person (their age, places, 13 | number of people in their household etc). 14 | Susceptibility is (broadly) a function of 2 people (a person's susceptibility 15 | to another person / potential infector). 16 | 17 | """ 18 | 19 | from .infection_status import InfectionStatus 20 | from .place_type import PlaceType 21 | from .personal_foi import PersonalInfection 22 | from .household_foi import HouseholdInfection 23 | from .place_foi import PlaceInfection 24 | from .spatial_foi import SpatialInfection 25 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/property/infection_status.py: -------------------------------------------------------------------------------- 1 | # 2 | # Infection status Class 3 | # 4 | 5 | from enum import Enum 6 | 7 | 8 | class InfectionStatus(Enum): 9 | """Enum representing a person's current infection status. 10 | 11 | """ 12 | Susceptible = 1 13 | Exposed = 2 14 | InfectASympt = 3 15 | InfectMild = 4 16 | InfectGP = 5 17 | InfectHosp = 6 18 | InfectICU = 7 19 | InfectICURecov = 8 20 | Recovered = 9 21 | Dead = 10 22 | Vaccinated = 11 23 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/property/place_type.py: -------------------------------------------------------------------------------- 1 | # 2 | # Place type Class 3 | # 4 | 5 | from enum import Enum 6 | 7 | 8 | class PlaceType(Enum): 9 | """Enum representing a place's type. 10 | 11 | """ 12 | PrimarySchool = 1 13 | SecondarySchool = 2 14 | SixthForm = 3 15 | Workplace = 4 # multiple groups represent different groups within the 16 | # company, all remain unchanged. 17 | CareHome = 5 # two groups, workers [0] and residents [1], both remain 18 | # unchanged, but interact differently. 19 | OutdoorSpace = 6 # one group, updated each timestep 20 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/py2c/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Py2C subpackage of the pyEpiabm module. 3 | # 4 | 5 | """ pyEpiabm.py2c provides methods used to convert python 6 | classes to C, for use in speeding up simulations 7 | """ 8 | 9 | 10 | from .py2c_population import py2c_convert_population 11 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/routine/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Routine subpackage of the pyEpiabm module. 3 | # 4 | 5 | """ pyEpiabm.routine provides various methods to act upon or 6 | create a population. 7 | 8 | """ 9 | 10 | from .abstract_population_config import AbstractPopulationFactory 11 | from .file_population_config import FilePopulationFactory 12 | from .simulation import Simulation 13 | from .toy_population_config import ToyPopulationFactory 14 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/routine/abstract_population_config.py: -------------------------------------------------------------------------------- 1 | # 2 | # Abstract factory for creation of any population 3 | # 4 | 5 | 6 | class AbstractPopulationFactory: 7 | """ Abstract class for population creation. 8 | 9 | """ 10 | @staticmethod 11 | def make_pop(): 12 | raise NotImplementedError 13 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/sweep/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Routine subpackage of the pyEpiabm module. 3 | # 4 | 5 | """ pyEpiabm.sweep provides methods which sweep over the population. 6 | 7 | """ 8 | 9 | from .abstract_sweep import AbstractSweep 10 | from .initial_demographics_sweep import InitialDemographicsSweep 11 | from .host_progression_sweep import HostProgressionSweep 12 | from .household_sweep import HouseholdSweep 13 | from .initial_household_sweep import InitialHouseholdSweep 14 | from .initial_infected_sweep import InitialInfectedSweep 15 | from .place_sweep import PlaceSweep 16 | from .initial_place_sweep import InitialisePlaceSweep 17 | from .queue_sweep import QueueSweep 18 | from .spatial_sweep import SpatialSweep 19 | from .update_place_sweep import UpdatePlaceSweep 20 | from .intervention_sweep import InterventionSweep 21 | from .travel_sweep import TravelSweep 22 | from .transition_matrices import StateTransitionMatrix, TransitionTimeMatrix 23 | from .initial_vaccine_sweep import InitialVaccineQueue 24 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/sweep/abstract_sweep.py: -------------------------------------------------------------------------------- 1 | # 2 | # AbstractSweep Class 3 | # 4 | 5 | from pyEpiabm.core import Population 6 | 7 | 8 | class AbstractSweep: 9 | """Abstract class for Population Sweeps. 10 | 11 | """ 12 | def bind_population(self, population: Population): 13 | """Set the population which the sweep will act on. 14 | 15 | Parameters 16 | ---------- 17 | population : Population 18 | Population: :class:`Population` to bind 19 | 20 | """ 21 | # Possibly add check to see if self._population has already been set 22 | self._population = population 23 | 24 | def __call__(self, time: float): 25 | """Run sweep over population. 26 | 27 | Parameters 28 | ---------- 29 | time : float 30 | Current simulation time 31 | 32 | """ 33 | raise NotImplementedError 34 | 35 | @staticmethod 36 | def store_infection_periods(infector, infectee, time): 37 | """Sets the exposure_period of the infectee (defined as the time 38 | between the infector having status I and the infectee having status 39 | E. Also sets stores the infector's latent period within the infectee 40 | (to be used in calculating the generation time). This is called during 41 | the daily sweeps. 42 | 43 | Parameters 44 | ---------- 45 | infector : Person 46 | Current primary case 47 | infectee : Person 48 | Current secondary case 49 | time : float 50 | Current simulation time 51 | """ 52 | inf_to_exposed = (time - 53 | infector.infection_start_times[-1]) 54 | infectee.set_exposure_period(inf_to_exposed) 55 | infectee.set_infector_latent_period(infector.latent_period) 56 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/sweep/queue_sweep.py: -------------------------------------------------------------------------------- 1 | # 2 | # Sweeps for enqueued persons to update infection status 3 | # 4 | import random 5 | import numpy as np 6 | 7 | from pyEpiabm.core import Parameters 8 | from pyEpiabm.property import InfectionStatus 9 | 10 | from .abstract_sweep import AbstractSweep 11 | 12 | 13 | class QueueSweep(AbstractSweep): 14 | """Class to sweep through the enqueued persons 15 | in each cell and update their infection status. 16 | 17 | """ 18 | 19 | def __call__(self, time: float): 20 | """Function to run through the queue of people to be exposed. 21 | 22 | Parameters 23 | ---------- 24 | time : float 25 | Simulation time 26 | 27 | """ 28 | for cell in self._population.cells: 29 | while not cell.person_queue.empty(): 30 | person = cell.person_queue.get() 31 | # Get takes person from the queue and removes them, so clears 32 | # the queue for the next timestep. 33 | # Update the infection status 34 | if person.is_vaccinated: 35 | vacc_params = Parameters.instance().\ 36 | intervention_params['vaccine_params'] 37 | delay = np.random.poisson(vacc_params['time_to_efficacy'], 38 | 1) 39 | if time > (person.date_vaccinated + 40 | delay): 41 | r = random.random() 42 | if r < vacc_params['vacc_protectiveness']: 43 | person.next_infection_status = InfectionStatus.\ 44 | Vaccinated 45 | else: 46 | person.next_infection_status = InfectionStatus.\ 47 | Exposed 48 | else: 49 | person.next_infection_status = InfectionStatus.Exposed 50 | else: 51 | person.next_infection_status = InfectionStatus.Exposed 52 | 53 | person.time_of_status_change = time 54 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Test module for pyEpiabm 3 | # 4 | # To run all tests, run ``python -m unittest discover`` from pyEpiabm*. 5 | # (or `python3` instead of `python` depending on your Python installation) 6 | # To run a particular test, use e.g. 7 | # ``python -m unittest pyEpiabm.tests.test_population``. 8 | # 9 | # These commands should both be run from epiabm/pyEpiabm 10 | # 11 | # Alternatively, use the run_tests.py methods for unit tests with coverage: 12 | # `coverage run pyEpiabm/run_tests.py --unit` (from the epiabm/ directory) 13 | # Report coverage with `coverage report -m`, or build html with `coverage html` 14 | # 15 | 16 | from .test_func import TestFunctional 17 | from .test_unit import TestMockedLogs, TestPyEpiabm 18 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_func/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Functional and Integration test subpackage for the pyEpiabm module 3 | # 4 | 5 | from .functional_testing_class import TestFunctional 6 | from .helper_func import HelperFunc 7 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_func/spatial_input.csv: -------------------------------------------------------------------------------- 1 | cell,microcell,location_x,location_y,household_number,place_number,Susceptible,InfectMild 2 | 1, 1, 0.1, 0.9, 3, 1, 22, 0 3 | 1, 2, 0.1, 0.9, 2, 0, 31, 0 4 | 2, 1, 0.6, 0.2, 1, 2, 14, 0 5 | 2, 2, 0.6, 0.2, 2, 1, 8, 0 6 | 3, 1, 0.8, 0.7, 3, 0, 27, 0 7 | 3, 2, 0.8, 0.7, 2, 1, 33, 5 8 | 4, 1, 0.3, 0.4, 5, 3, 18, 0 9 | 4, 2, 0.3, 0.4, 4, 0, 25, 3 10 | 11 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Unit test subpackage for the pyEpiabm module 3 | # 4 | 5 | from .mocked_logging_tests import TestMockedLogs 6 | from .parameter_config_tests import TestPyEpiabm 7 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/mocked_logging_tests.py: -------------------------------------------------------------------------------- 1 | # 2 | # Custom testing class to patching logging 3 | # 4 | 5 | from unittest.mock import patch 6 | 7 | from .parameter_config_tests import TestPyEpiabm 8 | 9 | 10 | class TestMockedLogs(TestPyEpiabm): 11 | """Inherits from the custom testing function, which is 12 | the unittest.TestCase class with a parameters file bolted 13 | on, but with mocked logging functions to prevent printing 14 | 15 | """ 16 | @classmethod 17 | def setUpClass(cls): 18 | """Inherits from the unittest setup, and patches the warning 19 | and error logging classes, that otherwise print to terminal 20 | """ 21 | super(TestMockedLogs, cls).setUpClass() 22 | cls.warning_patcher = patch('logging.warning') 23 | cls.error_patcher = patch('logging.error') 24 | 25 | cls.warning_patcher.start() 26 | cls.error_patcher.start() 27 | 28 | @classmethod 29 | def tearDownClass(cls): 30 | """Inherits from the unittest teardown, and remove all patches""" 31 | super(TestMockedLogs, cls).tearDownClass() 32 | cls.warning_patcher.stop() 33 | cls.error_patcher.stop() 34 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/parameter_config_tests.py: -------------------------------------------------------------------------------- 1 | # 2 | # Custom testing class to import parameters 3 | # 4 | 5 | import unittest 6 | import os 7 | 8 | import pyEpiabm as pe 9 | 10 | 11 | class TestPyEpiabm(unittest.TestCase): 12 | """Inherits from the default unittest class, but 13 | also sets up parameters config file for use in testing""" 14 | @classmethod 15 | def setUpClass(cls): 16 | """Inherits from the unittest setup, and patches the warning 17 | and error logging classes, that otherwise print to terminal 18 | """ 19 | super(TestPyEpiabm, cls).setUpClass() 20 | filepath = os.path.join(os.path.dirname(__file__), 21 | os.pardir, 'testing_parameters.json') 22 | pe.Parameters.set_file(filepath) 23 | 24 | @classmethod 25 | def tearDownClass(cls): 26 | super(TestPyEpiabm, cls).tearDownClass() 27 | if pe.Parameters._instance: 28 | pe.Parameters._instance = None 29 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_core/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.core 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_core/test_population.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import pyEpiabm as pe 4 | from pyEpiabm.tests.test_unit.mocked_logging_tests import TestMockedLogs 5 | 6 | 7 | class TestPopulation(TestMockedLogs): 8 | """Test the 'Population' class. 9 | """ 10 | @classmethod 11 | def setUpClass(cls) -> None: 12 | super(TestPopulation, cls).setUpClass() # Sets up patch on logging 13 | cls.population = pe.Population() 14 | 15 | def test__init__(self): 16 | self.assertEqual(self.population.cells, []) 17 | 18 | def test_repr(self): 19 | self.assertEqual(repr(self.population), 20 | "Population with 0 cells.") 21 | 22 | def test_add_cells(self, n=4, m=3): 23 | population = pe.Population() 24 | self.assertEqual(len(population.cells), 0) 25 | 26 | population.add_cells(n) 27 | self.assertEqual(len(population.cells), n) 28 | self.assertEqual(population.cells[-1].id, str(n-1)) 29 | 30 | population.add_cells(m) 31 | self.assertEqual(len(population.cells), n+m) 32 | self.assertEqual(population.cells[-1].id, str(n+m-1)) 33 | 34 | # Check all cell IDs are unique 35 | cell_ids = [cell.id for cell in population.cells] 36 | self.assertEqual(len(cell_ids), len(set(cell_ids))) 37 | 38 | def test_total_people(self): 39 | self.assertEqual(self.population.total_people(), 0) 40 | 41 | 42 | if __name__ == '__main__': 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_intervention/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.intervention 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_intervention/test_abstract_intervention.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import pyEpiabm as pe 4 | from pyEpiabm.intervention import AbstractIntervention 5 | 6 | 7 | class TestAbstractIntervention(unittest.TestCase): 8 | """Test the 'AbstractIntervention' class. 9 | """ 10 | 11 | @classmethod 12 | def setUpClass(cls) -> None: 13 | super(TestAbstractIntervention, cls).setUpClass() 14 | 15 | cls.population = pe.Population() 16 | cls.intervention_object = AbstractIntervention( 17 | start_time=1, 18 | policy_duration=10, 19 | case_threshold=20, 20 | population=cls.population) 21 | 22 | def test_construct(self): 23 | self.assertEqual(self.intervention_object.start_time, 1) 24 | self.assertEqual(self.intervention_object.policy_duration, 10) 25 | self.assertEqual(self.intervention_object.case_threshold, 20) 26 | self.assertEqual(self.intervention_object._population, 27 | self.population) 28 | 29 | def test_is_active(self): 30 | self.assertTrue(self.intervention_object.is_active(time=5, 31 | num_cases=50)) 32 | self.assertFalse(self.intervention_object.is_active(time=5, 33 | num_cases=5)) 34 | self.assertFalse(self.intervention_object.is_active(time=0, 35 | num_cases=50)) 36 | 37 | def test___call__(self): 38 | self.assertRaises(NotImplementedError, 39 | self.intervention_object.__call__, 1) 40 | 41 | def test_turn_off(self): 42 | self.assertRaises(NotImplementedError, 43 | self.intervention_object.turn_off) 44 | 45 | 46 | if __name__ == '__main__': 47 | unittest.main() 48 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_output/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.output 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_output/test_csv_writer.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import patch, mock_open, call, MagicMock 3 | import os 4 | 5 | import pyEpiabm as pe 6 | 7 | 8 | class TestCsvWriter(unittest.TestCase): 9 | """Test the methods of the '_CsvWriter' class. 10 | """ 11 | 12 | @patch('os.makedirs') 13 | def test_init(self, mock_mkdir): 14 | """Test the constructor method of the _CsvWriter class. 15 | """ 16 | mo = mock_open() 17 | with patch('pyEpiabm.output._csv_writer.open', mo): 18 | mock_content = ['1', '2', '3'] 19 | m = pe.output._CsvWriter('mock_folder', 'mock_filename', 20 | mock_content) 21 | del m 22 | mo.assert_called_once_with( 23 | os.path.join('mock_folder', 'mock_filename'), 'w') 24 | mo().write.assert_called_once_with('1,2,3\r\n') 25 | mock_mkdir.assert_called_with('mock_folder') 26 | 27 | @patch('os.makedirs') 28 | def test_write(self, mock_mkdir): 29 | """Test the write method of the _CsvWriter class. 30 | """ 31 | mo = mock_open() 32 | with patch('pyEpiabm.output._csv_writer.open', mo): 33 | mock_content = ['1', '2', '3'] 34 | new_content = ['a', 'b', 'c'] 35 | m = pe.output._CsvWriter('mock_folder', 'mock_filename', 36 | mock_content) 37 | m.write(new_content) 38 | mo().write.assert_has_calls([call('1,2,3\r\n'), call('a,b,c\r\n')]) 39 | 40 | @patch('os.makedirs') 41 | def test_del(self, mock_mkdir): 42 | """Test the destructor method of the _CsvWriter class. 43 | """ 44 | fake_file = MagicMock() 45 | with patch("builtins.open", return_value=fake_file, create=True): 46 | mock_content = ['1', '2', '3'] 47 | m = pe.output._CsvWriter('mock_folder', 'mock_filename', 48 | mock_content) 49 | m.__del__() 50 | fake_file.close.assert_called_once() 51 | 52 | 53 | if __name__ == '__main__': 54 | unittest.main() 55 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_property/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.property 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_property/test_infection_status.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from pyEpiabm.property import InfectionStatus 4 | 5 | 6 | class TestInfectionStatus(unittest.TestCase): 7 | """Test the 'InfectionStatus' enum. 8 | """ 9 | 10 | def test_construct(self): 11 | statuses = [ # noqa 12 | InfectionStatus.Susceptible, 13 | InfectionStatus.Exposed, 14 | InfectionStatus.InfectASympt, 15 | InfectionStatus.InfectMild, 16 | InfectionStatus.InfectGP, 17 | InfectionStatus.InfectHosp, 18 | InfectionStatus.InfectICU, 19 | InfectionStatus.InfectICURecov, 20 | InfectionStatus.Recovered, 21 | InfectionStatus.Dead] 22 | 23 | 24 | if __name__ == '__main__': 25 | unittest.main() 26 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_property/test_place_type.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import pyEpiabm as pe 4 | 5 | 6 | class TestPLaceType(unittest.TestCase): 7 | """Test the 'PlaceType' enum. 8 | """ 9 | 10 | def test_construct(self): 11 | statuses = [ # noqa 12 | pe.property.PlaceType.Workplace, 13 | pe.property.PlaceType.CareHome, 14 | pe.property.PlaceType.SecondarySchool, 15 | pe.property.PlaceType.OutdoorSpace] 16 | 17 | 18 | if __name__ == '__main__': 19 | unittest.main() 20 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_py2c/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.py2c 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_py2c/test_timer.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest import mock 3 | 4 | from pyEpiabm.py2c.py2c_population import _Timer 5 | from pyEpiabm.tests.test_unit.parameter_config_tests import TestPyEpiabm 6 | 7 | 8 | class TestTimer(TestPyEpiabm): 9 | """Test the 'Timer' class. 10 | """ 11 | 12 | @mock.patch('builtins.print') 13 | def test__init__(self, _): 14 | named_timer = _Timer('my_name') 15 | self.assertEqual(named_timer.name, 'my_name') 16 | 17 | @mock.patch('builtins.print') 18 | def test__del__(self, mock_print): 19 | timer = _Timer('timer') 20 | del timer 21 | mock_print.assert_called_once() 22 | args, _ = mock_print.call_args_list[0] 23 | re_scientific_notation = r"(?:0|[1-9]\d*)(?:\.\d+)?(?:[e][+\-]?\d+)?" 24 | self.assertRegex(args[0], f"timer took {re_scientific_notation}s") 25 | 26 | 27 | if __name__ == '__main__': 28 | unittest.main() 29 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_routine/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.routine 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_routine/test_abstract_population_config.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from pyEpiabm.routine import AbstractPopulationFactory 4 | 5 | 6 | class TestPopConfig(unittest.TestCase): 7 | """Test the 'ToyPopConfig' class. 8 | """ 9 | def test_make_pop(self): 10 | """Tests for a make population method. 11 | """ 12 | with self.assertRaises(NotImplementedError): 13 | AbstractPopulationFactory.make_pop() 14 | 15 | 16 | if __name__ == '__main__': 17 | unittest.main() 18 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_sweep/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.sweep 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_sweep/test_abstract_sweep.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import pyEpiabm as pe 4 | from pyEpiabm.tests.test_unit.parameter_config_tests import TestPyEpiabm 5 | 6 | 7 | class TestAbstractSweep(TestPyEpiabm): 8 | """Test the 'AbstractSweep' class. 9 | """ 10 | 11 | def test_construct(self): 12 | pe.sweep.AbstractSweep() 13 | 14 | def test_bind_population(self): 15 | subject = pe.sweep.AbstractSweep() 16 | population = pe.Population() 17 | subject.bind_population(population) 18 | 19 | def test___call__(self): 20 | subject = pe.sweep.AbstractSweep() 21 | self.assertRaises(NotImplementedError, subject.__call__, 1) 22 | 23 | def test_store_infection_periods(self): 24 | pop = pe.Population() 25 | pop.add_cells(1) 26 | cell = pop.cells[0] 27 | microcell = pe.Microcell(cell) 28 | infector = pe.Person(microcell) 29 | infectee = pe.Person(microcell) 30 | time = 15.0 31 | infector.infection_start_times = [4.0, 10.0] 32 | infector.set_latent_period(3.0) 33 | pe.sweep.AbstractSweep.store_infection_periods(infector, infectee, 34 | time) 35 | self.assertEqual(infectee.exposure_period, 5.0) 36 | self.assertEqual(infectee.infector_latent_period, 3.0) 37 | 38 | 39 | if __name__ == '__main__': 40 | unittest.main() 41 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_utility/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Tests for subpackage pyEpiabm.utility 3 | # 4 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_utility/test_covidsim_kernel.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | from parameterized import parameterized 4 | 5 | from pyEpiabm.utility import SpatialKernel 6 | 7 | numReps = 5 8 | 9 | 10 | class TestSpatialKernel(unittest.TestCase): 11 | """Test the 'SpatialKernel' class. 12 | """ 13 | @parameterized.expand([(np.random.rand(1) * numReps,) 14 | for _ in range(numReps)]) 15 | def test_kernel(self, dist): 16 | value = SpatialKernel.weighting(dist) 17 | self.assertTrue(0 <= value) 18 | 19 | @parameterized.expand([(np.random.rand(3) * numReps,) 20 | for _ in range(numReps)]) 21 | def test_kernel_shape_size(self, dist): 22 | value = SpatialKernel.weighting(dist[0], dist[1], dist[2]) 23 | self.assertTrue(0 <= value) 24 | 25 | def test_asserts(self): 26 | example = SpatialKernel.weighting(10, 10, 2) 27 | self.assertAlmostEqual(example, 0.25) 28 | example_small = SpatialKernel.weighting(1, 10, 2) 29 | # Assert smaller distance has larger kernel 30 | self.assertTrue(example < example_small) 31 | self.assertRaises(AssertionError, SpatialKernel.weighting, 10, -3, 2) 32 | self.assertRaises(AssertionError, SpatialKernel.weighting, 10, 2, -2) 33 | 34 | 35 | if __name__ == '__main__': 36 | unittest.main() 37 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_utility/test_exception_logger.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from unittest.mock import patch 3 | 4 | from pyEpiabm.utility import log_exceptions 5 | 6 | 7 | class ExampleClass: 8 | """Used to test the logger""" 9 | @log_exceptions() 10 | def sum_method(self, x, y): 11 | return x + y 12 | 13 | @log_exceptions(' - Fatal error in method') 14 | def annotated_method(self, x): 15 | x = 1/0 16 | return x 17 | 18 | 19 | class TestDistanceFunctions(unittest.TestCase): 20 | """Test the 'DistanceFunctions' class. 21 | """ 22 | @patch('logging.exception') 23 | def test_logger_no_return(self, mock_log): 24 | a = ExampleClass() 25 | a.sum_method(1, 'a') 26 | mock_log.assert_called_once_with("TypeError in" 27 | + " ExampleClass.sum_method()") 28 | 29 | def test_logger_return(self): 30 | """Ensure decorator allows value return""" 31 | a = ExampleClass() 32 | result = a.sum_method(1, 4) 33 | self.assertEqual(result, 5) 34 | 35 | @patch('logging.exception') 36 | def test_logger_annotated(self, mock_log): 37 | a = ExampleClass() 38 | a.annotated_method(1) 39 | mock_log.assert_called_once_with("ZeroDivisionError in" 40 | + " ExampleClass.annotated_method()" 41 | + " - Fatal error in method") 42 | 43 | 44 | if __name__ == '__main__': 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/tests/test_unit/test_utility/test_inverse_cdf.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import numpy as np 3 | from parameterized import parameterized 4 | 5 | from pyEpiabm.utility import InverseCdf 6 | from pyEpiabm.tests.test_unit.parameter_config_tests import TestPyEpiabm 7 | 8 | numReps = 1 9 | 10 | 11 | class TestInverseCdf(TestPyEpiabm): 12 | """Test the 'InverseCDF' class. 13 | """ 14 | def test_construct(self): 15 | mean = 5 16 | icdf_array = np.ones(21) 17 | icdf_object = InverseCdf(mean, icdf_array) 18 | self.assertEqual(icdf_object.mean, 5) 19 | self.assertEqual(icdf_object.icdf_array.all(), np.ones(21).all()) 20 | 21 | @parameterized.expand([(np.random.rand(21) * numReps,) 22 | for _ in range(numReps)]) 23 | def test_choose_noexp(self, icdf): 24 | icdf = np.sort(icdf) 25 | icdf = 10 * icdf 26 | icdf_object = InverseCdf(3, icdf) 27 | value = icdf_object.icdf_choose_noexp() 28 | self.assertTrue(0 < value) 29 | 30 | @parameterized.expand([(np.random.rand(21) * numReps,) 31 | for _ in range(numReps)]) 32 | def test_choose_exp(self, icdf): 33 | icdf = np.sort(icdf) 34 | icdf = 10 * icdf 35 | icdf_object = InverseCdf(3, icdf) 36 | value = icdf_object.icdf_choose_exp() 37 | self.assertTrue(0 <= value) 38 | 39 | 40 | if __name__ == '__main__': 41 | unittest.main() 42 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/utility/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Utility subpackage of the pyEpiabm module. 3 | # 4 | 5 | """ pyEpiabm.utility provides methods used to calculate infection 6 | and host progression parameters, and other calculations and 7 | algorithms that are called throughout pyEpiabm. 8 | """ 9 | 10 | from .distance_metrics import DistanceFunctions 11 | from .covidsim_kernel import SpatialKernel 12 | from .random_methods import RandomMethods 13 | from .inverse_cdf import InverseCdf 14 | from .exception_logger import log_exceptions 15 | from .rate_multiplier import RateMultiplier 16 | from .antibody_multiplier import AntibodyMultiplier 17 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/utility/covidsim_kernel.py: -------------------------------------------------------------------------------- 1 | # 2 | # Class of Covidsim-style gravity kernels 3 | # 4 | 5 | 6 | class SpatialKernel: 7 | """Class to create the gravity kernel used throughout 8 | CovidSim in the spatial weighting. 9 | """ 10 | @staticmethod 11 | def weighting(distance: float, scale: float = 1, shape: float = 1.0): 12 | r"""Returns the weighting given by the Covidsim distance 13 | weighting. 14 | The formula is given by 15 | 16 | .. math:: 17 | \frac{1}{(1+\frac{\text{distance}}{\text{scale}})^\text{shape}} 18 | 19 | and is further detailed in the wiki: 20 | https://github.com/SABS-R3-Epidemiology/epiabm/wiki/Comparison-to-Ferguson-Model 21 | 22 | Parameters 23 | ---------- 24 | distance : float 25 | Distance input as the main argument 26 | scale : float 27 | Parameter to scale the kernel function 28 | shape : float 29 | Parameter to change the shape of the kernel function 30 | 31 | Returns 32 | ------- 33 | weight : float 34 | Float of the weight function 35 | 36 | """ 37 | assert (scale > 0), "Spatial kernel scale must be positive." 38 | assert (shape > 0), "Spatial kernel shape must be positive." 39 | return 1 / (1 + distance / scale) ** shape 40 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/utility/exception_logger.py: -------------------------------------------------------------------------------- 1 | # 2 | # Decorator to log exceptions in function 3 | # 4 | 5 | import logging 6 | from functools import wraps 7 | 8 | 9 | def log_exceptions(message: str = ""): 10 | """Provides a try/except clause around the function it is applied to. 11 | Logs the type of error, and name of the function, if an error occurs, 12 | with an optional message appended on the end. 13 | 14 | Parameters 15 | ---------- 16 | message : str 17 | Optional message to append to default log text 18 | 19 | """ 20 | def decorator(func): 21 | @wraps(func) 22 | def wrapper(*args, **kwargs): 23 | try: 24 | return func(*args, **kwargs) 25 | except Exception as e: 26 | logging.exception(f"{type(e).__name__} in " 27 | + f"{func.__qualname__}()" + message) 28 | return wrapper 29 | return decorator 30 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/utility/random_methods.py: -------------------------------------------------------------------------------- 1 | # 2 | # Generate random number, as is done in Covidsim code 3 | # 4 | 5 | 6 | class RandomMethods: 7 | """Class to calculate methods in a style similar to CovidSim. 8 | 9 | """ 10 | def __init__(self): 11 | """s1 and s2 are integers in the range [1, 21474835621]. CovidSim 12 | initialises these using 32-bit integer memory location information. 13 | We just choose random integers by hand instead. See the wiki for 14 | more info on this and the following random algorithm. 15 | 16 | """ 17 | self.prev_s1 = 163858 18 | self.prev_s2 = 6573920043 19 | 20 | def covid_sim_rand(self): 21 | """Reproduction of the ranf_mt method in the Rand.cpp from CovidSim. 22 | In covid-sim, they would use the thread number to generate the output. 23 | 24 | Returns 25 | ------- 26 | float 27 | Returns random number between 0 and 1 28 | 29 | """ 30 | # Set parameters: 31 | Xm1 = 2147483563 32 | Xm2 = 2147483399 33 | Xa1 = 40014 34 | Xa2 = 40692 35 | # Parameters that would vary on thread number in covid-sim: 36 | s1 = self.prev_s1 37 | s2 = self.prev_s2 38 | # Coming up with the randomness: 39 | k = s1 // 53668 40 | s1 = Xa1 * (s1 - k * 53668) - k * 12211 41 | if (s1 < 0): 42 | s1 += Xm1 43 | k = s2 // 52774 44 | s2 = Xa2 * (s2 - k * 52774) - k * 3791 45 | if (s2 < 0): 46 | s2 += Xm2 47 | self.prev_s1 = s1 48 | self.prev_s2 = s2 49 | z = s1 - s2 50 | if (z < 1): 51 | z += (Xm1 - 1) 52 | return z/Xm1 53 | -------------------------------------------------------------------------------- /pyEpiabm/pyEpiabm/version_info.py: -------------------------------------------------------------------------------- 1 | # 2 | # Version information for pyEpiabm 3 | # 4 | # Version as a tuple (major, minor, revision) 5 | # - Changes to major are rare 6 | # - Changes to minor indicate new features, possible slight backwards 7 | # incompatibility 8 | # - Changes to revision indicate bugfixes, tiny new features 9 | VERSION_INT = 1, 1, 0 10 | 11 | # String version of the version number 12 | VERSION = '.'.join([str(x) for x in VERSION_INT]) 13 | -------------------------------------------------------------------------------- /pyEpiabm/requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib 2 | numpy>=1.8 3 | packaging 4 | parameterized 5 | pandas 6 | pandas>=1.4;python_version>="3.8" 7 | tqdm 8 | -------------------------------------------------------------------------------- /python_examples/age_stratified_example/simulation_outputs/age_stratify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/age_stratified_example/simulation_outputs/age_stratify.png -------------------------------------------------------------------------------- /python_examples/age_stratified_example/simulation_outputs/simulation_flow_SIR_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/age_stratified_example/simulation_outputs/simulation_flow_SIR_plot.png -------------------------------------------------------------------------------- /python_examples/antibody_igG_test/IgG_validation_graphs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/antibody_igG_test/IgG_validation_graphs.png -------------------------------------------------------------------------------- /python_examples/antibody_igG_test/Lumley_paper_igG_levels_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/antibody_igG_test/Lumley_paper_igG_levels_graph.png -------------------------------------------------------------------------------- /python_examples/basic_infection_history_simulation/simulation_outputs/demographics.csv: -------------------------------------------------------------------------------- 1 | id,kw_or_chr 2 | 0.0.0.0,X 3 | 0.0.0.1,X 4 | 0.0.0.2,X 5 | 0.0.0.3,X 6 | 0.0.0.4,X 7 | 0.0.1.0,X 8 | 0.0.1.1,X 9 | 0.0.1.2,X 10 | 0.0.2.0,X 11 | 0.0.2.1,X 12 | 0.0.2.2,X 13 | 0.0.3.0,X 14 | 0.0.3.1,X 15 | 0.0.3.2,X 16 | 0.0.3.3,X 17 | 0.0.4.0,X 18 | 0.0.4.1,X 19 | 0.0.4.2,X 20 | 0.0.4.3,X 21 | 0.0.4.4,X 22 | 0.0.4.5,X 23 | 0.0.4.6,X 24 | 0.0.4.7,X 25 | 0.0.4.8,X 26 | 0.1.0.0,X 27 | 0.1.0.1,X 28 | 0.1.0.2,X 29 | 0.1.0.3,X 30 | 0.1.0.4,X 31 | 0.1.0.5,X 32 | 0.1.0.6,X 33 | 0.1.0.7,X 34 | 0.1.0.8,X 35 | 0.1.1.0,X 36 | 0.1.1.1,X 37 | 0.1.1.2,X 38 | 0.1.1.3,X 39 | 0.1.1.4,X 40 | 0.1.1.5,X 41 | 0.1.2.0,X 42 | 0.1.2.1,X 43 | 0.1.2.2,X 44 | 0.1.2.3,X 45 | 0.1.2.4,X 46 | 0.1.2.5,X 47 | 0.1.2.6,X 48 | 0.1.3.0,X 49 | 0.1.3.1,X 50 | 0.1.4.0,X 51 | 0.1.4.1,X 52 | 0.1.4.2,X 53 | 0.1.4.3,X 54 | 0.1.4.4,X 55 | 0.1.4.5,X 56 | 0.1.4.6,X 57 | 0.1.4.7,X 58 | 1.0.0.0,X 59 | 1.0.0.1,X 60 | 1.0.0.2,X 61 | 1.0.0.3,X 62 | 1.0.0.4,X 63 | 1.0.0.5,X 64 | 1.0.0.6,X 65 | 1.0.0.7,X 66 | 1.0.0.8,X 67 | 1.0.1.0,X 68 | 1.0.1.1,X 69 | 1.0.1.2,X 70 | 1.0.1.3,X 71 | 1.0.1.4,X 72 | 1.0.2.0,X 73 | 1.0.2.1,X 74 | 1.0.3.0,X 75 | 1.0.3.1,X 76 | 1.0.3.2,X 77 | 1.0.4.0,X 78 | 1.0.4.1,X 79 | 1.0.4.2,X 80 | 1.0.4.3,X 81 | 1.0.4.4,X 82 | 1.1.0.0,X 83 | 1.1.0.1,X 84 | 1.1.1.0,X 85 | 1.1.1.1,X 86 | 1.1.1.2,X 87 | 1.1.2.0,X 88 | 1.1.2.1,X 89 | 1.1.2.2,X 90 | 1.1.2.3,X 91 | 1.1.2.4,X 92 | 1.1.3.0,X 93 | 1.1.3.1,X 94 | 1.1.3.2,X 95 | 1.1.3.3,X 96 | 1.1.3.4,X 97 | 1.1.4.0,X 98 | 1.1.4.1,X 99 | 1.1.4.2,X 100 | 1.1.4.3,X 101 | 1.1.4.4,X 102 | -------------------------------------------------------------------------------- /python_examples/basic_simulation/simulation_outputs/simulation_flow_SIR_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/basic_simulation/simulation_outputs/simulation_flow_SIR_plot.png -------------------------------------------------------------------------------- /python_examples/gibraltar_example/README.md: -------------------------------------------------------------------------------- 1 | # Gibraltar Examples 2 | Contained within the gibraltar_example/ directory, these scripts run simulations in which intervention is active or inactive in Gibraltar. Output graphs are contained within the gibraltar_example/simulation_outputs/ directory. Both simulations are run using the same input file, considering the actual population set-up in Gibraltar. 3 | 4 | ## Without Intervention 5 | The resulting infection curve shows the progression of the disease when the intervention is absent. The infection peak occurs around Day 25 with roughly 15k infected individuals. Nearly all of the population is recovered in 90 days, and a small proportion of the population are susceptible. 6 | 7 | ![without intervention.pt](./simulation_outputs/without_intervention/simulation_flow_SIR_plot.png) 8 | 9 | ## With Intervention 10 | The intervention conducted in our simulation is in line with the real instructions during the pandemic (https://www.gibraltar.gov.gi/press/covid-19-press-releases?year=2020&np=6). All interventions (i.e. case isolation, place closure, household quarantine, social distancing) start from the first day of the simulation, and most of them last for the entire simulation, except place closure, which ends at Day 74. 90% of the symptomatic individuals are self isolated, 75% of the households are compliant with household quarantine, and all forms of schools are closed during this time. These interventions affect the house, place and spatial effectiveness to different extents, and the exact values are derived from CovidSim. 11 | 12 | The infection peak occurs around 15 days later than without the intervention, and the number of infected individuals is below 7.5k. As a result, there are far more susceptible individuals in the intervention case, which still has almost 10k after the simulation. 13 | 14 | ![with intervention.pt](./simulation_outputs/with_intervention/simulation_flow_SIR_plot.png) 15 | -------------------------------------------------------------------------------- /python_examples/gibraltar_example/covidsim_results/WeeklyIncidenceCasesbyAgeGroup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/gibraltar_example/covidsim_results/WeeklyIncidenceCasesbyAgeGroup.png -------------------------------------------------------------------------------- /python_examples/gibraltar_example/gibraltar_inputs/wpop_gib.txt: -------------------------------------------------------------------------------- 1 | longitude latitude population country admin_unit 2 | -5.366667 36.15 81 24 240100 3 | -5.358333 36.15 1494 24 240100 4 | -5.35 36.15 7190 24 240100 5 | -5.366667 36.141666 1726 24 240100 6 | -5.358333 36.141666 6777 24 240100 7 | -5.35 36.141666 3569 24 240100 8 | -5.358333 36.133335 4909 24 240100 9 | -5.35 36.133335 938 24 240100 10 | -5.358333 36.125 2816 24 240100 11 | -5.35 36.125 1032 24 240100 12 | -5.358333 36.116665 761 24 240100 13 | -5.35 36.116665 1785 24 240100 14 | -------------------------------------------------------------------------------- /python_examples/gibraltar_example/simulation_outputs/with_intervention/age_stratify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/gibraltar_example/simulation_outputs/with_intervention/age_stratify.png -------------------------------------------------------------------------------- /python_examples/gibraltar_example/simulation_outputs/with_intervention/simulation_flow_SIR_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/gibraltar_example/simulation_outputs/with_intervention/simulation_flow_SIR_plot.png -------------------------------------------------------------------------------- /python_examples/gibraltar_example/simulation_outputs/without_intervention/age_stratify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/gibraltar_example/simulation_outputs/without_intervention/age_stratify.png -------------------------------------------------------------------------------- /python_examples/gibraltar_example/simulation_outputs/without_intervention/gibraltar_weeky_cases.csv: -------------------------------------------------------------------------------- 1 | dates,0-10,10-20,20-30,30-40,40-50,50-60,60-70,70-80,80-90 2 | 03-18,1.0205006993950556,6.826715684504396,19.541325275244233,37.363239661353994,35.54677432654712,33.65888042031168,23.725183816891487,16.015699401000415,16.72998511528613 3 | 03-25,17.80718661447171,42.114049352489296,115.47955614902216,201.51419361616007,306.32942009475937,254.92900741139354,210.12084916755947,146.8178163967866,154.19001000738427 4 | 04-01,86.48338581805442,191.20668322463837,462.6814943272582,880.2742392123296,1309.2481928794423,1265.2286016925723,969.9110510315687,706.2613333484622,755.4945509658281 5 | 04-08,140.45393027477834,335.9213496637954,827.7168354016801,1593.3744311683588,2342.7229549042995,2340.3381783122472,1916.0368524601568,1405.0023690200503,1679.2644248346971 6 | 04-15,106.50868781584411,256.8098344745219,645.1520357024534,1211.8217133688029,1902.2462874829419,1855.5377127783843,1763.2211253967944,1380.7424220112841,1683.25268517336 7 | 04-22,52.07784925209383,123.16147143194466,323.8181380863494,600.3204596842459,963.875320981731,952.0693685514717,960.5497798497056,835.6631189348328,1154.4264018759973 8 | 04-29,21.969896703815664,38.965095405421025,133.89463697229255,254.83539992179908,387.3885911516537,406.4183676886635,431.7889366485706,391.2219876859739,638.5960944358385 9 | 05-06,6.790839460563049,9.295964635411814,42.255610890125794,86.3834144962119,139.8987875356544,143.68450132434796,171.08199444763153,143.485590140567,280.20466114917906 10 | 05-13,0.9285714285714285,3.3571428571428568,14.969572827361539,30.37764226428395,39.729659548961436,51.2757853273671,69.93881770269877,40.94907033869176,108.3725093359114 11 | 05-20,0.5,1.357142857142857,2.8622680319916207,12.142856447028086,13.214285018456657,16.214284521435903,6.285714086905983,6.428571329167277,21.571426782153853 12 | 05-27,0.21428571428571427,0.5,0.21428571428571427,2.5714284720244205,5.285713987501833,3.5714283726202694,0.42857142857142855,0.14285714285714285,2.5714284720244205 13 | 06-03,0.0,0.2857142857142857,0.0,0.3571428571428571,0.8571428571428571,0.5,0.0,0.0,0.5714285714285714 14 | 06-10,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.07142857142857142 15 | -------------------------------------------------------------------------------- /python_examples/gibraltar_example/simulation_outputs/without_intervention/simulation_flow_SIR_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/gibraltar_example/simulation_outputs/without_intervention/simulation_flow_SIR_plot.png -------------------------------------------------------------------------------- /python_examples/gibraltar_example_cpp/output/new_cases.csv: -------------------------------------------------------------------------------- 1 | timestep,new_cases 2 | 0,100 3 | 1,0 4 | 2,43 5 | 3,144 6 | 4,198 7 | 5,244 8 | 6,315 9 | 7,400 10 | 8,494 11 | 9,512 12 | 10,630 13 | 11,616 14 | 12,666 15 | 13,643 16 | 14,683 17 | 15,624 18 | 16,604 19 | 17,589 20 | 18,487 21 | 19,524 22 | 20,438 23 | 21,401 24 | 22,389 25 | 23,344 26 | 24,291 27 | 25,223 28 | 26,211 29 | 27,201 30 | 28,179 31 | 29,144 32 | 30,133 33 | 31,101 34 | 32,95 35 | 33,90 36 | 34,61 37 | 35,50 38 | 36,39 39 | 37,48 40 | 38,36 41 | 39,39 42 | 40,29 43 | 41,25 44 | 42,15 45 | 43,11 46 | 44,16 47 | 45,12 48 | 46,9 49 | 47,6 50 | 48,7 51 | 49,6 52 | 50,2 53 | 51,3 54 | 52,5 55 | 53,0 56 | 54,1 57 | 55,2 58 | 56,2 59 | 57,0 60 | 58,0 61 | 59,0 62 | 60,0 63 | 61,0 64 | 62,0 65 | 63,0 66 | 64,1 67 | 65,0 68 | 66,0 69 | 67,0 70 | 68,0 71 | 69,0 72 | 70,0 73 | 71,0 74 | 72,0 75 | 73,0 76 | 74,0 77 | 75,0 78 | 76,0 79 | 77,0 80 | 78,0 81 | 79,0 82 | 80,0 83 | 81,0 84 | 82,0 85 | 83,0 86 | 84,0 87 | 85,0 88 | 86,0 89 | 87,0 90 | 88,0 91 | 89,0 92 | 90,0 93 | -------------------------------------------------------------------------------- /python_examples/intervention_example/intervention_outputs/case_isolation_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/intervention_example/intervention_outputs/case_isolation_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/intervention_example/intervention_outputs/case_isolation_via_testing_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/intervention_example/intervention_outputs/case_isolation_via_testing_plot.png -------------------------------------------------------------------------------- /python_examples/intervention_example/intervention_outputs/household_quarantine_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/intervention_example/intervention_outputs/household_quarantine_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/intervention_example/intervention_outputs/place_closure_closure_place_type_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/intervention_example/intervention_outputs/place_closure_closure_place_type_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/intervention_example/intervention_outputs/social_distancing_distancing_enhanced_prob_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/intervention_example/intervention_outputs/social_distancing_distancing_enhanced_prob_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/intervention_example/intervention_outputs/travel_isolation_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/intervention_example/intervention_outputs/travel_isolation_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/intervention_example/intervention_outputs/vaccination_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/intervention_example/intervention_outputs/vaccination_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/luxembourg_example/animation/population_output_intervention_simulation_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/animation/population_output_intervention_simulation_1.gif -------------------------------------------------------------------------------- /python_examples/luxembourg_example/animation/population_output_simulation_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/animation/population_output_simulation_1.gif -------------------------------------------------------------------------------- /python_examples/luxembourg_example/animation/population_output_simulation_1_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/animation/population_output_simulation_1_grid.png -------------------------------------------------------------------------------- /python_examples/luxembourg_example/animation/pre_population_output_simulation_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/animation/pre_population_output_simulation_1.gif -------------------------------------------------------------------------------- /python_examples/luxembourg_example/luxembourg_inputs/luxembourg_initial_infect.py: -------------------------------------------------------------------------------- 1 | # Script to infect an initial number of people in a specific cell 2 | # Outputs a csv file in the format required by pyEpiabm as an input 3 | 4 | import pandas as pd 5 | import random 6 | 7 | input = pd.read_csv('luxembourg_input_file.csv') 8 | listofzeros = [0] * len(input['location_x']) 9 | cell_number = 1664 10 | initial_infect = 5 11 | index_list = input.index[(input['cell'] == cell_number) & (input['Susceptible'] 12 | != 0)].tolist() 13 | for i in range(initial_infect): 14 | index = random.choice(index_list) 15 | listofzeros[index] += 1 16 | input['InfectMild'] = listofzeros 17 | input.to_csv('luxembourg_adapted_5_in_cell_input.csv', index=False) 18 | -------------------------------------------------------------------------------- /python_examples/luxembourg_example/paper_plots/incidence_rural_vs_urban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/paper_plots/incidence_rural_vs_urban.png -------------------------------------------------------------------------------- /python_examples/luxembourg_example/paper_plots/post_day_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/paper_plots/post_day_40.png -------------------------------------------------------------------------------- /python_examples/luxembourg_example/paper_plots/pre_day_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/paper_plots/pre_day_40.png -------------------------------------------------------------------------------- /python_examples/luxembourg_example/paper_plots/pre_post_raw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/paper_plots/pre_post_raw.png -------------------------------------------------------------------------------- /python_examples/luxembourg_example/paper_plots/pre_post_rural_vs_urban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/luxembourg_example/paper_plots/pre_post_rural_vs_urban.png -------------------------------------------------------------------------------- /python_examples/sim_speeds/Readme.md: -------------------------------------------------------------------------------- 1 | The 2 csv files in this folder contain data on the speed of our code before we sped it up. 2 | old_intervention_basic_speeds.csv uses the basic simulation after the interventions code was included for varying population sizes. 3 | old_intervention_spatial_speeds.csv uses the spatial simulation with 200 cells and 2 microcells per cell after the interventions code was included for varying population sizes. 4 | These files contain the necessary code for interventions but none of the interventions are active but the checks for whether they are active are included. 5 | To run this code again use the code as it was in the following commit: 6 | https://github.com/SABS-R3-Epidemiology/epiabm/commit/7c9d18345c65cefa3e685453383e4c2d68fc0d9a 7 | -------------------------------------------------------------------------------- /python_examples/sim_speeds/Sim_Speeds.txt: -------------------------------------------------------------------------------- 1 | Sim type Pop size Days Cells Time Peak reached (Y/N) 2 | basic 1000 60 1 00:02 Y 3 | basic 2000 60 1 00:04 Y 4 | basic 3000 60 1 00:09 Y 5 | basic 4000 60 1 00:11 Y 6 | basic 5000 60 1 00:19 Y 7 | basic 6000 60 1 00:25 Y 8 | basic 7000 60 1 00:25 Y 9 | basic 8000 60 1 00:30 Y 10 | basic 9000 60 1 00:45 Y 11 | basic 10000 60 1 00:52 Y 12 | basic 20000 60 1 02:52 Y 13 | basic 40000 60 1 11:44 Y 14 | basic 100000 60 1 52:32 Y -------------------------------------------------------------------------------- /python_examples/sim_speeds/basic_speed_plot.py: -------------------------------------------------------------------------------- 1 | # Code to plot runtime from .txt file 2 | 3 | import os 4 | import pandas as pd 5 | import matplotlib.pyplot as plt 6 | import numpy as np 7 | 8 | 9 | def get_seconds(time_str): 10 | """Converts a string for the time of a simulation of the form mm:ss 11 | into an integer value for the number of seconds that corresponds to 12 | 13 | Parameters 14 | ---------- 15 | time_str : time string in form mm:ss 16 | 17 | Returns 18 | ------- 19 | int 20 | Integer value of number of seconds for the given time string 21 | 22 | """ 23 | mm, ss = time_str.split(':') # split in mm, ss 24 | return int(mm) * 60 + int(ss) 25 | 26 | 27 | data_path = os.path.join(os.path.dirname(__file__), "Sim_Speeds.txt") 28 | 29 | df = pd.read_csv(data_path, header=0, sep=r"\s\s+") 30 | df['Seconds'] = df['Time'].apply(get_seconds) 31 | print(df.head()) 32 | 33 | x = df['Pop size'] 34 | y = df['Seconds'] 35 | 36 | plt.plot(x, y, marker='o', c='g') 37 | plt.title("Simulation time for basic simulation over 60 days") 38 | plt.xlabel('Population Size') 39 | plt.xscale('log') 40 | plt.yscale('log') 41 | plt.ylabel('time (s)') 42 | 43 | slope, intercept = np.polyfit(np.log10(x), np.log10(y), 1) 44 | print('The slope of the linear regression line and so the big O power is: ', 45 | slope) 46 | print(intercept) 47 | 48 | plt.plot(x, 10**intercept*x**slope, c='b', 49 | label=("Regression gradient", slope)) 50 | plt.legend() 51 | 52 | plt.savefig(os.path.join(os.path.dirname(__file__), 53 | "sim_speeds_plots/", "basic_sim_speed_from_file.png")) 54 | # Default file format is .png, but can be changed to .pdf, .svg, etc. 55 | plt.show() 56 | -------------------------------------------------------------------------------- /python_examples/sim_speeds/old_intervention_basic_speeds.csv: -------------------------------------------------------------------------------- 1 | pop_size,sim_time 2 | 1000,3.0474579334259033 3 | 2000,7.811213731765747 4 | 4000,11.241638422012329 5 | 8000,44.824697971343994 6 | 10000,49.49361824989319 7 | 20000,202.66147661209106 8 | 40000,606.2807509899139 9 | -------------------------------------------------------------------------------- /python_examples/sim_speeds/old_intervention_spatial_speeds.csv: -------------------------------------------------------------------------------- 1 | pop_size,sim_time 2 | 1000,0.08836674690246582 3 | 2000,10.330620050430298 4 | 4000,19.07038640975952 5 | 8000,32.0343656539917 6 | 10000,35.919424295425415 7 | 20000,72.8624632358551 8 | 40000,130.7392566204071 9 | 80000,268.1109652519226 10 | -------------------------------------------------------------------------------- /python_examples/sim_speeds/sim_speeds_plots/basic_sim_speed_from_file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/sim_speeds/sim_speeds_plots/basic_sim_speed_from_file.png -------------------------------------------------------------------------------- /python_examples/spatial_example/spatial_outputs/spatial_flow_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/spatial_example/spatial_outputs/spatial_flow_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/spatial_example/spatial_outputs/voronoi_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/spatial_example/spatial_outputs/voronoi_animation.gif -------------------------------------------------------------------------------- /python_examples/spatial_example/spatial_outputs/voronoi_grid_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/spatial_example/spatial_outputs/voronoi_grid_img.png -------------------------------------------------------------------------------- /python_examples/travel_example/travelling_outputs/travelling_constant_introduce_cases_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/travel_example/travelling_outputs/travelling_constant_introduce_cases_Icurve_plot.png -------------------------------------------------------------------------------- /python_examples/travel_example/travelling_outputs/travelling_ratio_introduce_cases_Icurve_plot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SABS-R3-Epidemiology/epiabm/7b073b4d0edae06001eceecd4e45fb7bc39c9288/python_examples/travel_example/travelling_outputs/travelling_ratio_introduce_cases_Icurve_plot.png --------------------------------------------------------------------------------