Esempio n. 1
0
 def setUp(self):
     self.joe = Person(42, NHANESGender.MALE,
                       NHANESRaceEthnicity.NON_HISPANIC_BLACK, 140, 90, 5.5,
                       50, 200, 25, 90, 150, 45, 0,
                       Education.COLLEGEGRADUATE, SmokingStatus.NEVER,
                       AlcoholCategory.NONE, 0, 0, 0, initializeAFib)
     self._always_positive_repository = AlwaysPositiveOutcomeRepository()
     self._always_negative_repository = AlwaysNegativeOutcomeRepository()
     self.cvDeterminer = CVOutcomeDetermination(
         self._always_positive_repository)
Esempio n. 2
0
 def assign_cv_outcome(self,
                       person,
                       years=1,
                       manualStrokeMIProbability=None):
     outcomeDet = CVOutcomeDetermination(
         self.mi_case_fatality, self.stroke_case_fatality,
         self.secondary_mi_case_fatality,
         self.secondary_stroke_case_fatality,
         self.secondary_prevention_multiplier)
     return outcomeDet.assign_outcome_for_person(
         self, person, years, self.manualStrokeMIProbability)
Esempio n. 3
0
    def recalibrate_bp_treatment(self):
        treatment_change_standard, effect_of_treatment_standard, treatment_outcome_standard = self._bpTreatmentStrategy(
            self)
        # estimate risk for the people alive at the start of the wave
        recalibration_pop = self.get_people_alive_at_the_start_of_the_current_wave(
        )
        treatedStrokeRisks, treatedMIRisks = self.estimate_risks(
            recalibration_pop)

        # rollback the treatment effect.
        # redtag: would like to apply to this to a deeply cloned population, but i can't get that to work
        # so, for now, applying it to the actual population and then rolling the effect back later.
        for _, person in recalibration_pop.iteritems():
            person._sbp[
                -1] = person._sbp[-1] - effect_of_treatment_standard['_sbp']
            person._dbp[
                -1] = person._dbp[-1] - effect_of_treatment_standard['_dbp']
            person._antiHypertensiveCount[-1] = person._antiHypertensiveCount[-1] - \
                treatment_change_standard['_antiHypertensiveCount']

        # estimate risk after applying the treamtent effect
        untreatedStrokeRisks, untreatedMIRisks = self.estimate_risks(
            recalibration_pop)

        # hacktag related to above — roll back the treatment effect...
        for _, person in recalibration_pop.iteritems():
            person._sbp[
                -1] = person._sbp[-1] + effect_of_treatment_standard['_sbp']
            person._dbp[
                -1] = person._dbp[-1] + effect_of_treatment_standard['_dbp']
            person._antiHypertensiveCount[-1] = person._antiHypertensiveCount[-1] + \
                treatment_change_standard['_antiHypertensiveCount']

        # recalibrate stroke
        self.create_or_rollback_events_to_correct_calibration(
            treatment_outcome_standard, treatedStrokeRisks,
            untreatedStrokeRisks, OutcomeType.STROKE,
            CVOutcomeDetermination()._will_have_fatal_stroke,
            recalibration_pop)

        # recalibrate MI
        self.create_or_rollback_events_to_correct_calibration(
            treatment_outcome_standard, treatedMIRisks, untreatedMIRisks,
            OutcomeType.MI,
            CVOutcomeDetermination()._will_have_fatal_mi, recalibration_pop)
Esempio n. 4
0
    def setUp(self):
        self.joe = Person(
            42,
            NHANESGender.MALE,
            NHANESRaceEthnicity.NON_HISPANIC_BLACK,
            140,
            90,
            5.5,
            50,
            200,
            25,
            90,
            150,
            45,
            0,
            Education.COLLEGEGRADUATE,
            SmokingStatus.NEVER,
            AlcoholCategory.NONE,
            0,
            0,
            0,
            0,
            initializeAFib,
        )

        self.joe_with_mi = copy.deepcopy(self.joe)
        self.joe_with_mi.add_outcome_event(Outcome(OutcomeType.MI, False))

        self.joe_with_stroke = copy.deepcopy(self.joe)
        self.joe_with_stroke.add_outcome_event(Outcome(OutcomeType.STROKE, False))

        self._population_dataframe = init_vectorized_population_dataframe(
            [self.joe, self.joe_with_mi, self.joe_with_stroke],
            with_base_gcp=True,
        )

        self._always_positive_repository = AlwaysPositiveOutcomeRepository()
        self._always_negative_repository = AlwaysNegativeOutcomeRepository()
        self.cvDeterminer = CVOutcomeDetermination(self._always_positive_repository)
Esempio n. 5
0
    def estimate_risks(self, recalibration_pop):
        combinedRisks = pd.Series([
            self._outcome_model_repository.get_risk_for_person(
                person, OutcomeModelType.CARDIOVASCULAR, 1)
            for _, person in recalibration_pop.iteritems()
        ])
        strokeProbabilities = pd.Series([
            CVOutcomeDetermination().get_stroke_probability(person)
            for _, person in recalibration_pop.iteritems()
        ])

        strokeRisks = combinedRisks * strokeProbabilities
        miRisks = combinedRisks * (1 - strokeProbabilities)
        return strokeRisks, miRisks
Esempio n. 6
0
 def estimate_risks(self, recalibration_df, prefix):
     recalibration_df[prefix + "combinedRisks"] = recalibration_df.apply(
         self._outcome_model_repository.get_risk_for_person_vectorized,
         axis="columns",
         args=(OutcomeModelType.CARDIOVASCULAR, 1),
     )
     recalibration_df[prefix +
                      "strokeProbabilities"] = recalibration_df.apply(
                          CVOutcomeDetermination().get_stroke_probability,
                          axis="columns",
                          vectorized=True)
     recalibration_df[prefix + "strokeRisks"] = (
         recalibration_df[prefix + "combinedRisks"] *
         recalibration_df[prefix + "strokeProbabilities"])
     recalibration_df[
         prefix +
         "miRisks"] = recalibration_df[prefix + "combinedRisks"] * (
             1 - recalibration_df[prefix + "strokeProbabilities"])
     return recalibration_df
Esempio n. 7
0
class TestPersonAdvanceOutcomes(unittest.TestCase):
    def setUp(self):
        self.joe = Person(
            42,
            NHANESGender.MALE,
            NHANESRaceEthnicity.NON_HISPANIC_BLACK,
            140,
            90,
            5.5,
            50,
            200,
            25,
            90,
            150,
            45,
            0,
            Education.COLLEGEGRADUATE,
            SmokingStatus.NEVER,
            AlcoholCategory.NONE,
            0,
            0,
            0,
            0,
            initializeAFib,
        )

        self.joe_with_mi = copy.deepcopy(self.joe)
        self.joe_with_mi.add_outcome_event(Outcome(OutcomeType.MI, False))

        self.joe_with_stroke = copy.deepcopy(self.joe)
        self.joe_with_stroke.add_outcome_event(Outcome(OutcomeType.STROKE, False))

        self._population_dataframe = init_vectorized_population_dataframe(
            [self.joe, self.joe_with_mi, self.joe_with_stroke],
            with_base_gcp=True,
        )

        self._always_positive_repository = AlwaysPositiveOutcomeRepository()
        self._always_negative_repository = AlwaysNegativeOutcomeRepository()
        self.cvDeterminer = CVOutcomeDetermination(self._always_positive_repository)

    def test_dead_is_dead_advance_year(self):
        self.joe._alive[-1] = False
        with self.assertRaises(RuntimeError, msg="Person is dead. Can not advance year"):
            self.joe.advance_year(None, None)

    def test_dead_is_dead_advance_risk_factors(self):
        self.joe._alive[-1] = False
        with self.assertRaises(RuntimeError, msg="Person is dead. Can not advance risk factors"):
            self.joe.advance_risk_factors(None)

    def test_dead_is_dead_advance_outcomes(self):
        self.joe._alive[-1] = False
        with self.assertRaises(RuntimeError, msg="Person is dead. Can not advance outcomes"):
            self.joe.advance_outcomes(None)

    def test_will_have_fatal_mi(self):
        joe_data = self._population_dataframe.iloc[0]

        is_max_prob_mi_fatal = self.cvDeterminer._will_have_fatal_mi(
            joe_data,
            vectorized=True,
            overrideMIProb=1.0,
        )
        is_min_prob_mi_fatal = self.cvDeterminer._will_have_fatal_mi(
            joe_data,
            vectorized=True,
            overrideMIProb=0.0,
        )

        self.assertTrue(is_max_prob_mi_fatal)
        self.assertFalse(is_min_prob_mi_fatal)

    def test_fatal_mi_secondary_prob(self):
        self.cvDeterminer.mi_secondary_case_fatality = 1.0
        self.cvDeterminer.mi_case_fatality = 0.0
        joe_data = self._population_dataframe.iloc[0]
        joe_with_mi_data = self._population_dataframe.iloc[1]  # same as joe_data plus 1 MI

        will_have_fatal_first_mi = self.cvDeterminer._will_have_fatal_mi(
            joe_data,
            vectorized=True,
            overrideMIProb=0.0,
        )
        will_have_fatal_second_mi = self.cvDeterminer._will_have_fatal_mi(
            joe_with_mi_data,
            vectorized=True,
            overrideMIProb=0.0,
        )

        self.assertFalse(will_have_fatal_first_mi)
        # even though the passed fatality rate is zero, it should be overriden by the
        # secondary rate given that joe had a prior MI
        self.assertTrue(will_have_fatal_second_mi)

    def test_fatal_stroke_secondary_prob(self):
        self.cvDeterminer.stroke_secondary_case_fatality = 1.0
        self.cvDeterminer.stroke_case_fatality = 0.0
        joe_data = self._population_dataframe.iloc[0]
        joe_with_stroke_data = self._population_dataframe.iloc[2]  # same as joe_data plus 1 stroke

        will_have_fatal_first_stroke = self.cvDeterminer._will_have_fatal_stroke(
            joe_data,
            vectorized=True,
            overrideStrokeProb=0.0,
        )
        will_have_fatal_second_stroke = self.cvDeterminer._will_have_fatal_stroke(
            joe_with_stroke_data,
            vectorized=True,
            overrideStrokeProb=0.0,
        )

        self.assertFalse(will_have_fatal_first_stroke)
        # even though the passed fatality rate is zero, it shoudl be overriden by the
        # secondary rate given that joeclone had a prior stroke
        self.assertTrue(will_have_fatal_second_stroke)

    def test_will_have_fatal_stroke(self):
        joe_data = self._population_dataframe.iloc[0]

        is_max_prob_stroke_fatal = self.cvDeterminer._will_have_fatal_stroke(
            joe_data,
            vectorized=True,
            overrideStrokeProb=1.0,
        )
        is_min_prob_stroke_fatal = self.cvDeterminer._will_have_fatal_stroke(
            joe_data,
            vectorized=True,
            overrideStrokeProb=0.0,
        )

        self.assertTrue(is_max_prob_stroke_fatal)
        self.assertFalse(is_min_prob_stroke_fatal)

    def test_has_mi_vs_stroke(self):
        joe_data = self._population_dataframe.iloc[0]

        has_mi_max_manual_prob = self.cvDeterminer._will_have_mi(
            joe_data,
            outcome_model_repository=None,
            vectorized=False,
            manualMIProb=1.0,
        )
        has_mi_min_manual_prob = self.cvDeterminer._will_have_mi(
            joe_data,
            outcome_model_repository=None,
            vectorized=False,
            manualMIProb=0.0,
        )

        self.assertTrue(has_mi_max_manual_prob)
        self.assertFalse(has_mi_min_manual_prob)

    def test_advance_outcomes_fatal_mi(self):
        self._always_positive_repository.stroke_case_fatality = 1.0
        self._always_positive_repository.mi_case_fatality = 1.0
        self._always_positive_repository.manualStrokeMIProbability = 1.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertTrue(self.joe.has_mi_during_simulation())
        self.assertFalse(self.joe.has_stroke_during_simulation())
        self.assertTrue(self.joe.is_dead())

    def test_advance_outcomes_fatal_stroke(self):
        self._always_positive_repository.stroke_case_fatality = 1.0
        self._always_positive_repository.mi_case_fatality = 1.0
        self._always_positive_repository.manualStrokeMIProbability = 0.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertFalse(self.joe.has_mi_during_simulation())
        self.assertTrue(self.joe.has_stroke_during_simulation())
        self.assertTrue(self.joe.is_dead())

    def test_advance_outcomes_nonfatal_mi(self):
        self.assertEqual(0, self.joe.is_dead())
        self._always_positive_repository.stroke_case_fatality = 0.0
        self._always_positive_repository.mi_case_fatality = 0.0
        self._always_positive_repository.manualStrokeMIProbability = 1.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertTrue(self.joe.has_mi_during_simulation())
        self.assertFalse(self.joe.has_stroke_during_simulation())

    def test_advance_outcomes_nonfatal_stroke(self):
        self._always_positive_repository.stroke_case_fatality = 0.0
        self._always_positive_repository.mi_case_fatality = 0.0
        self._always_positive_repository.manualStrokeMIProbability = 0.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertFalse(self.joe.has_mi_during_simulation())
        self.assertTrue(self.joe.has_stroke_during_simulation())
Esempio n. 8
0
class TestPersonAdvanceOutcomes(unittest.TestCase):
    def setUp(self):
        self.joe = Person(42, NHANESGender.MALE,
                          NHANESRaceEthnicity.NON_HISPANIC_BLACK, 140, 90, 5.5,
                          50, 200, 25, 90, 150, 45, 0,
                          Education.COLLEGEGRADUATE, SmokingStatus.NEVER,
                          AlcoholCategory.NONE, 0, 0, 0, initializeAFib)
        self._always_positive_repository = AlwaysPositiveOutcomeRepository()
        self._always_negative_repository = AlwaysNegativeOutcomeRepository()
        self.cvDeterminer = CVOutcomeDetermination(
            self._always_positive_repository)

    def test_dead_is_dead_advance_year(self):
        self.joe._alive[-1] = False
        with self.assertRaises(RuntimeError,
                               msg="Person is dead. Can not advance year"):
            self.joe.advance_year(None, None)

    def test_dead_is_dead_advance_risk_factors(self):
        self.joe._alive[-1] = False
        with self.assertRaises(
                RuntimeError,
                msg="Person is dead. Can not advance risk factors"):
            self.joe.advance_risk_factors(None)

    def test_dead_is_dead_advance_outcomes(self):
        self.joe._alive[-1] = False
        with self.assertRaises(RuntimeError,
                               msg="Person is dead. Can not advance outcomes"):
            self.joe.advance_outcomes(None)

    def test_will_have_fatal_mi(self):
        self.assertEqual(self.cvDeterminer._will_have_fatal_mi(self.joe, 1.0),
                         1)
        self.assertEqual(self.cvDeterminer._will_have_fatal_mi(self.joe, 0.0),
                         0)

    def test_fatal_mi_secondary_prob(self):
        self.cvDeterminer.mi_secondary_case_fatality = 1.0
        self.cvDeterminer.mi_case_fatality = 0.0

        joeClone = copy.deepcopy(self.joe)

        self.assertEqual(self.cvDeterminer._will_have_fatal_mi(joeClone, 0.0),
                         0)

        joeClone._outcomes[OutcomeType.MI] = (joeClone._age,
                                              Outcome(OutcomeType.MI, False))
        # even though the passed fatality rate is zero, it shoudl be overriden by the
        # secondary rate given that joeclone had a prior MI
        self.assertEqual(self.cvDeterminer._will_have_fatal_mi(joeClone, 0.0),
                         1)

    def test_fatal_stroke_secondary_prob(self):
        self.cvDeterminer.stroke_secondary_case_fatality = 1.0
        self.cvDeterminer.stroke_case_fatality = 0.0

        joeClone = copy.deepcopy(self.joe)

        self.assertEqual(
            self.cvDeterminer._will_have_fatal_stroke(joeClone, 0.0), 0)

        joeClone._outcomes[OutcomeType.STROKE] = (joeClone._age,
                                                  Outcome(
                                                      OutcomeType.STROKE,
                                                      False))
        # even though the passed fatality rate is zero, it shoudl be overriden by the
        # secondary rate given that joeclone had a prior stroke
        self.assertEqual(
            self.cvDeterminer._will_have_fatal_stroke(joeClone, 0.0), 1)

    def test_will_have_fatal_stroke(self):
        self.assertEqual(
            self.cvDeterminer._will_have_fatal_stroke(self.joe, 1.0), 1)
        self.assertEqual(
            self.cvDeterminer._will_have_fatal_stroke(self.joe, 0.0), 0)

    def test_has_mi_vs_stroke(self):
        self.assertEqual(self.cvDeterminer._will_have_mi(self.joe, None, 1.0),
                         1)
        self.assertEqual(self.cvDeterminer._will_have_mi(self.joe, None, 0.0),
                         0)

    def test_advance_outcomes_fatal_mi(self):
        self._always_positive_repository.stroke_case_fatality = 1.0
        self._always_positive_repository.mi_case_fatality = 1.0
        self._always_positive_repository.manualStrokeMIProbability = 1.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertTrue(self.joe.has_mi_during_simulation())
        self.assertFalse(self.joe.has_stroke_during_simulation())
        self.assertTrue(self.joe.is_dead())

    def test_advance_outcomes_fatal_stroke(self):
        self._always_positive_repository.stroke_case_fatality = 1.0
        self._always_positive_repository.mi_case_fatality = 1.0
        self._always_positive_repository.manualStrokeMIProbability = 0.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertFalse(self.joe.has_mi_during_simulation())
        self.assertTrue(self.joe.has_stroke_during_simulation())
        self.assertTrue(self.joe.is_dead())

    def test_advance_outcomes_nonfatal_mi(self):
        self.assertEqual(0, self.joe.is_dead())
        self._always_positive_repository.stroke_case_fatality = 0.0
        self._always_positive_repository.mi_case_fatality = 0.0
        self._always_positive_repository.manualStrokeMIProbability = 1.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertTrue(self.joe.has_mi_during_simulation())
        self.assertFalse(self.joe.has_stroke_during_simulation())

    def test_advance_outcomes_nonfatal_stroke(self):
        self._always_positive_repository.stroke_case_fatality = 0.0
        self._always_positive_repository.mi_case_fatality = 0.0
        self._always_positive_repository.manualStrokeMIProbability = 0.0

        self.joe.advance_outcomes(self._always_positive_repository)
        self.assertFalse(self.joe.has_mi_during_simulation())
        self.assertTrue(self.joe.has_stroke_during_simulation())
Esempio n. 9
0
    def recalibrate_bp_treatment(self, recalibration_df):
        treatment_outcome_standard = (
            self._bpTreatmentStrategy.
            get_treatment_recalibration_for_population())
        # estimate risk for the people alive at the start of the wave
        self.estimate_risks(recalibration_df, "treated")

        # rollback the treatment effect.
        # redtag: would like to apply to this to a deeply cloned population, but i can't get that to work
        # so, for now, applying it to the actual population and then rolling the effect back later.
        recalibration_df = recalibration_df.apply(
            self._bpTreatmentStrategy.rollback_changes_vectorized,
            axis="columns")

        # estimate risk after applying the treamtent effect
        self.estimate_risks(recalibration_df, "untreated")

        # hacktag related to above — roll back the treatment effect...
        recalibration_df = recalibration_df.apply(
            self._bpTreatmentStrategy.get_changes_vectorized, axis="columns")
        recalibration_df["rolledBackEventType"] = None
        maxMeds = 5
        # recalibrate within each group of added medicaitons so that we can stratify the treamtnet effects
        for i in range(1, maxMeds + 1):
            recalibrationPopForMedCount = recalibration_df.loc[
                (recalibration_df.bpMedsAddedNext == i)
                | (recalibration_df.bpMedsAddedNext.values >= maxMeds)]
            # the change standards are for a single medication
            recalibration_standard_for_med_count = treatment_outcome_standard.copy(
            )
            for key, value in recalibration_standard_for_med_count.items():
                recalibration_standard_for_med_count[key] = value**i

            if len(recalibrationPopForMedCount) > 0:
                # recalibrate stroke
                recalibratedForMedCount = self.create_or_rollback_events_to_correct_calibration(
                    recalibration_standard_for_med_count,
                    "treatedstrokeRisks",
                    "untreatedstrokeRisks",
                    "stroke",
                    OutcomeType.STROKE,
                    CVOutcomeDetermination()._will_have_fatal_stroke,
                    recalibrationPopForMedCount,
                )

                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "strokeNext"] = recalibratedForMedCount["strokeNext"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "strokeFatal"] = recalibratedForMedCount["strokeFatal"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "deadNext"] = recalibratedForMedCount["deadNext"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "ageAtFirstStroke"] = recalibratedForMedCount[
                        "ageAtFirstStroke"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "rolledBackEventType"] = recalibratedForMedCount[
                        "rolledBackEventType"]

                # recalibrate MI
                recalibratedForMedCount = self.create_or_rollback_events_to_correct_calibration(
                    recalibration_standard_for_med_count,
                    "treatedmiRisks",
                    "untreatedmiRisks",
                    "mi",
                    OutcomeType.MI,
                    CVOutcomeDetermination()._will_have_fatal_mi,
                    recalibrationPopForMedCount,
                )
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "miNext"] = recalibratedForMedCount["miNext"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "miFatal"] = recalibratedForMedCount["miFatal"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "deadNext"] = recalibratedForMedCount["deadNext"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "ageAtFirstMI"] = recalibratedForMedCount["ageAtFirstMI"]
                recalibration_df.loc[
                    recalibratedForMedCount.index,
                    "rolledBackEventType"] = recalibratedForMedCount[
                        "rolledBackEventType"]

        return recalibration_df
Esempio n. 10
0
    def __init__(self):
        self.mi_case_fatality = CVOutcomeDetermination.default_mi_case_fatality
        self.secondary_mi_case_fatality = CVOutcomeDetermination.default_secondary_mi_case_fatality
        self.stroke_case_fatality = CVOutcomeDetermination.default_stroke_case_fatality
        self.secondary_stroke_case_fatality = (
            CVOutcomeDetermination.default_secondary_stroke_case_fatality)
        self.secondary_prevention_multiplier = (
            CVOutcomeDetermination.default_secondary_prevention_multiplier)

        self.outcomeDet = CVOutcomeDetermination(
            self.mi_case_fatality,
            self.stroke_case_fatality,
            self.secondary_mi_case_fatality,
            self.secondary_stroke_case_fatality,
            self.secondary_prevention_multiplier,
        )

        # variable used in testing to control whether a patient will have a stroke or mi
        self.manualStrokeMIProbability = None

        self._models = {}
        femaleCVCoefficients = {
            "lagAge": 0.106501,
            "black": 0.432440,
            "lagSbp#lagSbp": 0.000056,
            "lagSbp": 0.017666,
            "current_bp_treatment": 0.731678,
            "current_diabetes": 0.943970,
            "current_smoker": 1.009790,
            "lagAge#black": -0.008580,
            "lagSbp#current_bp_treatment": -0.003647,
            "lagSbp#black": 0.006208,
            "black#current_bp_treatment": 0.152968,
            "lagAge#lagSbp": -0.000153,
            "black#current_diabetes": 0.115232,
            "black#current_smoker": -0.092231,
            "lagSbp#black#current_bp_treatment": -0.000173,
            "lagAge#lagSbp#black": -0.000094,
            "Intercept": -12.823110,
        }

        maleCVCoefficients = {
            "lagAge": 0.064200,
            "black": 0.482835,
            "lagSbp#lagSbp": -0.000061,
            "lagSbp": 0.038950,
            "current_bp_treatment": 2.055533,
            "current_diabetes": 0.842209,
            "current_smoker": 0.895589,
            "lagAge#black": 0,
            "lagSbp#current_bp_treatment": -0.014207,
            "lagSbp#black": 0.011609,
            "black#current_bp_treatment": -0.119460,
            "lagAge#lagSbp": 0.000025,
            "black#current_diabetes": -0.077214,
            "black#current_smoker": -0.226771,
            "lagSbp#black#current_bp_treatment": 0.004190,
            "lagAge#lagSbp#black": -0.000199,
            "Intercept": -11.679980,
        }

        self._models[OutcomeModelType.CARDIOVASCULAR] = {
            "female":
            ASCVDOutcomeModel(
                RegressionModel(
                    coefficients=femaleCVCoefficients,
                    coefficient_standard_errors={
                        key: 0
                        for key in femaleCVCoefficients
                    },
                    residual_mean=0,
                    residual_standard_deviation=0,
                ),
                tot_chol_hdl_ratio=0.151318,
                black_race_x_tot_chol_hdl_ratio=0.070498,
            ),
            "male":
            ASCVDOutcomeModel(
                RegressionModel(
                    coefficients=maleCVCoefficients,
                    coefficient_standard_errors={
                        key: 0
                        for key in maleCVCoefficients
                    },
                    residual_mean=0,
                    residual_standard_deviation=0,
                ),
                tot_chol_hdl_ratio=0.193307,
                black_race_x_tot_chol_hdl_ratio=-0.117749,
            ),
        }
        self._models[
            OutcomeModelType.GLOBAL_COGNITIVE_PERFORMANCE] = GCPModel()
        self._models[OutcomeModelType.DEMENTIA] = DementiaModel()

        # This represents non-cardiovascular mortality..
        nonCVModelSpec = load_model_spec("nhanesMortalityModelLogit")
        mortModel = StatsModelLogisticRiskFactorModel(
            RegressionModel(**nonCVModelSpec), False)
        # Recalibrate mortalitly model to align with life table data, as explored in notebook
        # buildNHANESMortalityModel
        mortModel.non_intercept_params[
            "age"] = mortModel.non_intercept_params["age"] * -1
        mortModel.non_intercept_params["squareAge"] = (
            mortModel.non_intercept_params["squareAge"] * 4)
        self._models[OutcomeModelType.NON_CV_MORTALITY] = mortModel
Esempio n. 11
0
class OutcomeModelRepository:
    def __init__(self):
        self.mi_case_fatality = CVOutcomeDetermination.default_mi_case_fatality
        self.secondary_mi_case_fatality = CVOutcomeDetermination.default_secondary_mi_case_fatality
        self.stroke_case_fatality = CVOutcomeDetermination.default_stroke_case_fatality
        self.secondary_stroke_case_fatality = (
            CVOutcomeDetermination.default_secondary_stroke_case_fatality)
        self.secondary_prevention_multiplier = (
            CVOutcomeDetermination.default_secondary_prevention_multiplier)

        self.outcomeDet = CVOutcomeDetermination(
            self.mi_case_fatality,
            self.stroke_case_fatality,
            self.secondary_mi_case_fatality,
            self.secondary_stroke_case_fatality,
            self.secondary_prevention_multiplier,
        )

        # variable used in testing to control whether a patient will have a stroke or mi
        self.manualStrokeMIProbability = None

        self._models = {}
        femaleCVCoefficients = {
            "lagAge": 0.106501,
            "black": 0.432440,
            "lagSbp#lagSbp": 0.000056,
            "lagSbp": 0.017666,
            "current_bp_treatment": 0.731678,
            "current_diabetes": 0.943970,
            "current_smoker": 1.009790,
            "lagAge#black": -0.008580,
            "lagSbp#current_bp_treatment": -0.003647,
            "lagSbp#black": 0.006208,
            "black#current_bp_treatment": 0.152968,
            "lagAge#lagSbp": -0.000153,
            "black#current_diabetes": 0.115232,
            "black#current_smoker": -0.092231,
            "lagSbp#black#current_bp_treatment": -0.000173,
            "lagAge#lagSbp#black": -0.000094,
            "Intercept": -12.823110,
        }

        maleCVCoefficients = {
            "lagAge": 0.064200,
            "black": 0.482835,
            "lagSbp#lagSbp": -0.000061,
            "lagSbp": 0.038950,
            "current_bp_treatment": 2.055533,
            "current_diabetes": 0.842209,
            "current_smoker": 0.895589,
            "lagAge#black": 0,
            "lagSbp#current_bp_treatment": -0.014207,
            "lagSbp#black": 0.011609,
            "black#current_bp_treatment": -0.119460,
            "lagAge#lagSbp": 0.000025,
            "black#current_diabetes": -0.077214,
            "black#current_smoker": -0.226771,
            "lagSbp#black#current_bp_treatment": 0.004190,
            "lagAge#lagSbp#black": -0.000199,
            "Intercept": -11.679980,
        }

        self._models[OutcomeModelType.CARDIOVASCULAR] = {
            "female":
            ASCVDOutcomeModel(
                RegressionModel(
                    coefficients=femaleCVCoefficients,
                    coefficient_standard_errors={
                        key: 0
                        for key in femaleCVCoefficients
                    },
                    residual_mean=0,
                    residual_standard_deviation=0,
                ),
                tot_chol_hdl_ratio=0.151318,
                black_race_x_tot_chol_hdl_ratio=0.070498,
            ),
            "male":
            ASCVDOutcomeModel(
                RegressionModel(
                    coefficients=maleCVCoefficients,
                    coefficient_standard_errors={
                        key: 0
                        for key in maleCVCoefficients
                    },
                    residual_mean=0,
                    residual_standard_deviation=0,
                ),
                tot_chol_hdl_ratio=0.193307,
                black_race_x_tot_chol_hdl_ratio=-0.117749,
            ),
        }
        self._models[
            OutcomeModelType.GLOBAL_COGNITIVE_PERFORMANCE] = GCPModel()
        self._models[OutcomeModelType.DEMENTIA] = DementiaModel()

        # This represents non-cardiovascular mortality..
        nonCVModelSpec = load_model_spec("nhanesMortalityModelLogit")
        mortModel = StatsModelLogisticRiskFactorModel(
            RegressionModel(**nonCVModelSpec), False)
        # Recalibrate mortalitly model to align with life table data, as explored in notebook
        # buildNHANESMortalityModel
        mortModel.non_intercept_params[
            "age"] = mortModel.non_intercept_params["age"] * -1
        mortModel.non_intercept_params["squareAge"] = (
            mortModel.non_intercept_params["squareAge"] * 4)
        self._models[OutcomeModelType.NON_CV_MORTALITY] = mortModel

    def get_random_effects(self):
        return {"gcp": npRand.normal(0, 4.84)}

    def get_risk_for_person_vectorized(self, x, outcome, years=1):
        personWrapper = PersonRowWrapper(x)
        return self.select_model_for_person(personWrapper,
                                            outcome).get_risk_for_person(
                                                x, years, True)

    def get_risk_for_person(self, person, outcome, years=1, vectorized=False):
        if vectorized:
            return self.get_risk_for_person_vectorized(person, outcome, years)
        else:
            return self.select_model_for_person(person,
                                                outcome).get_risk_for_person(
                                                    person, years, False)

    def get_gcp(self, person):
        gcp = (self.get_risk_for_person(
            person, OutcomeModelType.GLOBAL_COGNITIVE_PERFORMANCE) +
               person._randomEffects["gcp"])
        return gcp if gcp > 0 else 0

    # should the GCP random effct be included here or in the risk model?
    def get_gcp_vectorized(self, person):
        gcp = (self.get_risk_for_person(
            person,
            OutcomeModelType.GLOBAL_COGNITIVE_PERFORMANCE,
            years=1,
            vectorized=True) + person.gcpRandomEffect)
        return gcp if gcp > 0 else 0

    def get_dementia(self, person):
        if npRand.uniform(size=1) < self.get_risk_for_person(
                person, OutcomeModelType.DEMENTIA):
            return Outcome(OutcomeType.DEMENTIA, False)
        else:
            return None

    def get_dementia_vectorized(self, person):
        return npRand.uniform(size=1)[0] < self.get_risk_for_person(
            person, OutcomeModelType.DEMENTIA, years=1, vectorized=True)

    def select_model_for_person(self, person, outcome):
        return self.select_model_for_gender(person._gender, outcome)

    def select_model_for_gender(self, gender, outcome):
        models_for_outcome = self._models[outcome]
        if outcome == OutcomeModelType.CARDIOVASCULAR:
            gender_stem = "male" if gender == NHANESGender.MALE else "female"
            return models_for_outcome[gender_stem]
        else:
            return models_for_outcome

    def initialize_cox_model(self, modelName):
        model_spec = load_model_spec(modelName)
        return StatsModelCoxModel(CoxRegressionModel(**model_spec))

    def assign_cv_outcome(self,
                          person,
                          years=1,
                          manualStrokeMIProbability=None):
        return self.outcomeDet.assign_outcome_for_person(
            self, person, False, years, self.manualStrokeMIProbability)

    def assign_cv_outcome_vectorized(self,
                                     x,
                                     years=1,
                                     manualStrokeMIProbability=None):
        return self.outcomeDet.assign_outcome_for_person(
            self,
            x,
            vectorized=True,
            years=years,
            manualStrokeMIProbability=self.manualStrokeMIProbability,
        )

        # Returns True if the model-based logic vs. the random comparison suggests death

    def assign_non_cv_mortality(self, person, years=1):
        riskForPerson = self.get_risk_for_person(
            person, OutcomeModelType.NON_CV_MORTALITY)
        if npRand.uniform(size=1)[0] < riskForPerson:
            return True

    def assign_non_cv_mortality_vectorized(self, person, years=1):
        riskForPerson = self.get_risk_for_person(
            person, OutcomeModelType.NON_CV_MORTALITY, years, vectorized=True)
        return npRand.uniform(size=1)[0] < riskForPerson