-
Notifications
You must be signed in to change notification settings - Fork 2
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
Intervention manager skeleton and facemask example #31
base: main
Are you sure you want to change the base?
Conversation
docs/intervention.md
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before going into a more in-depth review of the code, I have some comments about the description. Mainly, I think we should plan to incorporate facemasks based the isolation guidance instead of randomly assigning them to people at the beginning of the simulation. This means that we need to think of how to incorporate masking under previous and updated isolation guidance, which is triggered by exiting isolation after symptoms.
Perhaps the important piece for us to figure out with this PR is the intervention manager and how we are going to figure out multiple interventions happening at the same time. In that case, assigning facemasks at random could be a particular case for a test or something like that?
OverviewUpdated docs to reflect desired API (infection.md) along with skeleton code (transmission_modifiers.rs). All of the detailed description of implementation lives in the infection.md. Facemasks as an instance of transmission modifiers can be put in once feedback is received on current skeleton, tests are made for transmission_modifiers.rs, and the hook to transmission_manager through Open concerns
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial review on the design doc. Will review code tomorrow.
docs/infection.md
Outdated
if context.get_person_property(contact_id, InfectiousStatus) | ||
== InfectiousStatusType::Susceptible | ||
{ | ||
let relative_transmission = query_modifiers(&context, transmitter_id, contact_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You haven't yet introduced your transmission_modifiers
API (and, let's please make query_modifiers()
a method that is part of the ContextTransmissionModifierExt
trait extension). I think it's challenging for your reader to follow if you throw them head first into code that has new methods without any prior context.
docs/infection.md
Outdated
@@ -0,0 +1,163 @@ | |||
# Overview | |||
Infection attempts are not always successful (i.e. result in transmission). This module provides a framework to incorporate the many factors that modify the probability of infection attempt success. In this module, we assume that an interaction between an infectious transmitter (I) and a susceptible contact (S) has already occured and we want to `evaluate_transmission` using the registered modifiers of both I and S. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You use the word "modifiers" in this intro snippet. However, you haven't really introduced what a modifier is or what it means. I think a little bit more context, potentially through a simple motivating example is necessary. I also noticed that you don't talk about what an intervention is, and that is of course the main use case of this module.
I also think it's critical to explain why this module is necessary. Why shouldn't a user just try to do all the tabulation for each intervention by hand? And, how can this module be generalized to be useful for modeling even more, like waning immunity or even variant effects?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think explaining why the transmission manager shouldn't just tabulate all interventions by hand is important to do up front because it also provides a nice transition into your code snippet below. Please also reference that this code snippet is in the transmission manager and not in code you propose to write in the transmission modifiers manager.
docs/infection.md
Outdated
The API hook to `evaluate_transmission` is independent of innate transmissiveness, which determines the number and timing of infection attempts made by infecitous individual I. | ||
|
||
## Modifier scope | ||
In this module, we ignore behaviors and modifications not directly relevant to changing the transmission potential of an infection attempt. The separation of contact selection and contact rates is apparent, but other distinctions may be less clear. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow what this first sentence means at all. It sounds like you are saying that you ignore things not relevant to modifying transmission.
docs/infection.md
Outdated
## Modifier scope | ||
In this module, we ignore behaviors and modifications not directly relevant to changing the transmission potential of an infection attempt. The separation of contact selection and contact rates is apparent, but other distinctions may be less clear. | ||
For example, facemasks modify the relative transmission potential of an infection attempt. The decision to wear a facemask based on a person's risk category or symptom category is an intervention-level behavior that does not directly modify relative transmission potential, meaning that such choices are excluded from this module. In contrast, symptoms may also modify the efficacy of wearing a facemask, which is a higher order modification that would need to be accounted for in the changes to relative transmission potential caused by facemasks. | ||
Compare this higher order modification to the instance in which an individual may be less likely to wear a mask at home, or may wear it for less time. This is a modifier created by the location of the infection attempt, and is thus separate from the relative transmission modifiers module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused. Intervention efficacy varies based on the site of the transmission event. I think that is very relevant to the transmission modifiers module because its express purpose is to calculate the efficacy of an intervention, conditioned on the nature of the contact. However, I agree that whether an agent changes the amount of time they spend in their home or not because of an intervention being present should not to be handled by the transmission modifiers module. Is that what you mean here?
docs/infection.md
Outdated
|
||
## Modifier scope | ||
In this module, we ignore behaviors and modifications not directly relevant to changing the transmission potential of an infection attempt. The separation of contact selection and contact rates is apparent, but other distinctions may be less clear. | ||
For example, facemasks modify the relative transmission potential of an infection attempt. The decision to wear a facemask based on a person's risk category or symptom category is an intervention-level behavior that does not directly modify relative transmission potential, meaning that such choices are excluded from this module. In contrast, symptoms may also modify the efficacy of wearing a facemask, which is a higher order modification that would need to be accounted for in the changes to relative transmission potential caused by facemasks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels too detail-oriented for being this high up in the document. It seems to what you are trying to say is that the transmission modifiers module does not control whether a person uses an intervention. Is that correct? I would explain at a high level that there is a difference between the manager that controls whether an intervention is turned on or not (what in GCM lingo would be an "actor") and the manager that holds the efficacy of the intervention (in GCM lingo, a "data manager").
docs/infection.md
Outdated
|
||
let intervention_container = self.get_data_container_mut(InterventionPlugin); | ||
|
||
// mismatched types: instance_map is of type {closure} but expected {dyn Fn(...)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
docs/infection.md
Outdated
} | ||
``` | ||
|
||
To register the `aggregator` functions, because we only can only have as many aggregators as there are `InfectiousStatusType` values, the user provides a `Vec` of all aggregator functions desired to the register function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand how the requirement that we have as many aggregators as infectious status types means we should provide a vector?
docs/infection.md
Outdated
|
||
We already defined the default aggregator through `impl InterventionContainer` so that the user does not need to specify all or even any aggregators in order to `run_aggregator` in `compute_intervention`. | ||
|
||
To calculate the total relative trasnmission potential change for an individual during an infection attempt, `Context` and the `PersonId` are supplied to `compute_intervention`, which is agnostic of the `InfectiousStatus` of the `PersonId` supplied. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To calculate the total relative trasnmission potential change for an individual during an infection attempt, `Context` and the `PersonId` are supplied to `compute_intervention`, which is agnostic of the `InfectiousStatus` of the `PersonId` supplied. | |
To calculate the total relative transmission potential change for an individual during an infection attempt, `Context` and the `PersonId` are supplied to `compute_intervention`, which is agnostic of the `InfectiousStatus` of the `PersonId` supplied. |
Are we calculating a "change" in relative transmission potential? I also don't think the function is agnostic to the infectious status -- it just knows to query the infectious status from the person's ID.
docs/infection.md
Outdated
intervention_plugin.run_aggregator(infectious_status, ®istered_interventions) | ||
} | ||
``` | ||
We use automatic detection of all the modifications applied to a person, which is necessary to remove multiple manual calls to query particular interventions that would otherwise be error-prone and inflexible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we automatically detect the modifications applied to a person. We just iterate through all available interventions that have been registered and see if any of them are applicable to the person. If there is an intervention that hasn't been registered, we don't "automatically" detect it.
I also think the point made in this sentence is really about creating a structure that encourages model modularity.
docs/infection.md
Outdated
|
||
```rust | ||
|
||
pub fn query_modifers(context: &mut Context, transmitter_id: PersonId, contact_id: PersonId) -> f64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment about this being part of the trait extension.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At a high level, I don't think having a big design that describes the implementation separate from the code is that helpful. This is reasonably straightforward code and so inline comments should be sufficient. To the extent to which they are not, I would prefer whole file docs, either as API doc or just at the top of the file. That keeps it with the code.
If you want to have a document which describes the model structure rather than the code, I think that's reasonable.
docs/intervention.md
Outdated
@@ -0,0 +1,14 @@ | |||
# Interventions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please spell check this file.
docs/intervention.md
Outdated
# Interventions | ||
|
||
## Overview | ||
Introducing interventions that affect the relative transmission potential in a given infection attempt, either through relative risk of the susceptible individual or through realtive infecitousness of the transmitter individual. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please wrap this to 80 columns
src/transmission_modifiers.rs
Outdated
); | ||
|
||
trait ContextTransmissionModifierExt { | ||
fn register_intervention<T: PersonProperty + 'static + std::cmp::Eq + std::hash::Hash>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need Eq
and Hash
here.
fn register_aggregator( | ||
&mut self, | ||
agg_functions: Vec<(InfectiousStatusType, Box<AggregatorFn>)>, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't love this. IMO you should either:
- Have people specify one.
- Force them to specify all of them.
The Vec seems like false sugar, especially as you don't let people supply a vec of infectiousstatustype for registering interventions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the option of having to specify each over all. Agreed that the difference between registering modifiers and aggregators was confusing. Changed to be a single call per InfectiousStatusType (your option # 1)
src/transmission_modifiers.rs
Outdated
person_property: T, | ||
instance_dict: Vec<(T::Value, f64)>, | ||
); | ||
fn register_aggregator( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would call this register_intervention_aggregator
.
src/transmission_modifiers.rs
Outdated
&mut self, | ||
agg_functions: Vec<(InfectiousStatusType, Box<AggregatorFn>)>, | ||
); | ||
fn compute_intervention(&mut self, person_id: PersonId) -> f64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you computing the intervention or computing the effect of the interventions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The effect across interventions - is compute_relative_transmission clearer
?
if property_val == item.0 { | ||
return item.1; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any cases in which you would have a lot of values? If so, I would use a hashmap here. You can just convert it from the vec
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that we would have more than a few. Robert's comments made it seem like several hundred would be the turning point for preferring Hash. I don't think we would ever have a case where something like PersonId is a key
src/transmission_modifiers.rs
Outdated
fn compute_intervention(&mut self, person_id: PersonId) -> f64 { | ||
let infectious_status = self.get_person_property(person_id, InfectiousStatus); | ||
|
||
let mut registered_interventions: Vec<(TypeId, f64)> = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't need to type hint here. Rust can infer it.
src/transmission_modifiers.rs
Outdated
&mut self, | ||
infectious_status: InfectiousStatusType, | ||
person_property: T, | ||
instance_dict: Vec<(T::Value, f64)>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you calling this an instance_dict
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the document could use one more clean up to better articulate that we are modifying relative probability of transmission. I put a bunch of changes here to help guide it in that direction, but I acknowledge that part of this is taste and how we are each independently choosing to conceptualize the idea between an infection attempt, reduction in infection, etc.
- Mask wearing | ||
- Isolation | ||
- Vaccines | ||
- [Transmission modifiers](infection.md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't link to a document that doesn't yet exist (infection.md
).
docs/transmission_modifiers.md
Outdated
# Overview | ||
Infection attempts are not always successful (i.e. result in transmission) and many factors modify | ||
the probability of infection attempt success. These "transmission modifiers" can originate from the | ||
natural history of infection or from interventions, which are measures that are aimed to reduce |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am having trouble of thinking of an example beyond immunity or a new variant (which we agree is not a "good" use case) for how natural history of infection could impact transmission. Since we are trying to make clear that the transmission modifiers do not impact intrinsic infectiousness, could you specify what you mean by natural history here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
natural history of infection or from interventions, which are measures that are aimed to reduce | |
natural history of infection or from interventions aimed at reducing |
docs/transmission_modifiers.md
Outdated
of a natural modifiers, or wearing a facemask, in the case of intervention-based transmission | ||
modifiers, can lower the relative transmission potential of an infection attempt interaction. | ||
Transmission modifiers are not strictly independent, nor is it convenient to repeatedly define | ||
their specific use cases, which would require independent querying that is repetitive and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't follow what you're trying to say in this sentence. I don't think the concern is specific use cases but rather that we want interventions to be modular from transmission. If module A defines an intervention that modifies transmission, the transmission module shouldn't have to know about it and explicitly need to query it, a code structure that is prone to forgetting things.
docs/transmission_modifiers.md
Outdated
Transmission modifiers are not strictly independent, nor is it convenient to repeatedly define | ||
their specific use cases, which would require independent querying that is repetitive and | ||
error-prone. To avoid these pitfalls, this module provides a framework to incorporate transmission | ||
modifiers in a flexible and generalized manner, such that all modifiers are detected and aggregated |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, basically I think the point you get to here by the end of this chunk of text is sufficient for what you're trying to say in this paragraph.
We assume that the infectiousness of transmitter I is independent of, and therefore additive | ||
to, the risk of infection of contact S. | ||
|
||
The API hook to `evaluate_transmission` is independent of innate transmissiveness, which determines |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, a "hook" implies that when the function is called, the transmission modifiers manager automatically knows that and executes a function. Instead, we call the methods in the transmission modifier in the function body of evaluate_transmission
.
docs/transmission_modifiers.md
Outdated
`modifier_key` is one, meaning there is no change in the relative risk for unregistered types. This | ||
functional format is acceptable because we `define_person_property_with_default!`, and don't allow | ||
`PersonId`s without a `RiskCategory` to also default to one. Without a default for the | ||
`PersonProperty`, all individuals would be effectively in the `RiskCateogryType::High` group in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`PersonProperty`, all individuals would be effectively in the `RiskCateogryType::High` group in | |
`PersonProperty`, all individuals would effectively be in the `RiskCateogryType::High` group in |
} | ||
``` | ||
|
||
We define a default aggregator so that the user does not need to specify all or even any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One design caveat I see here is that the aggregator function registration is not modular. If a user wants to register their own custom modifier function, they need to be aware of all other interventions and their TypeId
s. In the short term, we should write this down as a caveat. In the long term, I wonder if we can design an interface so that you can specify how two (or some subset of all interventions) interact with a custom aggregator and then the rest of the interventions default to using the independence aggregator.
|
||
### Hook to aggregator from PersonId | ||
To calculate the total relative transmission potential change for an individual during an infection | ||
attempt, `Context` and the `PersonId` are supplied to `compute_relative_transmission`, which |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Context
isn't provided as an argument. The method is implemented as part of a trait extension on Context
.
} | ||
``` | ||
|
||
We use automatic iteration through all the modifications applied to a person, which is necessary to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use automatic iteration through all the modifications applied to a person, which is necessary to | |
We automatically apply each transmission modifier function to determine all the modifications applied to a person, which is necessary to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about naming this file transmission_modifiers_manager.rs
? transmission_modifiers
on its own sounds like it is a list of transmission modifiers, not that it manages those modifiers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only reviewed the markdown document. See my comments. I am not entirely sure how this module should, if at all, connect with what we call now natural history module. For instance, how would anti-virals change transmissibility, is this at the instantaneous transmission attempt or does it modify the infectiousness over time that will result in changes in the timing of infection attempts?
docs/transmission_modifiers.md
Outdated
of a natural modifiers, or wearing a facemask, in the case of intervention-based transmission | ||
modifiers, can lower the relative transmission potential of an infection attempt interaction. | ||
Transmission modifiers are not strictly independent, nor is it convenient to repeatedly define | ||
their specific use cases, which would require independent querying that is repetitive and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean by this sentence "which would require independent querying that is repetitive and error-prone"
## Hook to transmission manager | ||
In this module, we assume that an interaction between an infectious transmitter (I) and a | ||
susceptible contact (S) has already occured. We alter the [transmission manager](transmission.md) | ||
function `evaluate_transmission` that is conditioned on such an interaction. This is done using the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So transmission.rs will use evaluate_transmission provided by transmission_modifiers.rs? That's not quite clear to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Describe here how evaluate_transmission connects to this module
|
||
```rust | ||
fn query_infection_modifers(&mut self, transmitter_id: PersonId, contact_id: PersonId) -> f64 { | ||
self.compute_relative_transmission(transmitter_id) * self.compute_relative_transmission(contact_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit confused here, shouldn't we find modifiers of infection for transmitter and of susceptibility for contact?
docs/transmission_modifiers.md
Outdated
{ | ||
let relative_transmission = context.query_infection_modifiers(transmitter_id, contact_id) | ||
let transmission_success = | ||
context.sample_range(TransmissionRng, 0.0..1.0) < relative_transmission; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe ixa has a sample_bool method
docs/transmission_modifiers.md
Outdated
potential between I and S during an infection attempt, we need to register relative infectiousness | ||
and risk, respectively, of each modifier. We therefore use a `HashMap` to relate | ||
`InfectiousStatusType` to transmission modifiers with `TypeId`. These `TypeId` values then map to | ||
supplied relative transmission function that takes in `Context` and a `PersonId`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does the relative transmission function do?
docs/transmission_modifiers.md
Outdated
Before obtaining the total effect of all transmission modifiers acting on the relative transmission | ||
potential between I and S during an infection attempt, we need to register relative infectiousness | ||
and risk, respectively, of each modifier. We therefore use a `HashMap` to relate | ||
`InfectiousStatusType` to transmission modifiers with `TypeId`. These `TypeId` values then map to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on what TypeId means?
} | ||
``` | ||
|
||
## Modifier registration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would help if you write first a motivating example using these functions and then describe the functions.
```rust | ||
fn register_transmission_modifier<T: PersonProperty + 'static + std::cmp::Eq + std::hash::Hash>( | ||
&mut self, | ||
infectious_status: InfectiousStatusType, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that someone could register an intervention that modifies the recovery status or something like that? Is infectious status only susceptible or infectious? I guess if we only have those two components, it seems to me confusing to save as "infection_status".
type TransmissionAggregatorFn = dyn Fn(&Vec<(TypeId, f64)>) -> f64; | ||
``` | ||
|
||
Other modules will implement particular instances of transmission modifiers and the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate? It isn't clear to me what you mean by "other modules will implement..."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think overall throughout the document it would be more readable if there was a motivating example
Intervention skeleton
This PR introduces a generalized intervention manager that maps an intentionally ambiguous intervention type to an effect on relative transmission. The intervention manager has a register function and a query function to accomplish this. The
InterventionPlugin
uses a nestedHashMap
to relate infectious status to the intervention - relative transmission effect, and thus query can obtain both the relative risk ofSusceptible
individuals and the relative infectiousness ofInfectious
individuals. The register function therefore requires anInfectiousStatus
to properly register the relative transmission, defaulting to 1.0 if not specified by the user.Other changes
Transmission success is now no longer guaranteed; success depends on the additive effects of relative risk and infectiousness of the contact and transmitter involved in the infection attempt. During infection attempts we take a uniform draw and consider the attempt a success if the draw is less than the aggregate relative transmission.
Facemask intervention example
This manager is an example of defining an$R_0$ generated by the intrinsic rate of reproduction and the impact of facemasks.
enum
intervention type and registering it using the intervention manager. The facemask manager assigns each person a status ofWearing
, at a rate defined in the parameters input, orNone
. Included in the tests of the facemask manager are some experiments to test that the epidemic size in a population of 500 is approximately what we would expect from the effectiveNext steps