Package: oru2xds
ORU2XDSoru2xds allows you to receive an HL7 v2.x message in ER7 format, with MLLP transport, into an IHE XDS.b Provide and Register Document Set-b [ITI-41] transaction, as actor Document Source, which is sent to an XDS repository as a properly formatted SOAP message over HTTP. The result of the operation is then used to build an HL7 v2.x ACK^R01 acknowledge message back to the source.Getting StartedThese instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.PrerequisitesYou should have some modules available to python3, in order to run oru2xds.
Required Python modules are hl7, striprtf, lxml, uuid, requests and requests-toolbelt. They are automatically installed by pip when satisfying the dependencies for oru2xds.Installing$ pip install oru2xdsIf you plan to use it right now, without first testing it using xdstoolkit, proceed to theConfigurationsectionIf you want to install and run oru2xds in a docker container, execute$ docker pull antocm/oru2xdsInstall and execute XDS toolkit for testing purposes (optional)If you do not have a tested IHE XDS repository, or if you want to try oru2xds first against a reference implementation like xdstoolkit, here is how to do it. We will run xdstoolkit as a docker container (fromhttps://hub.docker.com/r/antocm/xdstools774)$ docker pull antocm/xdstools774
$ docker image lsNow you have XDS toolkit installed as a docker image running inhttp://localhost>:8080/xdstools4/XDS Toolkit config password: easyTomcat UI username/password: admin/adminYou can now run the XDS toolkit with:$ docker run -it -p 8080:8080 -p 8888:8888 -p 8443:8443 -v $PWD/cache:/tmp/xdstoolkit-cache antocm/xdstools774And stop it with:$ docker stop $(docker ps -q --filter ancestor=antocm/xdstools774)If you want to restart it, you can just$ docker start `docker ps -q -l` # restart it in the background
$ docker attach `docker ps -q -l` # reattach the terminal & stdinTo list images use$ docker image lsTo list running containers use$ docker psPreparations for a test conversiona XDS toolkit should be available. Open a browser inhttp://localhost:8080/xdstools4/Go to "Toolkit configuration" on the left toolbar.Type the admin password "easy".Check the "External cache" to be /tmp/xdstoolkit-cache which should be now mapped to the directory "cache" of your current directory.Check the Toolkit Port to be 8080, as defined above.Close the "ToolkitConf" tab.Go to "Simulators" on the left toolbar.Select actor type and select "Document Repository/Registry", Simulator ID "1" and press "Create Actor Simulator".Select the row with ID "Default__1" and press the "Edit" button below.Confirm that PnR endpoint ishttp://localhost:8080/xdstools4/sim/default__1/rep/prbClose the "SimConfig default__1" tab.Close the "SimCntl" tab.Go to "Manage Patient IDs" on the left toolbar.In the "Favorite Patient IDs" list, select the patient "IHEBLUE-2709^^^&1.3.6.1.4.1.21367.13.20.3000&ISO"From the "Generate V2 Patient Identity Feed", make sure that "Patient ID to send" is "Selection in Favorites"From the SAML dropdown list, select "SAML OFF"From the "Send to"Document Registry:", select "default__1"Press "Run" to issue a patient identity feedYou are ready to perform an initial test.Running a test conversionFrom the working directory where you have oru2xds:$ python3 oru2xds.pyOpen another terminal window, and send an HL7 test message to the configured HL7 listening port$ mllp_send -p 2575 -f examples/sample3-ORU-R01.hl7 --loose localhostLook at the HL7 ACK response message. If it is a positive acknowledgement, everything went OK. If not, you should look into the log files for more details.Examine the resulting logsLog files are placed in the log directory.oru2xds-<DATE>.log- general logscda/- folder with the generated HL7 CDA documentxds_requests/- folder with the generated XDS Provide and Register Document Set-b requestssoap/- folder with the generated SOAP requests and responsesDepending on the configuration set on config.py, for the variablesLOG_XDS_REQUEST_TOFILE = True/False
    LOG_SOAP_ENVELOPE_TOFILE = True/False
    LOG_SOAP_RESPONSE_TOFILE = True/Falseyou may define if those files are generated or not.Configurationoru2xds general configurationsGeneral configuration for the oru2xds is located in the file config.py. You may edit the file to suit your needs.Mapping between HL7 v2.x ORU message:CDA metadata is placed in the file hl7_cda.pyXDS metadata is placed in the file ihe_xds.pyAll metadata configuration must be done in the section below the marker.HL7 CDA Metadata configurationsMetadata should be according to the Implementation Guide for CDA Release 2:Implementation Guide for CDA Release 2:Imaging Integration Levels 1, 2, and 3Basic Imaging Reports in CDA and DICOMDiagnostic Imaging Reports (DIR) – Universal Realm CDAR2_II_BIMGRPTS_R1_INF_2009MAR.pdfConfiguring the mapping of the fields is tricky. It should be done inside the Python scripts, setting the values of the properties of the class .Open the hl7_cda.py and look for the placeholder###################################################################
## Main configuration
###################################################################All the configuration should be done before the placeholder shows up:###################################################################
## End of Main configuration
###################################################################they must be inserted programatically under each metadata field structure, as sampled there.self.m_author = {
			"time": hl7message['OBR.F22'],
			"id_extension": hl7message['OBR.F32.R1.C1.S1'],
			"id_root": "1.3.6.1.4.1.55196.1.3.2.4",
			"assignedAuthorAssignedPersonName": hl7message['OBR.F32.R1.C1.S2'],
			"assignedAuthorRepresentedOrganizationIdRoot": "1.3.6.1.4.1.55196.1.3",
			"assignedAuthorRepresentedOrganizationName": "Example hospital - Radiology department"
		}XDS Metadata configurationsConfiguring the mapping of the fields is tricky. It should be done inside the Python scripts, setting the values of the properties of the class .Open the ihe_xds.py and look for the placeholder###################################################################
## Main configuration
###################################################################All the configuration should be done before the placeholder shows up:###################################################################
## End of Main configuration
###################################################################they must be inserted programatically under each metadata field structure, as sampled there.For example, the m_DocumentEntry_author is built as:m_DocumentEntry_author = [[
		{
			"authorvalue": [hl7message['OBR.F32.R1.C1.S2']],
			"authorrole": "authorPerson",
		},
		{
			"authorvalue": ["Example hospital - Radiology department"],
			"authorrole": "authorInstitution"
		}
	]]The authorPerson is taken from the HL7 message as hl7message['OBR.F32.R1.C1.S2'] meaning OBR segment, field 32, component 1, sub-component 2.
The authorRole is hard coded with a fixed value.Here are the fields that are required or optional in an XDS DocumentEntry and SubmissionSet. Folder is not supported.These are the following fields that should go into an XDS document submission requestMetadata Element 	Metadata Attribute 	XDS DSDocumentEntry		author					R2DocumentEntry		availabilityStatus		ODocumentEntry		classCode				RDocumentEntry		comments				ODocumentEntry		confidentialityCode		RDocumentEntry		creationTime			RDocumentEntry		entryUUID				RDocumentEntry		eventCodeList			ODocumentEntry		formatCode				RDocumentEntry		hash					ODocumentEntry		healthcareFacilityTypeCode		RDocumentEntry		homeCommunityId			ODocumentEntry		languageCode			RDocumentEntry		legalAuthenticator		ODocumentEntry		limitedMetadata			XDocumentEntry		mimeType				RDocumentEntry		objectType				RDocumentEntry		patientId				RDocumentEntry		practiceSettingCode		RDocumentEntry		referenceIdList			ODocumentEntry		repositoryUniqueId		ODocumentEntry		serviceStartTime		R2DocumentEntry		serviceStopTime			R2DocumentEntry		size					ODocumentEntry		sourcePatientId			RDocumentEntry		sourcePatientInfo		ODocumentEntry		title					ODocumentEntry		typeCode				RDocumentEntry		uniqueId				RDocumentEntry		URI						OSubmissionSet		author					R2SubmissionSet		availabilityStatus		OSubmissionSet		comments				OSubmissionSet		contentTypeCode			RSubmissionSet		entryUUID				OSubmissionSet		intendedRecipient		OSubmissionSet		limitedMetadata			XSubmissionSet		patientId				RSubmissionSet		sourceId				RSubmissionSet		submissionTime			RSubmissionSet		title					OSubmissionSet		uniqueId				RNote: Folder is not implementedFolder			availabilityStatus		OFolder			codeList				RFolder			comments				OFolder			entryUUID				RFolder			homeCommunityId			OFolder			lastUpdateTime			OFolder			limitedMetadata			XFolder			patientId				RFolder			title					RFolder			uniqueId				RRunningWhen oru2xds is executed, it will run forever as a daemon service.$ python3 /usr/local/lib/python3.10/site-packages/oru2xds/oru2xds.pyIf you want to send an HL7 example report message, issue$ mllp_send -p 2575 -f examples/sample3-ORU-R01.hl7 --loose localhostAs a docker imageIf you installed the docker image, you can now execute it.$ docker run -it --rm -p 2575:2575 antocm/oru2xdsThis command will automatically execute oru2xds and waits for HL7 messages in port 2575.If you want to send an HL7 example report message from the same container, issue:$ docker ps
$ docker exec -it <container_id> bash
# mllp_send -p 2575 -f examples/sample3-ORU-R01.hl7 --loose localhostIn case you also want to run xdstoolkit as a docker image to provide the XDS repository, proceed as in section [Install and execute XDS toolkit for testing purposes (optional)](#Install and execute XDS toolkit for testing purposes (optional)). Then, obtain the IP address of this container usingdocker ps, take note of the container id, then issuedocker inspect <container_id> | grep IPAddress. Take this address, then configure it in the antocm/oru2xds container dropping a shell into the containerdocker run -it --rm -p 2575:2575 antocm/oru2xds bash, editing the fileconfig.pyand setting the IP addres of the xdstoolkit container as the repository address in the variableSERVICE_URL. Finally, runpython3 oru2xds.py. Get the container id of the antocm/oru2xds usingdocker psand execute a second shell to the antocm/oru2xds container withdocker exec -it <container_id> bashand finally execute the issue of an HL7 example message usingmllp_send -p 2575 -f examples/sample3-ORU-R01.hl7 --loose localhost.Built Withlxml- All XML processingaiorun- creates the HL7 server servicepython-hl7- MLLP server and HL7 message parserstriprtf- Convert RTF file to stringsrequests- HTTP send and receiverequests-toolbelt- Multipart encoding and decodingAuthorAntonio Martins-Initial work- (https://github.com/antocm)LicenseThis project is licensed under the GPLv3 License - see theLICENSE.mdfile for detailsAcknowledgmentsIHE XDS.b profile and all the available documentationHL7 CDA Implementation Guide for CDA Release 2: Imaging Integration Levels 1, 2, and 3 Basic Imaging Reports in  CDA and DICOM Diagnostic Imaging Reports (DIR) – Universal Realm CDAR2_II_BIMGRPTS_R1_INF_2009MAR.pdf