====== Меняем кодировку в DICOM и конвертируем кириллицу в латиницу, пишем в базу и отправляем в ORTHANC. ======
Есть у нас рентген аппарат у которого в xml файле написана кодировка ISO-8859-5, а русские символы в Windows-1251.
Изменим тег с кодировкой и конвертируем кириллицу в латиницу с помощью python и отправим это все дело в ORTHANC.
[[https://github.com/AndreyGutov/DicomConverter.git|Ссылка на gitHub]]
=== Создадим базу данных: ===
-- phpMyAdmin SQL Dump
-- version 5.0.4deb2
-- https://www.phpmyadmin.net/
--
-- Хост: localhost:3306
-- Время создания: Июн 16 2022 г., 10:49
-- Версия сервера: 10.5.15-MariaDB-0+deb11u1
-- Версия PHP: 7.4.28
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- База данных: `DicomConvert`
--
-- --------------------------------------------------------
--
-- Структура таблицы `DicomSend`
--
CREATE TABLE `DicomSend` (
`id` int(11) NOT NULL,
`FileName` text NOT NULL,
`SendDate` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
`PatientName` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Индексы сохранённых таблиц
--
--
-- Индексы таблицы `DicomSend`
--
ALTER TABLE `DicomSend`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT для сохранённых таблиц
--
--
-- AUTO_INCREMENT для таблицы `DicomSend`
--
ALTER TABLE `DicomSend`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
=== Подключимся к базе: ===
cat connector.py
import mysql.connector
cnx = mysql.connector.connect(user='DicomConvert', password='d85El4459kqOq2q0',
host='127.0.0.1',
database='DicomConvert',
use_pure=False)
=== Сам скрипт конвертации и отправки: ===
cat dicomSend.py
import glob
import subprocess
import os
import signal
import sys
import time
import fileinput
import connector
import transliterate
server = '192.168.1.43 4242' # Сервер и порт куда будем посылать снимки
fileList = open("/root/python/files_to_copy", "r") # файл со списком изображений(построчно), пример: (/root/DCM/555_777.DCM)
from datetime import datetime
now= datetime.now()
while True:
lineFileList = fileList.readline()
if not lineFileList:
break
filePath=lineFileList.strip()
fileName=filePath.split('/')[-1]
cursor = connector.cnx.cursor()
select_query = (f"select * from DicomSend where FileName=%s")
cursor.execute(select_query,[fileName])
row = cursor.fetchone()
if row == None:
dcmToXml=subprocess.Popen("dcm2xml +M +Wb "+ filePath + " " + filePath + ".xml", shell=True)
dcmToXml.communicate()
fin = open(filePath + ".xml",encoding = "WINDOWS-1251")
fout = open(filePath +".xml.mod", "wt")
for line in fin:
fout.write( line.replace('ISO-8859-5', 'UTF-8') )
fin.close()
fout.close()
fullpathxml = filePath +'.xml.mod'
import xml.etree.ElementTree as ET
tree = ET.parse(fullpathxml)
PatientName=tree.findall('data-set/element[@name="PatientName"]')[0].text
if PatientName:
PatientNameTrans=transliterate.transliterate(PatientName)
else:
PatientNameTrans="NameErr"
tree.findall('data-set/element[@name="PatientName"]')[0].text = PatientNameTrans
BodyPE=tree.findall('data-set/element[@name="BodyPartExamined"]')[0].text
if BodyPE:
BodyPETrans=transliterate.transliterate(BodyPE)
else:
BodyPETrans="BodyErr"
tree.findall('data-set/element[@name="BodyPartExamined"]')[0].text = BodyPETrans
try:
ViewPos=tree.findall('data-set/element[@name="ViewPosition"]')[0].text
ViewPosTrans=transliterate.transliterate(ViewPos)
except:
ViewPosTrans="ViewErr"
tree.findall('data-set/element[@name="ViewPosition"]')[0].text = ViewPosTrans
tree.write(fullpathxml)
xmlToDcm=subprocess.Popen("xml2dcm -f "+ fullpathxml + " "+ fullpathxml +".dcm", shell=True)
xmlToDcm.communicate()
dcmSend=subprocess.Popen("dcmsend -nuc +ma "+server+" "+fullpathxml+".dcm", shell=True, text=True, stderr=subprocess.PIPE)
data=dcmSend.communicate()
for line in data:
if line:
line = line.strip()
line=line.split(':')[0]
if line=='W':
cursor = connector.cnx.cursor()
insert_query=(f"INSERT INTO DicomSend (id, FileName, SendDate, PatientName) values(NULL, %s, NULL, %s)")
cursor.execute(insert_query,[fileName, PatientNameTrans])
connector.cnx.commit()
fullpath='/'.join(fullpathxml.split('/')[:-1])
for xmlpath in glob.iglob(os.path.join(fullpath, '*.xml')):
os.remove(xmlpath)
for modpath in glob.iglob(os.path.join(fullpath, '*.mod')):
os.remove(modpath)
for moddcmpath in glob.iglob(os.path.join(fullpath, '*.mod.dcm')):
os.remove(moddcmpath)
else:
print('ERROR. ORTHANC NOT ANSWER = ',now)
else:
print('RECORD IS DUPLICATED = ', now)
=== Скрипт в крон для запуска конвертера: ===
* Проверяем, работает ли конвертер в данные момент.
* синхронизируем хранилище сервера с рабочей станцией мед. оборудования (на рабочих станциях хранилища со снимками у меня расшарены, а на сервере примонтированы в каталог /mnt).
* создаем файл со списком изображений.
* пишем лог.
#!/bin/bash
#!/bin/sh
if ps -ef | grep -v grep | grep dicomSend.py ; then
rsync -azvp --exclude 2020/ --exclude test.txt --exclude *.tgz /mnt/data/raid1/DicomShare/Roentgen /mnt/data/raid1/sendDCM/ ;
rsync -azvp --exclude 2020/ --exclude test.txt --exclude *.tgz /mnt/data/raid1/DicomShare/MRT /mnt/data/raid1/sendDCM/ ;
exit 0
else
rsync -azvp --exclude 2020/ --exclude test.txt --exclude *.tgz /mnt/data/raid1/DicomShare/Roentgen /mnt/data/raid1/sendDCM/ ;
rsync -azvp --exclude 2020/ --exclude test.txt --exclude *.tgz /mnt/data/raid1/DicomShare/MRT /mnt/data/raid1/sendDCM/ ;
find /mnt/data/raid1/sendDCM/ -type f -mmin -2880 -a -iname "*.dcm" > /root/python/files_to_copy ;
python /root/python/dicomSend.py >> /root/python/log/dicomConvert.log ;
exit 0
fi
=== Транслитерация: ===
cat transliterate.py
# -*- coding: utf-8 -*-
def transliterate(name):
"""
Автор: LarsKort
Дата: 16/07/2011; 1:05 GMT-4;
Не претендую на "хорошесть" словарика. В моем случае и такой пойдет,
вы всегда сможете добавить свои символы и даже слова. Только
это нужно делать в обоих списках, иначе будет ошибка.
"""
# Слоаврь с заменами
slovar = {'а':'a','б':'b','в':'v','г':'g','д':'d','е':'e','ё':'yo',
'ж':'zh','з':'z','и':'i','й':'i','к':'k','л':'l','м':'m','н':'n',
'о':'o','п':'p','р':'r','с':'s','т':'t','у':'u','ф':'f','х':'h',
'ц':'c','ч':'ch','ш':'sh','щ':'sch','ъ':'','ы':'y','ь':'','э':'e',
'ю':'u','я':'ya', 'А':'A','Б':'B','В':'V','Г':'G','Д':'D','Е':'E','Ё':'YO',
'Ж':'ZH','З':'Z','И':'I','Й':'I','К':'K','Л':'L','М':'M','Н':'N',
'О':'O','П':'P','Р':'R','С':'S','Т':'T','У':'U','Ф':'F','Х':'H',
'Ц':'C','Ч':'CH','Ш':'SH','Щ':'SCH','Ъ':'','Ы':'y','Ь':'','Э':'E',
'Ю':'U','Я':'YA',',':'','?':'',' ':' ','~':'','!':'','@':'','#':'',
'$':'','%':'','^':' ','&':'','*':'','(':'',')':'','-':'','=':'','+':'',
':':'',';':'','<':'','>':'','\'':'','"':'','\\':'','/':'','№':'',
'[':'',']':'','{':'','}':'','ґ':'','ї':'', 'є':'','Ґ':'g','Ї':'i',
'Є':'e', '—':''}
# Циклически заменяем все буквы в строке
for key in slovar:
name = name.replace(key, slovar[key])
return name