Integration of OpenMRS with OpenEMPI Module

Overview

There are various healthcare organizations around the globe which would require to use OpenMRS to maintain their patient records.The same patient visits different organizations(assuming all organizations have OpenMRS installed to maintain their practice details),and at each organization he/she may be added as a new patient.The objective of the OpenEMPI service is to create a single reference for a patient and demographic data across multiple systems.This would improve the quality of care provided to patients, and these different health care systems must be integrated and share patient data, to providing a comprehensive view of a patient's health care history across the group of collaborating providers.

OpenEMPI, once integrated as the EMPI for the federation of OpenMRS instances, will maintain a central registry of the unique patients that have attended any of the health care sites that utilize one of the OpenMRS instances from the federation. In addition to serving the role of an EMPI in the federation, OpenEMPI will be enhanced to serve the role of a Record Locator Service (RLS) for the federation6. The RLS maintains an index of pointers to the network location of patient information, but not the personal health information itself.An "Enterprise Master Person Index" (EMPI) or an "Entity Identification System" (EIS) is used to provide identity management services, including identification of duplicate patients within a single system, identification of the same patient across multiple systems, and automated linkage of new inbound clinical data to existing results

Some of the features that will be added as part of this project/module are::

  • A GUI for the registration of an OpenMRS instance with OpenEMPI.

  • A GUI to query and retrive patient demographics from OpenEMPI's central registry.

  • An adaptor is used to notify the OpenEMPI system about any add/update/delete events at the OpenMRS.

Requirements

The target of this project is to explore the integration of the open source EMPI (OpenEMPI) with OpenMRS. The following are the list of deliverables that i want to complete.

Phase 1

The interaction between the OpenMRS and OpenEMPI will take place through an adaptor which is a background service and does the following things:

a) Registration of an OpenMRS instance with OpenEMPI.

b) Add a Patient
When a patient gets added into an OpenMRS instance, the adaptor would submit patient demographics to PersonManagerService.

c) Update/Modify a Patient
When a patient gets updated into an OpenMRS instance, the adaptor would update patient demographics using PersonManagerService.

d) Delete a Patient
When a patient gets deleted from an OpenMRS instance, the adaptor would provide the patient local identifier to PersonManagerService.

e) To create a Timer Service which would take care of patient details when a patient is added in OpenMRS, Adaptor service is triggered, if there is a connection error or an application error at OpenEMPI site, there is a possibility that the patient data will be lost at OpenEMPI site(as the patient would not have been successfully added).

Phase 2
a) Revised Registration of an OpenMRS instance with OpenEMPI: Here the OpenMRS instance information like Organization's name and address are provided during registration.

b) Bulk export of patient details from OpenMRS to OpenEMPI when the OpenMRS instance registers with OpenEMPI.

c) *Look Up:*To query and retrieve patient demographics from OpenEMPI's central registry using PersonQueryService.

Design Notes

Registration of OpenMRS site with OpenEMPI (joining the federation of sites)

When a new OpenMRS site needs to join the federation of sites that share patient registration information, it needs to establish a unique site identifier. Following the
PIX (Patient Identifier Cross Referencing) model for cross-referencing of patient identifiers
across multiple patient identifier domains, each OpenMRS instance in the federation is considered to be a separate patient identifier domain.

PIX uses the HL7 assigning authority components to represent the patient identifier domain information. The three components are the namespace identifier, universal identifier, and universal identifier type code (see the specification for more details). Using this model, the domain identifier is uniquely identified either by the namespace ID or by the combination of universal identifier and universal identifier type code. Following this approach, each OpenMRS site that needs to register with OpenEMPI needs to obtain a unique identifier domain. The site will first need to obtain a list of known identifier domains by the OpenEMPI instance, select the universal identifier type code that corresponds to an OpenMRS identifier domain and then use that universal identifier type code to retrieve a unique identifier domain that it will need to store in persistent storage. This information will be needed any time patient information is added or updated from the OpenMRS site.


The sequence diagram above illustrates the interaction between an OpenMRS instance and OpenEMPI during the registration process.

Sequence diagrams for Integration of OpenMRS with OpenEMPI

Join Federation:

*1.*When OpenMRS instance wants to join the OpenEMPI federation, the request is sent to the Adaptor Service.

*2.*The service checks whether it is already a registered member. If yes, an error is thrown.

*3.*If no, then the context object is set up to obtain the reference of service at the OpenEMPI.

*4.*The Adaptor Service requests Identifier Domain Service to get the list of Identifier Domains.

*5.*The admin selects the Identifier Domain from the list, corresponding universalIdentifierTypeCode is send to IdentifierDomainService.

*6.*Identifier Domain object is created.

*7,8.*universalIdentifierId and universalIdentifierTypeCode is set on the Identifier domain object.

*9.*Identifier Domain object is added into OpenEMPI.

*10.*Identifier Domain Service sends an acknowledgement to the Adaptor Service after adding the Identifier Domain Object successfully.

*11.*After receiving the acknowledgment, the Adaptor service sets the global property.

*12.*After successful registration the option to import existing patients is enabled.

*13.*Send the patient data to the adaptor service. Which method on OpenEMPI side facilitates bulk import? Patient data should send in which format?

Odyseas We need to investigate step 13 a bit further. The concern I have regarding this operation is that we need to be careful in the design to make sure that we can handle cases where a particular OpenMRS site has lots of patients. To do the bulk upload to OpenEMPI, OpenMRS first needs to export all the patients (maybe into a file) and then we need to do an import of that groups of patients into OpenEMPI. OpenEMPI has an import operation for a single person record but that would be slow for large files (doing it over the network, record by record). It also has a file loader but it is not currently accessible remotely. We need to design a remotely accessible bulk import functionality that is web accessible.

Leave Federation:

*1.*When OpenMRS instance wants to leave the federation, it sends the request to Adaptor Service.

*2.*Adaptor Service checks whether the instance is a registered member or not(i.e, in the global properties).

*3.*Then the context object is set up to obtain the reference of service at the OpenEMPI.

*4.*Which method should it invoke to leave the federation?

Odysseas: Regarding item 4, this is primarily an OpenMRS issue. When an OpenMRS instance leaves the federation, you simply remove the registration information from the local OpenMRS site and you are done. We need to decide what to do regarding the patient data that is sitting at the OpenEMPI site from the OpenMRS site that left the federation. Do we delete the data or leave it there. Either way the OpenMRS instance identifier (the universal identifier that was assigned to the site) will remain on the OpenEMPI site permanently since it has been assigned.

Odysseas: This last comment brings up another question. Lets say that now the OpenMRS site attempts to reconnect to the OpenEMPI federation. Do we have a mechanism to recognize that this OpenMRS site used to be a member of the federation and to reassign it the same universal identifier? If there is a unique id from the OpenMRS site (like a UID) that we can associate with site and we can store this information along with the Universal identifier then we can always restore this association. This gets us more into the Record Locator Service functionality.

Add Patient:

*1.*When any patient is added at the OpenMRS instance the request is sent to Adaptor Service (AOP).

*2.*Adaptor Service checks whether OpenMRS instance is already a registered member or not (i.e in the global properties).

*3.*The context object is set up to obtain the reference of service at the OpenEMPI.

*4,5.*The Adaptor Service invokes authenticate method which returns a session key to the Adaptor Service.

*6.*The Adaptor Service maps the patient details of OpenMRS to OpenEMPI person object.

*7.*Adaptor Service invokes addPerson to add a patient to OpenEMPI.

OdysseasCan you now add some information here about the data exchanged between OpenMRS and OpenEMPI. You need to expand step 6 and explain how an OpenMRS person/patient record maps into the OpenEMPI person record. You will need to figure out how do we translate encoded fields during the mapping such as ethnic group, race, gender, religion, language, etc. We could keep the set of fields exchanged minimal at the beginning and expand it over time to accommodate more fields later one once everything is up and running.

Update Patient

1. When any patient is updated at the OpenMRS instance the request is sent to Adaptor Service (AOP).

2. Adaptor Service checks whether OpenMRS instance is already a registered member or not (i.e in the global properties).

3. The context object is set up to obtain the reference of service at the OpenEMPI.

4,5. The Adaptor Service invokes authenticate method which returns a session key to the Adaptor Service.

6. The Adaptor Service maps the patient details of OpenMRS to OpenEMPI person object.

7. Adaptor Service invokes updatePerson to update the patient to OpenEMPI.

Delete Patient


1. When any patient is deleted at the OpenMRS instance the request is sent to Adaptor Service (AOP).

2. Adaptor Service checks whether OpenMRS instance is already a registered member or not (i.e in the global properties).

3. The context object is set up to obtain the reference of service at the OpenEMPI.

4,5. The Adaptor Service invokes authenticate method which returns a session key to the Adaptor Service.

6. Adaptor Service invokes deletePerson to delete the patient to OpenEMPI.

Look Up Patient


1. When OpenMRS instance wants to perform look up on patients, it sends the request to Adaptor Service.

*2.*Adaptor Service checks whether OpenMRS instance is already a registered member or not (i.e in the global properties).

*3.*The context object is set up to obtain the reference of service at the OpenEMPI.

*4,5.*The Adaptor Service invokes authenticate method which returns a session key to the Adaptor Service.

*6.*Adaptor Service invokes findPersonsByAttributes()for patient look up to OpenEMPI.

Doubts

1) Patient mapping:

*a)*In OpenMRS we have different patient_Identifier_Type like: OpenMRS Identification number, Old Identification number,SSN, Driving license etc and each of the identifier value is of alphanumeric type.

*b)*These patient_idetifier_type and patient_identifier would be mapped to PersonIdentifier Object, where

String identifier----->* String patient_identifier_type

Integer identifier--->* String patient_identifier(alphanumeric type)

So please let us know how to map between these two.

Odysseas: The identifier that we are primarily interested in is the OpenMRS Identification number. There is a more detailed discussion of how this identifier is mapped to the OpenEMPI person identifier in the section that discusses the assignment of a universal identifier to a new OpenMRS site that joins the federation of sites.

Odysseas: The Old Identification number can be safely ignored and not be transferred to OpenEMPI. For the SSN and driver's license number, OpenEMPI will be pre-loaded with standard values for these two identifier domains (actually there is going to be one identifier domain for SSN and 50 for each of the states that issue drivers license numbers). The new method that returns all known identifier domains in OpenEMPI will be used by the OpenMRS site, which will then have to select the appropriate identifier domain corresponding to the identifier that is being mapped.

2) Error handling

Since adaptor service is a background process, when a patient is added in OpenMRS and the adaptor service is triggered, if there is a connection error , application error at the OpenEMPI what should the adaptor service do in those conditions. What would happen to the patient data?? (since the patient wont be added at the OpenEMPI)Also how should I handle other error like data not valid at OpenEMPI side etc. Please let us know about it.

*3)*There are about 7 attribute types in OpenMRS() like String, Date, Boolean, Integer etc. We can map these types to the fields in OpenMRS. But later if any new actor(admin,module,etc) adds attributes dynamically to OpenMRS, how would we map them to OpenEMPI.

Odysseas: These are interesting issues that are coming up now during the more detailed design of the integration process. We may need to design a table or other mechanism that stores these tasks (add new patient, update patient) as a work list and then the worklist is processed as the connection between OpenMRS and OpenEMPI becomes available. You can think of the table of tasks as a queue of work requests that are not removed from the table until the work is done.

Odysseas: Lets investigate issue 3 further. I need to spend some more time into this. We can leave it as work to be done for now.

4) Problem Scenario:

i) When a patient is added in OpenMRS, Adaptor service is triggered, if there is a connection error or an application error at OpenEMPI site, there is a possibility that the patient data will be lost at OpenEMPI site(as the patient would not have been successfully added).

Solution is:

  • To create a Timer service, this will be running say every 15 minutes.

  • To create a database table at OpenMRS which would store the patientId of the patient that was not successfully added to OpenEMPI and transactionType (i.e. the name of the method it was trying to execute when the error occurred viz add/update/delete).

  • So the timer service will eventually take the patientId and get the details of the patient from OpenMRS and invoke my service which would depending on the transactionType invoke the corresponding methods at OpenEMPI site.

ii) A patient has been added to the OpenMRS site, Adaptor service got triggered, but it could not successfully add the patient to OpenEMPI say the server was down. So now the patientId is stored in a database table at OpenMRS site waiting for the timer service to come and pick it up. Now before the timer service gets the chance to add that person to OpenEMPI, the OpenEMPIserver is up and that person was updated at OpenMRS and this would trigger my service, which would try to update that patient at OpenEMPI. This would cause a problem as we would be trying to update a non-existent patient at the OpenEMPI site.

Solution is:

  • To avoid the above problem when update is being performed, it would check to see if the same patientId exists in the database table.

  • If it exists then it checks for the transactionType. If it is add then this transaction is queued in then table.

  • Odysseas: My recommendation is that when an event is triggered, such as a patient add, patient update, patient remove, the module should always simply generate a request and add it to the queue but not attempt to process the request on the OpenEMPI side synchronously. When the timer mechanism comes up, it processes the queue, sorting the work requests using the date of creation in ascending order. This will resolve the problem of the add operation been queued and not being processed on the OpenEMPI side before the update request arrives. The timer could be setup to run every minute or so and most of the time the queue will be empty (just a guess; it depends of course on the arrival rate of the queue) Let me know your thoughts.

iii) How should I handle other errors like data not valid at OpenEMPI side.

Odysseas: We need to process the error conditions based on the exception generated. The OpenEMPI API currently throws an ApplicationException if you attempt to add a new patient and the patient already exists in the system or if you attempt to do an update and the patient doesn't yet exist. For these kinds of errors you need to catch them and decide how you would like to handle them in your integration logic. For example if you attempt to do an update and the patient cannot be found on the OpenEMPI side then you may want to attempt an add operation (somehow the add was lost; depending on how we decide to resolve issue ii this may or may not happen). If on the other hand you get a RuntimeException that means that the OpenEMPI server is down or is having a system problem. In these cases the request should be kept in the queue and should be attempted at a later point. We may want to add a retry count to the request queue table to keep track of how many times we attempted to process a request and then give up after a certain number of unsuccessful requests. This parameter could be configurable at the module level.

Resources

Project Documents

  • [ Deployment Scenario|http://openmrs.org/images/c/cf/Deployment_senario.pdf]

Project Plan

For Mid-term Evalution:

a) Registration of an OpenMRS instance with OpenEMPI.

b) Add a Patient
When a patient gets added into an OpenMRS instance, the Adaptor Service would submit patient demographics to PersonManagerService.

c) Update/Modify a Patient
When a patient gets updated into an OpenMRS instance, the Adaptor Service would update patient demographics using PersonManagerService.

d) Delete a Patient
When a patient gets deleted from an OpenMRS instance, the Adaptor Service would provide the patient local identifier to PersonManagerService.

e) To create a Timer Service which would take care of patient details when a patient is added in OpenMRS, Adaptor Service is triggered, if there is a connection error or an application error at OpenEMPI site, there is a possibility that the patient data will be lost at OpenEMPI site(as the patient would not have been successfully added).

For Final Evalution:

a) Revised Registration of an OpenMRS instance with OpenEMPI: Here the OpenMRS instance information like Organization's name and address are provided during registration.

b) Bulk export of patient details from OpenMRS to OpenEMPI when the OpenMRS instance registers with OpenEMPI.

c) *Look Up:*To query and retrieve patient demographics from OpenEMPI's central registry using PersonQueryService.

Developers

TBD