def nearest_snack(self, snack_datetime): if not self.mean_feeding_hours: return None base_date = snack_datetime.date() if snack_datetime.hour < 3: base_date = base_date - Timedelta(days=1) mm = Datetime.combine( base_date, self.mean_feeding_hours.breakfast) + Timedelta(minutes=180) af = Datetime.combine( base_date, self.mean_feeding_hours.lunch) + Timedelta(minutes=180) bb = Datetime.combine( base_date, self.mean_feeding_hours.dinner) + Timedelta(minutes=180) result = { mm: self.MID_MORNING_SNACK, af: self.AFTERNOON_SNACK, bb: self.BEFORE_BED_SNACK } nearest = Datetime.nearest_datetime_static(snack_datetime, [mm, af, bb]) return result[nearest]
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)
def nearest_meal(self, meal_datetime): if not self.mean_feeding_hours: return None base_date = meal_datetime.date() if meal_datetime.hour < 3: base_date = base_date - Timedelta(days=1) br = Datetime.combine(base_date, self.mean_feeding_hours.breakfast) lu = Datetime.combine(base_date, self.mean_feeding_hours.lunch) di = Datetime.combine(base_date, self.mean_feeding_hours.dinner) result = {br: self.BREAKFAST, lu: self.LUNCH, di: self.DINNER} nearest = Datetime.nearest_datetime_static(meal_datetime, [br, lu, di]) return result[nearest]
def main(): context = Context(1, Datetime(2017, 1, 12, 13, 0)) h = HbA1c(context) h.graph.show() import sys sys.exit()
def nearest_day_time(self, base_date): if not self.mean_feeding_hours: return None if base_date.hour < 3: base_date = base_date - Timedelta(days=1) base_date = base_date.date() br = Datetime.combine(base_date, self.mean_feeding_hours.breakfast) lu = Datetime.combine(base_date, self.mean_feeding_hours.lunch) di = Datetime.combine(base_date, self.mean_feeding_hours.dinner) mm = Datetime.combine( base_date, self.mean_feeding_hours.breakfast) + Timedelta(minutes=180) af = Datetime.combine( base_date, self.mean_feeding_hours.lunch) + Timedelta(minutes=180) bb = Datetime.combine( base_date, self.mean_feeding_hours.dinner) + Timedelta(minutes=180) result = { br: self.BREAKFAST, lu: self.LUNCH, di: self.DINNER, mm: self.MID_MORNING_SNACK, af: self.AFTERNOON_SNACK, bb: self.BEFORE_BED_SNACK, } nearest = Datetime.nearest_datetime_static(base_date, [br, lu, di, mm, af, bb]) return result[nearest]
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 """
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
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
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