diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..8ef3b7cdf --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,87 @@ +name: Documentation + +on: + push: + branches: [main] + pull_request: + types: [opened, reopened, synchronize, closed] + +permissions: + contents: read + pull-requests: write + +jobs: + # Publish main docs to atomica.tools/docs/main/ + publish: + if: github.event_name == 'push' + runs-on: ubuntu-latest + concurrency: + group: docs-${{ github.ref_name }} + cancel-in-progress: true + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: actions/setup-python@v5 + with: + python-version: '3.14' + - name: Install pandoc + run: sudo apt-get install -y pandoc + - name: Install Python dependencies + run: | + python -m pip install uv + uv pip install --system -e ".[docs]" + - name: Build documentation + run: python -m sphinx.cmd.build docs doc_build -j2 + - name: Deploy to atomicateam/docs + uses: JamesIves/github-pages-deploy-action@v4 + with: + repository-name: atomicateam/docs + token: ${{ secrets.DOCS_DEPLOY_TOKEN }} + branch: master # docs repo serves Pages from master root + folder: doc_build + target-folder: ${{ github.ref_name }} + clean: true # scoped to target-folder; leaves other folders, .nojekyll and index.html intact + single-commit: true # keep the docs repo history from ballooning + + # Deploy/remove a per-PR preview at atomica.tools/docs/pr-preview/pr-/ + preview: + # Skip forks: they cannot access the deploy secret + if: >- + github.event_name == 'pull_request' && + github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + concurrency: + group: docs-preview-${{ github.event.number }} + cancel-in-progress: true + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: actions/setup-python@v5 + if: github.event.action != 'closed' + with: + python-version: '3.14' + - name: Install pandoc + if: github.event.action != 'closed' + run: sudo apt-get install -y pandoc + - name: Install Python dependencies + if: github.event.action != 'closed' + run: | + python -m pip install uv + uv pip install --system -e ".[docs]" + - name: Build documentation + if: github.event.action != 'closed' + run: python -m sphinx.cmd.build docs doc_build -j2 + - name: Deploy / update / remove preview + uses: rossjrw/pr-preview-action@v1 + with: + token: ${{ secrets.DOCS_DEPLOY_TOKEN }} + source-dir: doc_build + deploy-repository: atomicateam/docs + preview-branch: master + umbrella-dir: pr-preview + pages-base-url: atomica.tools/docs + qr-code: false + wait-for-pages-deployment: true + action: auto diff --git a/azure-pipelines.yml b/azure-pipelines.yml index db3e5fad6..e4bd6a542 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -45,40 +45,7 @@ jobs: summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' # reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov' -- job: 'docs' - condition: and(ne(variables['Build.Reason'], 'PullRequest'), ne(variables['Build.Reason'], 'Schedule')) # Skip if it's a PR build or a scheduled build - pool: - vmImage: 'ubuntu-latest' - steps: - - task: UsePythonVersion@0 - displayName: 'Select python version' - inputs: - versionSpec: '3.14' - - script: | - sudo apt install pandoc -y - displayName: 'Install pandoc' - - script: | - python -m pip install uv - uv pip install --system -e ".[docs]" - displayName: 'Install Python dependencies' - - script: | - mkdir doc_build - python -m sphinx.cmd.build "docs" "doc_build/$(Build.SourceBranchName)" -j2 - displayName: 'Build documentation' - # Invoke directly with `python -m sphinx.cmd.build` instead of `sphinx-build` to avoid "sphinx-build: command not found" on Azure - - script: | - git clone --depth 1 https://github.com/atomicateam/docs doc_repo - rm -rf doc_repo/$(Build.SourceBranchName) - mv doc_build/$(Build.SourceBranchName) doc_repo/$(Build.SourceBranchName) - git -C doc_repo config user.email ci@azurepipelines - git -C doc_repo config user.name "Azure Pipelines" - git -C doc_repo add . - git -C doc_repo commit -m "Automatic update" - git -C doc_repo push https://$(GithubToken)@github.com/atomicateam/docs - displayName: 'Publish site' -# - publish: docs/_build -# artifact: docs -# displayName: 'Publish documentation as Azure zip file' +# Documentation is built and published via GitHub Actions (.github/workflows/docs.yml) - job: 'deploy' dependsOn: 'tox' diff --git a/docs/examples/Basic-workflow.ipynb b/docs/examples/Basic-workflow.ipynb index e2883826d..8e4cc5c12 100644 --- a/docs/examples/Basic-workflow.ipynb +++ b/docs/examples/Basic-workflow.ipynb @@ -148,7 +148,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For full details on plotting, please refer to the full plotting documentation [here](https://atomica.tools/docs/master/examples/Plotting.html)." + "For full details on plotting, please refer to the full plotting documentation [here](https://atomica.tools/docs/main/examples/Plotting.html)." ] }, { @@ -501,7 +501,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For more details on the optimization system, see the [general documentation](https://atomica.tools/docs/master/general/Optimization.html) on optimization." + "For more details on the optimization system, see the [general documentation](https://atomica.tools/docs/main/general/Optimization.html) on optimization." ] } ], diff --git a/docs/general/Optimization.md b/docs/general/Optimization.md index 7b472eed0..5f25a096b 100644 --- a/docs/general/Optimization.md +++ b/docs/general/Optimization.md @@ -62,7 +62,7 @@ An `Adjustment` contains An `Adjustment` has the following methods - `Adjustment.get_initialization(progset,instructions)` - this method returns a vector of initial values for each adjustable, which are the default initial values for ASD. There are several possible places where initial values can be stored. Consider spending values. In order of precedence, the places where default values could be defined are: - - In the `Adjustable`. For example, the `SpendingAdjustment` in an optimization might wish to explictly store an initial value to start the optimization at + - In the `Adjustable`. For example, the `SpendingAdjustment` in an optimization might wish to explicitly store an initial value to start the optimization at - In the `ProgramInstructions` - the program instructions optionally contains a `TimeSeries` of spending values that overwrite the data spending values stored in the `ProgramSet`, which is the used to implementing budget scenarios - In the `ProgramSet`, each program by default has spending specified in the Progbook file diff --git a/docs/general/population-types/Population-Types.rst b/docs/general/population-types/Population-Types.rst index 4131602ac..15aded547 100644 --- a/docs/general/population-types/Population-Types.rst +++ b/docs/general/population-types/Population-Types.rst @@ -40,7 +40,7 @@ The restriction that transfers cannot take place across population types helps t - There can never be a transfer between a mosquito population and a human population, because this would represent mosquitos turning into humans. Thus, a population type would be appropriate for this - Similarly, there can never be a transfer between a human population and the environment e.g. a human turning into a lake. Thus, an environment population to track water pollution would be well represented with a different population type -- There may be a separate set of disease states if a model includes coinfection. For example, there may be more possible treatment states for TB+HIV compared to TB or HIV alone. If it is possible for an individual to move from TB to TB+HIV or between other coinfection states, then these should *not* be different population types. Instead, the all of the coinfection states should be added as compartments within a single population type +- There may be a separate set of disease states if a model includes coinfection. For example, there may be more possible treatment states for TB+HIV compared to TB or HIV alone. If it is possible for an individual to move from TB to TB+HIV or between other coinfection states, then these should *not* be different population types. Instead, all of the coinfection states should be added as compartments within a single population type - Some nutrition models for maternal and child health model adult women and children completely independently, such that no children grow up and become adult women. In these types of models, children simply exit the model once they reach a certain age (e.g. 5 years old). For this type of model, it would be suitable to have separate population types for women and children. That way, stunting and wasting compartments would not need to be created for adults, only children. However, if it is possible for children to become adults within the model, then there should *not* be different population types - otherwise, it would be impossible to transfer people from the child populations to the adult population .. note:: @@ -77,7 +77,7 @@ Next, do the same for Characteristics and Parameters. Notice how the characteristics sheet has omitted the population type for the 'sir'-related quantities, which will be automatically assigned because the 'sir' population type is the first one in the list. In general, it is better to explicitly specify the population type for all quantities. However, if there are many quantities and only a few of them belong to a different population type, this default behaviour can make it easier to fill out the Framework. -Note that characteristics cannot span population types - the included compartments and the denominator must all belong to the same population type as the characteristic itself. This is because characteristics are always evaluated within a single population, so all of the constitutents of the characteristic must exist within that population. +Note that characteristics cannot span population types - the included compartments and the denominator must all belong to the same population type as the characteristic itself. This is because characteristics are always evaluated within a single population, so all of the constituents of the characteristic must exist within that population. .. image:: framework_4.png :width: 650px @@ -108,12 +108,12 @@ If your parameter function refers to an interaction, then the quantity being agg If you want to have an interaction only between certain populations within a population type - for example, if only adults contribute to water pollution - then create an Interaction and set the weights to 0 in the databook for the populations that should be excluded. -The final place population types appear in the Framework is in the transition matrix. Transitions are possible between compartments of the same population type. As a general rule, you should have as many transition matrices as you do population types with compartments. In the example above, there are three population types, but only the ``sir`` and ``udt`` population types have compartments within them. Therefore, we will have two transition matrices. These both appear on the 'Transitions' sheet. To define multiple transition matricies, simply insert them onto the transitions sheet stacked vertically, separated by an empty row. For example: +The final place population types appear in the Framework is in the transition matrix. Transitions are possible between compartments of the same population type. As a general rule, you should have as many transition matrices as you do population types with compartments. In the example above, there are three population types, but only the ``sir`` and ``udt`` population types have compartments within them. Therefore, we will have two transition matrices. These both appear on the 'Transitions' sheet. To define multiple transition matrices, simply insert them onto the transitions sheet stacked vertically, separated by an empty row. For example: .. image:: framework_6.png :width: 500px -In the top left cell of the transition matrix, enter the code name for the population type. For example, the above screenshot shows 'udt' entered into cell A7. If the population type is omitted, it will default to the first population type in the framework. So the empty cell A1 will be automatically populated with 'sir' in this example. All of the compartments in the transition matrix must have the same type as the transition matrix itself (e.g., with 'udt' in cell A7, the compartment in cell B7 must exist in the 'udt' population type). This is atuomatically checked and validated when the framework is loaded. Similarly, all of the parameters in each transition matrix must belong the corresponding population type. +In the top left cell of the transition matrix, enter the code name for the population type. For example, the above screenshot shows 'udt' entered into cell A7. If the population type is omitted, it will default to the first population type in the framework. So the empty cell A1 will be automatically populated with 'sir' in this example. All of the compartments in the transition matrix must have the same type as the transition matrix itself (e.g., with 'udt' in cell A7, the compartment in cell B7 must exist in the 'udt' population type). This is automatically checked and validated when the framework is loaded. Similarly, all of the parameters in each transition matrix must belong the corresponding population type. Databook population types -------------------------- @@ -137,7 +137,7 @@ Notice how every population has both a label and a type. The 'Population Definit .. warning:: - The data entry rows are created when the databook is generated, and they take into account the population types. It is not possible to change the type of a population after it has been created. The population type cells are grey to reflect this. Changing the population type by overwriting those cells will likely result in an error (unless all of the data entry tables are also updated manually). Instead, you should load the databook into Atomica and programatically remove the old population, and make a new one with the desired type. + The data entry rows are created when the databook is generated, and they take into account the population types. It is not possible to change the type of a population after it has been created. The population type cells are grey to reflect this. Changing the population type by overwriting those cells will likely result in an error (unless all of the data entry tables are also updated manually). Instead, you should load the databook into Atomica and programmatically remove the old population, and make a new one with the desired type. The data entry tables are essentially unchanged from normal databooks where there is only one population type. However, notice that the available populations under each quantity depend on the population type. For example, 'All people with condition' is defined in the 'udt' population type, so data entry is provided only for the UDT populations. @@ -174,7 +174,7 @@ Programs and population types Programs also support population types, but the implementation is relatively simple compared to frameworks and databooks. -On the 'Program targeting' sheet, all populations and all compartments are shown, regardless of which population type they are in. You can select any population and any compartment to target. The number of people targeted by the program is defined as the sum of all compartments that are targeted by the program. Thus, any nonexistent compartments will simply be skipped in the this summation. Consider the example shown below: +On the 'Program targeting' sheet, all populations and all compartments are shown, regardless of which population type they are in. You can select any population and any compartment to target. The number of people targeted by the program is defined as the sum of all compartments that are targeted by the program. Thus, any nonexistent compartments will simply be skipped in this summation. Consider the example shown below: .. image:: progbook_1.png :width: 650px diff --git a/docs/general/programs/Programs.rst b/docs/general/programs/Programs.rst index 23eaf0200..c6356c814 100644 --- a/docs/general/programs/Programs.rst +++ b/docs/general/programs/Programs.rst @@ -70,7 +70,7 @@ When the program book is loaded in, these data are stored in three key classes - A :class:`ProgramSet` contains a collection of :class:`Program` objects and a collection of :class:`Covout` objects - A :class:`Program` object contains all of the information on the 'Program targeting' sheet and the 'Spending data' sheet. There is one program object for each row in the 'Program targeting' sheet -- A :class:`Covout` object contains all of the information on a single row of the 'Program effects' sheet. It thus contains all of the program outcomes for a single parameter in a single population. Storing the program outcomes grouped by parameter rather than grouped by program facilitates computing interations between programs. This process is described in more detail below - :ref:`Outcomes`. +- A :class:`Covout` object contains all of the information on a single row of the 'Program effects' sheet. It thus contains all of the program outcomes for a single parameter in a single population. Storing the program outcomes grouped by parameter rather than grouped by program facilitates computing interactions between programs. This process is described in more detail below - :ref:`Outcomes`. This class structure is depicted visually below: diff --git a/docs/general/timed-transitions/Timed-Transitions.rst b/docs/general/timed-transitions/Timed-Transitions.rst index c1ab6860b..3d3611be1 100644 --- a/docs/general/timed-transitions/Timed-Transitions.rst +++ b/docs/general/timed-transitions/Timed-Transitions.rst @@ -4,18 +4,18 @@ Timed transitions Motivation ********** -In Atomica, compartments typically correspond to states than an individual can be in. Often, in reality an individual needs to spend a certain amount of time in a particular state. For example, a particular treatment might have a certain duration, or an asymptomatic initial infection state might last for a particular amount of time. In a compartment based model that has reached a steady state, the inflow of people into a compartment is equal to the outflow. In that case, the equilibrium value of the compartment is equal to the duration. For example, suppose a compartment has an inflow of 100 people/year. If the duration is 5 years, the equilibrium value would be 500 people - each year, 100 people arrive and 100 people leave, so on average, it takes 5 years to leave the compartment. +In Atomica, compartments typically correspond to states that an individual can be in. Often, in reality an individual needs to spend a certain amount of time in a particular state. For example, a particular treatment might have a certain duration, or an asymptomatic initial infection state might last for a particular amount of time. In a compartment based model that has reached a steady state, the inflow of people into a compartment is equal to the outflow. In that case, the equilibrium value of the compartment is equal to the duration. For example, suppose a compartment has an inflow of 100 people/year. If the duration is 5 years, the equilibrium value would be 500 people - each year, 100 people arrive and 100 people leave, so on average, it takes 5 years to leave the compartment. This approach is widely used and is entirely valid in the steady state. In the steady state, the arrival times of people in the compartment can be considered uniformly distributed over the compartment's duration, so randomly selecting a portion of people to move out of the compartment results in the correct number of transitions. This assumption breaks down when inflow to the compartment varies over time. Because the true arrival time is not tracked, it's possible for someone to enter the compartment and immediately leave it in the next time step. This is reflected in the fact that the duration of a particular compartment is really an average duration, not a strict duration. In most circumstances, the standard compartment assumptions are sufficiently satisfied for the model to produce results within required tolerances. In particular, the fact that the duration assumptions are not exactly met is of secondary importance either when the inflow and outflow is approximately matched (typically when the inflow is significantly smaller than the compartment's size, which implies that the inflow has only a small effect on the outflow) or when the compartment's duration is short (e.g. a few timesteps). -There are some circumstances however, when both of these requirements are grossly violated. In that case, the model does not produce usable results. A common example would be mass vaccination campaigns. In that case, the proportion of people vaccinated changes very quickly, e.g. from 0% to 70% in a single year. Further, the duration of protection of vaccines tends to be quite long, for example, 5 years. In a simulation with quarterly timesteps, this would correspond to 20 timesteps. We might model this as vaccination moving people from a 'susceptible' compartment to a 'vaccinated' compartment, and protection wearing off as a transition from 'vaccinated' back to 'susceptible'. However, if we simply used the standard compartment assumptions, then people would be allowed to transition from 'vaccinated' to 'susceptible' immediately after being vaccinated. In this example, it is particularly noticable because the initial proportion vaccinated was 0% - therefore, it is obvious that *nobody* should lose their vaccinated status until after 5 years. Further, the dynamics of the simulation would be significantly affected because the proportion vaccinated was very large (70%). Finally, if the mass vaccination is a temporary program (e.g. 1 year long) then the vaccination rate changes rapidly (from 0, to 70% of the population, then back to 0) over just a few timesteps. The standard compartment assumptions will not produce useful projections in these circumstances, so a different approach is required. To address this, Atomica implements **timed compartments** that explictly track arrival times, and allow transitions to take place only after a period of time has elapsed. +There are some circumstances however, when both of these requirements are grossly violated. In that case, the model does not produce usable results. A common example would be mass vaccination campaigns. In that case, the proportion of people vaccinated changes very quickly, e.g. from 0% to 70% in a single year. Further, the duration of protection of vaccines tends to be quite long, for example, 5 years. In a simulation with quarterly timesteps, this would correspond to 20 timesteps. We might model this as vaccination moving people from a 'susceptible' compartment to a 'vaccinated' compartment, and protection wearing off as a transition from 'vaccinated' back to 'susceptible'. However, if we simply used the standard compartment assumptions, then people would be allowed to transition from 'vaccinated' to 'susceptible' immediately after being vaccinated. In this example, it is particularly noticeable because the initial proportion vaccinated was 0% - therefore, it is obvious that *nobody* should lose their vaccinated status until after 5 years. Further, the dynamics of the simulation would be significantly affected because the proportion vaccinated was very large (70%). Finally, if the mass vaccination is a temporary program (e.g. 1 year long) then the vaccination rate changes rapidly (from 0, to 70% of the population, then back to 0) over just a few timesteps. The standard compartment assumptions will not produce useful projections in these circumstances, so a different approach is required. To address this, Atomica implements **timed compartments** that explicitly track arrival times, and allow transitions to take place only after a period of time has elapsed. Use cases --------- -Timed compartment should generally **not** be used when there is a constant inflow/outflow, or if inflows and outflows are slowly changing, even if there is a 'duration' associated with the state. In a compartment model, the amount of time people spend in the compartment follows an exponential distribution. In the steady state, only the mean matters. When things change rapidly, then discrepencies can occur. These discrepencies are largest if the compartment has a long expected duration relative to the step size, and if the inflow changes dramatically. Therefore, timed compartments are typically suitable under the following circumstances +Timed compartment should generally **not** be used when there is a constant inflow/outflow, or if inflows and outflows are slowly changing, even if there is a 'duration' associated with the state. In a compartment model, the amount of time people spend in the compartment follows an exponential distribution. In the steady state, only the mean matters. When things change rapidly, then discrepancies can occur. These discrepancies are largest if the compartment has a long expected duration relative to the step size, and if the inflow changes dramatically. Therefore, timed compartments are typically suitable under the following circumstances - The expected time in the compartment is long relative to the step size (e.g. >4 timesteps), and - At the end of the duration, all individuals transition to the same compartment (although this could be a junction), and @@ -51,7 +51,7 @@ One example of where this usage would be inappropriate Basic implementation ******************** -Fundamentally, timed compartments leverage the fact that in Atomica, an individual must spend at least one timestep in each compartment (except for junction compartments) because new arrivals to a compartment are not eligible to move out of the compartment in the same timestep. Thus, we can explictly model a duration within the standard Atomica framework as a chain of compartments, where there are multiple compartments corresponding to a single state. For example, consider the case where a state lasts for 1 year, and there are quarterly timesteps. This could be set up as shown in the top part of the figure below: +Fundamentally, timed compartments leverage the fact that in Atomica, an individual must spend at least one timestep in each compartment (except for junction compartments) because new arrivals to a compartment are not eligible to move out of the compartment in the same timestep. Thus, we can explicitly model a duration within the standard Atomica framework as a chain of compartments, where there are multiple compartments corresponding to a single state. For example, consider the case where a state lasts for 1 year, and there are quarterly timesteps. This could be set up as shown in the top part of the figure below: .. image:: Slide1.PNG :width: 100% @@ -65,7 +65,7 @@ Therefore, timed compartments are implemented as the bottom sequence shown below .. note:: - A 'timed parameter' is one that is marked with a 'y' in the 'Timed' column of the framework - - A 'flush link' is a transition goverened by a 'timed parameter'. There can only be one flush link per compartment. After the duration period has expired, all individuals that have been in the compartment for the specified duration are moved out of the compartment via the flush link. The figure shows the flush link as a red dashed arrow. + - A 'flush link' is a transition governed by a 'timed parameter'. There can only be one flush link per compartment. After the duration period has expired, all individuals that have been in the compartment for the specified duration are moved out of the compartment via the flush link. The figure shows the flush link as a red dashed arrow. - A 'timed compartment' is a compartment that has a flush link - The 'flush state' is the compartment that the flush link transfers people to - The 'initial subcompartment' is the 'compartment' where new arrivals enter (the 'T=1' compartment in the figure above) @@ -186,7 +186,7 @@ As described above, links across duration groups can transfer people in all subc .. image:: Slide10.PNG :width: 450px -Suppose that the step size is 1, the duration of protection ``dur`` is 10, and the people in ``vac`` are uniformly distributed over arrival times. Thus, 10 people need to transition from ``vac`` to ``sus`` and they are thus ineligible to move to ``vacdxr``. The parameter ``tx`` needs to be split across the two links. Should this be done in a ``200:100`` ratio, or a ``200:90`` ratio? The model uses the ``200:100`` ratio, so the logic is the same regardless of whether a timed link or a link is driving the transition. The interpretation of this is that the eligiblity of people for the transition is not known ahead of time. In general, it is common for links to move a smaller number of people than the corresponding number parameter, simply because links often get downscaled to prevent negative compartment sizes. The other reason for using the ``200:100`` is that it better preserves the equivalency between probability and number, where the number transitioning can always be expressed as a probability relative to the number of people in the source compartments, and using that probability as the parameter value instead of a number would provide identical results. +Suppose that the step size is 1, the duration of protection ``dur`` is 10, and the people in ``vac`` are uniformly distributed over arrival times. Thus, 10 people need to transition from ``vac`` to ``sus`` and they are thus ineligible to move to ``vacdxr``. The parameter ``tx`` needs to be split across the two links. Should this be done in a ``200:100`` ratio, or a ``200:90`` ratio? The model uses the ``200:100`` ratio, so the logic is the same regardless of whether a timed link or a link is driving the transition. The interpretation of this is that the eligibility of people for the transition is not known ahead of time. In general, it is common for links to move a smaller number of people than the corresponding number parameter, simply because links often get downscaled to prevent negative compartment sizes. The other reason for using the ``200:100`` is that it better preserves the equivalency between probability and number, where the number transitioning can always be expressed as a probability relative to the number of people in the source compartments, and using that probability as the parameter value instead of a number would provide identical results. Although using ``200:100`` instead of ``200:90`` can seem counterintuitive, this occurs in many other places too. For example, a treatment may be provided to someone who dies of unrelated causes prior to being successfully treated. All the implementation is saying is that flows are not targeted at specific subcompartments, and if someone needs to leave the duration group and they are also eligible for a transition that would see them remain in the duration group, they are guaranteed to leave the group. @@ -199,7 +199,7 @@ Transfers Transfers between populations also need to preserve time spent in a duration group - for example, children that have been vaccinated and that subsequently change age groups retain their duration of protection. However, in some cases, the duration associated with the timed compartment may differ across populations. For example, a vaccine may last longer in adults than in children, or coinfection with HIV could decrease incubation time. -The figure below shows how discrepencies in durations are managed. The incoming ``TimedLink`` corresponds to the duration in the source population. If the duration in the destination is longer, then the original time remaining until the individual needs to leave the duration group is preserved. For example, if an 11 year old is vaccinated with a vaccine that has a duration protection of 5 years in children and 10 years in adults, and they are subsequently transferred from a ``5-14`` population to a ``15-64`` population when they turn 15, they will retain their original 5 year duration of protection, and will have their vaccine expire after spending 1 more year in ``15-64``. +The figure below shows how discrepancies in durations are managed. The incoming ``TimedLink`` corresponds to the duration in the source population. If the duration in the destination is longer, then the original time remaining until the individual needs to leave the duration group is preserved. For example, if an 11 year old is vaccinated with a vaccine that has a duration protection of 5 years in children and 10 years in adults, and they are subsequently transferred from a ``5-14`` population to a ``15-64`` population when they turn 15, they will retain their original 5 year duration of protection, and will have their vaccine expire after spending 1 more year in ``15-64``. In contrast, if the destination population has a shorter duration of protection than the source population, individuals are 'accelerated' by transferring them into the initial subcompartment. For example, suppose the normal incubation period of a disease is 4 weeks, but in a PLHIV population it is 1 week. If an individual acquires the disease in the main population, and then is transferred to the PLHIV population 1 week later, they would normally have 3 weeks of incubation remaining, but this would be reduced to 1 week after the transfer. @@ -216,7 +216,7 @@ Timed compartments can be used in conjunction with junctions. However, we have s In the top case, without a junction, the two links have different eligibility in the ``vac`` compartment. However, with the junction, only a single link connects ``vac`` to the junction. What should the eligibility of this link be? In general, we cannot have outflows from a junction where some links preserve durations, and others do not. -Similarly, junctions that recieve a flush link from a duration group cannot then move those people back into the duration group. The interpretation of a flush link is that it transfers people out of the duration group. These rules must be satisfied even if the junction is indirect (transferring people via additional junctions). +Similarly, junctions that receive a flush link from a duration group cannot then move those people back into the duration group. The interpretation of a flush link is that it transfers people out of the duration group. These rules must be satisfied even if the junction is indirect (transferring people via additional junctions). .. image:: Slide16.PNG :width: 100% diff --git a/docs/tutorial/T1-Defining-a-model.ipynb b/docs/tutorial/T1-Defining-a-model.ipynb index 228145598..fafb5c48a 100644 --- a/docs/tutorial/T1-Defining-a-model.ipynb +++ b/docs/tutorial/T1-Defining-a-model.ipynb @@ -317,7 +317,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The plotting system in Atomica is fairly large - refer to the code documentation http://atomica.tools/docs/master/examples/Plotting.html for more information." + "The plotting system in Atomica is fairly large - refer to the code documentation http://atomica.tools/docs/main/examples/Plotting.html for more information." ] }, { diff --git a/docs/tutorial/T2-Calibration.ipynb b/docs/tutorial/T2-Calibration.ipynb index 9c0dbab23..fb3244df0 100644 --- a/docs/tutorial/T2-Calibration.ipynb +++ b/docs/tutorial/T2-Calibration.ipynb @@ -212,7 +212,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "See [https://atomica.tools/docs/master/general/Compartment-Initialization.html](https://atomica.tools/docs/master/general/Compartment-Initialization.html) for more information on how the initialization of compartment sizes is carried out by Atomica. " + "See [https://atomica.tools/docs/main/general/Compartment-Initialization.html](https://atomica.tools/docs/main/general/Compartment-Initialization.html) for more information on how the initialization of compartment sizes is carried out by Atomica. " ] }, { diff --git a/docs/tutorial/T6-Programs.ipynb b/docs/tutorial/T6-Programs.ipynb index d38860beb..e2e0fbdde 100644 --- a/docs/tutorial/T6-Programs.ipynb +++ b/docs/tutorial/T6-Programs.ipynb @@ -85,7 +85,7 @@ "- 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", + "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/main/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:" ] diff --git a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb index f557fd602..74f897c5e 100644 --- a/docs/tutorial/T7/T7_YAML_autocalibration.ipynb +++ b/docs/tutorial/T7/T7_YAML_autocalibration.ipynb @@ -47,7 +47,7 @@ "source": [ "## Basic calibration example\n", "\n", - "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](https://atomica.tools/docs/master/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `T7/assets`." + "In this tutorial, we will work with a simple version of a typhoid model. This model captures typhoid infections, as well as asymptomatic carriers and vaccination. Firstly, we need to create an Atomica `Project` by loading in the Framework and Databook files, just like we did in [the first Atomica tutorial](https://atomica.tools/docs/main/tutorial/T1-Defining-a-model.html). The Framework and Databook for this project can be found in the Atomica repository under `T7/assets`." ] }, { @@ -289,7 +289,7 @@ "\n", "- `meas_label` (required): Measurable parameter codename (can be found in the framework)\n", "- `pop_name`: Population to use for calibration (default: all populations)\n", - "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/master/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", + "- `weight`: Weight for a particular population (default: 1). By default, all populations are weighted equally regardless of size. See [the documentation on weights](https://atomica.tools/docs/main/general/YAML_calibration.html#Measurable-Weights \"Measurable weights\") for further details.\n", "- `metric`: Metric to be used by the optimization algorithm (default: fractional)\n", "- `cal_start`: Starting year that the calibration will be evaluated from (default: `sim_start`)\n", "- `cal_end`: End year until which the calibration will be evaluated (default: `sim_end`)\n", @@ -353,7 +353,7 @@ " \tcal_start: 2000\n", " \tcal_end: 2040\n", "\n", - "Finally, the same syntax we use to calibrate populations can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on how to calibrate in these cases, see the documentation on [Calibrating transfers and interactions](https://atomica.tools/docs/master/general/YAML_calibration.html#Calibrating-transfers-and-interactions \"Calibrating transfers and interactions\")." + "Finally, the same syntax we use to calibrate populations can be used to calibrate transfers and interactions, but in such cases the tuple should have three elements - the parameter name, the _from_ population and the _to_ population. For more information on how to calibrate in these cases, see the documentation on [Calibrating transfers and interactions](https://atomica.tools/docs/main/general/YAML_calibration.html#Calibrating-transfers-and-interactions \"Calibrating transfers and interactions\")." ] }, { @@ -385,7 +385,7 @@ "\n", "\"Post-initialization\n", "\n", - "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient can still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases a small initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation on this topic](https://atomica.tools/docs/master/general/Compartment-Initialization.html \"Initializing compartments\").\n", + "If the model parameters are not roughly constant, the equilibrium that the model converges to in the future might not correspond to the equilibrium solution for the model's initial parameter values. In that case, an initial transient can still occur. To address this, we can remove any time variation in the model's parameter values using the `ParameterSet.make_constant()` method. This will return a copy of the parset in which all parameters are constant over time, thus ensuring that the future compartment sizes are computed based on the same parameter values as the initial simulation year. This often provides a suitable solution, although changes to the total population size due to births and deaths can still take place, so in some cases a small initial transient may still be present. In such cases, repeatedly setting initialization based on a shorter simulation can help minimize the discrepancy. For more information on Atomica initializations, see the [documentation on this topic](https://atomica.tools/docs/main/general/Compartment-Initialization.html \"Initializing compartments\").\n", "\n", "In the YAML file, we indicate that we want to set a new initialization by making a YAML block with the title `set_initialization`. Under this title, we can specify further settings:\n", "\n", @@ -733,7 +733,7 @@ "\n", "### Documentation\n", "\n", - "For more information on using Atomica's YAML calibration functionality, see [the documentation](https://atomica.tools/docs/master/general/YAML_calibration.html \"YAML documentation page\").\n" + "For more information on using Atomica's YAML calibration functionality, see [the documentation](https://atomica.tools/docs/main/general/YAML_calibration.html \"YAML documentation page\").\n" ] } ],