Source code for laser_cholera.metapop.humantohumanvax

"""Human-to-human transmission rate."""

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.figure import Figure


[docs] class HumanToHumanVax: def __init__(self, model, verbose: bool = False) -> None: self.model = model self.verbose = verbose model.patches.add_vector_property("V1_incidence_hum", length=model.params.nticks + 1, dtype=np.int32, default=0) model.patches.add_vector_property("V2_incidence_hum", length=model.params.nticks + 1, dtype=np.int32, default=0) return
[docs] def check(self): assert hasattr(self.model, "patches"), "HumanToHuman: model needs to have a 'patches' attribute." assert hasattr(self.model.patches, "Lambda"), "HumanToHuman: model patches needs to have a 'Lambda' attribute." assert hasattr(self.model, "agents"), "HumanToHuman: model needs to have a 'agents' attribute." assert hasattr(self.model.agents, "E"), "HumanToHuman: model agents needs to have a 'E' (exposed) attribute." assert hasattr(self.model.agents, "V1sus"), ( "HumanToHuman: model agents needs to have a 'V1sus' (vaccinated 1 susceptible) attribute." ) assert hasattr(self.model.agents, "V1inf"), ( "HumanToHuman: model agents needs to have a 'V1inf' (vaccinated 1 infectious) attribute." ) assert hasattr(self.model.agents, "V2sus"), ( "HumanToHuman: model agents needs to have a 'V2sus' (vaccinated 2 susceptible) attribute." ) assert hasattr(self.model.agents, "V2inf"), ( "HumanToHuman: model agents needs to have a 'V2inf' (vaccinated 2 infectious) attribute." ) assert hasattr(self.model, "params"), "HumanToHuman: model needs to have a 'params' attribute." assert "tau_i" in self.model.params, "HumanToHuman: model params needs to have a 'tau_i' (emmigration probability) parameter." return
[docs] def __call__(self, model, tick: int) -> None: r""" Calculate the current human-to-human transmission rate per patch. $\Lambda_{j,t+1} = \frac {\beta^{hum}_{jt}((S_{jt}(1 - \tau_j))(I_{jt}(1 - \tau_j) + \sum_{\forall i \neq j (\pi_{ij} \tau_j I_{it})}))^{\alpha_1}} {N^{\alpha_2}_{jt}}$ """ Lambda = model.patches.Lambda[tick + 1] Enext = model.agents.E[tick + 1] # LambdaV1 V1sus = model.agents.V1sus[tick] local = np.round((1 - model.params.tau_i) * V1sus).astype(V1sus.dtype) infections = model.prng.binomial(local, -np.expm1(-Lambda)).astype(V1sus.dtype) V1sus_next = model.agents.V1sus[tick + 1] V1inf_next = model.agents.V1inf[tick + 1] V1sus_next -= infections V1inf_next += infections Enext += infections assert np.all(V1sus_next >= 0), f"V1sus' should not go negative ({tick=}\n\t{V1sus_next})" # LambdaV2 V2sus = model.agents.V2sus[tick] local = np.round((1 - model.params.tau_i) * V2sus).astype(V2sus.dtype) infections = model.prng.binomial(local, -np.expm1(-Lambda)).astype(V2sus.dtype) V2sus_next = model.agents.V2sus[tick + 1] V2inf_next = model.agents.V2inf[tick + 1] V2sus_next -= infections V2inf_next += infections Enext += infections assert np.all(V2sus_next >= 0), f"V2sus' should not go negative ({tick=}\n\t{V2sus_next})" return
[docs] def plot(self, fig: Figure = None): # pragma: no cover yield plot_helper(fig, "V1 Incidence (Human Transmission)", self.model.patches.V1_incidence_env, self.model.params.location_name) yield plot_helper(fig, "V2 Incidence (Human Transmission)", self.model.patches.V2_incidence_env, self.model.params.location_name) return
# TODO - copy-paste from envtohumanvax.py, should consider consolidating
[docs] def plot_helper(fig, title, data, names): # pragma: no cover _fig = plt.figure(num=title, figsize=(12, 9), dpi=128) if fig is None else fig rows, cols = 10, 4 x_axes_refs = [None] * cols y_axes_refs = [None] * rows ymin, ymax = 0, max(data.max(), 100) # avoid warning about ylim below for i in range(data.shape[1]): row = i // cols col = i % cols sharex = x_axes_refs[col] sharey = y_axes_refs[row] ax = _fig.add_subplot(rows, cols, i + 1, sharex=sharex, sharey=sharey) color = ["green", "red"][np.any(data[:, i] > 0)] ax.plot(data[:, i], color) # , label=f"{self.model.params.location_name[ipatch]}") ax.set_ylim(ymin, ymax) ax.set_title(f"{names[i]}", fontsize=8) show_xticks = row == rows - 1 show_yticks = col == 0 ax.tick_params(axis="x", which="both", bottom=show_xticks, labelbottom=show_xticks) ax.tick_params(axis="y", which="both", left=show_yticks, labelleft=show_yticks) x_axes_refs[col] = ax if x_axes_refs[col] is None else x_axes_refs[col] y_axes_refs[row] = ax if y_axes_refs[row] is None else y_axes_refs[row] _fig.text(0.5, 0.04, "Ticks", ha="center", fontsize=9) # bottom center _fig.text(0.04, 0.5, "Incidence", va="center", rotation="vertical", fontsize=9) # left center plt.tight_layout(rect=[0.06, 0.06, 1, 1]) # leave space for global labels return title