Не вызвавший интерес у широкой публики симулятор инсулиновой помпы в виде десктопного приложения определил необходимость поиска другого формата. В качестве нового формата был выбран телеграмм бот на Питоне. При этом пришлось пожертвовать частью функционала, но это позволило упростить процесс начала работы с симулятором. Но обо все по порядку.
Главная цель разработки — тренажер подборки настроек инсулинотерапии с обратной реакцией в виде значения глюкозы.
Для навигации в боте разработано меню, представленное ниже
Первой задачей является разработка генератора пациентов. Генерить эти данные с помощью генератора случайных чисел, идея конечно рабочая, но она отдаляет от реальности. Ведь в медицине давно сформированы соотношения всех взаимосвязанных параметров, которые характеризуют пациента: возраст, вес, суточная доза инсулина, УК (углеводный коэффициент), ФЧИ (фактор чувствительности к инсулину), БП (базальный профиль/ базальная скорость). Воспользуемся известными соотношениями и научим будущего бота генерить пациентов с «адекватными» параметрами. Ниже представлен код модуля формирования пациента.
if call.data == "btn_new" and chet == 0: # Обработка нажатия inline кнопки для вывода списка продуктов users[call.from_user.id]['uk_et'] = 0 users[call.from_user.id]['phi_et'] = 0 users[call.from_user.id]['bp_et'] = 0 users[call.from_user.id]['uk'] = 0 users[call.from_user.id]['phi'] = 0 users[call.from_user.id]['bp'] = 0 users[call.from_user.id]['mode'] = 0 users[call.from_user.id]['chas'] = 0 users[call.from_user.id]['summ_gluk'] = 5.5 users[call.from_user.id]['N_gluk'] = 1 users[call.from_user.id]['gluk_tek'] = 5.5 users[call.from_user.id]['kol_xe'] = 0 users[call.from_user.id]['about'] = " " users[call.from_user.id]['insulin'] = 0 # Сброс режима fin_stroka = [] fin_stroka.append("Описание пациента:") temp_vozr = random.randint(1, 69) fin_stroka.append("1.Возраст пациента [лет]: " + str(temp_vozr)) if temp_vozr == 1: temp_ves = 10 + random.randint(0, 2) elif temp_vozr == 2: temp_ves = 11 + random.randint(0, 3) elif temp_vozr == 3: temp_ves = 13 + random.randint(0, 2) elif temp_vozr == 4: temp_ves = 13 + random.randint(0, 5) elif temp_vozr == 5: temp_ves = 15 + random.randint(0, 7) elif temp_vozr == 6: temp_ves = 18 + random.randint(0, 4) elif temp_vozr == 7: temp_ves = 20 + random.randint(0, 8) elif temp_vozr == 8: temp_ves = 22 + random.randint(0, 9) elif temp_vozr == 9: temp_ves = 25 + random.randint(0, 10) elif temp_vozr == 10: temp_ves = 28 + random.randint(0, 10) elif temp_vozr == 11: temp_ves = 30 + random.randint(0, 11) elif temp_vozr == 12: temp_ves = 34 + random.randint(0, 7) elif temp_vozr == 13: temp_ves = 38 + random.randint(0, 15) elif temp_vozr == 14: temp_ves = 44 + random.randint(0, 13) elif temp_vozr == 15: temp_ves = 46 + random.randint(0, 23) elif temp_vozr == 16: temp_ves = 48 + random.randint(0, 27) elif temp_vozr == 17: temp_ves = 49 + random.randint(0, 30) else: temp_ves = 51 + random.randint(0, 48) fin_stroka.append("2.Вес пациента [кг]: " + str(temp_ves)) if temp_vozr > 0 and temp_vozr <= 10: temp_sdi = round(temp_ves * (7 + random.randint(0, 2)) / 10, 0) else: temp_sdi = round(temp_ves * (10 + random.randint(0, 9)) / 10, 0) temp_staz = random.randint(0, 4) if temp_staz < 2: temp_sdi = round(temp_ves * (3 + random.randint(0, 2)) / 10, 0) # bot.send_message(message.chat.id, "Стаж сахарного диабета меньше 2 лет.") fin_stroka.append("3.Стаж сахарного диабета меньше 2 лет.") else: fin_stroka.append("3.Стаж сахарного диабета больше 2 лет.") fin_stroka.append("4.Суточная доза инсулина [ЕД]: " + str(temp_sdi)) temp_staz = random.randint(0, 4) if temp_staz < 2: temp_sdi = round(temp_sdi * 0.8) fin_stroka.append("5.Частые гипогликемии.") elif temp_staz > 1 and temp_staz < 4: temp_sdi = round(temp_sdi * 0.9) fin_stroka.append("5.Хорошие показатели глюкозы в крови, редкие гипогликемии.") else: fin_stroka.append("5.Высокие показатели глюкозы в крови.") # Определение БП, УК if temp_vozr < 7: users[call.from_user.id]['bp_et'] = round(temp_sdi * (30 + random.randint(0, 4)) / (100 * 24), 1) elif temp_vozr < 13 and temp_vozr > 6: users[call.from_user.id]['bp_et'] = round(temp_sdi * (35 + random.randint(0, 4)) / (100 * 24), 1) else: users[call.from_user.id]['bp_et'] = round(temp_sdi * (40 + random.randint(0, 9)) / (100 * 24), 1) users[call.from_user.id]['uk_et'] = round(temp_sdi * random.randint(12, 20) / (10 * temp_ves), 1) users[call.from_user.id]['phi_et'] = round(random.randint(100, 110) / temp_sdi, 1) bot.send_message(call.from_user.id, '\n'.join(fin_stroka)) users[call.from_user.id]['about'] = fin_stroka
После выполнения данного кода, пользователю представляется описание пациента. На основании описания пользователь может определить примерные коэффициенты УК, ФЧИ и БП. Данное описание доступно на любой стадии выполнения задания при клике на кнопку «О пациенте».
Кнопка «Инфо», код которой представлен ниже, предназначена для вывода текущей информации о состоянии симулятора. Данная информация позволяет отслеживать изменение глюкозы, просматривать текущие настройки и значение гликированного гемоглобина за период симуляции.
if call.data == "btn_info" and chet == 0: gg = round((users[call.from_user.id]['summ_gluk']*0.6302/users[call.from_user.id]['N_gluk'])+1.584, 1) fin_stroka = [] fin_stroka.append("Время: " + str(users[call.from_user.id]['chas'])+":00") fin_stroka.append(" ") fin_stroka.append("Глюкоза [мМ/л]: " + str(round(users[call.from_user.id]['gluk_tek'],1))) fin_stroka.append("Еда [ХЕ]: " + str(users[call.from_user.id]['kol_xe'])) fin_stroka.append("Инсулин [ЕД]: " + str(users[call.from_user.id]['insulin'])) fin_stroka.append(" ") fin_stroka.append("Текущие настройки:") fin_stroka.append("БП [ЕД/ч]: " + str(users[call.from_user.id]['bp'])) fin_stroka.append("УК [ЕД/ХЕ]: " + str(users[call.from_user.id]['uk'])) fin_stroka.append("ФЧИ [мМ/л]: " + str(users[call.from_user.id]['phi'])) fin_stroka.append(" ") fin_stroka.append("Гликированный гемоглобин: " + str(gg)) bot.send_message(call.message.chat.id, '\n'.join(fin_stroka))
Кнопка «Еда» позволяет симулировать прием пищи. При этом требуется указание количества ХЕ.
if users[message.from_user.id]['mode'] == 1: if is_number(message.text): users[message.from_user.id]['kol_xe'] = float(message.text) users[message.from_user.id]['mode'] = 0 menu(message) else: bot.send_message(message.chat.id, "Можно ввести только число") bot.send_message(message.chat.id, "Сколько ХЕ?")
Кнопка «Инсулин» запускает калькулятор болюса, позволяющий рассчитать количество инсулина на коррекцию и еду. Подробный расчет доступен пользователю. При этом расчет ведется в соответствии с установленными в симуляторе значениями УК, ФЧИ и БП.
if call.data == "btn_insulin" and chet == 0: if users[call.from_user.id]['uk'] != 0 and users[call.from_user.id]['bp'] != 0 and users[call.from_user.id]['phi'] != 0: fin_stroka = [] fin_stroka.append("Помощник болюса:") eat = users[call.from_user.id]['kol_xe']*users[call.from_user.id]['uk'] fin_stroka.append("Инсулин на еду [ЕД]: " + str(users[call.from_user.id]['kol_xe'])+" * "+str(users[call.from_user.id]['uk'])+" = "+str(round(eat, 1))) korr = (users[call.from_user.id]['gluk_tek']-7)/users[call.from_user.id]['phi'] fin_stroka.append("Инсулин на коррекц. [ЕД]: (" + str(users[call.from_user.id]['gluk_tek'])+" - 7)/ "+str(users[call.from_user.id]['phi'])+" = "+str(round(korr, 1))) itog = eat+korr fin_stroka.append("Итого [ЕД]:" + str(round(eat, 1))+" + "+str(round(korr, 1))+" = "+ str(round(itog, 1))) bot.send_message(call.message.chat.id, '\n'.join(fin_stroka)) bot.send_message(call.message.chat.id, "Введите количество инсулина[ЕД]") chet = 1 # Выбран режим работы bot.register_next_step_handler(call.message, btn_insulin) # Вызов функции калькулятора болюса else : bot.send_message(call.message.chat.id, "Не введены УК, ФЧИ, БП.")
Кнопки УК, ФЧИ и БП предназначены для ввода соответствующих настроек симулятора.
Запуск шага симуляции осуществляется нажатием кнопки «Перемотка 2 часа». Соответствующий код представлен ниже.
if call.data == "btn_peremotka" and chet == 0: bot.send_message(call.message.chat.id, "Перемотка времени на 2 часа.") if users[call.from_user.id]['chas']<24: users[call.from_user.id]['chas'] +=2 else: users[call.from_user.id]['chas'] = 0 users[call.from_user.id]['summ_gluk'] += users[call.from_user.id]['gluk_tek'] users[call.from_user.id]['N_gluk'] += 1 users[call.from_user.id]['gluk_tek'] += (users[call.from_user.id]['bp_et']-users[call.from_user.id]['bp'])*2*users[call.from_user.id]['phi_et'] users[call.from_user.id]['gluk_tek'] += ((users[call.from_user.id]['kol_xe']*users[call.from_user.id]['uk_et'])-users[call.from_user.id]['insulin'])*users[call.from_user.id]['phi_et'] users[call.from_user.id]['kol_xe'] = 0 users[call.from_user.id]['insulin'] = 0
После клика данной кнопки выполнится шаг симуляции и новое состояние симулятора будет доступно по клику на кнопку «Инфо».
!!!Данный бот предназначен исключительно для тестирования и определения актуальности разработки и не может использоваться для определения настроек помпы или количества инсулина без рекомендации врача!!!
На текущий момент данный бот доступен для тестирования
https://t.me/Sugarnorm_pomp_bot
В комментариях просьба описать Ваше видение проблематики и возможности данного формата для обучающего программного обеспечения.
В качестве направления дальнейшего исследования хочу добавить проверку правильности подбора параметров с выводом об этом информации пользователю, ведение статистики по количеству и скорости выполнения вариантов подбора параметров, аварийный вариант завершения работы симулятора в случае допущения значения глюкозы меньше 2 мМ/л или больше 20 мМ/л.
ссылка на оригинал статьи https://habr.com/ru/articles/838426/
Добавить комментарий