Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor for more multi dispatch #79

Merged
merged 21 commits into from
Feb 27, 2024
Merged

Conversation

SamuelBrand1
Copy link
Collaborator

@SamuelBrand1 SamuelBrand1 commented Feb 27, 2024

Goal

To refactor the code base to enforce a separation between types which define the behaviour of the model, e.g. targetting direct log-infections for inference as opposed to the time-varying reproductive number, from the implementation of this which is handled by methods.

Lower-level interface

The core lower level methods are:

  • generate_latent_process(latent_process::AbstractLatentProcess, n) which implements the latent process for n steps
  • generate_latent_infs(epimodel::AbstractEpiModel, latent_process) which implements initial incidence and ingestion of latent process to generate latent infections.
  • generate_observations(observation_model::AbstractObservationModel, y_t, I_t; pos_shift) which implements how the latent incidence I_t either generates observations (if y_t = missing) or accumulates log-like if y_t is given with pos_shift being an up-jitter to miss out on exact zeros in prediction.

Higher-level interface

Based on make_epi_inference_model which takes in obs. data (or missing) and defined structs to dispatch the lower level methods on.

New model diagram

flowchart LR

A["Underlying GI
Bijector"]

EpiModel["AbstractEpiModel
----------------------
Choice of target
for latent process:

DirectInfections
    ExpGrowthRate
    Renewal"]

InitModel["Priors for
initial scale of incidence"]

DataW[Data wrangling and QC]


ObsData["Observational Data
---------------------
Obs. cases y_t"]

LatentProcPriors["Latent process priors"]

LatentProc["AbstractLatentProcess
---------------------
RandomWalkLatentProcess"]

ObsModelPriors["Observation model priors
choice of delayed obs. model"]

ObsModel["AbstractObservationModel
---------------------
DelayObservations"]

E["Turing model constructor
---------------------
make_epi_inference_model"]

G[Posterior draws]
H[Posterior checking]
I[Post-processing]



A --> EpiData
EpiData --> EpiModel
InitModel --> EpiModel
EpiModel -->E
ObsData-->E
DataW-.->ObsData
LatentProcPriors-->LatentProc
LatentProc-->E
ObsModelPriors-->ObsModel
ObsModel-->E


E-->|sample...NUTS...| G
G-.->H
H-.->I
Loading

Closes #78
Closes #75

@seabbs
Copy link
Collaborator

seabbs commented Feb 27, 2024

Thanks looking now.

Do you have a view on the CI failures?

Also could you address how/why this the questions in #78 directly

Copy link
Collaborator

@seabbs seabbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much improved from sight read. Running locally now but could you address the design question in #78 directly please

EpiAware/src/epimodel.jl Show resolved Hide resolved
EpiAware/src/epimodel.jl Show resolved Hide resolved
EpiAware/src/epimodel.jl Show resolved Hide resolved
EpiAware/src/initialisation.jl Outdated Show resolved Hide resolved
EpiAware/src/initialisation.jl Outdated Show resolved Hide resolved
EpiAware/src/initialisation.jl Outdated Show resolved Hide resolved
@SamuelBrand1
Copy link
Collaborator Author

Do you have a view on the CI failures?

The current CI problem seems to be some kind of async between my pre-commit hook of format style that has emerged since I switched to my laptop... Possibly need to update SciMLStyle(). I'll look into it.

@SamuelBrand1
Copy link
Collaborator Author

Also could you address how/why this the questions in #78 directly

#78 addresses potential problems with splatting unknown Dicts of priors down to a function call which expects some definite arguments.

My contention is that this refactor solves that problem in a different way; by creating a concrete type to dispatch a behaviour (e.g. choose Random walk latent process) with known and typed fields. This allows the input of the method that implements random walk to use the struct as an input.

Copy link
Collaborator

@seabbs seabbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good and seems to work nicely. Thanks for the explanation and I'm happy to go with the pure struct approach. I would like us to make sure we very clearly document the connect between the struct and their functions and what and how internal struct objects are used by those functions (as that is my remaining concern).

@seabbs seabbs merged commit 8b9edf9 into main Feb 27, 2024
5 checks passed
@seabbs seabbs deleted the refactor-for-more-multi-dispatch branch February 27, 2024 21:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor to promote greater use of multiple dispatch and one paradigm programming
2 participants