## Network Protocols in Healthcare Special Pain Treatment and Remedies for Network Protocols in Healthcare by Christoph Lohmann <20h@r-36.net> ## Intro This is an introduction into healthcare network protocols. #pause * how they evolved #pause * how they are used now #pause * what we can expect #pause * how to have fun with them #pause * some anecdotes on pain in this topic #pause * how a better healthcare protocol world could look like ## xDT German Order: D ... Daten T ... Transfer x ... xA, B, G, L... #pause A ... Abrechnung / Accounting #pause KADT ... Kurärztlich / Spa Town #pause SADT ... Schwangerschaftsabbruch / Pregnancy Termination #pause B ... Behandlungs-DatenTransfer (BDT) #pause G ... Geräte / Devices #pause L ... Labor / Laboratory ## xDT Overview Pretty German style official PDF definition: https://update.kbv.de/ita-update/Abrechnung/KBV_ITA_VGEX_Datensatzbeschreibung_KVDT.pdf * PDF is only readable by German-socialized humans * everything is stored in files * these files are written out and exchanged based on the need * format is pretty simple and easy to parse, it is from the 1990ies * GDT (Devices) is between devices * ADT (Accounting) is for getting your money * LDT (Lab) is for getting blood results * BDT SHOULD be for transfer of patient data ## xDT Structure CON File #pause Date Packet #pause Sentence #pause Field #pause Everything is lines: LLLFFFFXXXXXXXXX LLL ... Length in decimal in bytes FFFF ... Field number XXXX ... Content of length LLL ## xDT Example Con File 0138000con0 #con container begins "0" #pause 017910331032011 #the file was created on 2011-03-31 #pause 01091064 #the encoding is ISO-8859-1 #pause 01091321 #there is "1" data packet in the file #pause 0138000besa #begin "BEtriebsStättendAten" / practice meta data ... #pause 0190216Callenberg #the practice is in Callenberg ... #pause 0138000adt0 #adt data packet begins ... #pause 0199212ADT0199.01 #ADT version ... #pause 01380000101 #data structure "0101" begins, a patient quarterly accounting #pause 01030002 #the patient has the number "2" ... #pause 0138000adt9 #adt data packet ends "9" 0138000con9 #con container ends "9" ## xDT Failures 01091064 4 ... only ISO-8859-1 allowed #pause Only readable by Germans. #pause Unit tests are all written in the PDF for humans. #pause Every quarter the definition can change by some bureaucrat #pause No reference implementation #pause GDT (Devices) restricted to Germany * noone is implementing that for an international market ## HL7 * Health Level 7 founded in the USA in 1987 * 7 ... OSI level 7 (You are level 8!) #pause * many iterations and version # pause * provides interoperability internationally #pause Example: MSH|^~\&|Sender||Subsystem||YYYYMMDDHHmm||ADT^A01|checksum|P|Version| #pause MSG ... Segment Type (MeSsage Header) EVN ... Event MSA ... Message ACK OBR ... Observation Request OBX ... Observation Result ORC ... Common Order PID ... Patient Identification PV1 ... Patient Visit SFT ... Software Segment ERR ... Error ## HLv2 PID PID||ID|UID|Evil^Bob^^^||YYYYMMDD|M|||Street Nr^^City^^Postal^^N||||N||||Insurance||||||||| #pause Can you guess the values? #pause Notice the ^^ #pause Notice the static fields #pause Notice the redundancy ## HLv3 #pause * complete bullshit #pause * heard of UML (Unified Model Language)? #pause * do this in Excel in doc files and exchange them #pause * avoid touching this at all cost ## FHIR Fast Healthcare Interoperability Resources #pause * standardized since 2014 #pause * exposes REST interface over HTTP #pause * all web standards from the past and future apply * TLS, OAuth, ... #pause * gives back JSON or XML ## FHIR Example GET /fhir/Patient/{patientid} ... { "resourceType": "Patient", "id": "{patientid}", "name": [ { "family": ["Evil"], "given": ["Bob"] } ] } #pause Pretty neat? #pause How can we fuck this up in the old style thinking? ## Fucking FHIR Up https://ig.fhir.de/basisprofile-de/0.1/FHIR_Leitfaden_Basis_DE_0.1.pdf #pause Unreadable PDFs again! #pause German localisation again! #pause "/ui/ig/LeitfadenBasisDE/Adresse" instead of "address" #pause WTF?????? ## Next Topic #pause More fuckups. ## DICOM Digital Imaging and Communications in Medicine (DICOM) #pause Standardize by ACR/NEMA starting from 1985 #pause https://www.dicomstandard.org/current/ #pause Unreadable PDFs again! ## DICOM The Good Works in basic features back to 1985: #pause * DICOM files on CDs can be read into the future. * Yes, "file" is a transfer method. #pause * File transfer was first defined in detail over two wires #pause * Now adapts to modern stuff like REST #pause * DICOM machines from 1985 can send (raw!) images to modern PACS * PACS: Picture Archiving and Communication System ## DICOM The Bad * Standard is only a recommendation. #pause * Vendors only need to give some mandatory(!) compliance statement #pause * They can completely leave out, that there is connection testing #pause * Unicode is third-class citizen #pause * Really old conventions, like names in uppercase * BOB^EVIL (yes, ^ is back) #pause * ugly binary protocol #pause * vendors created their own extensions #pause * all baggage of failed history * XML encoding to binary overlays for example ## Learning From What Was Said Compare everything to gopher: #pause * xDT #pause * started simple and easy to parse #pause * restricted itself to Germany #pause * failed, only survived on being enforced by law #pause * HLv2 #pause * started simple and easy to parse #pause * is not flexble to adapt to modern usage #pause * is kept alive by old non-changable medical devices #pause * FHIR #pause * has good birth conditions, easy to use #pause * we did not enforce bureaucrats to leave for pension who already ruined xDT and HLv2 for us #pause * Gopher * has perfect birth conditions, easy to use #pause * was not tortured by commerical interest (Gopher+ was that try) #pause * can be easily adapted to UTF-8, TLS, modern media types #pause * has a thriving community with compassion, not just corpos who must ## DICOM Hackathon Let us get back to fun. #pause We learned we can store all kind of images in some raw format in DICOM. #pause DICOM will be alive until eternity due to old machines forever. #pause How can we combine DICOM in ways it was not supposed to be used but can be used due to its birth flexibility? #pause Let us store QGIS data in DICOM and see the earth like a human skull! ## Solving Maintained Complexity #pause Abstraction! ## world2dicom #pause import numpy as np from pydicom.dataset import Dataset, FileDataset from pydicom.uid import generate_uid, ExplicitVRLittleEndian from PIL import Image #pause map_img = Image.open("world_map_gray.png").convert("L") #pause rows, cols = 512, 512 map_img = map_img.resize((cols, rows)) arr = np.array(map_img, dtype=np.uint16) ## world2dicom ds = FileDataset("synthetic_world", {}, file_meta=None, preamble=b"\0" * 128) dds.file_meta = Dataset() ds.file_meta.TransferSyntaxUID = ExplicitVRLittleEndian ds.SOPClassUID = generate_uid() ds.SOPInstanceUID = generate_uid() ds.StudyInstanceUID = generate_uid() ds.SeriesInstanceUID = generate_uid() ds.FrameOfReferenceUID = generate_uid() #pause ds.PatientName = "ANON^MAP" ds.PatientID = "MAP-EXPERIMENT-001" ## world2dicom ds.Modality = "OT" #pause ds.Rows = rows ds.Columns = cols ds.SamplesPerPixel = 1 ds.PhotometricInterpretation = "MONOCHROME2" ds.BitsAllocated = 16 ds.BitsStored = 16 ds.HighBit = 15 ds.PixelRepresentation = 0 ds.PixelData = arr.tobytes() #pause ds.ImageComments = "Synthetic world map raster embedded into DICOM" ds.is_little_endian = True ds.is_implicit_VR = False ds.save_as("world_map_experiment.dcm", write_like_original=False) ## dcm2pacs import argparse from pynetdicom import AE, StoragePresentationContexts from pydicom import dcmread #pause ds = dcmread("world_map_experiment.dcm") #pause ae = AE(ae_title="MAP") #pause for context in StoragePresentationContexts: ae.add_requested_context(context.abstract_syntax) #pause assoc = ae.associate("pacs.bitreich.org", 104, ae_title="PACS") #pause status = assoc.send_c_store(ds) print(status) #pause assoc.release() ## The Unix Way storescu \ #pause --aet "MAP" \ #pause --aec "PACS" \ #pause pacs.bitreich.org 104 \ #pause world_map_experiment.dcm ## Questions Any questions? ## Thanks Thanks for listening. Send comments to Christoph Lohmann <20h@r-36.net>