Interventions in STEM
STEM uses triggers, predicates and modifiers to implement interventions. A trigger contains predicate which, when satisfied, invokes one or more modifiers that changes some aspect of a running simulation. When the predicate is not satisfied any longer, the modified entities are set back to their original values.
STEM currently supports two types of predicate tests, which can be combined using boolean expressions. The tests are:
- Elapsed Time Test - Used to modify some aspect of a scenario after a given period of time has elapsed in a simulation.
- Label Value Test - Used to test the value of a disease or population label in a region
Observe that predicates are evaluated at each whole time step (e.g. day), and not during each incremental step when using the integrating solver (Runge Kutta).
Social Distancing Example
In the first example, we want to control an outbreak by implementing some sort of social distancing after a certain period of time has elapsed. We already have a scenario set up of an outbreak occuring in Malaysia, starting in Kuala Lumpur:
First create a new predicate by selecting the 'New predicate' button in the toolbar. Give it a name, e.g. "ElapsedTimePredicate". The editor for the predicate will open in a new window. Right click on the predicate and select "New Child", then "Elapsed Time Test":
Next, we need to specify the number of days we want to wait. Open the Properties sheet and enter '30' for the 'number of Days' property:
Now we need to determine what we want to modify in the scenario after 30 days have elapsed. Social distancing (e.g. distributing face masks, closing public buildings) reduces the transmissibility of an outbreak, so changing the transmission rate in the disease makes sense. In this case, reducing the transmission rate from 1.3 to 0.3 ensures that the reproductive number falls below 1.0 and the outbreak should be halted.
To create a modifier for a disease, right click on on the disease in the project explorer and select "Create Modifier":
The wizard for creating modifiers opens up. On the row for "Transmission Rate" (scroll down if needed), and in the column for "Select Modifier Type", press the "Single" option (the "Range" and "Sequence" options are only used in STEM Experiments). Enter 0.3 for the new value of transmission rate and then "Finish":
Now we need to create a trigger that will contain our predicate and modifier. Select the "New Trigger" button in the toolbar and give it a name (e.g. "SocialDistancingTrigger"). Drag the predicate and the modifier from the project explorer into the trigger:
Finally drag the trigger into the scenario:
When you run the scenario, you'll notice how after 30 days the outbreak is halted.
Now, let's say we want to only implement social distancing for a period of time. This is common since social distancing usually have economic impact. For instance, in Mexico City during the swine flu outbreak in 2009, restaurants, schools and public buildings were closed for approximately two weeks. While the outbreak was slowed down by that action, it bounced back when businesses re-opened again. Implementing social distancing for only a period of time can be accomplished in STEM simply by modifying the predicate we just created. We can use a boolean expression using an "AND' clause and a 'NOT' clause. First, delete the Elapsed Time Test under your 'ElapsedTimePredicate'. Next create a new child under 'ElapsedTimePredicate' by selecting 'And' from the popup menu:
Now right click on the & symbol and select "New Child" then "Elapsed Time Test". Use the properties sheet to set the number of days to 30. Right-click on the & symbol again, select "New Child" then "Not". Finally right-click on the ! symbol, select "New Child" then "Elapsed Time Test". Set the number of days to 44 in the properties sheet for the new elapsed time test (so the window of reduced transmissibility will be 2 weeks). In the end, it should look like this:
When you run the scenario again, you'll notice how the outbreak at first is halted after 30 days, but that it bounces back later since the social distancing policy stops:
In the social distancing example above, a reduction of the transmission rate applied globally and equally in all regions. In STEM, it is possible to handle interventions on a regional level by adding a control graph to your model. A control graph contains intervention labels that supports:
- Vaccinations - The total number of vaccinations carried out in a region in a time period. The time period is the period specified in the disease model (i.e. the same time period used for rate parameters).
- Isolations - The total number of patients isolated in a region in a time period.
When a developer implements a disease model in STEM, it is up to the developer to determine how vaccinations and isolations should be handled. Currently, for the deterministic SIR and SEIR models, vaccinations move people from the susceptible compartment to the recovered compartment, and isolations move people from the infectious compartment to the recovered compartment. Observe that in a more realistic model, vaccinations and isolations should have compartments of their own.
First, to add a control graph to your model press the "Define a new graph" button in the STEM toolbar and from the Source drop-down select "Control Label Graph Generator":
You have the option of entering values for the Fraction vaccinated and Fraction isolated. It is assumed that your project already has a model containing regional population graphs with population data. The new control graph will contain intervention labels for each region that exist in any model of your project, and the number of vaccinations/isolations in each region is the local population scaled by the fractions specified. If you only want to create a control graph for a subset of the regions in your model, you can pick a location and intervention labels will only be created for that region and any regions contained within.
For now, we will keep the Vaccinated and Isolated fractions as 0 meaning that no intervention are in place initially. We will change this later by a trigger in our scenario. Give the new control graph a name (e.g. InterventionGraph) and click 'Finish'. Ignore any warning messages that show up here.
Given that our project contained a model of Malaysia, the new InterventionGraph.graph should have intervention labels for the 15 regions in Malaysia with vaccinations and isolations set to 0 each each region:
Next, drag the InterventionGraph into the model in your scenario and save the model:
We now have the capability needed to implement interventions at a regional level, but so far no interventions are taking place. Let's say we want to start a mass-vaccination program when the total number of daily cases showing up in Malaysia goes above a threshold, say 100. First, we need to create a new predicate of the type 'Label Value Test'. Use the toolbar in STEM to create a new predicate, give it a name (e.g. "TotalIncidenceTest'). Next, right click on the new predicate, select "New Child", then "LabelValue Test". Select the new "Label Value Test" item in the editor and then open the property sheet. For the Model Name, enter the name of your disease (in this case 'Flu'). Observe this is the disease name attribute specified in your disease model, not the name of the disease file. Keep the Population Identifier as 'human', Predicate '>' (can be >, <, >=, <= or =), State 'incidence' (this is the value we want to test), Target URI 'stem://org.eclipse.stem/node/geo/region/MYS' (the URI of the target node, in this case Malaysia. You can find the URI from the Identifier Dublin Core attribute of the node in the graph containing the level 0 node of Malaysia. Keep the threshold at 100.
The new predicate aggregates the total incidence in all of Malaysia and when it goes above 100 total cases per day the predicate is satisfied and modifications are triggered. We want to implement a mass vaccination program, and to do this we increase the vaccination rate in each of the 15 regions from the current value of 0 to 10,000 (in reality the number should match the actual capacity which depends on the number of hospitals and clinics available in each region). We create 15 new modifiers for the vaccination labels in our InterventionGraph.graph file. Open the file in the editor, right click on the vaccination label (one at a time) then select "New Modifier". Give it a name, e.g. 'VaccinationModifier1", select Modifier type as 'Single' then enter 10000 for the number of vaccinations. Click finish. Repeat 15 times for each vaccination label in Malaysia.
Finally, create a new Trigger (using the New Trigger button in the toolbar), drag your predicate and the 15 modifiers into the trigger, then drag the trigger into your scenario.
When we run the scenario with the mass vaccination trigger, we get a dramatic difference in the total disease deaths at the end of the outbreak: