GSOC 2018 with OpenMRS and mUzima

og-image           logo-200             edited_muzima_logo

I’m really proud getting selected as a student for Google Summer of Code 2018. This is my second time got select GSoC with OpenMRS. This time I will work with both OpenMRS organization and mUzima organization. This will be a really impressive experience for me in my life.

My experience with OpenMRS was started at 2015, When I was beginning of my opensource software developer carrier path, I heard about OpenMRS organization from my brother. Since knowing about the organization, I started working with the community, When my first GSoC project discussion period at 2015, Sashrika gave a lot of motivations and guidelines to contribute to the organization. I would like to give my special thanks for “Sashrika Waidyarathna“, he is my turning point on the OpenMRS. Since starting my project at OpenMRS, Harsha Kumara helped me a lot to get through some difficult tasks. Thank you very much, Harsha!. Also, I like to thanks to Judy Gichoya, Suranga Kasthurirathne, and Daniel Kayiwa! and every other member of the organizations to success my previous GSoC project and other works!

At the beginning of the GSoC 2018 project, I have worked on both Apache and OpenMRS project to getting selected GSoC project. In the Apache organization, I have prepared my works on Tomcat project. It’s project about creating AJP client and Command line tool. I would like to thanks for having a nice interview with Mark Thomas. At the GSoC 2018 project discussion period I worked with “Merge Patient data from Multiple Installations” project. However, I think Samuel Male is the right person for that GSoC project. I would like to wish for him and other GSoC students!

Finally, I have selected “Patient Merge Enhancement” project. Thanks, very much Daniel FutermanSimon Savai, and Ada Yeung to getting selected me for this project. Thank you very much OpenMRS for selecting me as a student!.

Mapping ImagingStudy Resource Attributes to OpenMRS

We are currently developing Radiology Handler. By the time, we got into implementing ImagingStudy FHIR resource. It’s a FHIR resource which is referenced by DiragnosticReport FHIR resource. So, we had to came up with a mapping to store those data in a good way using OpenMRS API.

ImagingStudy (Obs) 0..*
  - Patient : Person
  - uid : uuid
  - accession : AccessionNumber
  - numberOfSeries : Get Size of Series of Obs
  - numberOfInstance : ? Answer to the concept
  - clinicalInformation : comment
  |
  |--> Series (Obs) 0..*
         - modality : ?
         - uid : uuid
         - numberOfInstances: ? Answer ot the concept
         - url : comment
          |
          |--> Instance (Obs) 0..*
                 - number : ?
                 - uid: uuid
                 - sopclass : ?
                 - type : ?
                 - title : ?
                 - content : Complex Obs

But Judy (my mentor) suggested following mapping.

ImagingStudy
Started – saved as a date time concept (162830)
Patient – Patient object in openmrs
Uid – is numeric for identifier for the study –ideally should be unique but not sure if this is the practical case
Accession – ID number saved as obs
Order – should be saved under the OrderObject in openmrs
ModalityList – Text object in obs
Referrer – obs free text
Availability – coded concept with options of ONLINE |OFFLINE|NEARLINE and UNAVAILABLE – really not important to save this
url – saved as text in obs
numberofseries – numeric obs saved
numberofinstances – numeric obs save
clinicalinformation – free text obs save
procedure – saved as obs
interpreter – free text obs
descrition – NO NEED TO SAVE THIS – but can be free text obs
series (these will be likely repeated as there can be more than one series --- so use the numberofseries to add these)- Each series should be an obs group .. then all above obs should be grouped together under a CONVENIENT SET
-       number :– obs  numeric
-       modality – Text obs
-       uid - Unique ID for series
-       description – obs text
-       numberofInstances – obs numeric
-       availability – No need to save this but t would be OBS
-       url – obs text
-       bodysite – obs
-       laterality – obs
-       dateTime – obs datetime
        -       instance   > obs for uid,sopclass,type,title,content

Also she suggested flowing work flow as well;

  1. Confirming that the schema of the report you receive is valid DSTU2 report
  2. Saving the data as a nested OBS using the relevant concept
  3. Suranga I know you never wanted anything to be input but don’t you think we should have had global properties that one can update the concept (saved as a convenient set ) they want to use for the data
  4. Thereafter we could check whats present in the DB and you can save it – Not sure how we delt with non existing concepts for importing lab

Enable log4j in OpenMRS

This is an issue that I faced during OpenMRS development. I used to print helpful output with

System.out.println("Hi, Milan Karunarathne");

But my mentor pointed out, that’s a bad practice and I have to use log4j instead. So, I read about log4j. It contains different level of logs which can enable according to necessity.

How do levels work ?

A log request of level p in a logger with level q is enabled if p >= q. This rule is at the heart of log4j. It assumes that levels are ordered. For the standard levels, we have ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF.

As an example, when we want to debug our code, we can set level into `DEBUG`. Then we can see all the logs such as FATAL, ERROR, WARN, INFO, DEBUG. When we want to host this in a server, we just only interesting about errors. So, we can set level into `ERROR`. Then we only get ERROR and FATAL. Hope, you got the point.

How to enable logs in OpenMRS ?

The configuration file for logs are kept in `/opt/apache-tomcat-7.0.59/webapps/openmrs/WEB-INF/classes/log4j.xml`. Also you can enable logs base on the package. E.g. if you want to enable logs for Java class which are located inside `org.openmrs.molude`, then add following entry to the above file.

<logger name="org.openmrs.module">
     <level value="DEBUG" />
</logger>

Get FHIR Resources by using HAPI FHIR Client II

As we discussed in previous week, we have to face with a new problem of retrieving data from a third party FHIR server due to incompatibility of server versions. So, at the end of the day, we planned to implementing a mock server.

I got a chance to discussed with Paul (co-founder of OpenMRS)  and Grahame about the issue. So, we came into a conclusion of using http://fhir-dev.healthintersections.com.au/open server, even it doesn’t have enough data. I found that there is another test server[1] which support DSTU2. But as you can see, it’s only contains one DiagnosticReport for `serviceCategory=RAD` (Radiology), it hasn’t any links to other FHIR `imagingStudy` resources like SIIM server.

Within that server, the `ImagingStudy` FHIR resources don’t have any useful content about Radiology data, only have some links to http://localhost/fhir/ . Need some real Radiology images like SIIM server PACS do.

Get FHIR Resources by using HAPI FHIR Client

I was able to get interact with HAPI FHIR client in order to fetch some FHIR DiagnosticReports from a remote third party server. We have came into a conclusion of using SIIM server while implementing the Radiology Report for demonstration purpose. After I sent request to that server, it response with;

<feed
 xmlns="http://www.w3.org/2005/Atom">
 <title type="text">Search on resources in collection 'DiagnosticReport'</title>
 <id>urn:uuid:2ae1a76c-abfe-4808-8e55-900e478c5540</id>
 <updated>2015-07-14T18:33:24.3398792Z</updated>
 <author>
 <name>Spark MatchBox Search Engine</name>
 </author>
 <totalResults
 xmlns="http://a9.com/-/spec/opensearch/1.1/">8
 </totalResults>

So, I reported about this in HAPI FHIR group, and that’s happened due to SIIM server is using DSTU1 version. The bundling format is differ between DSTU1 and DSTU2 version.

Then I tried to use DSTU1 client in order to make requests. But we can’t import only that dependency since HAPI FHIR is coming as a single jar file. Another option will be using Apache HTTP client library to get data. But it’ll not be a vise decision since we are putting our effort into just for a demonstration.

Thus we came up with an idea to implement a demo server.

The Workflow of the Radiology Handler

Before we are going to implement Radiology Handler, first we had to define the workflow of the Radiology Handler. After I discussed with my mentor, I came up with following workflow as a initial point to address that issue.

  • call to “GetRadiologyReport(String name){
    • make a call to http://fhir.hackathon.siim.org/fhir/DiagnosticReport?subject=Patient/{name} <– this url should be a constant for this handler
    • get back a bundle of diagnostic reports
    • get this diagnostic report metadata, and store it as an encounter / obs (one encounter per each diagnostic report)
    • Note that the imaging study attribute contains a link on how to access the DICOM image. this link should be stored as an obs What is returned to the user is basically the bundle of diagnostic reports that the server sent us.
    • What we’re doing is getting the data from a third party server, storing metadata in OpenMRS and passing on the bundle to the requester.
  • }

So, how does a user view the actual DICOM image based on the metadata that was stored?

We write a separate handler that is supposed to be added to the Obs handlers. What it will do is get the link to access from the obs value, make a call for the DICOM image, and display it to the user.