Example #1
0
 def assign_cv_outcome(self,
                       person,
                       years=1,
                       manualStrokeMIProbability=None):
     return Outcome(
         OutcomeType.STROKE,
         False) if np.random.random() < self._stroke_rate else None
Example #2
0
 def assign_cv_outcome(self,
                       person,
                       years=1,
                       manualStrokeMIProbability=None):
     return (Outcome(OutcomeType.MI,
                     np.random.random() < self._fatality_rate)
             if np.random.random() < self._mi_rate else None)
Example #3
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)
Example #4
0
    def create_or_rollback_events_to_correct_calibration(
            self, treatment_outcome_standard, treatedRisks, untreatedRisks,
            outcomeType, fatalityDetermination, recalibration_pop):
        modelEstimatedRR = treatedRisks.mean() / untreatedRisks.mean()
        # use the delta between that effect and the calibration standard to recalibrate the pop.
        delta = modelEstimatedRR - treatment_outcome_standard[outcomeType]
        eventsForPeople = [
            person.has_outcome_during_wave(self._currentWave, outcomeType)
            for _, person in recalibration_pop.iteritems()
        ]

        numberOfEventStatusesToChange = abs(
            int(
                round(delta * pd.Series(eventsForPeople).sum() /
                      modelEstimatedRR)))
        nonEventsForPeople = [not item for item in eventsForPeople]
        # key assumption: "treatment" is applied to a population as opposed to individuals within a population
        # analyses can be setup either way...build two populations and then set different treatments
        # or build a ur-population adn then set different treamtents within them
        # this is, i thikn, the first time where a coding decision is tied to one of those structure.
        # it would not, i think, be hard to change. but, just spelling it out here.

        # if negative, the model estimated too few events, if positive, too mnany
        if delta < 0:
            if numberOfEventStatusesToChange > 0:
                new_events = recalibration_pop.loc[nonEventsForPeople].sample(
                    n=numberOfEventStatusesToChange,
                    replace=False,
                    weights=pd.Series(
                        untreatedRisks).loc[nonEventsForPeople].values)
                for i, event in new_events.iteritems():
                    event.add_outcome_event(
                        Outcome(outcomeType, fatalityDetermination(event)))

        # redtag - two problems here...1. rolling back events in people that may not have events
        # 2. probably usign the wrong weights...need to roll back inversely proportionately to the likeliood of an event, riht?

        elif delta > 0:
            if numberOfEventStatusesToChange > pd.Series(
                    eventsForPeople).sum():
                numberOfEventStatusesToChange = pd.Series(
                    eventsForPeople).sum()
            if numberOfEventStatusesToChange > 0:
                events_to_rollback = recalibration_pop.loc[
                    eventsForPeople].sample(
                        n=numberOfEventStatusesToChange,
                        replace=False,
                        weights=pd.Series(
                            1 - untreatedRisks).loc[eventsForPeople].values)
                for i, event in events_to_rollback.iteritems():
                    event.rollback_most_recent_event(outcomeType)
Example #5
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 assign_outcome_for_person(self,
                                  outcome_model_repository,
                                  person,
                                  years=1,
                                  manualStrokeMIProbability=None):

        cvRisk = outcome_model_repository.get_risk_for_person(
            person, OutcomeModelType.CARDIOVASCULAR, years=1)

        if person._stroke or person._mi:
            cvRisk = cvRisk * self.secondary_prevention_multiplier

        if self._will_have_cvd_event(cvRisk):
            if self._will_have_mi(person, outcome_model_repository,
                                  manualStrokeMIProbability):
                if self._will_have_fatal_mi(person):
                    return Outcome(OutcomeType.MI, True)
                else:
                    return Outcome(OutcomeType.MI, False)
            else:
                if self._will_have_fatal_stroke(person):
                    return Outcome(OutcomeType.STROKE, True)
                else:
                    return Outcome(OutcomeType.STROKE, False)
 def get_outcome(self, person, mi, fatal, vectorized):
     if vectorized:
         person.miNext = mi
         person.strokeNext = not mi
         person.deadNext = fatal
         person.miFatal = mi and fatal
         person.strokeFatal = not mi and fatal
         person.ageAtFirstMI = (
             person.age
             if (person.ageAtFirstMI is None) or (np.isnan(person.ageAtFirstMI))
             else person.ageAtFirstMI
         )
         person.ageAtFirstStroke = (
             person.age
             if (person.ageAtFirstStroke is None) or (np.isnan(person.ageAtFirstStroke))
             else person.ageAtFirstStroke
         )
         return person
     else:
         return Outcome(OutcomeType.MI if mi else OutcomeType.STROKE, fatal)
Example #8
0
    def update_person(self, person, x):
        if person.is_dead():
            raise Exception(f"Trying to update a dead person: {person}")
        for rf in self._riskFactors:
            attr = getattr(person, "_" + rf)
            attr.append(x[rf + str(self._currentWave)])

        for treatment in self._treatments:
            attr = getattr(person, "_" + treatment)
            attr.append(x[treatment + str(self._currentWave)])

        # advance outcomes - this will add CV eath
        for outcomeName, outcomeType in {
                "stroke": OutcomeType.STROKE,
                "mi": OutcomeType.MI,
                "dementia": OutcomeType.DEMENTIA,
        }.items():
            if x[outcomeName + "Next"]:
                fatal = False if outcomeName == "dementia" else x[outcomeName +
                                                                  "Fatal"]
                # only one dementia event per person
                if outcomeName == "dementia" and person._dementia:
                    break
                else:
                    person.add_outcome_event(Outcome(outcomeType, fatal))

        person._gcp.append(x.gcp)
        person._qalys.append(x.qalyNext)
        person._bpMedsAdded.append(x.bpMedsAddedNext)

        # add non CV death to person objects
        if x.nonCVDeathNext:
            person._alive.append(False)

        # only advance age in survivors
        if not x.deadNext:
            person._age.append(person._age[-1] + 1)
            person._alive.append(True)
        return person
Example #9
0
 def get_dementia(self, person):
     return Outcome(OutcomeType.DEMENTIA, False)
Example #10
0
 def assign_cv_outcome(self, person, years=1, manualStrokeMIProbability=None):
     return Outcome(OutcomeType.MI, 0)
Example #11
0
    def __init__(
        self,
        age: int,
        gender: NHANESGender,
        raceEthnicity: NHANESRaceEthnicity,
        sbp: int,
        dbp: int,
        a1c: float,
        hdl: int,
        totChol: int,
        bmi: float,
        ldl: int,
        trig: int,
        waist: int,  # Waist circumference in cm
        anyPhysicalActivity: int,
        education: Education,
        smokingStatus: SmokingStatus,
        alcohol: AlcoholCategory,
        antiHypertensiveCount: int,
        statin: int,
        otherLipidLoweringMedicationCount: int,
        creatinine: float,
        initializeAfib: Callable,
        initializationRepository=None,
        selfReportStrokeAge=None,
        selfReportMIAge=None,
        randomEffects=None,
        **kwargs,
    ) -> None:

        # building in manual bounds on extreme values
        self._lowerBounds = {"sbp": 60, "dbp": 20}
        self._upperBounds = {"sbp": 300, "dbp": 180}

        self._gender = gender
        self._raceEthnicity = raceEthnicity

        self._alive = [True]

        self._age = [age]
        self._sbp = [self.apply_bounds("sbp", sbp)]
        self._dbp = [self.apply_bounds("dbp", dbp)]
        self._a1c = [a1c]
        self._hdl = [hdl]
        self._ldl = [ldl]
        self._trig = [trig]
        self._totChol = [totChol]
        self._bmi = [bmi]
        self._waist = [waist]
        self._anyPhysicalActivity = [anyPhysicalActivity]
        self._alcoholPerWeek = [alcohol]
        self._education = education
        # TODO : change smoking status into a factor that changes over time
        self._smokingStatus = smokingStatus
        self._antiHypertensiveCount = [antiHypertensiveCount]
        self._statin = [statin]
        self._otherLipidLoweringMedicationCount = [
            otherLipidLoweringMedicationCount
        ]
        self._creatinine = [creatinine]

        # outcomes is a dictionary of arrays. each element in the dictionary represents
        # a differnet outcome type each element in the array is a tuple representting
        # the age of the patient at the time of an event (element zero). and the outcome
        # (element one).multiple events can be accounted for by having multiple
        # elements in the array.
        self._outcomes = {
            OutcomeType.MI: [],
            OutcomeType.STROKE: [],
            OutcomeType.DEMENTIA: []
        }
        self._selfReportStrokePriorToSim = 0
        self._selfReportMIPriorToSim = 0

        # a variable to track changes in BP meds compared to the baseline
        self._bpMedsAdded = [0]

        # convert events for events prior to simulation
        if selfReportStrokeAge is not None and selfReportStrokeAge > 1:
            self._selfReportStrokeAge = (selfReportStrokeAge if
                                         selfReportStrokeAge <= self._age[-1]
                                         else self._age[-1])
            self._selfReportStrokePriorToSim = 1
            self._outcomes[OutcomeType.STROKE].append(
                (-1, Outcome(OutcomeType.STROKE, False)))
        if selfReportMIAge is not None and selfReportMIAge > 1:
            self._selfReportMIAge = (selfReportMIAge
                                     if selfReportMIAge <= self._age[-1] else
                                     self._age[-1])
            self._selfReportMIPriorToSim = 1
            self._outcomes[OutcomeType.MI].append(
                (-1, Outcome(OutcomeType.MI, False)))
        for k, v in kwargs.items():
            setattr(self, k, v)
        if initializeAfib is not None:
            self._afib = [initializeAfib(self)]
        else:
            self._afib = [False]

        # for outcome mocels that require random effects, store in this dictionary
        self._randomEffects = {"gcp": 0}
        if randomEffects is not None:
            self._randomEffects.update(randomEffects)

        # lucianatag: for this and GCP, this approach is a bit inelegant. the idea is to have classees that can be swapped out
        # at the population level to change the behavior about how people change over time.
        # but, when we instantiate a person, we don't want to keep a refernce tot the population.
        # is the fix just to have the population create people (such that the repository/strategy/model classes can be assigned from within
        # the population)
        self._qalys = []
        self._gcp = []
        if initializationRepository is not None:
            initializers = initializationRepository.get_initializers()
            for initializerName, method in initializers.items():
                attr = getattr(self, initializerName)
                attr.append(method(self))

        self._bpTreatmentStrategy = None
 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
Example #13
0
    def __init__(
        self,
        age: int,
        gender: NHANESGender,
        raceEthnicity: NHANESRaceEthnicity,
        sbp: int,
        dbp: int,
        a1c: float,
        hdl: int,
        totChol: int,
        bmi: float,
        ldl: int,
        trig: int,
        waist: int,  # Waist circumference in cm
        anyPhysicalActivity: int,
        education: Education,
        smokingStatus: SmokingStatus,
        alcohol: AlcoholCategory,
        antiHypertensiveCount: int,
        statin: int,
        otherLipidLoweringMedicationCount: int,
        initializeAfib: Callable,
        selfReportStrokeAge=None,
        selfReportMIAge=None,
        **kwargs,
    ) -> None:

        # building in manual bounds on extreme values
        self._lowerBounds = {"sbp": 60, "dbp": 20}
        self._upperBounds = {"sbp": 300, "dbp": 180}

        self._gender = gender
        self._raceEthnicity = raceEthnicity

        self._alive = [True]

        self._age = [age]
        self._sbp = [self.apply_bounds("sbp", sbp)]
        self._dbp = [self.apply_bounds("dbp", dbp)]
        self._a1c = [a1c]
        self._hdl = [hdl]
        self._ldl = [ldl]
        self._trig = [trig]
        self._totChol = [totChol]
        self._bmi = [bmi]
        self._waist = [waist]
        self._anyPhysicalActivity = [anyPhysicalActivity]
        self._alcoholPerWeek = [alcohol]
        self._education = education
        # TODO : change smoking status into a factor that changes over time
        self._smokingStatus = smokingStatus
        self._antiHypertensiveCount = [antiHypertensiveCount]
        self._statin = [statin]
        self._otherLipidLoweringMedicationCount = [
            otherLipidLoweringMedicationCount
        ]

        # outcomes is a dictionary of arrays. each element in the dictionary represents
        # a differnet outcome type each element in the array is a tuple representting
        # the age of the patient at the time of an event (element zero). and the outcome
        # (element one).multiple events can be accounted for by having multiple
        # elements in the array.
        self._outcomes = {OutcomeType.MI: [], OutcomeType.STROKE: []}
        self._selfReportStrokePriorToSim = 0
        self._selfReportMIPriorToSim = 0

        # convert events for events prior to simulation
        if selfReportStrokeAge is not None and selfReportStrokeAge > 1:
            self._selfReportStrokePriorToSim = 1
            self._outcomes[OutcomeType.STROKE].append(
                (-1, Outcome(OutcomeType.STROKE, False)))
        if selfReportMIAge is not None and selfReportMIAge > 1:
            self._selfReportMIPriorToSim = 1
            self._outcomes[OutcomeType.MI].append(
                (-1, Outcome(OutcomeType.MI, False)))
        for k, v in kwargs.items():
            setattr(self, k, v)
        if initializeAfib is not None:
            self._afib = [initializeAfib(self)]
        else:
            self._afib = [False]

        self._gcp = []
        # for outcome mocels that require random effects, store in this dictionary
        self._randomEffects = dict()

        self._bpTreatmentStrategy = None
Example #14
0
 def assign_cv_outcome(self,
                       person,
                       years=1,
                       manualStrokeMIProbability=None):
     return Outcome(OutcomeType.STROKE, 1) if person._age[-1] > 50 else None
 def assign_cv_outcome(self, person):
     return Outcome(OutcomeType.MI, False)