All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Transfer repository to Jameel Institute @jameel-institute oragnisation
- Added small script
docs/sync_readme.jlto update package version in website index and Readme.md
daedalus()function signature refactored: second positional argument now takes infection parameters (infection) instead of scalar/vectorr0. Users must pass parameters viaInfectionDataobject rather than individual keyword arguments- Old interface:
daedalus(country, r0::Float64; sigma=..., epsilon=..., eta=..., ...) - New interface:
daedalus(country, infection; npi=..., log_rt=..., time_end=..., increment=..., n_threads=...)
- Old interface:
- Removed all infection-parameter keyword arguments:
sigma,p_sigma,epsilon,rho,eta,omega,gamma_Ia,gamma_Is,gamma_H,nu- All epidemiological parameters now encapsulated in
InfectionDataobject - Users customize parameters by fetching
InfectionDataand modifying fields before callingdaedalus()
- All epidemiological parameters now encapsulated in
- New dispatch methods for
daedalus():- String pathogen name:
daedalus(country, "sars-cov-2 delta"; ...) - Single
InfectionData:daedalus(country, infection_obj; ...) - Vector
InfectionData:daedalus(country, [inf1, inf2, ...]; ...)
- String pathogen name:
extract_infection_params()helper function to extract and expand epidemiological parameters fromInfectionDataInfectionDatais mutable, allowing users to customize parameters post-fetch:inf = get_pathogen("sars-cov-2 delta"); inf.r0 = 2.5- Infection names are normalized to lowercase: all pathogen names are stored and looked up as lowercase strings (e.g.,
"sars-cov-2 delta","influenza 2009")
# Old (no longer works):
result = daedalus("Australia", 2.5, sigma=0.217, epsilon=0.58, time_end=200.0)
# New (string pathogen, lowercase names):
result = daedalus("Australia", "sars-cov-2 delta", time_end=200.0)
# New (custom infection):
infection = Daedalus.DataLoader.get_pathogen("sars-cov-2 delta")
infection.r0 = 2.5
result = daedalus("Australia", infection, time_end=200.0)
# New (vector of infections):
infections = [
Daedalus.DataLoader.get_pathogen("sars-cov-2 delta"),
Daedalus.DataLoader.get_pathogen("influenza 2009")
]
results = daedalus("Australia", infections, time_end=200.0)-
daedalus()function signature:countryis now the first positional argument andr0is the second positional argument, enabling method dispatch onr0type (scalarFloat64vs vectorVector{Float64}) across two separate implementations insrc/Model.jlandsrc/Ensemble.jl - All documentation examples and benchmarks updated to reflect the new calling convention:
daedalus(country, r0, ...)instead of previous keywords-first approach - All test files updated to use new positional argument signature for daedalus calls
- Function calls now use positional arguments:
daedalus("Australia", 2.5, time_end=200.0)instead of previous keyword-based calling conventions - Function
get_ngm()requires transmission rate beta and not the$R_0$ ; functionget_beta()is now vectorised over multiple values of$R_0$ . The use case is generating multiple NGMs for ensemble runs without runningget_beta()an equal number of times.get_ngm()has a method for a vector ofbeta().
- Multiple dispatch implementation for
daedalus(): scalar and vector R0 inputs are now handled via distinct function methods - Vector R0 dispatch in file
src/Ensemble.jl:daedalus(country, r0::Vector{Float64}; ...)runs multiple R0 values in a single call - Implementation of
SciMLBase.EnsembleProbleminsrc/Model.jl(daedalus_internalfunction): usesEnsembleThreads()solver withprob_funcwrapper to efficiently orchestrate multi-run ODE solving. The ensemble approach reuses a base ODE problem and remakes it for each trajectory with its corresponding parameters, enabling automatic thread-safe parallel execution across multiple r0 values without explicit locking - Helper functions
prepare_shared_data()anddaedalus_internal()exported from Model.jl for use by ensemble dispatch - Comprehensive function documentation improvements: added or enhanced docstrings for all exported functions in
Helpers.jl,Data.jl,Events.jl,Model.jl, andOde.jlwith argument lists and return type annotations
- Documentation page
docs/src/settings.mdexplaining the multiple-contact-settings feature: how to assign aVector{Matrix{Float64}}toCountryData.contact_matrix, howcontacts3dstacks them into a 3D array, and how beta calibration usestotal_contacts(sum of all matrices) - Tests for multiple contact settings:
get_settingscount,contacts3dshape,total_contactselement-wise sum, model execution with two settings, and calibration-equivalence check (two equal settings produces the same epidemic as one setting for the same R0)
- Lowered
StatisticsandLinearAlgebracompat bounds to1.10.0(matching Julia 1.10 LTS stdlib versions) so the package resolves correctly on Julia 1.10 LTS
CountryDatastruct now accepts aVectorof contact matrices asMatrix{Float64}for multiple contact settings. Helper functions process this list, or a singleMatrix, to give total contacts where needed includingHelpers.get_betaandHelpers.get_ngm.- Moved away from using
StaticArraysfor contact matrices as operating on them was slower than using regular arrays.
- Docstring for
Helpers.weighted_slice_sum!explaining the tensor contraction algorithm, arguments, and performance notes - Docstring for
Data.total_contactsexplaining the dispatch on single vs. vector-of-matrices input - Expanded docstring for
Data.contacts3dexplaining the 3D stacking, theK=1reshape fallback, and the role of the third dimension in the ODE - Tests for
Helpers.weighted_slice_sum!covering unit weights, slice selection, scalar scaling, zero weights, in-place overwrite, and agreement with a reference loop
daedalusnow acceptscountryas either aStringor aDataLoader.CountryDatastruct; aStringis resolved toCountryDataviaDataLoader.get_countryat the start of the function, making both call styles equivalent- Updated
test/test_basic.jlandtest/test_eigenvalue.jlto replace removedData.australia_contacts()calls withDataLoader.get_country("Australia").contact_matrix; replaced zero-argData.prepare_contacts()call withData.prepare_contacts("Australia")
prepare_demog(cd::CountryData)now clamps worker counts to a minimum of 1, preventing division-by-zero when the result is used as a scaling denominator. 30 countries (Australia, Belgium, Brunei, Cambodia, Chile, China, Costa Rica, Cyprus, Estonia, Finland, Hong Kong, Iceland, Japan, Kazakhstan, Laos, Latvia, Luxembourg, Malaysia, Malta, Mexico, Morocco, Myanmar, New Zealand, Portugal, Romania, Rwanda, Singapore, Slovenia, Switzerland, Tunisia) had at least one sector with zero workers in the data, causingInfin the scaled contact matrix, which propagated toNaNin the ODE step-size calculation and immediate solver exit withdt_NaNwarnings.
daedalusnow requires acountrystring directly instead of separateinitial_state,contacts, andcwarguments; all tests, examples, and documentation updated accordingly- Simplified UK example in
docs/src/index.mdto usedaedalus(country="United Kingdom", ...) - Updated
docs/src/country_data.mdto reflect thatdaedalusacceptscountrydirectly
- Documentation page for country and pathogen data (
docs/src/country_data.md) DataLoadermodule added to function reference autodocs- Basic model and helper tests extracted into
test/test_basic.jl
- Added explicit
du[end] = 0.0indaedalus_ode!to prevent undefined Rt derivative between callback updates - Changed
Ia * p.epsilontoIa .* p.epsilonin ODE for consistency with broadcasting conventions - Removed
cm_scaling .* p.contactsStaticArrays broadcasting failure; replaced withsum(p.contacts, dims=3)[:,:,1]
- Core epidemiological model mirroring the R package {daedalus}
- ODE-based compartmental disease transmission model with demographic groups
- Effective reproduction number (Rt) calculation and logging at specified timesteps
- Next Generation Matrix (NGM) method for Rt calculation
- Power iteration for faster Rt calculation
- Flexible event handling system with both timed and reactive (state-dependent) events
- Non-pharmaceutical intervention (NPI) modeling with timed and reactive triggers
- Time dependent NPIs as a struct
TimedNpi - Contact matrix support for modeling population mixing patterns
- Option to toggle contact matrix scaling
- Functions for dynamic parameter modification and reset during simulations
- Support for both increasing and decreasing threshold detection in event callbacks
- Worker contact modeling with static vector optimization
- Documentation with basic usage examples and plots
- Documentation workflow via GitHub Actions
- Data layer (
DataLoader) with lazy-loaded country, pathogen, economic contacts, closure strategy, and vaccination scenario data mirroring the R {daedalus} data package - Bundled CSV data files: country demographics, hospital capacity, sector GVA, sector contacts, economic closure strategies, and seven pathogen parameter sets
- Output timeseries access function for structured post-simulation analysis
- Simplified NPI handling and data structures
- Improved event logic for better state-dependent triggering
- Unified contact calculation using single contact matrix approach
- Optimized dependency management for lighter package footprint
- Updated ODE system to account for worker-specific transmission dynamics
- Refined beta (transmission rate) calculation for arbitrary contact matrix sizes
- Enhanced model interface to return NPIs and remove unused inputs
- Applied JuliaFormatter across codebase for consistent style
- Corrected Rt calculation method
- Fixed ODE formulation for accurate disease dynamics
- Resolved issues with
SavedValuestype handling in callbacks - Fixed error when output timebin is an exact factor of tmax
- Package version: 0.0.1
- Julia compatibility: 1.6.7+
- Key dependencies: OrdinaryDiffEq.jl, DiffEqCallbacks.jl, StaticArrays.jl, CSV.jl, DataFrames.jl