Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crcsim/experiment/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Experiment: Test exp-diagnostic-and-screening-compliance-interaction with 100% and 80% Diagnostic Compliance for FQHCs

This branch tests 80% and 100% compliance for FQHCs 1-8 with differing screening uptake and low and extra low costs for Stage III and Stage IV inital treatment and a new parameter propagate_diagnostic_noncompliance set to true.The branch was created from the branch diagnostic-and-screening-compliance-interaction (#435d041) to test the newly merged propagate_diagnostic_noncompliance parameter.
This branch tests 80% and 100% compliance for FQHCs 1-8 with differing screening uptakes and a new parameter propagate_diagnostic_noncompliance toggled on and off.The branch was created from the branch diagnostic-and-screening-compliance-interaction (#435d041) to test the newly merged propagate_diagnostic_noncompliance parameter.

## Results

The results show a small difference between a previous 100% and 80% compliance for FQHCs. Results are included in the summary folder.
The results show expected changes when propagation is toggled on and off for these FQHC experiments.

## Experiment Workflow

Expand Down Expand Up @@ -70,7 +70,7 @@ The subdirectories and files in `scenarios/` must be uploaded to AWS S3 for the

To upload the files to S3, run
```
aws s3 cp ./scenarios s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-interaction/scenarios --recursive
aws s3 cp ./scenarios s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-together/scenarios --recursive
```
*(Another note: this manual step is necessary because `boto3` does not include functionality to upload a directory to S3 recursively. Future experiments could improve this workflow by writing a function to upload the directory recursively in `prepare.py`. Or submit a patch to resolve https://github.com/boto/boto3/issues/358)*

Expand Down
45 changes: 37 additions & 8 deletions crcsim/experiment/parameters.json

Large diffs are not rendered by default.

248 changes: 175 additions & 73 deletions crcsim/experiment/prepare.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
import random
from copy import deepcopy
from enum import Enum, unique
from pathlib import Path
from typing import Callable, Dict, List, Optional

Expand All @@ -10,6 +10,18 @@
NUM_ITERATIONS: int = 100


@unique
class Test(Enum):
FIT = "FIT"
COLONOSCOPY = "Colonoscopy"


@unique
class ConditionalComplianceParam(Enum):
PREV_COMPLIANT = "compliance_rate_given_prev_compliant"
NOT_PREV_COMPLIANT = "compliance_rate_given_not_prev_compliant"


class Scenario:
def __init__(self, name: str, params: Dict):
self.name = name
Expand Down Expand Up @@ -87,6 +99,13 @@ def transform(params):
return transform


def transform_propagate_diagnostic_noncompliance(noncompliance: bool) -> Callable:
def transform(params):
params["propagate_diagnostic_noncompliance"] = noncompliance

return transform


def transform_diagnostic_compliance(rate: float) -> Callable:
def transform(params):
params["diagnostic_compliance_rate"] = rate
Expand All @@ -108,6 +127,75 @@ def transform(params):
return transform


def transform_fit_only() -> Callable:
"""Transform parameters to use FIT tests only."""

def transform(params):
# Set FIT as the only test
params["routine_testing_year"] = list(range(45, 76)) # Ages 45-75
params["variable_routine_test"] = ["FIT"] * 31 # FIT for all years

# Disable other tests by setting their routine ages outside valid range
for test_name in params["tests"]:
if test_name != "FIT":
params["tests"][test_name]["routine_start"] = -1
params["tests"][test_name]["routine_end"] = -1
else:
params["tests"]["FIT"]["routine_start"] = 45
params["tests"]["FIT"]["routine_end"] = 75

return transform


def transform_colonoscopy_only() -> Callable:
"""Transform parameters to use Colonoscopy tests only."""

def transform(params):
# Set FIT as the only test
params["routine_testing_year"] = list(range(45, 76)) # Ages 45-75
params["variable_routine_test"] = ["Colonoscopy"] * 31 # FIT for all years

# Disable other tests by setting their routine ages outside valid range
for test_name in params["tests"]:
if test_name != "Colonoscopy":
params["tests"][test_name]["routine_start"] = -1
params["tests"][test_name]["routine_end"] = -1
else:
params["tests"]["Colonoscopy"]["routine_start"] = 45
params["tests"]["Colonoscopy"]["routine_end"] = 75

return transform


def transform_conditional_compliance_rates(
param: ConditionalComplianceParam, rates: List[float]
) -> Callable:
"""
Replaces a conditional compliance parameter with a new set of rates.
"""

def transform(params):
for test in params["tests"]:
params["tests"][test][param.value] = rates

return transform


def transform_routine_ages(test: Test, start_age: int, end_age: int) -> Callable:
def transform(params):
params["tests"][test.value]["routine_start"] = start_age
params["tests"][test.value]["routine_end"] = end_age

return transform


def transform_routine_proportion(test: Test, proportion: float) -> Callable:
def transform(params):
params["tests"][test.value]["proportion"] = proportion

return transform


def create_scenarios() -> List:
# For each health center, define the initial compliance rate in the baseline
# scenario and the implementation scenario and vary diagnostic compliance.
Expand All @@ -121,99 +209,113 @@ def create_scenarios() -> List:
"fqhc7": (0.257, 0.354),
"fqhc8": (0.190, 0.390),
}
low_initial_stage_3_treatment_cost = 67_300
low_initial_stage_4_treatment_cost = 97_931
extra_low_initial_stage_3_treatment_cost = 50_000
extra_low_initial_stage_4_treatment_cost = 80_000

diagnostic_compliance_rates = {
"100Compliance": 1.0,
"80Compliance": 0.8,
}

propagate_diagnostic_noncompliance = {
"Propagation_on": True,
"Propagation_off": False,
}
scenarios = []

for fqhc, sreening_rates in initial_compliance.items():
for compliance, diagnostic_rate in diagnostic_compliance_rates.items():
baseline = (
Scenario(
name=f"{fqhc}_{compliance}_baseline", params=get_default_params()
for (
propogation_name,
propagation_value,
) in propagate_diagnostic_noncompliance.items():
baseline = (
Scenario(
name=f"{propogation_name}_{fqhc}_{compliance}_baseline",
params=get_default_params(),
)
.transform(transform_initial_compliance(sreening_rates[0]))
.transform(transform_diagnostic_compliance(diagnostic_rate))
.transform(
transform_propagate_diagnostic_noncompliance(propagation_value)
)
)
.transform(transform_initial_compliance(sreening_rates[0]))
.transform(transform_diagnostic_compliance(diagnostic_rate))
)
scenarios.append(baseline)

implementation = (
Scenario(
name=f"{fqhc}_{compliance}_implementation",
params=get_default_params(),
scenarios.append(baseline)

implementation = (
Scenario(
name=f"{propogation_name}_{fqhc}_{compliance}_implementation",
params=get_default_params(),
)
.transform(transform_initial_compliance(sreening_rates[1]))
.transform(transform_diagnostic_compliance(diagnostic_rate))
.transform(
transform_propagate_diagnostic_noncompliance(propagation_value)
)
)
.transform(transform_initial_compliance(sreening_rates[1]))
.transform(transform_diagnostic_compliance(diagnostic_rate))
scenarios.append(implementation)

for (
propogation_name,
propagation_value,
) in propagate_diagnostic_noncompliance.items():
# No screening baseline scenario
no_screening = (
Scenario(
name=f"{propogation_name}_no_screening", params=get_default_params()
)
scenarios.append(implementation)

# Sensitivity analysis 2. Lower cost for stage III and stage IV initial phase
baseline_low_cost = deepcopy(baseline)
baseline_low_cost.transform(
transform_treatment_cost(
"3", "initial", low_initial_stage_3_treatment_cost
)
).transform(
transform_treatment_cost(
"4", "initial", low_initial_stage_4_treatment_cost
)
.transform(transform_fit_only())
.transform(transform_routine_proportion(Test.FIT, 1.0))
.transform(transform_routine_ages(Test.FIT, -1, -1))
.transform(transform_propagate_diagnostic_noncompliance(propagation_value))
)
scenarios.append(no_screening)

# Full FIT compliance baseline
full_FIT_compliance = (
Scenario(
name=f"{propogation_name}_full_FIT_compliance",
params=get_default_params(),
)
baseline_low_cost.name = (
f"{fqhc}_{compliance}_baseline_low_initial_treat_cost"
)
scenarios.append(baseline_low_cost)

implementation_low_cost = deepcopy(implementation)
implementation_low_cost.transform(
transform_treatment_cost(
"3", "initial", low_initial_stage_3_treatment_cost
)
).transform(
transform_treatment_cost(
"4", "initial", low_initial_stage_4_treatment_cost
.transform(transform_fit_only())
.transform(transform_routine_proportion(Test.FIT, 1.0))
.transform(transform_routine_proportion(Test.COLONOSCOPY, 0.0))
.transform(transform_initial_compliance(1.0))
.transform(
transform_conditional_compliance_rates(
ConditionalComplianceParam.PREV_COMPLIANT, [float(1.0)] * 31
)
)
implementation_low_cost.name = (
f"{fqhc}_{compliance}_implementation_low_initial_treat_cost"
)
scenarios.append(implementation_low_cost)

# Sensitivity analysis 2a. Extra low cost for stage III and stage IV initial phase
baseline_extra_low_cost = deepcopy(baseline)
baseline_extra_low_cost.transform(
transform_treatment_cost(
"3", "initial", extra_low_initial_stage_3_treatment_cost
)
).transform(
transform_treatment_cost(
"4", "initial", extra_low_initial_stage_4_treatment_cost
.transform(
transform_conditional_compliance_rates(
ConditionalComplianceParam.NOT_PREV_COMPLIANT, [float(1.0)] * 31
)
)
baseline_extra_low_cost.name = (
f"{fqhc}_{compliance}_baseline_extra_low_initial_treat_cost"
.transform(transform_propagate_diagnostic_noncompliance(propagation_value))
)
scenarios.append(full_FIT_compliance)

# Full Colonoscopy compliance baseline
full_Colonoscopy_compliance = (
Scenario(
name=f"{propogation_name}_full_Colonoscopy_compliance",
params=get_default_params(),
)
scenarios.append(baseline_extra_low_cost)

implementation_extra_low_cost = deepcopy(implementation)
implementation_extra_low_cost.transform(
transform_treatment_cost(
"3", "initial", extra_low_initial_stage_3_treatment_cost
)
).transform(
transform_treatment_cost(
"4", "initial", extra_low_initial_stage_4_treatment_cost
.transform(transform_colonoscopy_only())
.transform(transform_routine_proportion(Test.FIT, 0.0))
.transform(transform_routine_proportion(Test.COLONOSCOPY, 1.0))
.transform(transform_initial_compliance(1.0))
.transform(
transform_conditional_compliance_rates(
ConditionalComplianceParam.PREV_COMPLIANT, [float(1.0)] * 31
)
)
implementation_extra_low_cost.name = (
f"{fqhc}_{compliance}_implementation_extra_low_initial_treat_cost"
.transform(
transform_conditional_compliance_rates(
ConditionalComplianceParam.NOT_PREV_COMPLIANT, [float(1.0)] * 31
)
)
scenarios.append(implementation_extra_low_cost)
.transform(transform_propagate_diagnostic_noncompliance(propagation_value))
)
scenarios.append(full_Colonoscopy_compliance)
return scenarios


Expand Down
6 changes: 3 additions & 3 deletions crcsim/experiment/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ authors = [
]

dependencies = [
# Clone the specific commit of the model that you want to use for the experiment
"crcsim @ git+https://github.com/RTIInternational/crcsim.git@6c264ca5e35c1b9ae20a6e4b95818f6e00970d71",
"fire==0.5.0",
# installing crcsim from latest commit on main to get propagate noncompliance feature
"crcsim @ git+https://github.com/RTIInternational/crcsim.git@c4e08bffba34c07d18b784c0632de506a36611e8",
"fire==0.7.0",
"pandas==2.1.1",
"openpyxl==3.0.9",
"wheel==0.41.2",
Expand Down
6 changes: 3 additions & 3 deletions crcsim/experiment/run_iteration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if [ ! -d "$output_dir" ]; then
mkdir $output_dir
fi

aws s3 cp "s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-interaction/scenarios/$scenario/params.json" "./params.json"
aws s3 cp "s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-together/scenarios/$scenario/params.json" "./params.json"

crc-simulate \
--npeople=$npeople \
Expand All @@ -23,5 +23,5 @@ crc-simulate \
crc-analyze \
--params-file=./params.json &&

aws s3 cp ./results.csv "s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-interaction/scenarios/$scenario/results_$iteration.csv"
aws s3 cp ./output.csv "s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-interaction/$scenario/output_$iteration.csv"
aws s3 cp ./results.csv "s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-together/scenarios/$scenario/results_$iteration.csv"
aws s3 cp ./output.csv "s3://crcsim-exp-fqhc-diagnostic-and-screening-compliance-together/$scenario/output_$iteration.csv"
Loading