diff --git a/input/maps/HIVObservationHIVCondition.http b/input/maps/HIVObservationHIVCondition.http new file mode 100644 index 000000000..eb6118530 --- /dev/null +++ b/input/maps/HIVObservationHIVCondition.http @@ -0,0 +1,56 @@ +### @host = http://localhost:8080/matchboxv3/fhir +@host = https://test.ahdis.ch/matchbox/fhir + + +### Convert FML to StructureMap +POST {{host}}/StructureMap/$convert HTTP/1.1 +Content-Type: text/fhir-mapping +Accept: application/fhir+json + + +< ./HIVObservationHIVCondition.map + + +### Put it +PUT {{host}}/StructureMap/HIVObservationHIVCondition HTTP/1.1 +Content-Type: application/fhir+json +Accept: application/fhir+JSON + +< ./StructureMap-HIVObservationHIVCondition.json + + +# Or, just do this one... + +### PUT FML to StructureMap (combined previous 2 steps in one) +PUT {{host}}/StructureMap/HIVObservationHIVCondition HTTP/1.1 +Content-Type: text/fhir-mapping +Accept: application/fhir+json + +< ./HIVObservationHIVCondition.map + + +# Then... + + +### Verify StructureMap is created +GET {{host}}/StructureMap/HIVObservationHIVCondition HTTP/1.1 +Accept: application/fhir+JSON + + + +### Transforms +POST {{host}}/StructureMap/$transform?source=https://path-global-health.github.io/MERindicators/StructureMap/HIVObservationHIVCondition +Accept: application/fhir+json;fhirVersion=4.0 +Content-Type: application/fhir+json;fhirVersion=4.0 + +< ./test-data1.json + + + +### Transforms +POST {{host}}/StructureMap/$transform?source=https://path-global-health.github.io/MERindicators/StructureMap/HIVObservationHIVCondition +Accept: application/fhir+json;fhirVersion=4.0 +Content-Type: application/fhir+json;fhirVersion=4.0 + +< ./test-data2.json + diff --git a/input/maps/HIVObservationHIVCondition.map b/input/maps/HIVObservationHIVCondition.map new file mode 100644 index 000000000..cdfea97b3 --- /dev/null +++ b/input/maps/HIVObservationHIVCondition.map @@ -0,0 +1,53 @@ +map "https://path-global-health.github.io/MERindicators/StructureMap/HIVObservationHIVCondition" = "HIVObservationHIVCondition" + +uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias bund as source +uses "http://hl7.org/fhir/StructureDefinition/Bundle" alias output as target + + + +group HIVObservationHIVCondition( + source src: bund, + target tgt: output +) { + + src -> tgt.type = 'collection' "setBundleType"; + + src.entry as entry -> tgt.entry as tentry then { + entry.resource : Patient as patient -> tentry.resource = patient then { + + src.entry as obsentry where resource.is(Observation) and resource.subject.exists(reference=("Patient/" & patient.id)) and resource.code.exists(coding.exists(system='https://openconceptlab.org/orgs/CIEL/sources/CIEL' and code='160540')) + -> tgt.entry as newentry, newentry.resource = create("Condition") as cond, uuid() as cid then { + obsentry.resource as obs -> newentry.fullUrl = ( "urn:uuid:" & cid ) then { + //obsentry -> newentry.resource = cond, cond.id = cid "setConditionRes"; + obsentry -> cond.id = cid "setCId"; + patient -> cond.subject as subject then { + patient -> subject.reference = reference(patient) "setSubjectRef"; + } "setSubject"; + obsentry -> cond.code as ccode then { + obsentry -> ccode.coding as coding then { + obsentry -> coding.code = '86406008', + coding.display = "HIV Condition Positive", + coding.system = 'http://snomed.info/sct' "setCondSystemCode"; + } "setCondCoding"; + } "SetCondCode"; + obs -> tgt.entry as pentry, pentry.resource = create("Provenance") as prov, uuid() as pid then { + obs -> prov.id = pid "setPId"; + obs -> pentry.fullUrl = ( "urn:uuid:" & pid ) "setFullUrl"; + obs -> prov.target as ptarg then { + obs -> ptarg.reference = reference(cond) "setTargetRef"; + } "setTarget"; + obs -> prov.entity as entity then { + obs -> entity.role = "source" "setRole"; + obs -> entity.what as pwhat then { + obs -> pwhat.reference = reference(obs) "setWhatRef"; + } "setWhat"; + } "setEntity"; + } "setProvenance"; + } "setCondition"; + } "getObservation"; + } "patientResource"; + } "copyPatient"; + + } + + diff --git a/input/maps/README.md b/input/maps/README.md new file mode 100644 index 000000000..bdcc902e8 --- /dev/null +++ b/input/maps/README.md @@ -0,0 +1,23 @@ +# How to use this folder + +This folder is standalone and dependent on the IG it is in. + +Follow the directions below then open `input/maps/HIVObservationHIVCondition.http` in VS Code. Click on: +* Convert FML to StructureMap and Put it or... +* PUT FML to StructureMap which combines the two operations. This converts FML (.map) files to FHIR StructureMaps and PUTs it on the server. +* Verify StructureMap is created +* Transform + +The $transform operation will transform the bundle in the payload to an output bundle. In production, the returned bundle would be put on a FHIR server. + +## Setup + +* The operations use a publicly available server. Please setup a private server with the usual protections before transforming patient data. The open source server used here is the publicly available hosted [Matchbox](https://github.com/ahdis/matchbox) server which is a version of HAPI FHIR Server with additional operations. Standard HAPI FHIR JPA Server does not have the operations needed for this demo. + +* Do not post real data. Please use the de-identified examples. + +* Install REST Client if using VS Code. Otherwise, use an extension in other editors that can execute .http files. +[VS Marketplace](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) + +* It's recommended to install the FHIR Mapping Language extension if using VS Code [VS Marketplace](https://marketplace.visualstudio.com/items?itemName=HealexSystems.fhir-mapping-language-support) + diff --git a/input/maps/_convert.sh b/input/maps/_convert.sh new file mode 100755 index 000000000..9fb034c0d --- /dev/null +++ b/input/maps/_convert.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +export HEADER1="content-type:application/fhir+json" +export HEADER2="content-type:text/fhir-mapping" +export ACCEPT="accept:application/fhir+json" + +export FHIR="https://test.ahdis.ch/matchbox/fhir" +export CONVERT="${FHIR}/StructureMap/$convert" +export MAP="${FHIR}/StructureMap" + +# curl --request POST -H 'accept: application/fhir+json' -H 'content-type: text/fhir-mapping' --data-binary @HIVObservationHIVCondition.map --url 'https://test.ahdis.ch/matchbox/fhir/StructureMap/$convert' + +function convertput { + # curl -s -X POST -H ${ACCEPT} -H ${HEADER2} --data-binary @${1}.map --url ${CONVERT} | \ + # curl -s -X PUT -H ${HEADER1} --data-binary @- --url "${MAP}/${1}" | \ + # curl -s -X GET -H ${ACCEPT} --url "${MAP}/${1}" | \ + # jq . + + curl -s -X POST -H ${ACCEPT} -H ${HEADER2} --data-binary @${1}.map --url ${CONVERT} | jq . > StructureMap-${1}.json + printf "StructureMap created\n" + + curl -s -X PUT -H ${HEADER1} --data-binary @StructureMap-${1}.json --url "${MAP}/${1}" | jq . + printf "StructureMap loaded on server\n" + + curl -s -X GET -H ${ACCEPT} --url "${MAP}/${1}" | jq . + printf "Confirm StructureMap loaded on server\n" +} + +convertput HIVObservationHIVCondition + diff --git a/input/maps/_transform.sh b/input/maps/_transform.sh new file mode 100755 index 000000000..6017d3078 --- /dev/null +++ b/input/maps/_transform.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +export HEADER1="content-type:application/fhir+json" +export ACCEPT="accept:application/fhir+json" + +export FHIR="https://test.ahdis.ch/matchbox/fhir" +export TRANSFORM="${FHIR}/StructureMap/${1}/$transform" + + + +curl --request POST "https://test.ahdis.ch/matchbox/fhir/StructureMap/\$transform?source=https://path-global-health.github.io/MERindicators/StructureMap/HIVObservationHIVCondition" \ + --data-binary @test-data1.json \ + -H "Accept: application/fhir+json" -H "Content-Type: application/fhir+json" + + + +# curl --request POST -H 'accept: application/fhir+json' -H 'content-type: text/fhir+json' --data-binary @test-data1.json --url 'https://test.ahdis.ch/matchbox/fhir/StructureMap/HIVObservationHIVCondition/$transform' + +function transform { + curl -s -X POST -H ${ACCEPT} -H ${HEADER1} --data-binary @${2} --url ${TRANSFORM} | jq . +} + +transform HIVObservationHIVCondition test-data1.json +# transform HIVObservationHIVCondition test-data2.json + diff --git a/input/maps/test-data1.json b/input/maps/test-data1.json new file mode 100644 index 000000000..65173de6c --- /dev/null +++ b/input/maps/test-data1.json @@ -0,0 +1,304 @@ +{ + "resourceType": "Bundle", + "entry": [ { + "resource": { + "resourceType": "Patient", + "id": "3e990510-1d51-4a25-abd4-3885cf9e8be9", + "meta": { + "lastUpdated": "2023-05-22T09:19:47.000+03:00" + }, + "identifier": [ { + "id": "3196030c-ca05-4f66-8e47-e3251ef1b1a0", + "extension": [ { + "url": "http://fhir.openmrs.org/ext/patient/identifier#location", + "valueReference": { + "reference": "Location/807b5afd-579c-422f-abd2-96d497235a7d", + "type": "Location", + "display": "Lumumba Sub County Hospital" + } + } ], + "use": "official", + "type": { + "coding": [ { + "code": "dfacd928-0370-4315-99d7-6ec1c9f7ae76" + } ], + "text": "OpenMRS ID" + }, + "value": "MK3JYU" + }, { + "id": "8a517664-6531-4c10-b64b-0137192a3e30", + "extension": [ { + "url": "http://fhir.openmrs.org/ext/patient/identifier#location", + "valueReference": { + "reference": "Location/807b5afd-579c-422f-abd2-96d497235a7d", + "type": "Location", + "display": "Lumumba Sub County Hospital" + } + } ], + "use": "usual", + "type": { + "coding": [ { + "code": "49af6cdc-7968-4abb-bf46-de10d7f4859f" + } ], + "text": "National ID" + }, + "value": "20981456" + }, { + "id": "219d9836-acd4-425f-afec-1f1beaf29e43", + "extension": [ { + "url": "http://fhir.openmrs.org/ext/patient/identifier#location", + "valueReference": { + "reference": "Location/807b5afd-579c-422f-abd2-96d497235a7d", + "type": "Location", + "display": "Lumumba Sub County Hospital" + } + } ], + "use": "usual", + "type": { + "coding": [ { + "code": "05ee9cf4-7242-4a17-b4d4-00f707265c8a" + } ], + "text": "Unique Patient Number" + }, + "value": "1373821796" + }, { + "id": "ca797003-7714-4829-bf98-943696e84d79", + "extension": [ { + "url": "http://fhir.openmrs.org/ext/patient/identifier#location", + "valueReference": { + "reference": "Location/807b5afd-579c-422f-abd2-96d497235a7d", + "type": "Location", + "display": "Lumumba Sub County Hospital" + } + } ], + "use": "usual", + "type": { + "coding": [ { + "code": "b4d66522-11fc-45c7-83e3-39a1af21ae0d" + } ], + "text": "Patient Clinic Number" + }, + "value": "21796" + }, { + "id": "f80556fe-fe18-4fde-bd93-a9a054012308", + "extension": [ { + "url": "http://fhir.openmrs.org/ext/patient/identifier#location", + "valueReference": { + "reference": "Location/807b5afd-579c-422f-abd2-96d497235a7d", + "type": "Location", + "display": "Lumumba Sub County Hospital" + } + } ], + "use": "usual", + "type": { + "coding": [ { + "code": "f85081e2-b4be-4e48-b3a4-7994b69bb101" + } ], + "text": "National Unique patient identifier" + }, + "value": "MOHEJ9VG3KGJ1" + } ], + "active": true, + "name": [ { + "id": "bf2968dd-b45f-436e-9d9c-55c46ba3fb14", + "family": "Musamia", + "given": [ "Musamia", "Musamia" ] + } ], + "gender": "male", + "birthDate": "1977", + "deceasedBoolean": false, + "address": [ { + "id": "692e88a0-f844-4f9f-a2b3-f90bac6c430a", + "extension": [ { + "url": "http://fhir.openmrs.org/ext/address", + "extension": [ { + "url": "http://fhir.openmrs.org/ext/address#address1", + "valueString": "39857 address1" + }, { + "url": "http://fhir.openmrs.org/ext/address#address2", + "valueString": "39857 address2" + }, { + "url": "http://fhir.openmrs.org/ext/address#address4", + "valueString": "Manyatta B" + } ] + } ], + "use": "home", + "city": "kolwa central", + "district": "Kisumu", + "state": "Kisumu East" + } ] + }, + "request": { + "method": "PUT", + "url": "Patient" + } + }, { + "resource": { + "resourceType": "Observation", + "id": "455f8701-aaad-4f85-b59a-1bf75d2c36ac", + "meta": { + "lastUpdated": "2023-05-18T16:28:53.000+03:00" + }, + "status": "final", + "code": { + "coding": [ { + "code": "160540AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "display": "Method of enrollment" + }, { + "system": "https://openconceptlab.org/orgs/CIEL/sources/CIEL", + "code": "160540", + "display": "Method of enrollment" + }, { + "system": "http://loinc.org", + "code": "45252-4", + "display": "Method of enrollment" + } ], + "text": "Method of enrollment" + }, + "subject": { + "reference": "Patient/3e990510-1d51-4a25-abd4-3885cf9e8be9", + "type": "Patient", + "display": "Musamia Musamia Musamia (OpenMRS ID: MK3JYU)" + }, + "encounter": { + "reference": "Encounter/0fc09b3f-6a41-4da3-be19-c0479ef4fa28", + "type": "Encounter" + }, + "effectiveDateTime": "2023-05-18T16:27:52+03:00", + "issued": "2023-05-18T16:28:53.000+03:00", + "valueCodeableConcept": { + "coding": [ { + "code": "160542AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "display": "Outpatient department" + }, { + "system": "https://openconceptlab.org/orgs/CIEL/sources/CIEL", + "code": "160542", + "display": "Outpatient department" + }, { + "system": "http://snomed.info/sct", + "code": "33022008", + "display": "Outpatient department" + } ], + "text": "Outpatient department" + } + }, + "request": { + "method": "POST", + "url": "Observation" + } + }, { + "resource": { + "resourceType": "Observation", + "id": "10a95d01-efa0-4a0e-a032-022db3b87ddc", + "meta": { + "lastUpdated": "2023-05-18T16:34:10.000+03:00" + }, + "status": "final", + "code": { + "coding": [ { + "code": "1193AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "display": "CURRENT DRUGS USED" + }, { + "system": "https://openconceptlab.org/orgs/CIEL/sources/CIEL", + "code": "1193", + "display": "CURRENT DRUGS USED" + } ], + "text": "CURRENT DRUGS USED" + }, + "subject": { + "reference": "Patient/3e990510-1d51-4a25-abd4-3885cf9e8be9", + "type": "Patient", + "display": "Musamia Musamia Musamia (OpenMRS ID: MK3JYU)" + }, + "encounter": { + "reference": "Encounter/54d2e662-0168-4546-9895-c1850b3e535d", + "type": "Encounter" + }, + "effectiveDateTime": "2023-05-18T00:00:00+03:00", + "issued": "2023-05-18T16:34:10.000+03:00", + "valueCodeableConcept": { + "coding": [ { + "code": "9fb85385-b4fb-468c-b7c1-22f75834b4b0", + "display": "Tenofovir / Lamivudine / Dolutegravir" + } ], + "text": "Tenofovir / Lamivudine / Dolutegravir" + } + }, + "request": { + "method": "POST", + "url": "Observation" + } + }, { + "resource": { + "resourceType": "Observation", + "id": "750babe9-f061-432e-b11b-6c14e702ebd4", + "meta": { + "lastUpdated": "2023-05-22T09:10:17.000+03:00" + }, + "status": "final", + "code": { + "coding": [ { + "code": "5096AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "display": "RETURN VISIT DATE" + }, { + "system": "https://openconceptlab.org/orgs/CIEL/sources/CIEL", + "code": "5096", + "display": "RETURN VISIT DATE" + } ], + "text": "RETURN VISIT DATE" + }, + "subject": { + "reference": "Patient/3e990510-1d51-4a25-abd4-3885cf9e8be9", + "type": "Patient", + "display": "Musamia Musamia Musamia (OpenMRS ID: MK3JYU)" + }, + "encounter": { + "reference": "Encounter/e3c73712-99ba-4380-97f6-78dc59c35044", + "type": "Encounter" + }, + "effectiveDateTime": "2023-05-18T12:33:08+03:00", + "issued": "2023-05-22T09:10:17.000+03:00", + "valueDateTime": "2023-05-31T00:00:00+03:00" + }, + "request": { + "method": "POST", + "url": "Observation" + } + }, { + "resource": { + "resourceType": "Observation", + "id": "67e881f8-212f-4332-b085-ceaa052b3b62", + "meta": { + "lastUpdated": "2023-05-31T08:37:59.000+03:00" + }, + "status": "final", + "code": { + "coding": [ { + "code": "5096AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "display": "RETURN VISIT DATE" + }, { + "system": "https://openconceptlab.org/orgs/CIEL/sources/CIEL", + "code": "5096", + "display": "RETURN VISIT DATE" + } ], + "text": "RETURN VISIT DATE" + }, + "subject": { + "reference": "Patient/3e990510-1d51-4a25-abd4-3885cf9e8be9", + "type": "Patient", + "display": "Musamia Musamia Musamia (OpenMRS ID: MK3JYU)" + }, + "encounter": { + "reference": "Encounter/b690a37c-bef9-49b9-99ad-a533f0775309", + "type": "Encounter" + }, + "effectiveDateTime": "2023-05-31T08:13:37+03:00", + "issued": "2023-05-31T08:37:59.000+03:00", + "valueDateTime": "2023-06-28T00:00:00+03:00" + }, + "request": { + "method": "POST", + "url": "Observation" + } + } ] +} \ No newline at end of file diff --git a/input/maps/test-data2.json b/input/maps/test-data2.json new file mode 100644 index 000000000..a79130926 --- /dev/null +++ b/input/maps/test-data2.json @@ -0,0 +1,155 @@ +{ + "resourceType": "Bundle", + "entry": [ + { + "resource": { + "resourceType": "Patient", + "id": "445beebb-e886-11ea-87c2-00155d017200", + "meta": { + "lastUpdated": "2020-08-27T19:56:35.000+03:00" + }, + "identifier": [ + { + "id": "4462a315-e886-11ea-87c2-00155d017200", + "extension": [ + { + "url": "http://fhir.openmrs.org/ext/patient/identifier#location", + "valueReference": { + "reference": "Location/f4934663-bf3a-4778-81b8-4c1e79398069", + "type": "Location", + "display": "Machakos Level 5 Hospital" + } + } + ], + "use": "official", + "type": { + "coding": [ + { + "code": "dfacd928-0370-4315-99d7-6ec1c9f7ae76" + } + ], + "text": "OpenMRS ID" + }, + "value": "MHECKF" + }, + { + "id": "c4c3233b-7dad-440f-8bab-a473d4abfb1a", + "use": "usual", + "type": { + "coding": [ + { + "code": "05ee9cf4-7242-4a17-b4d4-00f707265c8a" + } + ], + "text": "Unique Patient Number" + }, + "value": "1243898765" + } + ], + "active": true, + "name": [ + { + "id": "445bfd9c-e886-11ea-87c2-00155d017200", + "family": "MUNINI NJOROGE", + "given": [ + "MUNINI NJOROGE", + "MUNINI NJOROGE" + ] + } + ], + "gender": "female", + "birthDate": "2001-11-30", + "deceasedBoolean": false, + "address": [ + { + "id": "445c0ea0-e886-11ea-87c2-00155d017200", + "extension": [ + { + "url": "http://fhir.openmrs.org/ext/address", + "extension": [ + { + "url": "http://fhir.openmrs.org/ext/address#address1", + "valueString": "15034 address1" + }, + { + "url": "http://fhir.openmrs.org/ext/address#address2", + "valueString": "15034 address2" + }, + { + "url": "http://fhir.openmrs.org/ext/address#address4", + "valueString": "KITHIMANI" + } + ] + } + ], + "use": "home", + "district": "MACHAKOS", + "state": "YATTA" + } + ] + }, + "request": { + "method": "PUT", + "url": "Patient" + } + }, + { + "resource": { + "resourceType": "Observation", + "id": "fa1ea8e7-7d90-4a5b-a320-9ee61f7a6ad5", + "meta": { + "lastUpdated": "2023-08-01T12:04:19.000+03:00" + }, + "status": "final", + "code": { + "coding": [ + { + "code": "160540AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "display": "Method of enrollment" + }, + { + "system": "https://openconceptlab.org/orgs/CIEL/sources/CIEL", + "code": "160540", + "display": "Method of enrollment" + }, + { + "system": "http://loinc.org", + "code": "45252-4", + "display": "Method of enrollment" + } + ], + "text": "Method of enrollment" + }, + "subject": { + "reference": "Patient/445beebb-e886-11ea-87c2-00155d017200", + "type": "Patient", + "display": "MUNINI NJOROGE MUNINI NJOROGE MUNINI NJOROGE (OpenMRS ID: MHECKF)" + }, + "encounter": { + "reference": "Encounter/9be7ce16-1543-4e93-937e-469b657e6827", + "type": "Encounter" + }, + "effectiveDateTime": "2023-08-01T12:02:11+03:00", + "issued": "2023-08-01T12:04:19.000+03:00", + "valueCodeableConcept": { + "coding": [ + { + "code": "160539AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "display": "Voluntary counseling and testing program" + }, + { + "system": "https://openconceptlab.org/orgs/CIEL/sources/CIEL", + "code": "160539", + "display": "Voluntary counseling and testing program" + } + ], + "text": "Voluntary counseling and testing program" + } + }, + "request": { + "method": "POST", + "url": "Observation" + } + } + ] +} \ No newline at end of file