Wiki Spaces
Documentation
Projects
Resources
Get Help from Others
Q&A: Ask OpenMRS
Discussion: OpenMRS Talk
Real-Time: IRC Chat | Slack
Primary mentor |
|
Backup mentor |
|
Assigned to |
Most of the data collected by OpenMRS is stored as patient-specific observations (e.g., weight, pulse, serum potassium level, their answer to "How many children live in your home?", etc.). OpenMRS has a finite list of data types for observables:
We have long wanted a way to include coded observables for users, patients, locations, and other OpenMRS domain objects; however, we do not want to add attributes to our obs table for every domain object. For example, adding attributes for value_location
, value_person
, etc. would allow us to store references to these other domain objects within observations, but would grow our obs table wider & wider. Also, making changes to the obs table are expensive – e.g., the AMPATH system in Kenya contains nearly 100 million observations, so adding a lot of columns to the obs table is not desirable.
The goal of this project is to provide a mechanism for supporting observations that point to domain objects like persons or locations. There are several
TBD
obs
table.
obs
table: value_code_system
, making the source of value_coded
vary depending on the code system (concept dictionary vs. locations vs. something else).
value_complex
, might end up coding against complex obs handlers within coreAfter Initial discussions regarding design requirements we have decided to drop design idea number two in favor of three. (See above)
The reason behind this decision is the recent dialogue regarding the need to,
For an idea on Complex Obs handlers, see here
The aim of moving towards the handler approach is as follows,
Therefore we need to develop the existing UI to support data types such as Person, location etc.
This will require some reworking of the existing UI and controllers.
Test and finalize a good interface hierarchy for handlers, one which will support the existing system while providing above mentioned functionality.
TO DO // Needs further clarification on-
Research to identify the best solution for managing custom data types, given the already existing means used in OpenMRS
enhancements to the interface -- e.g., to answer questions like "what are the valid choices" or "what are the valid choices given this search string" or "how should this data type be rendered in the user interface"
Automating registration of handlers as opposed to the manual entry of a Spring Key.
I will follow this technical design with the main objective of changing as little of the existing code as possible.
Step one :
Creating new Handler classes for Domain Objects.
Existing handler classes store / retrieve complex data from an external file system. (See Text and ImageHandlers) these handlers perform file I/O operations.
On the other hand the implementation of handlers for domain objects will be much more different.
These will record data in the Obs table itself.
Example: the saveObs(obs) method of PatientHandler will look as follows,
@Override
public Obs saveObs(Obs obs) throws APIException {
Object data = obs.getComplexData().getData();
//No File I/O operations necessary for this handler
// Set the required value to be stored in the database column
obs.setValueComplex(data.toString());
// Remove the ComlexData from the Obs
obs.setComplexData(null);
return obs;
}
A value similar to PatientHandler|PatientId:1 will initially be stored in the database.
The getObs(obs, view) method will retrieve this value and use it to return a patient object where patient Id equals 1.
Creating a Concept of Type ‘Patient’.
There will be no changes to the ‘Creating new Concept’ page initially.
Therefore creating a concept of type Patient is similar to the existing process to create other complex concepts.
Go to the UI screen, Select concept datatype = Complex and then select the ’PatientHandler’ displayed in the drop down list displayed below.
Design modifications to the Observation page
Initially, all complex concepts were based on uploading complex files into the file system (and their subsequent retrieval). However this changed drastically with the new requirements to store / retrieve domain objects.
In the design of the existing ObsForm.jsp page, javascript identified the data type of the concept selected by the user, and then displays one of eight input options (each contained within a <tr> row) for him to input data values.
For example, a Boolean concept will prompt the page to display ‘valueBooleanRow’ etc. etc.
However in the case of a complex concept, the page needs to be modified to display one of two different <tr>s based on whether the concept handler is a text or image hander(thus needing to upload external files) or an PatientHandler(needing to select existing domain objects)
To this end,
1. In the obsForm.jsp, create two table rows, one for the existing data upload facility, the second for object selection using an auto complete box.
2. Display the appropriate <tr> accordingly.
Design Issue:
A minor complication here is that the custom <openmrs_tag:conceptField> used to retrieve concepts does not downcast concepts to ConceptComplex. This means a concept is only aware of its data type, such as (in the case of a complex concept)
tmpConcept.hl7Abbreviation = ‘ED’
Thus the concept is not aware of what its handler value is.
This led to problems, since I do not wish to alter the existing and widely used <openmrs_tag:conceptField> tag class to meet my requirements. Also given that casting would not achieve my desired result, I decided on the following method,
In the JavaScript of the ObsForm.jsp page,
else if (datatype == 'ED') {
DWRConceptService.getConceptComplex(tmpConcept.conceptId,checkHandler);
{color:#3366ff}}
As you can see, if datatype == 'ED', I call the DWRConceptService to retrieve a ConceptComplex object, access its handler string and use that to decide on which option to select.
To provide an auto complete box to search for Patient objects, I have decided to use the existing <openmrs:fieldGen> tag class.
This would work for the initial stage, which is to implement a working handler for a single Domain Object.
If I am unable to expand this tag to support multiple domain objects (in the event of further expansion to admit other domain data types) then I will consider the option of creating a similar tag with my own custom implementation.
Implement ability to store complex Obs of a single domain object type (etc. patients)
i. Consider possibility of a generic auto complete box which supports all domain object types
ii. Consider possibility to create a custom tag class which supports all domain objects, in order to carry out the above step more efficiently.
Timeline
May 23 - May 25 |
Steps 1.a and 1.b |
May 26 - May 30 |
Step 2.a |
May 31 – June 5 |
Step 2.b |
June 6 – June 15 |
Step 2.c |
June 16 – July 15 |
Step 3.a |
1. Made alterations to PatientHandler class so that the displayable version of 'valueComplex' for Patients follows the format 'firstName middleName familyName (id) | patient id' -- e.g., "Bob Smith (123-0)|4"
This change will provide a more detailed description when displaying multiple observations.
Example : See the Obs search option found on the 'Find /Edit Observation(s)' widget in the Observation management page.
2 Comments
Nyoman Ribeka
Some notes from the call: http://notes.openmrs.org/design-call-05-04-2011
Burke Mamlin
Take a look at user-d1d98 and Darius Jazayeri to discuss relationship of this project with person attribute types & visit attribute types (perhaps on a design call).
and and consider meeting with