Syringe Services
name: str
Name of feature in the params file. Also used to name the attribute in Agent
init_class(params)
classmethod
Initialize enrolled risk to 0.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
params |
|
the population params |
required |
Source code in titan/features/syringe_services.py
@classmethod
def init_class(cls, params):
"""
Initialize enrolled risk to 0.
args:
params: the population params
"""
cls.enrolled_risk = 0.0
update_pop(model)
classmethod
Update the feature for the entire population (class method). This is useful for initializing class level trackers that need to be reset each time step, or if enabling a feature for agents needs to be evaluated within the context of the full population (limited slots, or similar).
Enroll PWID agents in syringe services according to the syring_services timeline and params.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model |
hiv_model.TITAN |
the instance of TITAN currently being run |
required |
Source code in titan/features/syringe_services.py
@classmethod
def update_pop(cls, model: "hiv_model.TITAN"):
"""
Update the feature for the entire population (class method). This is useful for initializing class level trackers that need to be reset each time step, or if enabling a feature for agents needs to be evaluated within the context of the full population (limited slots, or similar).
Enroll PWID agents in syringe services according to the syring_services timeline and params.
args:
model: the instance of TITAN currently being run
"""
logging.info(("\n\n!!!!Engaging syringe services program"))
ssp_num_slots = 0
ssp_agents = {
agent for agent in model.pop.pwid_agents if agent.syringe_services.active # type: ignore[attr-defined]
}
for item in model.params.syringe_services.timeline.values():
if item.start_time <= model.time < item.stop_time:
cls.enrolled_risk = item.risk
# linearly interpolate slots between start and stop
ssp_num_slots = (item.num_slots_stop - item.num_slots_start) / (
item.stop_time - item.start_time
) * (model.time - item.start_time) + item.num_slots_start
# If cap indicates all or no agents, do not change
# otherwise, find true number of slots through distribution
num_pwid_agents = model.pop.pwid_agents.num_members()
if 0 < ssp_num_slots < num_pwid_agents:
ssp_num_slots = round(
model.run_random.betavariate(
ssp_num_slots,
num_pwid_agents - ssp_num_slots,
)
* num_pwid_agents
)
break
target_set = utils.safe_shuffle(
(model.pop.pwid_agents.members - ssp_agents), model.run_random
)
# unenroll agents if above cap
for agent in ssp_agents.copy():
if len(ssp_agents) > ssp_num_slots:
agent.syringe_services.active = False # type: ignore[attr-defined]
ssp_agents.remove(agent)
else:
break
# enroll agents if below cap
for agent in target_set:
if len(ssp_agents) < ssp_num_slots:
agent.syringe_services.active = True # type: ignore[attr-defined]
ssp_agents.add(agent)
else:
break
logging.info(
f"SSP has {ssp_num_slots} target slots with "
f"{len(ssp_agents)} slots filled"
)