====== Меняем кодировку в 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