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

Pre-baked scenarios #16

Merged
merged 6 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ approach.

## Model Description

This repo contains code to apply the next-generation method of Diekman et al. (1990) to calculate R0 for an SIR model with 4 risk groups and flexible inputs for varying vaccine allocation to the 4 groups.
This repo contains code to apply the next-generation method of Diekman et al. (1990) to calculate R0 for an SIR model with 3 risk groups and flexible inputs for varying vaccine allocation to each group.

### Next generation matrix calculation

Expand All @@ -33,13 +33,12 @@ Default parameters in the widget assume the following about transmission:
| --------- | ------------------------------------------------ | ------------------------------------------------ | -------------------------------------- |
| Core | High | High | Low |
| Children | Low | Low | High |
| Travelers | Low | High | Low |
| General | Low | Low | Low |

Other Inputs to the widget:

- Sizes of the groups, $N_i$
- Vaccination efficacy (VE) and number of doses allocated to each group ($V_i$)
- Vaccination efficacy (VE) and number of doses allocated to each group ($v_i$)
- Within and between group contact rates; $\beta_{ij}$
- Per-group probability of severe infection

Expand Down
20 changes: 10 additions & 10 deletions docs/approach.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Using Next Generation Matrices

The NGM for a 4-Group Infectious Disease Model with compartments $S_i$, $I_i$, $R_i$: Susceptible, Infected, and Recovered compartments.
The NGM for a 3-Group Infectious Disease Model with compartments $S_i$, $I_i$, $R_i$: Susceptible, Infected, and Recovered compartments.

The dynamics for $i$ in each group given by:
The dynamics for $I$ in each group given by:

$$
\frac{d I_i}{dt} = \sum_{j} \frac{\beta_{ij} S_i I_j}{N} - \gamma_i I_i
Expand All @@ -21,31 +21,31 @@ $$
I_i = 0, S_i \approx N_i \ \text{for all\ } i
$$

And then the NGM $\mathbf{R}_{ij}$ is given by:
The NGM $\mathbf{R}_{ij}$ is given by:

$$
\mathbf{R}_{ij} = \frac{\beta_{ij} S_{i}}{\gamma N}
$$

If all $\gamma_i = \gamma$ and we assume SIR dynamics.
Where we assume all $\gamma_i = \gamma$ and SIR dynamics.

The basic reproductive number $R_0$ is calculated as the dominant eigenvalue of $R$.
The basic reproductive number $R_0$ is calculated as the [spectral radius](https://en.wikipedia.org/wiki/Spectral_radius) (the largest absolute value of the eigenvalues) of $\mathbf{R}$.

This model incorporates vaccination by recalculating the distribution of susceptible individuals in each group $S_{i}^{vax}$ (assuming all or nothing vaccination, with vaccine efficacy given by $ve$ and the proportion of $i$ vacinated is $v_i$):
This model incorporates vaccination by recalculating the number of susceptible individuals in each group $S_{i}^{\mathrm{vax}}$ (assuming all or nothing vaccination, with vaccine efficacy given by $\mathrm{VE}$ and the proportion of $i$ vacinated is $v_i$):

$$
\mathbf{S_{i}^\mathrm{vax}} = S_{i} - v_{i} * \mathrm{VE}
$$

So that $S_i^\mathrm{vax}$ is the population $i$ that is still susceptible post vaccination administration. Then \mathbf{R}_{ij} with vaccination factored in is given by
So that $S_i^\mathrm{vax}$ is the population $i$ that is still susceptible post vaccination administration. Then $\mathbf{R}_{ij}$ is, accounting for vaccination,

$$
\mathbf{R}_{ij}^{vax} = \mathbf{R}_{ij} \frac{S_{i}^\mathrm{vax}}{N_i}
\mathbf{R}_{ij}^\mathrm{vax} = \mathbf{R}_{ij} \frac{S_{i}^\mathrm{vax}}{N_i}
$$


The dominant eigenvalue of $R$ with vaccination is $R_e$.
The spectral radius of $\mathbf{R}^\mathrm{vax}$ is $R_e$.

The distribution of infections is calculated from the dominant eigenvector of $R$ (specifying that its elements add to 1).
The distribution of infections is calculated from the eigenvector that corresponds to the spectral radius of $\mathbf{R}^\mathrm{vax}$ (specifying that the elements of said eigenvector sum to 1).

Severe infections are calculated by multiplying the proportion of infections in each group by a group-specific probability of severe infection.
33 changes: 23 additions & 10 deletions widget/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@


def app():
st.title("4-Group NGM Calculator")
st.title("3-Group NGM Calculator")

# Group names
group_names = ["Core", "Kids", "Travelers", "General Population"]
group_names = ["Core", "Kids", "General Population"]

# Sidebar for inputs
st.sidebar.header("Model Inputs")

# Population size
st.sidebar.subheader("Population Sizes")
default_values = np.array([0.2, 0.2, 0.005, 0.595]) * 1000000
default_values = np.array([0.2, 0.2, 0.595]) * 1000000
N = np.array(
[
st.sidebar.number_input(f"Population ({group})", value=int(default_values[i]), min_value=0)
Expand All @@ -26,12 +26,26 @@ def app():
)

# Vaccine doses
st.sidebar.subheader("Vaccine Doses")

ndoses = 100000
st.sidebar.subheader("Vaccine Doses (Pre-filled Scenarios)")
starting_vax = st.sidebar.selectbox("Vaccine allocation strategy", ["No vaccination", "All core", "All kids", "Even"])
# No vax is default
allocation = [0, 0, 0]
if starting_vax == "All core":
allocation = [1, 0, 0]
elif starting_vax == "All kids":
allocation = [0, 1, 0]
elif starting_vax == "Even":
allocation = [1/3, 1/3, 1/3]
allocation = np.floor(np.array(allocation) * ndoses).astype("int")

st.sidebar.subheader("Vaccine Doses (Customization)")
V = np.array(
[
st.sidebar.number_input(
f"Vaccine Doses ({group})",
value=0,
value=allocation[i],
min_value=0,
max_value=N[i],
)
Expand All @@ -48,10 +62,9 @@ def app():
# Create the contact matrix K
beta = np.array(
[
[hi, lo, hi, lo], # core
[lo, lo, lo, lo], # kids
[hi, lo, lo, lo], # travelers
[lo, lo, lo, lo], # general
[hi, lo, lo], # core
[lo, lo, lo], # kids
[lo, lo, lo], # general
]
)

Expand All @@ -61,7 +74,7 @@ def app():

# Perform the NGM calculation
result = ngm.simulate(
n=N, n_vax=V, beta=beta, p_severe=np.array([0.02, 0.06, 0.02, 0.02]), ve=VE
n=N, n_vax=V, beta=beta, p_severe=np.array([0.02, 0.06, 0.02]), ve=VE
)

# Display the adjusted contact matrix
Expand Down
Loading