Skip to content

Overview

Agent Exposures

Exposures (transmissible items such as HIV and knowledge) from params.exposures are implemented in standalone files that implement the interface from exposures.BaseExposure. This allows for all of the logic related to an exposure to be consolidated in one place and additionally makes incorporating a new exposure into the model as simple as possible.

To add a new exposure:

  • Add the param to param.exposures
  • Add a file to exposures/ which creates a class that is a sub-class of BaseExposure
    • Implement the methods of BaseExposure which are needed for this exposure
    • Not all methods are needed for all exposures (see below for details on the methods)
  • Re-export the exposure from exposures/__init__.py
  • Add tests in tests/exposures/
  • Add it to the docs in docs/api/exposures/ and to the nav in mkdocs.yml

The TITAN, Population, and Agent classes all use sub-classes of BaseFeature to initialize the object/call methods as appropriate.

BaseExposure

Source code in titan/exposures/base_exposure.py
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
class BaseExposure:
    name: str = ""
    """Name of exposure in the params file.  Also used to name the attribute in Agent"""

    stats: List[str] = []
    """List of names of stats that come from this exposure (e.g. hiv.dx)"""

    def __init__(self, agent: "agent.Agent"):
        self.active = False
        self.agent = agent

    @classmethod
    def init_class(cls, params):
        """
        Initialize any class level attributes (such as setting counters to zero). Called on every active exposure on population initialization.

        args:
            params: parameters for this population
        """
        pass

    def init_agent(self, pop: "population.Population", time: int):
        """
        Initialize the agent for this exposure during population initialization (`Population.create_agent`).  Called only on exposures that are enabled per the params.

        args:
            pop: the population this agent is a part of
            time: the current time step
        """
        pass

    def update_agent(self, model: "model.TITAN"):
        """
        Update the agent for this exposure for a time step.  Called once per time step in `TITAN.update_all_agents`.

        args:
            model: the instance of TITAN currently being run
        """
        pass

    @classmethod
    def add_agent(cls, agent: "agent.Agent"):
        """
        Add an agent to the class (not instance).  This can be useful if tracking population level statistics or groups, such as counts or newly active agents.

        This method is not called from anywhere in the model, but creates a cohesive api with `remove_agent`, which is called from `Population.remove_agent`.

        args:
            agent: the agent to add to the class attributes
        """
        pass

    @classmethod
    def remove_agent(cls, agent: "agent.Agent"):
        """
        Remove an agent from the class (not instance).  This can be useful if tracking population level statistics or groups, such as counts.

        This method is called from `Population.remove_agent`, but may also need to be called within the feature if an agent transitions from `active == True` to `active == False`.

        args:
            agent: the agent to remove from the class attributes
        """
        pass

    def set_stats(self, stats: Dict[str, int], time: int):
        """
        Update the `stats` dictionary passed for this agent.  Called from `output.get_stats` for each enabled exposure in the model.

        The stats to be updated must be declared in the class attribute `stats` to make sure the dictionary has the expected keys/counter value initialized.

        args:
            stats: the dictionary to update with this agent's feature statistics
            time: the time step of the model when the stats are set
        """
        pass

    @staticmethod
    def expose(
        model: "model.TITAN",
        interaction: str,
        rel: "agent.Relationship",
        num_acts: int,
    ):
        """
        Expose a relationship to the exposure for a number of acts for a specific interaction type.  Typically, this determines if the exposure can cause conversion/change in one of the agents, then if so, determines the probability of that and then converts the succeptible agent.

        args:
            model: The running model
            interaction: The type of interaction (e.g. sex, injection)
            rel: The relationship where the interaction is occuring
            num_acts: The number of acts of that interaction
        """
        pass

    def get_transmission_probability(
        self,
        model: "model.TITAN",
        interaction: str,
        partner: "agent.Agent",
        num_acts: int,
    ) -> float:
        """
        Determines the probability of a transmission event from agent to partner based on
            interaction type.

        This is not called from anywhere else in the model, but is recommended as a way to structure the exposure method into getting the transmission probability, then doing the conversion.

        args:
            model: The running model
            interaction : The type of interaction (e.g. `sex`, `injection`)
            partner: The agent's partner
            num_acts: The number of acts where exposure occured

        returns:
            probability of transmission from agent to partner
        """
        return 0.0

    def convert(self, model: "model.TITAN"):
        """
        Convert the agent to the exposure (i.e. become active).

        args:
            model: The running model
        """
        pass

    def diagnose(self, model: "model.TITAN"):
        """
        Diagnose the agent with the exposure (if applicable).

        args:
            model: The running model
        """
        pass

name: str = '' class-attribute instance-attribute

Name of exposure in the params file. Also used to name the attribute in Agent

stats: List[str] = [] class-attribute instance-attribute

List of names of stats that come from this exposure (e.g. hiv.dx)

add_agent(agent) classmethod

Add an agent to the class (not instance). This can be useful if tracking population level statistics or groups, such as counts or newly active agents.

This method is not called from anywhere in the model, but creates a cohesive api with remove_agent, which is called from Population.remove_agent.

Parameters:

Name Type Description Default
agent Agent

the agent to add to the class attributes

required
Source code in titan/exposures/base_exposure.py
48
49
50
51
52
53
54
55
56
57
58
@classmethod
def add_agent(cls, agent: "agent.Agent"):
    """
    Add an agent to the class (not instance).  This can be useful if tracking population level statistics or groups, such as counts or newly active agents.

    This method is not called from anywhere in the model, but creates a cohesive api with `remove_agent`, which is called from `Population.remove_agent`.

    args:
        agent: the agent to add to the class attributes
    """
    pass

convert(model)

Convert the agent to the exposure (i.e. become active).

Parameters:

Name Type Description Default
model TITAN

The running model

required
Source code in titan/exposures/base_exposure.py
126
127
128
129
130
131
132
133
def convert(self, model: "model.TITAN"):
    """
    Convert the agent to the exposure (i.e. become active).

    args:
        model: The running model
    """
    pass

diagnose(model)

Diagnose the agent with the exposure (if applicable).

Parameters:

Name Type Description Default
model TITAN

The running model

required
Source code in titan/exposures/base_exposure.py
135
136
137
138
139
140
141
142
def diagnose(self, model: "model.TITAN"):
    """
    Diagnose the agent with the exposure (if applicable).

    args:
        model: The running model
    """
    pass

expose(model, interaction, rel, num_acts) staticmethod

Expose a relationship to the exposure for a number of acts for a specific interaction type. Typically, this determines if the exposure can cause conversion/change in one of the agents, then if so, determines the probability of that and then converts the succeptible agent.

Parameters:

Name Type Description Default
model TITAN

The running model

required
interaction str

The type of interaction (e.g. sex, injection)

required
rel Relationship

The relationship where the interaction is occuring

required
num_acts int

The number of acts of that interaction

required
Source code in titan/exposures/base_exposure.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
@staticmethod
def expose(
    model: "model.TITAN",
    interaction: str,
    rel: "agent.Relationship",
    num_acts: int,
):
    """
    Expose a relationship to the exposure for a number of acts for a specific interaction type.  Typically, this determines if the exposure can cause conversion/change in one of the agents, then if so, determines the probability of that and then converts the succeptible agent.

    args:
        model: The running model
        interaction: The type of interaction (e.g. sex, injection)
        rel: The relationship where the interaction is occuring
        num_acts: The number of acts of that interaction
    """
    pass

get_transmission_probability(model, interaction, partner, num_acts)

Determines the probability of a transmission event from agent to partner based on interaction type.

This is not called from anywhere else in the model, but is recommended as a way to structure the exposure method into getting the transmission probability, then doing the conversion.

Parameters:

Name Type Description Default
model TITAN

The running model

required
interaction

The type of interaction (e.g. sex, injection)

required
partner Agent

The agent's partner

required
num_acts int

The number of acts where exposure occured

required

Returns:

Type Description
float

probability of transmission from agent to partner

Source code in titan/exposures/base_exposure.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
def get_transmission_probability(
    self,
    model: "model.TITAN",
    interaction: str,
    partner: "agent.Agent",
    num_acts: int,
) -> float:
    """
    Determines the probability of a transmission event from agent to partner based on
        interaction type.

    This is not called from anywhere else in the model, but is recommended as a way to structure the exposure method into getting the transmission probability, then doing the conversion.

    args:
        model: The running model
        interaction : The type of interaction (e.g. `sex`, `injection`)
        partner: The agent's partner
        num_acts: The number of acts where exposure occured

    returns:
        probability of transmission from agent to partner
    """
    return 0.0

init_agent(pop, time)

Initialize the agent for this exposure during population initialization (Population.create_agent). Called only on exposures that are enabled per the params.

Parameters:

Name Type Description Default
pop Population

the population this agent is a part of

required
time int

the current time step

required
Source code in titan/exposures/base_exposure.py
29
30
31
32
33
34
35
36
37
def init_agent(self, pop: "population.Population", time: int):
    """
    Initialize the agent for this exposure during population initialization (`Population.create_agent`).  Called only on exposures that are enabled per the params.

    args:
        pop: the population this agent is a part of
        time: the current time step
    """
    pass

init_class(params) classmethod

Initialize any class level attributes (such as setting counters to zero). Called on every active exposure on population initialization.

Parameters:

Name Type Description Default
params

parameters for this population

required
Source code in titan/exposures/base_exposure.py
19
20
21
22
23
24
25
26
27
@classmethod
def init_class(cls, params):
    """
    Initialize any class level attributes (such as setting counters to zero). Called on every active exposure on population initialization.

    args:
        params: parameters for this population
    """
    pass

remove_agent(agent) classmethod

Remove an agent from the class (not instance). This can be useful if tracking population level statistics or groups, such as counts.

This method is called from Population.remove_agent, but may also need to be called within the feature if an agent transitions from active == True to active == False.

Parameters:

Name Type Description Default
agent Agent

the agent to remove from the class attributes

required
Source code in titan/exposures/base_exposure.py
60
61
62
63
64
65
66
67
68
69
70
@classmethod
def remove_agent(cls, agent: "agent.Agent"):
    """
    Remove an agent from the class (not instance).  This can be useful if tracking population level statistics or groups, such as counts.

    This method is called from `Population.remove_agent`, but may also need to be called within the feature if an agent transitions from `active == True` to `active == False`.

    args:
        agent: the agent to remove from the class attributes
    """
    pass

set_stats(stats, time)

Update the stats dictionary passed for this agent. Called from output.get_stats for each enabled exposure in the model.

The stats to be updated must be declared in the class attribute stats to make sure the dictionary has the expected keys/counter value initialized.

Parameters:

Name Type Description Default
stats Dict[str, int]

the dictionary to update with this agent's feature statistics

required
time int

the time step of the model when the stats are set

required
Source code in titan/exposures/base_exposure.py
72
73
74
75
76
77
78
79
80
81
82
def set_stats(self, stats: Dict[str, int], time: int):
    """
    Update the `stats` dictionary passed for this agent.  Called from `output.get_stats` for each enabled exposure in the model.

    The stats to be updated must be declared in the class attribute `stats` to make sure the dictionary has the expected keys/counter value initialized.

    args:
        stats: the dictionary to update with this agent's feature statistics
        time: the time step of the model when the stats are set
    """
    pass

update_agent(model)

Update the agent for this exposure for a time step. Called once per time step in TITAN.update_all_agents.

Parameters:

Name Type Description Default
model TITAN

the instance of TITAN currently being run

required
Source code in titan/exposures/base_exposure.py
39
40
41
42
43
44
45
46
def update_agent(self, model: "model.TITAN"):
    """
    Update the agent for this exposure for a time step.  Called once per time step in `TITAN.update_all_agents`.

    args:
        model: the instance of TITAN currently being run
    """
    pass