Здравствуйте. Меня зовут Андрей, я работаю в компании, создающей IT-решения в области медицины. В качестве основного языка разработки мы используем Clojure, а также (в зависимости от проекта/модуля) Python, Javascript, Go, C, C#, Rust, Objective-C и т.д.

Важное место в нашем технологическом стеке занимает международный стандарт FHIR (Fast Healthcare Interoperability Resources), определяющий формат хранения/обмена/предоставления медицинской информации в электронном виде и включающий в себя спецификацию RESTful API клиент-серверного взаимодействия.

Некоторое время назад я начал пет-проект приложения, которое визуализирует содержимое ресурсов произвольного FHIR-сервера и позволяет производить базовые CRUD — операции. В КДПВ показан скриншот страницы редактирования элемента ресурса типа Patient.

Под катом небольшое описание и ссылка на онлайн-демо — можно будет пощупать настоящий живой FHIR-сервер, потыкать кнопочки, посмотреть/посоздавать/поредактировать различные ресурсы и даже попробовать вызвать тот самый хабраэффект! )

Пара слов про FHIR


Я не буду переписывать сюда описание стандарта, желающие смогут узнать все подробности по ссылке выше, почитать другие материалы на различных ресурсах, а также задать вопросы и присоединиться к обсуждению в FHIR-чате. Дам только общее представление: центральным понятием является ресурс, ресурсы разделены по типам и группам, каждый тип имеет собственную структуру полей, значения которых могут быть примитивными или композитными типами и ссылками на другие ресурсы. Поля могут быть обязательными или не обязательными к заполнению, содержать одно значение или коллекцию значений. Например, ресурс Patient имеет поля примитивного типа: дата рождения/пол/..., композитного типа: имя/адрес/...., ссылки на организацию и список лечащих врачей и т.п.

Для каждого ресурса хранится история его изменений как перечень состояний с датами их актуальности и номером версии объекта. RESTful API позволяет запросить метаданные о составе и структуре ресурсов, поддерживаемых данным FHIR-сервером, список элементов ресурса любого типа с широкими возможностями фильтрации по значениям отдельных параметров, включением зависимых ресурсов, ограничить выдачу результата значениями перечисленных полей, сортировать результат запроса по сложным критериям, и т.д. Также есть методы поддержки CRUD на уровне элемента ресурса — создание/обновление с валидацией структуры и наличием обязательных полей, удаление элемента. Существуют методы API для просмотра истории изменений как на уровне элемента так и на уровне типа ресурса.

В типичном приложении использование этого универсального API абстрагировано толстым слоем бизнес-логики конкретного клиента. Например, при назначении визита пациента к врачу запрашиваются данные о количестве его медицинских страховок и сроках их действия, история предыдущих визитов, сведения о балансе взаиморасчетов пациента с клиникой и т.д., данные о расписании выбранного врача и наличии свободных часов для приема и т.п. И все это в удобной форме представляется на экране рабочего места сотрудника, осуществляющего запись. Или автоматический планировщик задач периодически по заданному расписанию запускает процесс, запрашивающий список ближайших предстоящих визитов и автоматически рассылающий пациентам смс с текстом напоминаний или уведомлений по заранее заданным шаблонам.

Но мне пришла идея сделать универсальную визуализацию содержимого ресурсов FHIR-сервера, и так появился проект под названием…

FHIR-face


Приложение позволяет подключиться к любому FHIR-серверу и осуществлять просмотр содержимого ресурсов и базовый CRUD. Одна из сложностей такого универсального подхода заключается в том, что разные сервера могут иметь разные версии FHIR-стандарта, реализовывать его не в полном объеме, иметь отклонения в перечне, составе и структуре ресурсов и API, а также иметь дополнительную функциональность, не входящую в спецификацию. Но если данный сервер позволяет запросить метаданные о составе и структуре поддерживаемых ресурсов, то можно добавить его поддержку в этом проекте.

Интерфейс проекта имхо интуитивно понятный. Выбор адреса сервера осуществляется через параметр адресной строки, но в текущей демо-версии по умолчанию выбран hapi.fhir.org. Со стартовой страницы происходит загрузка состава и структуры ресурсов, и предлагается выбрать конкретный тип ресурса для просмотра его содержимого. При выборе типа ресурса делается запрос на ограниченное число его элементов, которые выводятся в таблицу с колонками: идентификатор, условное пользовательское представление (при возможности его получения) и размер в символах строковой сериализации. Работает полнотекстовый поиск по содержимому ресурса. При клике на строку таблицы или на кнопку создания нового элемента происходит редирект на страницу содержимого элемента ресурса.

В верхней части страницы элемента есть кнопки полной свертки/развертки иерархического содержимого и кнопка изменения стиля представления реквизитов. Содержимое элемента представлено списком реквизитов. Каждый реквизит имеет имя, тип, краткое описание и значение. Залитый черным кружок слева от реквизита означает что этот реквизит присутствует в ресурсе (даже если не выбрано его значение — в этом случае в элементе есть этот реквизит, но он имеет пустое значение), пустой кружок означает отсутствие данного реквизита в элементе, но наличие в списке реквизитов структуры данного типа ресурса. Любой реквизит можно добавлять/удалять из элемента по клику мышкой на пиктограмму кружка слева от имени. Реквизиты, не перечисленные в составе структуры типа ресурса, но имеющиеся в элементе, выделены пурпурным цветом.

Значения примитивных типов представлены соответствующими типизированными виджетами — дата, время, число, строка и т.п. Пиктограмма правее строковых реквизитов переключает режим ввода/редактирования текста — с переводом строк или без. При редактировании автоматически изменяется размер виджета в зависимости от его содержимого. При стартовом заполнении формы все текстовые поля длиннее 50 символов представлены виджетами textArea с переводом строк. Виджеты ссылок представлены типом ресурса-ссылки и значением, при выборе значения работает полнотекстовый поиск по содержимому ресурса-ссылки.

Реквизиты композитных типов могут быть свернуты с подсветкой количества возможных и заполненных подчиненных реквизитов или развернуты — с демонстрацией содержимого. При клике на имя/тип/описание реквизита срабатывает полная глубокая свертка/развертка содержимого, при клике на подсветку количество полей — развертка реквизитов следующего уровня. Реквизиты-коллекции (с произвольным количеством значений) имеют пиктограмму + справа от описания реквизита — для добавления новых значений в коллекцию. Свертка/развертка элемента коллекции (если он в свою очередь является значением композитного типа) осуществляется по клику на крайнюю правую часть рамки, ограничивающей элемент коллекции. При клике на крестик в правом верхнем углу рамки элемент коллекции удаляется.

Данный интерфейс позволяет редактировать содержимое любого ресурса. В нижней части страницы находится кнопка сохранения ресурса в отредактированном состоянии. При записи ресурса FHIR-сервер производит валидацию его содержимого, и при наличии ошибок не записывает ресурс, а возвращает список ошибок валидации. В этом случае текст этих ошибок выводится красным ниже кнопки сохранения. Структура объекта ошибок валидации определяется реализацией сервера, поэтому был выбран вариант его универсального текстового представления. При отсутствии ошибок происходит запись элемента ресурса и редирект обратно на страницу списка элементов.

И наконец, обещанные ссылки:

Онлайн-демо проекта

Гитхаб проекта — кот не выставочное чучело, а живой рабочий, поэтому присутствуют закомментированные участки, строительные леса и прочие элементы, необходимые для проведения строительно-монтажных работ, надевайте каски )

Комментарии (9)


  1. impwx
    12.10.2018 10:18

    Но почему на скриншоте шрифт Papyrus?..


    1. brevis
      12.10.2018 10:19

      Месть врачам за почерк.


  1. dMitin
    12.10.2018 11:03
    +1

    Спасибо! Я знал что такой проект должен был появиться!


  1. Naves
    12.10.2018 12:43

    Какие медицинские системы поддерживают стандарт FHIR?
    А в России?


    1. IIvana Автор
      12.10.2018 20:42

      Насчет систем не скажу, но насколько я помню доклады на конференции — в Австралии и Канаде муниципальные структуры используют FHIR, в США также, но у них ситуация немного отличается — проще в чатике по ссылке из статьи напрямую спросить, там присутствуют участники, непосредственно занимающиеся этими вопросами. Россия традиционно не спешит быть в авангарде, присматривается к чужому опыту )


  1. Wayfarer15
    12.10.2018 23:32

    Логичнее было бы совместить отображение данных ресурса с его описанием аналогично профайлам в Simplifier. Также, не совсем понятно по какому принципу отображаются поля. Например, некоторые из них пользователь не может менять и, по идее, вообще не должен о них знать (Resource.id, Resource.impliciteRule и т.д.).

    Для конечного пользователя ресурс предоставляет Narrative, причём его содержимое не обязано совпадать с остальной частью (если status не generated). Для разработчика же возможно важнее видеть сам ресурс и иметь возможность его валидации design time с помощью XML/JSON Schema, профайлов и прочих подобных вещей (см. 7.5 Validating Resources).


    1. IIvana Автор
      13.10.2018 00:10

      Поля (как на верхнем уровне, так и в любом вложенном объекте) отображаются в алфавитном порядке (для унификации, хотя можно сортировать по условному ордеру в схеме структуры ресурса). Список полей ресурса (вместе с их типами, списками допустимых значений, флагами обязательности и множественности значения) берется из StructureDefinition конкретного типа — независимо от наличия/отсутствия значений этих полей в выбранном элементе. Если при этом в элементе ресурса присутствуют поля, не перечисленные в StructureDefinition, то они показываются ниже и всегда как строки — потому что без метаданных я не знаю их тип, но как честный человек должен показать их наличие и дать некоторую возможность редактирования ) Насчет того, что не может менять — я конечно могу сделать id и часть других реквизитов недоступными для редактирования, но тот же id во многих ресурсах может нести некоторую семантику (например при синхронизации со сторонней системой или при загрузке стандартного каталога с четко определенными айдишниками). Поэтому, а еще для универсальности, я не стал запрещать их редактирование.
      То, что вы говорите про "видеть сам ресурс"… Конечно, мне самому привычнее смотреть содержимое ресурса в форматированном ямле или жсоне ) Но так можно дойти до того, что — используйте Postman или просто браузер, кидайте запросы вручную и смотрите ответы текстом ) Но имхо это не лишает данный проект права на жизнь. Наглядная визуализация структуры ресурса, типов и описаний полей, демонстрация возможно незаполненных реквизитов, да и просто — почему бы и нет? В комментарии выше даже предвосхищали появление визуализатора подобного рода )


  1. Sepulina
    13.10.2018 13:41

    Большое спасибо за статью Андрей! Подскажите еще ресурсы, если не сложно, по опыту имплементации FHIR и c2s в проектах? Про чатик я понял — зарегистрировался. В данный момент я изучаю проекты от SAMHSA и все в этой области очень интересно. Заранее благодарен!


    1. IIvana Автор
      13.10.2018 23:39

      Спасибо.
      Можно почитать обзорные статьи (и соседние по ссылкам), про опыт имплементации еще рассказывают на различных конференциях, как в России ОТКРЫТЫЕ СТАНДАРТЫ API, КАК ИНФРАСТРУКТУРА ДЛЯ ИННОВАЦИЙ: ПРИМЕРЫ МЕДИЦИНСКИХ ДАННЫХ HL7 FHIR INTERNATIONAL PATIENT SUMMARY, так и на многочисленных зарубежных. Но я не уверен насчет наличия материалов с них в сети.