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 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)
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)
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 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
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
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())
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())
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
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
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