示例#1
0
    def __init__(self,
                 value=None,
                 scorename='symptom',
                 triggered_by_equal=True,
                 min_triggered=1,
                 **kwargs):
        '''
        value: what value triggers this milestone (None means minimum possible given the scorename)
        scorename: which score the value refers to
        triggered_by_equal: if True, use <= for trigger, if False, use < for trigger
        min_triggered: the number of days in a row to fulfill the condition when sampling
        kwargs: passed to parent class
        '''
        super().__init__(name='magnitude', **kwargs)

        #check and set scorename
        if scorename not in {'symptom', 'visual', 'symptom_noerror'}:
            raise ValueError(f"scorename of {scorename} not understood")
        self.scorename = scorename

        #check and set triggered_by_equal
        if not isinstance(triggered_by_equal, bool):
            raise TypeError(
                f"triggred_by_equal of {triggered_by_equal} should be a boolean"
            )
        self.triggered_by_equal = triggered_by_equal

        #check and set value
        if value is None:
            value = get_MIN(self.scorename)
        if self.triggered_by_equal:
            if value < get_MIN(self.scorename):
                warn(
                    f"value of {value} may be unobtainable since it is smaller than "
                    f"{self.scorename}'s min of MIN of {get_MIN(self.scorename)}"
                )
        else:
            if value <= get_MIN(self.scorename):
                warn(
                    f"value of {value} may be unobtainable since it is smaller or equal to "
                    f"{self.scorename}'s MIN of {get_MIN(self.scorename)}")
        self.value = value

        #check and set min_triggered
        if not isinstance(min_triggered, int) or min_triggered < 1:
            raise TypeError(
                f"min_triggered of {min_triggered} should be an int of at least 1"
            )
        self.min_triggered = min_triggered
示例#2
0
 def _get_excluded_magnitude_late(self,
                                  scorename='symptom',
                                  recovered_score=None,
                                  lastday=NDAYS):
     if recovered_score is None:
         recovered_score = get_MIN(scorename)
     persons_recovered_late = np.min(self.scores[scorename][:, :lastday],
                                     axis=1) > recovered_score
     return persons_recovered_late
示例#3
0
 def _get_excluded_magnitude_early(self,
                                   scorename='symptom',
                                   recovered_score=None,
                                   firstday=FIRSTVISIT):
     if recovered_score is None:
         recovered_score = get_MIN(scorename)
     persons_recovered_early = np.any(
         self.scores[scorename][:, :firstday] <= recovered_score, axis=1)
     return persons_recovered_early
示例#4
0
    def sample(self, population, order, sampling_days):
        smilescores = population.scores[
            self.scorename]  #scores which the method value refers to
        smilescore_lowerbound = get_MIN(self.scorename)

        # Compute the days where the milestones are triggered
        comparison_array = (
            smilescores <= self.value) if self.triggered_by_equal else (
                smilescores < self.value)
        # Compute the days where the milestones are triggered consecutively
        if self.min_triggered == 1:
            pass  #don't change comparison_array
        elif self.min_triggered > 1:
            triggered_in_a_row = np.ones_like(
                comparison_array[:, self.min_triggered - 1:])  #initial
            for start in range(self.min_triggered):
                end = start + 1 - self.min_triggered
                if end == 0: end = None
                triggered_in_a_row = triggered_in_a_row * comparison_array[:,
                                                                           start:
                                                                           end]  # accumulate
            comparison_array[:, self.min_triggered -
                             1:] = triggered_in_a_row  #we only checked when enough days have passed
            comparison_array[:, :self.min_triggered -
                             1] = False  #the rest can't have had enough days in a row

        #only check on or after previous (valid) sample day by
        #setting the comparison values from days 0 to prev sample day (excluding end) to False
        if order > 0:
            for i in range(population.npersons):
                #for getting valid prev day
                for prev_order in range(order - 1, 0 - 1, -1):
                    prev_sample_day = sampling_days[i, prev_order]
                    if prev_sample_day < NDAYS: break
                #for setting days until then as don't consider
                comparison_array[i, :prev_sample_day] = False
        #if it is True on the same day as the previous sample day, the finish_sampling will consider it already_reached

        #the day at which the milestone is reached for each person
        sampling_days_temp = np.argmax(comparison_array, axis=1)
        #the day at which the milestone is reached for each person, inc. 0 for 'never reached'
        sampling_days[:, order] = sampling_days_temp
        #record of which persons reached the milestones
        persons_reached_milestone = np.take_along_axis(
            comparison_array, helper.to_vertical(sampling_days_temp), axis=1)
        #give invalid day to those who didn't reach
        sampling_days[~persons_reached_milestone.flatten(),
                      order] = _UNREACHED_MAGNITUDE
        if not np.all(persons_reached_milestone):
            warn(
                f"There are {(~persons_reached_milestone.flatten()).sum()} who didn't reach their milestone"
            )

        super().finish_sampling(population, order, sampling_days)
示例#5
0
 def _get_excluded_ratio_late(self,
                              scorename='symptom',
                              index_day=0,
                              recovered_ratio=0.15,
                              lastday=NDAYS):
     score_lowerbound = get_MIN(scorename)
     recovered_scores = (self.scores[scorename][:, index_day] -
                         score_lowerbound) * ratio + score_lowerbound
     persons_recovered_late = np.min(self.scores[scorename][:, :lastday],
                                     axis=1) > recovered_scores
     return persons_recovered_late
示例#6
0
 def _get_excluded_ratio_early(self,
                               scorename='symptom',
                               index_day=0,
                               recovered_ratio=0.15,
                               firstday=FIRSTVISIT):
     score_lowerbound = get_MIN(scorename)
     recovered_scores = (
         self.scores[scorename][:, index_day] -
         score_lowerbound) * recovered_ratio + score_lowerbound
     persons_recovered_early = self.scores[
         scorename][:, firstday] <= recovered_scores
     return persons_recovered_early
示例#7
0
    def sample(self, population, order, sampling_days):
        smilescores = population.scores[
            self.scorename]  #scores which the method ratio refers to
        smilescore_lowerbound = get_MIN(self.scorename)

        #get and check index days
        if isinstance(self.index, int):
            index_days = np.full((population.npersons, ), self.index)
        elif isinstance(self.index, tuple):
            prev_sampling_days = sampling_days[:, :order]
            index_days = prev_sampling_days[:, self.day[1]]
        elif callable(self.index):
            prev_sampling_days = sampling_days[:, :order]
            #TODO check if int not outside NDAYS, FIRSTVISIT, LASTVISIT
            index_days = self.index((population.npersons, ),
                                    prev_sampling_days)

        # Compute the scores which will trigger milestones
        smilescores_at_index = np.take_along_axis(
            smilescores, helper.to_vertical(index_days), axis=1)  #column array
        smile_vals = (smilescores_at_index - smilescore_lowerbound
                      ) * self.ratio + smilescore_lowerbound  #column array

        # Compute the days where the milestones are triggered
        comparison_array = (
            smilescores <= smile_vals) if self.triggered_by_equal else (
                smilescores < smile_vals)
        # Compute the days where the milestones are triggered consecutively
        if self.min_triggered == 1:
            pass  #don't change comparison_array
        elif self.min_triggered > 1:
            triggered_in_a_row = np.ones_like(
                comparison_array[:, self.min_triggered - 1:])  #initial
            for start in range(self.min_triggered):
                end = start + 1 - self.min_triggered
                if end == 0: end = None
                triggered_in_a_row = triggered_in_a_row * comparison_array[:,
                                                                           start:
                                                                           end]  # accumulate
            comparison_array[:, self.min_triggered -
                             1:] = triggered_in_a_row  #we only checked when enough days have passed
            comparison_array[:, :self.min_triggered -
                             1] = False  #the rest can't have had enough days in a row

        #only check on or after previous sample day by
        #setting the comparison values from days 0 to prev sample day (excluding end) to False
        for i in range(population.npersons):
            comparison_array[i, :sampling_days[i, order - 1]] = False
        #if it is True on the same day as the previous sample day, the finish_sampling will consider it already_reached

        #the day at which the milestone is reached for each person
        sampling_days_temp = np.argmax(comparison_array, axis=1)
        #the day at which the milestone is reached for each person, inc. 0 for 'never reached'
        sampling_days[:, order] = sampling_days_temp

        #record of which persons actually reached the milestones
        persons_reached_milestone = np.take_along_axis(
            comparison_array, helper.to_vertical(sampling_days_temp), axis=1)
        #give invalid day to those who didn't reach
        sampling_days[~persons_reached_milestone.flatten(),
                      order] = _UNREACHED_SMILE
        if not np.all(persons_reached_milestone):
            warn(
                f"There are {(~persons_reached_milestone.flatten()).sum()} who didn't reach their milestone"
            )

        super().finish_sampling(population, order, sampling_days)