Skip to content

Commit

Permalink
Added restarting PrEP.
Browse files Browse the repository at this point in the history
  • Loading branch information
pineapple-cat committed Nov 7, 2024
1 parent d894d3e commit a4dcf3e
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 1 deletion.
62 changes: 61 additions & 1 deletion src/hivpy/prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,9 +648,10 @@ def continue_prep(self, pop: Population, time_step):
"""
Update PrEP usage for people continuing PrEP.
"""
# people who have used prep before but not started this time step
# people who have used prep before but not yet started this time step
eligible = pop.get_sub_pop(AND(COND(col.EVER_PREP, op.eq, True),
COND(col.PREP_JUST_STARTED, op.eq, False),
COND(col.LAST_PREP_STOP_DATE, op.eq, None),
OR(COND(col.LAST_TEST_DATE, op.ne, pop.date),
AND(COND(col.LAST_TEST_DATE, op.eq, pop.date),
COND(col.HIV_DIAGNOSED, op.eq, False)))))
Expand Down Expand Up @@ -728,6 +729,63 @@ def calc_current_prep(self, prep_type, favoured_prep, size):

return prep

def restart_prep(self, pop: Population, time_step):
"""
Update PrEP usage for people restarting PrEP.
"""
# people who have used prep before and previously stopped using it
eligible = pop.get_sub_pop(AND(COND(col.EVER_PREP, op.eq, True),
COND(col.LAST_PREP_STOP_DATE, op.lt, pop.date),
COND(col.LAST_TEST_DATE, op.eq, pop.date)))

if len(eligible) > 0:
# starting prep outcomes
prep_types = pop.transform_group([col.FAVOURED_PREP_TYPE], self.calc_restarting_prep,
sub_pop=eligible, dropna=True)
# people who are restarting prep
restarting_prep_pop = pop.apply_bool_mask(prep_types.notnull(), eligible)

if len(restarting_prep_pop) > 0:
# set prep types
pop.set_present_variable(col.PREP_TYPE, prep_types, restarting_prep_pop)
pop.set_present_variable(col.PREP_JUST_STARTED, True, restarting_prep_pop)
# set start dates
pop.set_present_variable(col.LAST_PREP_START_DATE, pop.date, restarting_prep_pop)
self.set_prep_first_start_date(
pop, restarting_prep_pop, PrEPType.Oral, col.FIRST_ORAL_START_DATE)
self.set_prep_first_start_date(
pop, restarting_prep_pop, PrEPType.Cabotegravir, col.FIRST_CAB_START_DATE)
self.set_prep_first_start_date(
pop, restarting_prep_pop, PrEPType.Lenacapavir, col.FIRST_LEN_START_DATE)
self.set_prep_first_start_date(
pop, restarting_prep_pop, PrEPType.VaginalRing, col.FIRST_VR_START_DATE)
# set continuous use
pop.set_present_variable(col.CONT_ON_PREP, time_step, restarting_prep_pop)
pop.set_present_variable(col.CONT_ACTIVE_ON_PREP, time_step, restarting_prep_pop)
# increment cumulative use
self.set_prep_cumulative_cont(
pop, restarting_prep_pop, PrEPType.Oral, col.CUMULATIVE_PREP_ORAL, time_step)
self.set_prep_cumulative_cont(
pop, restarting_prep_pop, PrEPType.Cabotegravir, col.CUMULATIVE_PREP_CAB, time_step)
self.set_prep_cumulative_cont(
pop, restarting_prep_pop, PrEPType.Lenacapavir, col.CUMULATIVE_PREP_LEN, time_step)
self.set_prep_cumulative_cont(
pop, restarting_prep_pop, PrEPType.VaginalRing, col.CUMULATIVE_PREP_VR, time_step)
# unset stop date
pop.set_present_variable(col.LAST_PREP_STOP_DATE, None, restarting_prep_pop)

def calc_restarting_prep(self, favoured_prep, size):
"""
Returns PrEP types for people restarting PrEP.
Individual preferences and availability are taken into account.
"""
# outcomes
r = rng.uniform(size=size)
restarting = r < self.prob_prep_restart
prep = [favoured_prep if r else None for r in restarting]

return prep

def prep_usage(self, pop: Population, time_step):
"""
Update PrEP usage for people starting, continuing, switching, restarting, and stopping PrEP.
Expand All @@ -736,3 +794,5 @@ def prep_usage(self, pop: Population, time_step):
self.start_prep(pop, time_step)
# continuing prep
self.continue_prep(pop, time_step)
# restarting prep
self.restart_prep(pop, time_step)
31 changes: 31 additions & 0 deletions src/tests/test_prep.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,3 +833,34 @@ def test_continuing_prep():
(pop.data[col.PREP_TYPE] == PrEPType.VaginalRing)) |
((pop.data[col.CUMULATIVE_PREP_VR] == time_step) ==
(pop.data[col.LAST_PREP_STOP_DATE] == pop.date)))


def test_restarting_prep():
N = 100
time_step = timedelta(months=1)
pop = Population(size=N, start_date=date(5000, 1, 1))
pop.prep.date_prep_intro = [date(2000), date(3000), date(4000), date(5000)]
pop.data[col.EVER_PREP] = True
pop.data[col.LAST_PREP_STOP_DATE] = pop.date - time_step
pop.data[col.PREP_JUST_STARTED] = False
pop.data[col.CONT_ON_PREP] = timedelta(months=0)
pop.data[col.CONT_ACTIVE_ON_PREP] = timedelta(months=0)
pop.data[col.LAST_TEST_DATE] = pop.date
pop.data[col.PREP_TYPE] = None
# everyone is taking their favoured prep type
pop.data[col.FAVOURED_PREP_TYPE] = [PrEPType.Oral, PrEPType.Cabotegravir,
PrEPType.Lenacapavir, PrEPType.VaginalRing] * (N // 4)
# 50% chance to restart prep
pop.prep.prob_prep_restart = 0.5

pop.prep.restart_prep(pop, time_step)
# expecting 90% of people to restart prep
no_on_prep = sum(pop.data[col.LAST_PREP_STOP_DATE].isnull())
mean = N * pop.prep.prob_prep_restart
stdev = sqrt(mean * (1 - pop.prep.prob_prep_restart))
assert mean - 3 * stdev <= no_on_prep <= mean + 3 * stdev
# check continuous prep usage
assert all((pop.data[col.CONT_ON_PREP] == time_step) ==
(pop.data[col.LAST_PREP_STOP_DATE].isnull()))
assert all((pop.data[col.CONT_ACTIVE_ON_PREP] == time_step) ==
(pop.data[col.LAST_PREP_STOP_DATE].isnull()))

0 comments on commit a4dcf3e

Please sign in to comment.