Skip to content

Incarceration

Bases: BaseFeature

Source code in titan/features/incar.py
 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
class Incar(base_feature.BaseFeature):
    name = "incar"
    stats = ["incar", "incar_hiv", "new_release", "new_release_hiv"]
    """
        Incar collects the following stats:

        * incar - number of agents with active incar
        * incar_hiv - number of agents with active incar and HIV
        * new_release - number of agents released this timestep
        * new_release_hiv - number of agents releasted this timestep with HIV
    """

    def __init__(self, agent: "agent.Agent"):
        super().__init__(agent)

        self.active = False
        self.time: Optional[int] = None
        self.release_time: Optional[int] = None

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

        Run incarceration assignment on an agent.  The duration of incarceration at initialization is different than the ongoing to reflect that agents with longer durations will be more highly represented in that population at any given point in time.

        args:
            pop: the population this agent is a part of
            time: the current time step
        """
        incar_params = (
            self.agent.location.params.demographics[self.agent.race]
            .sex_type[self.agent.sex_type]
            .incar
        )
        jail_duration = incar_params.duration.init

        prob_incar = incar_params.init
        if pop.pop_random.random() < prob_incar:
            self.active = True
            bin = 1
            current_p_value = jail_duration[bin].prob
            p = pop.pop_random.random()

            while p > current_p_value:
                bin += 1
                current_p_value += jail_duration[bin].prob

            self.time = time
            self.release_time = time + pop.pop_random.randrange(
                jail_duration[bin].min, jail_duration[bin].max
            )

    def update_agent(self, model: "model.TITAN"):
        """
        Update the agent for this feature for a time step.  Called once per time step in `TITAN.update_all_agents`. Agent level updates are done after population level updates.   Called on only features that are enabled per the params.

        Incarcerate an agent or update their incarceration variables

        args:
            model: the instance of TITAN currently being run
        """
        hiv_bool = self.agent.hiv.active  # type: ignore[attr-defined]

        if hiv_bool:
            hiv_multiplier = self.agent.location.params.incar.hiv.multiplier
        else:
            hiv_multiplier = 1.0

        # agent is incarcerated
        if self.active:
            # Release agent
            if self.release_time == model.time:
                self.active = False

                # does agent stay on haart
                if hiv_bool:
                    if self.agent.haart.active:  # type: ignore[attr-defined]
                        if (
                            model.run_random.random()
                            <= self.agent.location.params.incar.haart.discontinue
                        ):
                            self.agent.haart.active = False  # type: ignore[attr-defined]
                            self.agent.haart.adherent = False  # type: ignore[attr-defined]

        # should the agent become incarcerated?
        elif model.run_random.random() < (
            self.agent.location.params.demographics[self.agent.race]
            .sex_type[self.agent.sex_type]
            .incar.prob
            * hiv_multiplier
            * model.calibration.incarceration
        ):
            incar_duration = (
                self.agent.location.params.demographics[self.agent.race]
                .sex_type[self.agent.sex_type]
                .incar.duration.prob
            )

            bin = utils.get_cumulative_bin(model.run_random, incar_duration)

            self.time = model.time
            self.release_time = model.time + utils.safe_random_int(
                incar_duration[bin].min, incar_duration[bin].max, model.run_random
            )
            self.active = True

            if hiv_bool:
                if not self.agent.hiv.dx:  # type: ignore[attr-defined]
                    if (
                        model.run_random.random()
                        < self.agent.location.params.incar.hiv.dx
                    ):
                        self.agent.hiv.diagnose(model)  # type: ignore[attr-defined]
                else:  # Then tested and HIV, check to enroll in ART
                    if (
                        model.run_random.random()
                        < self.agent.location.params.incar.haart.prob
                    ):
                        self.agent.haart.adherent = model.run_random.random() < self.agent.location.params.incar.haart.adherence  # type: ignore[attr-defined]
                        # Add agent to HAART class set, update agent params
                        self.agent.haart.active = True  # type: ignore[attr-defined]

    def set_stats(self, stats: Dict[str, int], time: int):
        if self.release_time == time:
            stats["new_release"] += 1
            if self.agent.hiv.active:  # type: ignore[attr-defined]
                stats["new_release_hiv"] += 1

        if self.active:
            stats["incar"] += 1
            if self.agent.hiv.active:  # type: ignore[attr-defined]
                stats["incar_hiv"] += 1

stats = ['incar', 'incar_hiv', 'new_release', 'new_release_hiv'] class-attribute instance-attribute

Incar collects the following stats:

  • incar - number of agents with active incar
  • incar_hiv - number of agents with active incar and HIV
  • new_release - number of agents released this timestep
  • new_release_hiv - number of agents releasted this timestep with HIV

init_agent(pop, time)

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

Run incarceration assignment on an agent. The duration of incarceration at initialization is different than the ongoing to reflect that agents with longer durations will be more highly represented in that population at any given point in time.

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/features/incar.py
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
def init_agent(self, pop: "population.Population", time: int):
    """
    Initialize the agent for this feature during population initialization (`Population.create_agent`).  Called on only features that are enabled per the params.

    Run incarceration assignment on an agent.  The duration of incarceration at initialization is different than the ongoing to reflect that agents with longer durations will be more highly represented in that population at any given point in time.

    args:
        pop: the population this agent is a part of
        time: the current time step
    """
    incar_params = (
        self.agent.location.params.demographics[self.agent.race]
        .sex_type[self.agent.sex_type]
        .incar
    )
    jail_duration = incar_params.duration.init

    prob_incar = incar_params.init
    if pop.pop_random.random() < prob_incar:
        self.active = True
        bin = 1
        current_p_value = jail_duration[bin].prob
        p = pop.pop_random.random()

        while p > current_p_value:
            bin += 1
            current_p_value += jail_duration[bin].prob

        self.time = time
        self.release_time = time + pop.pop_random.randrange(
            jail_duration[bin].min, jail_duration[bin].max
        )

update_agent(model)

Update the agent for this feature for a time step. Called once per time step in TITAN.update_all_agents. Agent level updates are done after population level updates. Called on only features that are enabled per the params.

Incarcerate an agent or update their incarceration variables

Parameters:

Name Type Description Default
model TITAN

the instance of TITAN currently being run

required
Source code in titan/features/incar.py
 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
def update_agent(self, model: "model.TITAN"):
    """
    Update the agent for this feature for a time step.  Called once per time step in `TITAN.update_all_agents`. Agent level updates are done after population level updates.   Called on only features that are enabled per the params.

    Incarcerate an agent or update their incarceration variables

    args:
        model: the instance of TITAN currently being run
    """
    hiv_bool = self.agent.hiv.active  # type: ignore[attr-defined]

    if hiv_bool:
        hiv_multiplier = self.agent.location.params.incar.hiv.multiplier
    else:
        hiv_multiplier = 1.0

    # agent is incarcerated
    if self.active:
        # Release agent
        if self.release_time == model.time:
            self.active = False

            # does agent stay on haart
            if hiv_bool:
                if self.agent.haart.active:  # type: ignore[attr-defined]
                    if (
                        model.run_random.random()
                        <= self.agent.location.params.incar.haart.discontinue
                    ):
                        self.agent.haart.active = False  # type: ignore[attr-defined]
                        self.agent.haart.adherent = False  # type: ignore[attr-defined]

    # should the agent become incarcerated?
    elif model.run_random.random() < (
        self.agent.location.params.demographics[self.agent.race]
        .sex_type[self.agent.sex_type]
        .incar.prob
        * hiv_multiplier
        * model.calibration.incarceration
    ):
        incar_duration = (
            self.agent.location.params.demographics[self.agent.race]
            .sex_type[self.agent.sex_type]
            .incar.duration.prob
        )

        bin = utils.get_cumulative_bin(model.run_random, incar_duration)

        self.time = model.time
        self.release_time = model.time + utils.safe_random_int(
            incar_duration[bin].min, incar_duration[bin].max, model.run_random
        )
        self.active = True

        if hiv_bool:
            if not self.agent.hiv.dx:  # type: ignore[attr-defined]
                if (
                    model.run_random.random()
                    < self.agent.location.params.incar.hiv.dx
                ):
                    self.agent.hiv.diagnose(model)  # type: ignore[attr-defined]
            else:  # Then tested and HIV, check to enroll in ART
                if (
                    model.run_random.random()
                    < self.agent.location.params.incar.haart.prob
                ):
                    self.agent.haart.adherent = model.run_random.random() < self.agent.location.params.incar.haart.adherence  # type: ignore[attr-defined]
                    # Add agent to HAART class set, update agent params
                    self.agent.haart.active = True  # type: ignore[attr-defined]