예제 #1
0
파일: hba1c.py 프로젝트: koyadovic/Dia
    def recalculate(self, day_times):
        glucoses = diacore.get_glucoses(
            user_pk=self._c.user_pk,
            from_utc_timestamp=(self._c.current_datetime -
                                Timedelta(days=120)).utc_timestamp,
            until_utc_timestamp=self._c.current_datetime.utc_timestamp,
            order_by_utc_timestamp=True,
            order_ascending=True)

        value = 0.
        total = 0.
        n = 0.

        last_days_old = None
        meals_day_times = []
        snacks_day_times = []

        for glucose in glucoses:
            day_time = day_times.nearest_day_time(
                Datetime.utcfromtimestamp(glucose.utc_timestamp))
            days_old = (
                self._c.current_datetime -
                Datetime.utcfromtimestamp(glucose.utc_timestamp)).total_days

            if last_days_old == None: last_days_old = days_old

            if last_days_old != days_old:
                if len(snacks_day_times) < len(meals_day_times):
                    number = len(meals_day_times) - len(snacks_day_times)
                    for _ in range(number):
                        total += 150. * HbA1c._weight(last_days_old)
                        n += HbA1c._weight(last_days_old)

                last_days_old = days_old
                meals_day_times = []
                snacks_day_times = []

            if day_times.is_meal(
                    Datetime.utcfromtimestamp(glucose.utc_timestamp)):
                meals_day_times.append(day_time)
            else:
                snacks_day_times.append(day_time)

            total += glucose.mgdl_level * HbA1c._weight(days_old)
            n += HbA1c._weight(days_old)

        if n > 0.:
            value = HbA1c._mgdl2hba1cpercentage(total / n)
            _HbA1cRecord.update_value(self._c.user_pk,
                                      self._c.current_datetime.date(), value)
예제 #2
0
def basal_checks(insulin):
    context = Context(insulin.user_pk,
                      Datetime.utcfromtimestamp(insulin.utc_timestamp))
    day_times = DayTimes(context)
    if day_times.is_ready():
        basal = BasalInsulin(context, day_times)
        pattern = basal.insulin_pattern
        dose_24h = basal.doses_24h
        """
예제 #3
0
    def mean_feeding_hours(self):
        # Hacemos una primera aproximación con las insulinas rápidas o cortas
        # administradas. Allí estarán las comidas
        insulins = diacore.get_insulin_administrations(
            user_pk=self.user_pk, limit=30, order_by_utc_timestamp=True)

        targets = [
            insulin for insulin in insulins
            if insulin.insulin_type in [InsulinType.RAPID, InsulinType.SHORT]
        ]

        DAY_HOURS = 24
        DAY_MINUTES = DAY_HOURS * 60
        WIDE_HOURS = 3
        WIDE_MINUTES = WIDE_HOURS * 60

        result = []

        max_i = 0.
        max_mean = 0.
        last_mean = 0.

        for minute in range(0, DAY_MINUTES, 30):
            i = 0.
            total = 0.
            for target in targets:
                minutes = Time.time2minutes(
                    Datetime.utcfromtimestamp(target.utc_timestamp))
                if minutes < 180:
                    minutes += DAY_MINUTES
                if minutes >= minute and minutes <= minute + WIDE_MINUTES:
                    i += 1
                    total += minutes
            mean = 0
            if i > 0:
                mean = total / i
            if i > max_i:
                max_mean = mean
                max_i = i
            if last_mean > 0 and mean == 0:
                if max_mean > DAY_MINUTES:
                    max_mean -= DAY_MINUTES
                result.append(max_mean)
                max_mean = 0.
                max_i = 0.
            last_mean = mean
        if max_mean > 0:
            if max_mean > DAY_MINUTES:
                max_mean -= DAY_MINUTES
            result.append(max_mean)
        """
        result es una lista donde:
        result[0] <== desayuno
        result[1] <== comida
        result[2] <== cena
        """
        if len(result) == 3:
            breakfast = Time.minutes2time(result[0])
            lunch = Time.minutes2time(result[1])
            dinner = Time.minutes2time(result[2])

            times = type('MeanFeedingHours', (), {})()
            times.breakfast = breakfast
            times.lunch = lunch
            times.dinner = dinner

            return times

        return None
예제 #4
0
    def doses_24h(self):
        """
        self._insulins está ordenado de más actual a menos actual
        
        Tenemos que coger un día en el que se estén administrando los pinchazos por día
        que se suelen hacer, cuyo día anterior también los tenga y el anterior del 
        anterior también.
        
        Tres días consecutivos en los que el número de pimchazos que se deberían aplicar
        se hayan aplicado
        """
        pattern = self.insulin_pattern
        """
        Si esto no se cumple retornamos None
        """
        if pattern == None or len(self._insulins) == 0:
            return None
        """
        Para comparar recogemos el último dato guardado
        """
        last_24h_doses = None
        last_24h_doses_record = _BasalInsulin24hDoses.most_recent_record(
            self._c)

        if last_24h_doses_record != None:
            last_24h_doses = last_24h_doses_record.doses_absorved_24h
        """
        Comenzamos el cálculo
        """
        current_24h_doses = None
        injections = pattern['injections_per_day']

        last_day = 0
        insulins_selected = []
        temp_insulins_selected = []

        for insulin in self._insulins:
            if last_day == 0:
                last_day = Datetime.utcfromtimestamp(insulin.utc_timestamp).day

            if Datetime.utcfromtimestamp(
                    insulin.utc_timestamp).day != last_day:
                last_day = Datetime.utcfromtimestamp(insulin.utc_timestamp).day
                """
                Si el número de insulinas administradas temporalmente recogidas
                coincide con el número de pinchazos que hay que hacer al día las añadimos a la lista definitiva
                """
                if len(temp_insulins_selected) == injections:
                    insulins_selected += temp_insulins_selected
                    """
                    Si la lista definitiva tiene 3 días de insulinas en rango, rompemos el bucle
                    """
                    if len(insulins_selected) > 0 and \
                    round(abs(insulins_selected[0].utc_timestamp - insulins_selected[-1].utc_timestamp)/60./60./24.) >= 3:
                        break
                else:
                    """
                    Si el día cambió y las insulinas temporales no coinciden con el número de pinchazos
                    al día, eliminamos la lista definitiva. Necesitamos tres días completos
                    """
                    insulins_selected = []
                """
                Reinicializamos la lista temporal de insulinas elegidas
                """
                temp_insulins_selected = []
            """
            Añadimos a la lista temporal la insulina actual
            """
            temp_insulins_selected.append(insulin)

        if len(temp_insulins_selected) == injections:
            insulins_selected += temp_insulins_selected

        if len(insulins_selected) > 0:
            total = 0.
            for insulin in insulins_selected:
                total += insulin.dose

            total /= len(insulins_selected)
            total *= injections

            if total > 0.:
                current_24h_doses = total
        else:
            """
            Algoritmo alternativo
            """
            if self._insulins != None:
                n = 0.
                total_doses = 0.

                last_day = 0.
                for insulin in self._insulins:
                    if last_day == 0:
                        last_day = Datetime.utcfromtimestamp(
                            insulin.utc_timestamp).day

                    if Datetime.utcfromtimestamp(
                            insulin.utc_timestamp).day != last_day:
                        last_day = Datetime.utcfromtimestamp(
                            insulin.utc_timestamp).day
                        n += 1

                    total_doses += insulin.dose

                if len(self._insulins) > 0:
                    n += 1

                if n > 2:
                    current_24h_doses = round(total_doses / n)

        if current_24h_doses != None:
            if last_24h_doses == None or current_24h_doses != last_24h_doses:
                """
                Tenemos que guardar una nueva entrada
                """
                basal_doses = _BasalInsulin24hDoses(
                    user_pk=self._c.user_pk,
                    datetime=self._c.current_datetime,
                    doses_absorved_24h=current_24h_doses)
                s = analysis_session()
                s.add(basal_doses)
                s.commit()
        elif last_24h_doses != None:
            return last_24h_doses

        return current_24h_doses
예제 #5
0
    def insulin_pattern(self):
        assert not self.day_times.not_ready(
        ), "day_times no está preparado aún"

        last_result = {}
        most_recent_pattern_record = _BasalInsulinPattern.most_recent_record(
            self._c)
        if most_recent_pattern_record != None:
            most_recent_pattern_datetime = most_recent_pattern_record.datetime
            patterns = _BasalInsulinPattern.records_at_datetime(
                self._c, most_recent_pattern_datetime)
            if patterns != None and len(patterns) > 0:
                for pattern in patterns:
                    last_result[pattern.day_time] = {}
                    last_result[
                        pattern.day_time]['proportion'] = pattern.proportion
                    last_result[pattern.day_time]['type'] = pattern.type
                last_result['injections_per_day'] = len(patterns)

        result = {}
        for day_time in DayTimes.ALL_DAY_TIMES:
            result[day_time] = {}
            result[day_time]['number_of_ocurrences'] = 0.
            result[day_time]['total_doses'] = 0.
            result[day_time]['types_encountered'] = []
            result[day_time]['mean_dose'] = 0.
            result[day_time]['proportion'] = 0.
            result[day_time]['type'] = 0.

        total_ocurrences = 0.
        for insulin in self._insulins:
            day_time = self.day_times.nearest_day_time(
                Datetime.utcfromtimestamp(insulin.utc_timestamp))
            total_ocurrences += 1.
            result[day_time]['number_of_ocurrences'] += 1
            result[day_time]['total_doses'] += insulin.dose
            result[day_time]['types_encountered'].append(insulin.type)

        if total_ocurrences == 0.:
            return None
        """
        Primero nos quedamos con aquellos day times en los que el número
        de ocurrencias haya superado el 20%
        """
        day_times_with_basal_injections = []
        for day_time in DayTimes.ALL_DAY_TIMES:
            percent = (result[day_time]['number_of_ocurrences'] /
                       total_ocurrences) * 100
            if percent > 20.:
                day_times_with_basal_injections.append(day_time)
        """
        Nos guardamos el número de inyecciones por día
        """
        result['injections_per_day'] = len(day_times_with_basal_injections)
        """
        El siguiente paso es conseguir la dosis media aplicada en cada day_time
        """
        total_doses = 0.
        for day_time in day_times_with_basal_injections:
            day_time_mean_dose = result[day_time]['total_doses'] / result[
                day_time]['number_of_ocurrences']
            total_doses += day_time_mean_dose

        for day_time in day_times_with_basal_injections:
            day_time_mean_dose = result[day_time]['total_doses'] / result[
                day_time]['number_of_ocurrences']
            result[day_time]['proportion'] = day_time_mean_dose / total_doses

            types_count = {}
            for insulin_type in result[day_time]['types_encountered']:
                if insulin_type not in types_count:
                    types_count[insulin_type] = 0
                types_count[insulin_type] += 1
            """
            Nos quedamos en el day_time con el tipo de insulina basal más repetido
            """
            result[day_time]['type'] = max(types_count.iterkeys(),
                                           key=(lambda key: types_count[key]))
        """
        Y llegados a este punto tenemos que eliminar del diccionario resultado
        todas las claves que no sirvan y devolverlo
        """
        for day_time in DayTimes.ALL_DAY_TIMES:
            if day_time not in day_times_with_basal_injections:
                del result[day_time]
            else:
                del result[day_time]['number_of_ocurrences']
                del result[day_time]['total_doses']
                del result[day_time]['types_encountered']
                del result[day_time]['mean_dose']
        """
        result[day_times]['type']
        result[day_times]['proportion']
        result['injections_per_day']
        
        
        Hay que comprobar si los patrones de insulina actuales son los guardados en la db,
        si en la bd no hubiese datos, o si hubiesen cambiado, hay que guardar el nuevo patron de
        insulinas e intentar hacer la recomendación, pero sin modificar lo que el usuario
        se viene pinchando, al no tener aún datos de glucosas que analizar
        """
        pattern_changed = False

        if last_result != {}:
            for day_time in last_result:
                if day_time not in DayTimes.ALL_DAY_TIMES:
                    continue
                if day_time not in result:
                    pattern_changed = True
                elif result[day_time]['proportion'] != last_result[day_time][
                        'proportion']:
                    pattern_changed = True
                if pattern_changed:
                    break
        else:
            pattern_changed = True

        if pattern_changed:
            """
            Hay que guardar el nuevo patron de insulinas
            """
            s = analysis_session()
            for day_time in result:
                if day_time not in DayTimes.ALL_DAY_TIMES:
                    continue

                pattern = _BasalInsulinPattern(
                    user_pk=self._c.user_pk,
                    datetime=self._c.current_datetime,
                    day_time=day_time,
                    type=result[day_time]['type'],
                    proportion=result[day_time]['proportion'])
                s.add(pattern)
            s.commit()
        """
        Nos queda sólo:
        result[day_time]['proportion']
        result[day_time]['type']
        result['injections_per_day']
        """
        return result