{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# T6 - Programs\n", "\n", "We have seen in previous tutorials how the flow rates between compartments are specified using _parameters_. Thus far, we have considered parameter values being specified in two ways\n", "\n", "- Directly specified via the databook\n", "- Computed as a function of other parameters\n", "\n", "However, a key function of Atomica is to model the impact of interventions. These interventions are typically framed in the following way:\n", "\n", "- The intervention has a unit cost associated with it (e.g. a treatment that costs \\$100/person)\n", "- A specified amount of money is made available for the intervention (e.g. \\$1000/year)\n", "- The intervention defines a parameter value (matching a parameter in the Framework) for people reached by the intervention. For example, the natural recovery rate for a rate for individuals on treatment may be 20\\%, but if someone is on treatment, they have a 90\\% chance of recovery\n", "\n", "At a high level, the calculation we wish to implement is as follows. Suppose we have an SIR model and there are 100 people infected and diagnosed at the start of the year. The \\$1000 of available funding means that 10 people can be treated that year. Of those 10 people, 90\\% of them recover, leading to 9 people moving to the 'Recovered' state. For the remaining 90 people, 20\\% of them recover, leading to 18 natural recoveries. So that year, a total of 27 people will move from 'Infected' to 'Recovered'. \n", "\n", "In the calculation above, the natural recovery rate of 20\\% is readily entered in the databook. However, we wish to parametrize the effect of the intervention in terms of spending, unit cost, and the impact of the intervention for those it reaches. Although it would be possible to implement the calculation via parameter functions, it quickly becomes cumbersome if there are multiple interventions affecting the same model parameter. Therefore, we introduce a second pathway for calculating parameter values, using **'Programs'**. A schematic overview of how programs relate to model parameter values is shown below: \n", "\n", "![t6-parameter-overview](assets/T6/t6_parameter_overwrite.png)\n", "\n", "The role of programs is to generate parameter values as a function of spending and coverage. These parameter values then replace the parameter values from the databook during a simulation.\n", "\n", "Parameter values from the _databook_ are stored in a _ParameterSet_ which is used to produce results for any given databook and calibration. Similarly, program-specific inputs are read in from the _program book_ which maps to a _ProgramSet_. A ProgramSet together with a set of _program instructions_ is used to generate results incorporating the effect of programs. A schematic overview of how these inputs relate to results is shown below:\n", "\n", "![t6-model-structure](assets/T6/t6_model_structure.png)\n", "\n", "We will now implement the SIR model with a treatment program described above, to see how these different components are instantiated and used within Atomica. First, we will load in a framework and databook for a simple SIR model:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import atomica as at\n", "import matplotlib.pyplot as plt\n", "P = at.Project(framework='assets/T6/t6_framework_1.xlsx',databook='assets/T6/t6_databook_1.xlsx', do_run=False)\n", "P.settings.update_time_vector(dt=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This framework is much the same as the SIR framework in previous tutorials, except that on the parameters sheet, an additional column called 'Targetable' is present. This column specifies whether certain parameters should appear in program books. Since we know that the treatment program is going to change the value of the disease recovery rate, this parameter has a 'y' in the 'Targetable' column:\n", "\n", "![t6-framework-targetable](assets/T6/t6_framework_targetable.png)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "res = P.run_sim(P.parsets[0]);\n", "d = at.PlotData(res,['sus','inf','rec'])\n", "at.plot_series(d,plot_type='stacked');\n", "plt.title('Population disease state breakdown');\n", "\n", "d = at.PlotData(res,'inf:rec')\n", "at.plot_series(d);\n", "plt.title('Recovery flow (people/year)');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will now produce a 'Program book' (sometimes referred to as a 'Progbook') to define our treatment program. The key attributes that we need to capture for the program are\n", "\n", "- _Who_ is eligible to receive the program - this is referred to as the program targeting\n", "- _How much_ the program costs per person\n", "- _What_ is the effect of the program on parameter values\n", "\n", "The example earlier in this tutorial corresponds to the following\n", "\n", "- Everyone who is infected is eligible for the program\n", "- The program costs $100/person\n", "- Individuals that are treated have a 90\\% recovery rate\n", "\n", "Within each of these three main areas are various additional options for more sophisticated programs - for example, programs targeted only at particular sub-populations, programs that can only be scaled up to a finite limit, and programs interacting with other programs. These are discussed in more detail in the full program documentation [here](http://atomica.tools/docs/master/general/programs/Programs.html).\n", "\n", "Notice that program targeting needs to specify which disease states are targeted (e.g. 'Infected') and which populations are targeted (e.g. 'Adults'). These are defined in the framework and databook, respectively. Therefore, while the databook depends only on the framework, the program book depends on both the framework and the databook. This is reflected in the command to create a new program set, which takes in both a framework and a databook:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "progset = at.ProgramSet.new(framework=P.framework, data=P.data, tvec=[2020], progs=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the same way that databook and a `ProjectData` object are interchangable and can be thought of as different representations of the same data, the same is true for a program book and a `ProgramSet`. Therefore, the command above is used to produce a new `ProgramSet` which can then be written to a file using the `save` method: " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "progset.save('temp.xlsx');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Alternatively, a program book can be created for a given project by using the project's `make_progbook` method, which will automatically pass in the project's framework and data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "P.make_progbook('temp.xlsx',progs=1,data_start=2020,data_end=2021);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The program book contains three sheets, corresponding to the three key attributes being captured. On the 'Program targeting' sheet, the populations and compartments reached by the program are entered. For the treatment program here, we select only the 'Infected' compartment. We also need to enter 'Y' for the 'Adults' population.\n", "\n", "![t6-sheet-targeting](assets/T6/t6_sheet_targeting.png)\n", "\n", "