Skip to content

Commit

Permalink
Merge pull request #185 from pph-collective/develop
Browse files Browse the repository at this point in the history
Main
  • Loading branch information
mcmcgrath13 authored Apr 15, 2021
2 parents e2bc287 + acdcec3 commit c3b37c8
Show file tree
Hide file tree
Showing 10 changed files with 241 additions and 50 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "titan-model"
version = "2.5.0"
version = "2.5.1"
description = "TITAN Agent Based Model"
license = "GPL-3.0-only"
authors = ["Sam Bessey <[email protected]>", "Mary McGrath <[email protected]>"]
Expand Down
191 changes: 183 additions & 8 deletions tests/integration_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,13 @@ def test_target_partners(make_model_integration, tmpdir):

# change the partner distribution mean upward for creating model b
for bond in model_a.params.classes.bond_types:
model_a.params.demographics.black.sex_type.MSM.drug_type["None"].num_partners[
bond
].vars[1].value *= 10
model_a.params.demographics.black.sex_type.MSM.drug_type["Inj"].num_partners[
bond
].vars[1].value *= 10
for race in model_a.params.classes.races:
model_a.params.demographics[race].sex_type.MSM.drug_type[
"None"
].num_partners[bond].vars[1].value *= 10
model_a.params.demographics[race].sex_type.MSM.drug_type[
"Inj"
].num_partners[bond].vars[1].value *= 10
model_a.params.model.seed.run = model_a.run_seed
model_a.params.model.seed.ppl = model_a.pop.pop_seed

Expand Down Expand Up @@ -305,8 +306,10 @@ def test_syringe_services(params_integration, tmpdir):
"""
If we use syringe services, does the incidence of hiv decrease?
"""
params_integration.demographics.black.sex_type.MSM.drug_type.Inj.ppl = 1.0
params_integration.demographics.black.sex_type.MSM.drug_type["None"].ppl = 0.0
for race in params_integration.classes.races:
params_integration.demographics[race].sex_type.MSM.drug_type.Inj.ppl = 1.0
params_integration.demographics[race].sex_type.MSM.drug_type["None"].ppl = 0.0

params_integration.model.num_pop = 500
model_a = TITAN(params_integration)
model_a.params.partnership.sex.frequency.Sex = (
Expand Down Expand Up @@ -435,3 +438,175 @@ def test_incar(params_integration, tmpdir):
# agents should not hiv convert during incar
for agent in time_1_incar_hiv_neg:
assert not agent.hiv.active


@pytest.mark.integration_stochastic
def test_assort_mix(params_integration, tmpdir):
"""
Do vastly different assorting rules result in different networks
"""
path_a = tmpdir.mkdir("a")
path_a.mkdir("network")
path_b = tmpdir.mkdir("b")
path_b.mkdir("network")
path_c = tmpdir.mkdir("c")
path_c.mkdir("network")

params_integration.features.assort_mix = True
params_integration.assort_mix = ObjMap(
{
"same_race": {
"attribute": "race",
"partner_attribute": "__agent__",
"bond_types": [],
"agent_value": "__any__",
"partner_values": {"__same__": 0.9, "__other__": 0.1},
}
}
)

model_a = TITAN(params_integration)
model_a.run(path_a)

params_integration.assort_mix = ObjMap(
{
"cross_race": {
"attribute": "race",
"partner_attribute": "__agent__",
"bond_types": [],
"agent_value": "__any__",
"partner_values": {"__same__": 0.5, "__other__": 0.5},
}
}
)

model_b = TITAN(params_integration)
model_b.run(path_b)

params_integration.features.assort_mix = False
model_c = TITAN(params_integration)
model_c.run(path_c)

model_a_rels = model_a.pop.relationships
a_same_race = sum([1 for r in model_a_rels if r.agent1.race == r.agent2.race])
a_diff_race = sum([1 for r in model_a_rels if r.agent1.race != r.agent2.race])

model_b_rels = model_b.pop.relationships
b_same_race = sum([1 for r in model_b_rels if r.agent1.race == r.agent2.race])
b_diff_race = sum([1 for r in model_b_rels if r.agent1.race != r.agent2.race])

model_c_rels = model_c.pop.relationships
c_same_race = sum([1 for r in model_c_rels if r.agent1.race == r.agent2.race])
c_diff_race = sum([1 for r in model_c_rels if r.agent1.race != r.agent2.race])

assert a_same_race > a_diff_race
assert a_same_race > b_same_race
assert b_diff_race > a_diff_race
assert math.isclose(b_same_race, c_same_race, abs_tol=50)

# close to proportion expected
assert math.isclose(0.9, a_same_race / (a_same_race + a_diff_race), abs_tol=0.05)
assert math.isclose(0.5, b_same_race / (b_same_race + b_diff_race), abs_tol=0.1)
assert math.isclose(0.5, c_same_race / (c_same_race + c_diff_race), abs_tol=0.1)


@pytest.mark.integration_stochastic
def test_treatment_cascade(params_integration, tmpdir):
"""
Does an increase in HAART result in less HIV, AIDS and death
"""
path_a = tmpdir.mkdir("a")
path_a.mkdir("network")
path_b = tmpdir.mkdir("b")
path_b.mkdir("network")

params_integration.features.die_and_replace = True
params_integration.model.num_pop = 1000
params_integration.model.time.num_steps = 20

def run_get_death(model, path):
deaths = set()
hiv_start = set(a.id for a in model.pop.all_agents if a.hiv.active)
aids_start = set(a.id for a in model.pop.all_agents if a.hiv.aids)
hiv_only_start = hiv_start - aids_start
unique_hiv = set()
unique_aids = set()
while model.time < model.params.model.time.num_steps:
model.time += 1
model.step(path)
deaths |= set(a.id for a in model.deaths)
unique_hiv |= set(
a.id
for a in model.pop.all_agents
if a.hiv.active and a.hiv.time == model.time
)
unique_aids |= set(a.id for a in model.pop.all_agents if a.hiv.aids)
model.reset_trackers()

return (
len(unique_hiv - unique_aids - hiv_only_start),
len(unique_aids - aids_start),
len(deaths & (unique_hiv | hiv_start)),
)

model_a = TITAN(params_integration) # low haart
new_hiv_a, new_aids_a, hiv_deaths_a = run_get_death(model_a, path_a)

for race in params_integration.classes.races:
for drug_type in params_integration.classes.drug_types:
haart_params = (
params_integration.demographics[race]
.sex_type.MSM.drug_type[drug_type]
.haart
)
haart_params.init = 0.9
haart_params.enroll.rule.prob = 0.9
haart_params.adherence.init = 0.9
haart_params.adherence.prob = 0.9

model_b = TITAN(params_integration) # high haart
new_hiv_b, new_aids_b, hiv_deaths_b = run_get_death(model_b, path_b)

assert hiv_deaths_b <= hiv_deaths_a, "HIV deaths not down"
assert new_aids_b <= new_aids_a, "new AIDS not down"
assert new_hiv_b < new_hiv_a, "new HIV not down"


@pytest.mark.integration_stochastic
def test_pca_awareness(params_integration, tmpdir):
"""
Does a change in the threshhold for PCA result in more knowledge?
"""
params_integration.exposures.knowledge = True
params_integration.knowledge.init = 0.1
params_integration.model.time.num_steps = 20

path_a = tmpdir.mkdir("a")
path_a.mkdir("network")
path_b = tmpdir.mkdir("b")
path_b.mkdir("network")

params_integration.knowledge.threshold = 3.5
model_a = TITAN(params_integration) # low knowledge

init_active_a = sum([1 for a in model_a.pop.all_agents if a.knowledge.active])
init_prep_a = sum([1 for a in model_a.pop.all_agents if a.prep.active])
model_a.run(path_a)
end_active_a = sum([1 for a in model_a.pop.all_agents if a.knowledge.active])
end_prep_a = sum([1 for a in model_a.pop.all_agents if a.prep.active])

params_integration.knowledge.threshold = 1.5
params_integration.knowledge.prob = 0.05
model_b = TITAN(params_integration) # high knowledge

init_prep_b = sum([1 for a in model_b.pop.all_agents if a.prep.active])
init_active_b = sum([1 for a in model_b.pop.all_agents if a.knowledge.active])
model_b.run(path_b)
end_active_b = sum([1 for a in model_b.pop.all_agents if a.knowledge.active])
end_prep_b = sum([1 for a in model_b.pop.all_agents if a.prep.active])

assert math.isclose(init_active_b, init_active_a, abs_tol=20)
assert (end_active_b - init_active_b) > (end_active_a - init_active_a)

assert math.isclose(init_prep_b, init_prep_a, abs_tol=20)
assert (end_prep_b - init_prep_b) > (end_prep_a - init_prep_a)
7 changes: 2 additions & 5 deletions tests/model_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,10 @@ def test_update_all_agents(make_model, make_agent):
# make agent 0
model = make_model()
assert model.params.agent_zero.interaction_type == "injection"
a = make_agent(race="white", DU="Inj")
p = make_agent(race="white", DU="Inj")
# make sure at least 1 relationship is compatible with agent 0 type
Relationship(a, p, 10, bond_type="Inj")
model.time = 1
model.params.features.die_and_replace = False
# update all agents passes with agent 0
model.update_all_agents()
assert a.knowledge.active is False

# remove all bonds compatible with agent 0. agent 0 fails
for rel in copy(model.pop.relationships):
Expand All @@ -58,6 +54,7 @@ def test_update_all_agents(make_model, make_agent):

with pytest.raises(ValueError) as excinfo:
model.update_all_agents()

assert "No agent zero!" in str(excinfo)


Expand Down
4 changes: 2 additions & 2 deletions tests/params/basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ demographics:
haart:
init: 0.1
enroll: &haart_prob
0:
begin:
prob: 0.1
start: 0
stop: 10
1:
end:
prob: 1.0
start: 10
stop: 100
Expand Down
73 changes: 45 additions & 28 deletions tests/params/simple_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ classes:
races:
black:
hispanic: false
white:
hispanic: false
sex_types:
MSM:
gender: M
Expand All @@ -13,8 +15,8 @@ classes:
- None

demographics:
black:
ppl: 1.0
black: &race_dems
ppl: 0.5
sex_type:
MSM:
ppl: 1.0
Expand Down Expand Up @@ -46,18 +48,18 @@ demographics:
drug_type:
Inj:
ppl: 0.2
hiv:
init: 0.1
hiv: &base_hiv
init: 0.2
dx:
init: 0.1
prob: 0.1
init: 0.9
prob: 0.9
aids:
init: 0.1
haart:
haart: &base_haart
init: 0.1
prob:
1:
enroll: 0.1
enroll:
rule:
prob: 0.1
start: 0
stop: 999
adherence:
Expand Down Expand Up @@ -91,31 +93,16 @@ demographics:
type: int
None:
ppl: 0.8
hiv:
init: 0.1
dx:
init: 0.1
prob: 0.1
aids:
init: 0.1
haart:
init: 0.1
prob:
1:
enroll: 0.1
start: 0
stop: 999
adherence:
init: 0.1
prob: 0.1
discontinue: 0.1
hiv: *base_hiv
haart: *base_haart
num_partners:
Sex:
dist_type: poisson
vars:
1:
value: 2
type: float
white: *race_dems

partnership:
duration:
Expand Down Expand Up @@ -144,6 +131,13 @@ partnership:
prob: 1.0
min: 1
max: 10
Social:
type: bins
bins:
1:
prob: 1.0
min: 1
max: 10
sex:
frequency:
Sex:
Expand All @@ -157,6 +151,24 @@ partnership:
prob: 1.0
min: 10
max: 37
SexInj:
type: bins
bins:
1:
prob: 0.5
min: 10
max: 50
2:
prob: 1.0
min: 10
max: 37
Social:
type: bins
bins:
1:
prob: 1.0
min: 10
max: 100
acquisition:
MSM:
insertive: 0.0011
Expand Down Expand Up @@ -191,6 +203,7 @@ features:
static_network: false
incar: false
partner_tracing: false
die_and_replace: false

model:
num_pop: 300
Expand All @@ -203,3 +216,7 @@ model:
calibration:
partnership:
break_point: 0

hiv:
aids:
prob: 0.1
Loading

0 comments on commit c3b37c8

Please sign in to comment.