Разработка программных средств поддержки служб назначений на обследования и хранения изображений в медицинском архиве

Автор: Пользователь скрыл имя, 12 Января 2014 в 13:47, дипломная работа

Описание работы

Часто из вида упускается вклад DICOM и PACS на фактического пациента. DICOM обеспечивает весь рабочий процесс с момента, когда пациент входит в радиологическое отделение, собирая важные данные и изображения с цифровых модальностей и доставляя их за считанные минуты рентгенологам в самой точной для диагностики форме. Сравнение предыдущих исследований с новыми не требуют огромных усилий с DICOM, что приводит к более точной диагностики и лучшему лечению. Нет пленок, которые можно потерять, перепутать, просрочить, а отсюда и меньше повторных исследований. Все это позволяет ускорить и значительно улучшить современное здравоохранение. Важность DICOM, как неотъемлемой части IT–инфраструктуры, будет расти. Количество существующих и доступных DICOM и PACS приложений просто ошеломляет. Выбор PACS с каждым годом становится все сложнее, а понимание DICOM все важнее.

Работа содержит 1 файл

Пояснительная записка (диплом).doc

— 1.40 Мб (Скачать)

Таким образом, в рамках данной работы ставится цель создать программы, расширяющие функциональные возможности информационной системы МЕДАРМ, путем добавления в нее функций: сопровождения листов назначений и подтверждения хранения изображения.

 

  1. Разработка клиентской части дополнительных служб

 

Для реализации SCM и MWL было необходимо выбрать язык и среду разработки. Был необходим язык с поддержкой ООП, а также с возможностью создания исполняемого файла, не привязанного к среде разработки и каким-либо фреймворкам. Выбор языка пал на C++, так как на кажущуюся простоту и ясность, язык на самом деле является сложным и глубоким, а из-за своей всеобъемлемости пригоден для любых целей. Средой разработки была выбрана Microsoft Visual Studio 6.0. Во-первых, сама ИС была написана в этой среде и портирование на другую заняло бы много времени. Во-вторых, она имеет простой и интуитивно понятный интерфейс, что позволяет целиком и полностью сосредоточиться на работе.

    1. Система МЕДАРМ

 

Система МЕДАРМ является программным обеспечением для рентгенографических  аппаратов и флюорографов КАРС. Аппараты КАРС позволяют получать цифровые рентгеновские  изображения (снимки) с автоматическим определением условий экспозиции и вычислением эквивалентной и эффективной дозы облучения. Компоненты МЕДАРМ могут так же использоваться независимо от аппаратов КАРС для работы с цифровыми снимками, включая их хранение, поиск, обработку, просмотр.

Название «МЕДАРМ» является акронимом фразы «Автоматизированное Рабочее Место для МЕДицины». Рабочее место может быть настроено для врача, рентгенлаборанта и регистратора. В состав МЕДАРМ входит сервер медицинских изображений (PACS), который служит архивом в сети медицинского учреждения. На рисунке 2.1.1 показано основное окно программы с окном создания нового снимка.

 

Рисунок 2.1.1 Основное окно программы

 

Ядро системы МЕДАРМ составляют рабочие места врача-рентгенолога и рентгенлаборанта. Как правило, врачебных мест устанавливается несколько, по числу практикующих врачей, а место лаборанта одно, связанное с цифровым аппаратом КАРС. Но в общем случае таких мест может быть несколько (по числу аппаратов). На рисунке 2.1.2 показано упрощённое устройство системы МЕДАРМ, для одного рабочего места каждого типа.

 

 Рисунок 2.1.2 Устройство системы МЕДАРМ

 

Источник данных «Текущие»  — это получаемые на компьютере лаборанта снимки. Каждый новый снимок при появлении или правке копируется в локальный, лаборантский архив  в сжатом виде. Врач читает текущие снимки на своём компьютере, но поступают они с компьютера лаборанта и сохраняются с результатами описания на нём же. Каждый описанный врачом снимок сохраняется в сетевой папке, а копия снимка попадает в локальный, врачебный архив.

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

Архивные снимки занимают примерно в 16 раз меньше места, чем  исходные. Сжатие производится по алгоритму JPEG-2000 настолько качественно, что  на глаз почти никогда не удаётся  увидеть разницу между исходным и сжатым снимком. Таким образом, архив наполняется в 16 раз медленнее, чем папка текущих снимков и занимает обычно не очень много места на диске.

    1. Разработка службы Modality Worklist

 

Было решено начать со службы Modality Worklist, так как некоторые наработки по ней уже были в МЕДАРМе.

По сути, клиентская часть MWL заключается в следующем:

  • Установка ассоциации с сервером MWL
  • Отправка пакета с DIMSE командой C-FIND-RQ на какую либо модальность
  • Прием пакета с DIMSE командой C-FIND-RSP со списками назначения
  • Окончание ассоциации
  • Разбор пакета

Служба Modality Worklist стала некоторым расширением класса Scanner.

      1. Класс Scanner

 

Класс Scanner является оболочкой виртуальной базы данных МЕДАРМа. На рисунке 2.2.1 показано общее устройство этой базы.

 

Рисунок 2.2.1 Устройство виртуальной  базы данных

 

Данный класс занимается заполнением данной базы данных из разных источников.

Поля класса Scanner:

  • int stop – состояние сканера (0 – запуск, 1 – остановка, 2 – рестарт)
  • HANDLE canrun – событие, которое следит за возможностью работы с источником
  • int depth – глубина вложенности каталогов
  • int nupd – номер обновления базы данных
  • int lastpri – последний приоритет какого-либо источника
  • unsigned int bksize – общий размер в байтах несохраненных снимков
  • int id – уникальный идентификатор источника
  • char path[512] – путь до источника
  • int plen – длина пути
  • std::string name – название в базе данных
  • bib::bibrec *bip – список в базе данных
  • bool cdrom – является ли источник сменным носителем типа CD
  • int loglev – уровень логирования
  • short anytext – 1: любые расширения (иначе только *.iod, *.jpc, *.dcm), 2:любые имена папок
  • bool needdir – пропускать ли папки без DICOMDIR’а
  • int timeout – тайм-аут источника

Функции класса Scanner:

    • scanner () – конструктор
    • ~scanner () – деструктор
    • int scan () – сканирует различные источники и заполняет базу данных
    • void finish () – заканчивает сканирование источников
    • void pause (bool red) – приостанавливает работу, если red = true
    • void watch () – обрабатывает события
  • void push (int restart) – начинает работу в зависимости от режима, который задается параметром restart
  • int egetz (const char *path, char *s, int len) – ищет xml и извлекает из него описание
  • void dirtdel (const char *s) – удаляет папку из списка
  • int fill_buf (char *buf, int len, ...) – разработанная в рамках данной работы функция, которая заполняет буфер buf

Заголовочный файл класса представлен в приложении А

      1. Работа над службой

 

В классе Scanner, а именно в функции Scan, которая сканирует разные источники данных и передает их виртуальной базе, уже была начата работа над MWL, однако не все из требуемых задач были выполнены и код не был отлажен. Первая задача, которую нужно было решить - заполнение буфера необходимыми данными. Для этого была разработана функция fill_buf. Созданная функция fill_buf работает следующим образом: получает входными параметрами указатель на буфер, его размер и пары «тэг—значение», считает длины каждого значения и заполняет буфер элементами (тэг-длина-значение), в случае переполнения буфера записываются только те элементы, на которые хватило места

После выполнения fill_buf, буфер заполнен необходимыми тэгами, и его можно отправить вместе с командой C-FIND. Этой задачей занимается функция у asklist. Функция asklist получает массив структур TAGVAL, который является набором элементов, формирует пакет с помощью функции sendatag, который после наполнения буфера отправляет его в сокет с помощью функции Send. Если все прошло успешно, то МЕДАРМ ожидает ответа от сервера. В случае если ответ получен, то пакет читается из сокета, пока не будет получено необходимое число байт и база данных заполняется полученными от сервера рабочими листами. Коды функций представлены в приложении Б. На рисунке 2.2.2 показано общее устройство разработанной службы.

 

Рисунок 2.2.2 Принцип работы службы MWL в МЕДАРМе

    1. Разработка службы Storage Commitment

 

После окончания работы над клиентской части Modality Worklist было необходимо начать работу над Storage Commitment. Было решено создать отдельную утилиту, работа которой заключалась бы в следующем:

  • Получить адрес, порт, AE Title сервера, а также UID'ы или DICOM – изображения, которые необходимо подтвердить
  • Установить ассоциацию с сервером
  • Отправить пакет с DIMSE командой N-ACTION с UID'ми
  • Принять пакет N-EVENT-REPORT с результатами в виде двух последовательностей
  • Закончить ассоциацию
  • Разобрать пакет, выдать полную информацию о UID'ах и DICOM-изображениях

Для создания данной утилиты использовался DICOM-модуль ПО МЕДАРМ, который подвергся расширению. Рассмотрим класс, который использовался в данной утилите.

      1. Класс XSOP

 

Класс XSOP занимается всей работой с DICOM в МЕДАРМе. Именно этот класс и расширялся в рамках данной работы.

Поля класса XSOP:

  • int len – длина сообщения с заголовком в порядке от старшего байта к младшему
  • int ver – версия DICOM
  • char CalledAE[16] – AE Title вызывающего узла
  • char CallingAE[16] – AE Title вызываемого узла
  • int lenc – длина сообщения без заголовка в порядке от старшего байта к младшему
  • short c01, c10, c20, c30 – сервисные поля нужные для формирования пакета
  • int ncli – число клиентов
  • SOCKET sin – входной сокет
  • int maxlen – максимальная длина PDU
  • unsigned char short dcmerr – код ошибки, который соответствует перечислению
  • CLICTX ci – контекст связи для самого себя. Т.е. все что связано с клиентом: порт, сообщение и т.д)
  • CLICTX *cpool[128] – пул клиентов

Функции класса XSOP:

  • XSOP () – конструктор класса
  • ~XSOP () – деструктор класса
  • int bad (int err, bool stopsrv) – закрывает сокет, если ошибка связана с ним, а также останавливает сервер, если stopsrv = true
  • int opensock (LPCTSRT hostname, int port) – открывает сокет по заданному имени хоста и порту
  • int Send (CLICTX *cc, const char *buf, int n) – посылает в сокет пакет (отложено, если заведен буфер)
  • int recvait (SOCKET s, char *buf, int n, int tout) – читает из сокета нужное количество байт
  • int associate (char *whom, char *why, char *ae, char *more) – создает ассоциацию
  • unsigned char *find_tag (unsigned char *p, int len, int tag, int offs) – ищет тэги в пакете
  • short get_status (char *buf, int n, int tag) – разбирает ответ от сервера
  • bool sendatag (CLICTX *cc, int tag, int len, void *data) – записывает в канал связи один тэг
  • bool pdata (CLICTX *cc, int len, int synid, int flag) – формирует начало посылки данных через буфер
  • bool commands (CLICTX *cc, int len, const char *sop, short cmd, short mid, short hasdata, short prty, short synid, short ret, const char *aet) – формирует пакет с командой, параметрами и данными
  • int senddoc (char *buf, int size, char *dump, int len, int skip2) – посылает документ (изображение + аннотация) на PACS
  • int asklist (TAGVAL *mt, int nt, int isop) – запрашивает рабочий лист с PACS
  • int askimg (const char *pname, const char *pid, const char *qlev, const char *mod, const char *date, const char *stid, int isop) – запрашивает снимки с PACS
  • int bye (int err) – заканчивает ассоциацию
  • int getresponce (char *film, char *image, int fsize, int isize, char** uid, int *nuid) – читает ответ от сервера, ставит код ошибки DICOM
  • bool sendpixels (CLICTX *cc, char *buf, int m) – отсылает изображение
  • int ass_any (const char *pa, const char *sop, const char *ae, CLICTX *cc) – соединиться с первым, кто ответит из списка PACS’ов
  • int dping (const char *address, const char *ae) – проверка DICOM связи
  • int Server (XSOP_SOCK *xs) – обслуживает соединение с клиентом по сокету

Класс XSOP также содержит в себе несколько перечислений: коды ошибок, DICOM тэги, состояние работы. Кроме этого содержатся несколько пользовательских структур. Код класса представлен в приложении В.

      1. Работа над службой

 

Для начала было необходимо разработать новую версию функции commands, которая получала бы на вход контекст связи (все, что связано с клиентом), тип пакета (данные или команда) и неопределенное количество элементов (тэг-длина-значение). В процессе работы функция должна была подсчитать общую длину этих элементов и передать эту длину функции, которая выделит буфер, куда они будут передаваться, пока он не заполнится и передастся в сокет. Для начала нужно было придумать способ передачи элементов, количество которых будет известно только во время работы. Для этого было решено помещать элементы в вектор, а функции передавать ссылку на него. После функция выполняет свою запланированную работу: подсчет длины буфера, передача элементов до заполнения. Передача осуществляется, как и в случае с MWL, с помощью функции sendatag, которая в случае заполнения буфера отправит его в сокет с помощью вызова функции Send. Для осуществления работы службы необходимо отправить серверу два пакета: запрос N-ACTION и пакет с данными. На рисунках 2.3.1 и 2.3.2 показано общее устройство этих пакетов.

 

Рисунок 2.3.1 Пакет с  запросом N-ACTION

 

Рисунок 2.3.2 Пакет с последовательностью  UID’ов

 

Если все прошло успешно, то данные от сервера можно получить двумя способами: закончить ассоциацию и ожидать начала новой ассоциации от сервера или ожидать ответа в текущей. Особенностью стандарта является то, что там нет понятия клиент-сервер в привычном понимании. Тот, кто инициирует ассоциацию, является клиентом (SCU), а тот, кто принимает ее -  сервером (SCP). Если утилита работает по первому принципу, то она становится сервером и с помощью функции ServerWait ожидает входных соединений. При запросе на ассоциацию утилита ее принимает, получает пакет и обрабатывает его. Она записывает его в два вектора good и bad, которые позже сообщаться пользователю. Если же мы ожидаем ответ в текущей ассоциации, то вызывается функция getresponce, она получает буфер из сокета с помощью функции recuvait и начинает его обработку. Пакеты от сервера весьма схожи с теми, которые ему посылает клиент. На рисунке 2.3.3 и 2.3.4 показано их общее устройство.

 

Рисунок 2.3.3 Пакет с запросом N-EVENT-REPORT

 

Рисунок 2.3.4 Пакет с  двумя последовательностями

 

 Обработкой пакета является: определение DIMSE команды, UID SOP класса и других параметров. Для работы SCM, как SCU нужно было доработать getresponce таким образом, чтобы она могла обрабатывать команду N-EVENT-REPORT. Обработка заключается в следующем: записать UID’ы подтвержденных в массив указателей. Далее они сообщаются пользователю. На рисунке 2.3.5 показан принцип работы разработанной службы. Коды функций представлены в приложении Г.

Информация о работе Разработка программных средств поддержки служб назначений на обследования и хранения изображений в медицинском архиве