Currently we can define ranges for concepts in OpenMRS. There are normal ranges and permissible ranges.
But there can only be one of these range per concept.
Quite often a lot of medical concepts have normal ranges according to age and gender. Thus it would be good to have the ability to define multiple ranges on the basis of age and gender. We wanted to know if OpenMRS supports this and if any implementations are using dynamic ranges like this.
We can come up with a list of possible scenarios to explain this requirement further. Also, we are looking to develop this.
Please let us know if any further information is needed on the same.
On the endTB Bahmni project we need to define different normal ranges for concepts depending on age and gender. (There shouldnât be anything endTB-specific about the feature request though.)
The OpenMRS API doesnât support this today, so weâd like to add it. How do people suggest we implement this, such that it can be most cleanly merged into openmrs-core when itâs done?
(Or, has someone already implemented this in a module somewhere?)
@akanter, @burke, @jteich, your advice for how this is typically modeled is most welcome!
Mmm. This is an interesting topic. I have always been of mixed mind when it comes to the normal ranges on the concepts. I typically do not populate them unless they are obvious. I think we have to recognize that concepts might have different states based on their purpose or use case. The same concept could have a different normal range based on age or gender, but also perhaps as to HOW it is being used. We know that a given lab test might have different ranges based on the machine, even if it has the same LOINC code. I really donât want to go down the road of having to create gender-specific concepts or perhaps versions of concepts for each particular use case. It is bad enough that I think we need to do that for aggregations (value sets/groupers). I donât know if anyone has done this right yet. I wonder whether meta data like normal ranges should really be split out entirely from the concept and be mapped based on other meta data (age, gender, purpose). That would be entirely extensible.
Rather than trying to model all the possible reference ranges for each concept, I would suggest the following approach:
Continue to include reference ranges that are globally applicable at the concept level as @akanter has been doing.
Add obs_reference_range (low, high, meaning, age, & text linked 1-to-many to obs) to align with FHIR.
Our default HL7 processor could be adapted to recognize and store reference ranges when reported with results. Other tools (like Chart Search & reporting) could then grow to include reference ranges (if present) when showing results.
@burke, so if Iâm understanding you correctly youâre suggesting that the changes to OpenMRS Core are:
create an obs_reference_range table
FK to obs, and has columns like from FHIR: low, high, meaning, age, text
can have many of these for one obs.
no changes to obs table
add Obs.getReferenceRanges (returns List)
Then within Bahmni weâd be responsible for:
defining our own tables to store guidelines for range definitions by age, sex, etc
either put this in a bahmni_concept_reference_ranges or maybe implement concept_attributes for this
within the form entry technology +/- application UI weâd need to
(a) recognize when a user is entering an obs that matches a known range definition, and give them visual feedback
(b) include this in the submission to the API call
Further, every numeric obs we save for which ranges are defined would lead to 3 rows in obs_reference_range (if we defined abnormal, critical, and absolute).
Iâm not completely sold that this is the right approachâŠ
(One minor variation would be have a reference_range_definition table and then an obs_reference_range_map table, to make this a many to many relationship. But I donât know if thatâs better.)
While FHIR does support many-to-one ranges per observation, most labs will report a single reference range (the ânormalâ range) ± additional text with the result. Labs donât typically report critical or absolute ranges with the results.
This leads to something I left out: the interpretation (aka abnormal flag):
add interpretation column to the obs table. This would either store the codes in HL7 Table 0078 or be a FK to concept (FK may be overkill).
Since the determination of the abnormal flag and appropriate reference range is the responsibility of the party generating the result, any application generating lab results (including Bahmni) would be responsible for deciding if the lab being reported should be flagged as abnormal or include a reference range. We would continue to have canonical reference ranges (normal, critical, and absolute) in the concept dictionary.
Every numeric obs could include an abnormal flag and a normal range ± any range-specific information. In most cases, this is a single normal range (low & high) and, for abnormal results, an abnormal flag. Some labs include canned text like:
Normal <0.05 ng/mL
Intermediate Risk 0.05-0.09 ng/mL
High Risk >=0.10 ng/mL
95% Sensitivity and Specificity for MI: >0.6 ng/mL
This is how everyone else is handling ranges (i.e., itâs up to the system reporting the result to report abnormal flag and reference range)
When you inevitably start needing to accept results from other systems, you can still properly report abnormal flags and reference ranges.
Lab machines often report results with abnormal flag and reference range.
Reference ranges can vary by machine used and vary over time, so trying to manage them in the dictionary can get even uglier than managing at the point of result generation.
While we could approach these as extensions of concepts, I think it helps to take this approach:
A concept reference range is a canonical reference range â i.e., absolute ranges ± normal or critical ranges independent of context or method.
Context-specific reference ranges belong not to the concept, but to the filler â i.e., the system or tool generating the result.
So, while storing context-specific reference ranges metadata alongside our concepts may help provide a central source for various data input methods to use, the important thing is that the data entry tools can get to these metadata (not that theyâre part of the dictionary).
This extra context is very helpful. So taking a step back, there are two things going on:
(1) OpenMRS Core should support flagging obs as abnormal
We agree 100%.
Bahmni already has a workaround for this: we store lab results in an obs group with a boolean obs for normal/abnormal, and numeric obs for min and max range. (In fact these are our 3 most-used concepts.)
We would welcome native support for this in openmrs-core, via some mechanism like interpretation and range. This seems like a good GSoC project, or maybe a good independent project for a team doing hack nights.
But this is actually what we meant for the point of this thread to be.
(2) Help us define a common approach for storing multiple reference ranges in an OpenMRS system
Our endTB implementation wants to define project-wide reference ranges that differ by age and gender. We think that a (maybe simplistic) 80% solution to this problem would be valuable for other implementations too.
Can we define a common approach for storing reference ranges by age, gender, and a couple more common criteria (but without solving the fully general case)? Maybe weâd put the data model for this in a âSimple Reference Rangesâ module.
Agree to what Burke said. Should we introduce additional column âobs.interpretationâ. I am guessing the column datatype would be VARCHAR. Should OpenMRS do anything in terms of only allowed values from HL7 0078 valueset table or should it just leave it to the implementers?
Q: When (OpenMRS version) can we introduce this?
Starting OpenMRS 2.0, we have concept attributes. How about introducing a âreference rangeâ attribute type, which just defines the contextual ranges (gender, age).
Alternate would be to have a different model to do this (separate tables, but linked with a concept)
(1)
I think it makes sense to add an optional varchar obs.interpretation column. I donât think we should limit it to any particular valueset in the underlying API, though we should recommend that people use the FHIR valueset that @angshuonline links to (and in Bahmni weâd standardize on this).
Weâd do this in the next minor OpenMRS Platform release, i.e. Platform 2.1. (If itâs especially important to Bahmni to get this released sooner than currently scheduled, this could be a chance to develop a process to empower a motivated community member do a non-LTS release, and pushing the next scheduled-and-supported release to be Platform 2.2.)
(2)
It would be fine for our Bahmni use case if we use concept attributes for this in our Bahmni use case (rather than introducing a new module/table). However this would conflict with our intended future push for people to use CIEL concepts
Do we still care about (2), since this is no longer prioritized for endTB?
Perhaps instead we should think about adding obs.referenceRange, which is what FHIR does, for some future use case?
Executive summary: Bahmni will prioritize adding this; someone like AMPATH needs to ensure that MySQLâs online DDL is sufficient to add these columns while the system is online.
Bumping this up for attention. The ranges topic and requirements are coming up from many prospects.
Can we get to some sort of agreement for possible modelling for ref ranges for age & gender?
One thought I had was, how about just a simple reference model (can be a csv or table - external to core openmrs, but invoke-able from openmrs core) ?
@angshuonline, my takeaway from this thread is that OpenMRS for doesnât want to model these reference ranges.
So we should propose some approach for this in a module, and hopefully the next interested person will follow our lead.
A csv seems sensible and an easy way for implementers to maintain/enter the data. And I would lean towards a simple new DB table, rather than concept attributes.
Are you expecting openmrs-core to consume this data and use it for something?
I assume weâd want to use it from some Bahmni display controls, but that OpenMRS core doesnât need to know.
to be able to display at patient level in UI - this is easy by fetching some reference range from CSV and using attributes for a concept, we can even figure out which CSV to fetch. Although, I would preferred that fetching a concept gives me details or a link that provides me HATEOAS way of leading me to the reference ranges. That was the question/query of whether we want to extend the openmrs to support the extensibility.
To be able to raise flags against a patient while saving/capturing data - this is also, where I can having the concept model extendable will help for validating results and raising appropriate flags/alerts.
Of course, in Bahmni we can always use concept attribute and/or configuration to extend the above features.
How would concept_attribute work in this case? Would you have to have an attribute called âNORMAL_RANGE_MALE_LOWâ and the value of the attribute be the lower bound? And then another for each low, high and stratification?
Thats not really the option I had in mind, as this will mean
We need to come up with convention of naming the attribute, and Bahmni will have to interpret the naming convention.
At a given point of time support only known attributes.
None of the above are extensible. Ranges or their references are more complex.
Again, not disregarding the above approach for simpler things.
What I meant, was using concept attribute to specify where the references ranges can be found.
imagine a âHEIGHTâ concept having an attribute âreference ranges chartâ, like here
Whether to use the references range chart, is decided by an extension (example: a display control, or other script) - which takes into consideration of the patientâs age & gender and shows (or even updates) information.
So I guess what youâre suggesting is that the OpenMRS platform should know how to interpret certain kinds of reference range documents, with certain known types of patient constraints (gender, age in years)?
The growth chart example would be one, and I can imagine another thatâs equivalent except that the column headings are hiAbsolute, hiCritical, hiNormal, lowAbsolute, lowCritical, lowNormal.
@akanter, @burke, @jteich, @terry is there any standard representation of this, or precedent for it in other EHR systems?
(Burke I can see that we wouldnât want to build specific attributes into openmrs-core, but we could build it into some other platform module so that when you fetch a concept via REST you have some nice semantic access to this reference range data if itâs provided in a concept attribute. Or alternately we could have a built-in CustomDatatype for this in openmrs-core which webservices.rest would know how to represent.)
The most common approach Iâve seen is to leave these context-specific ranges within the purview of the lab performing the test â i.e., focus on reporting abnormal & ranges with results and leave the data entry validation to the lab.
In OpenMRS, this would mean adding interpretation (abnormal flag) and a mechanism for reporting reference range to obs. If/when input validation for context-specific ranges was needed, it would either be performed in a lab module or in an integrated lab information system.
Iâm not aware of a standard way that EHRs do this. In some cases LOINC sets up a different code for a different reference range (e.g., creatinine results in African-American and non-African-American patients), but I suspect thatâs way too complicated and creates as many problems as it solves.
Iâd go with something similar to the most recent few suggestions above:
Provide a field for text description of the more complex range instructions (âabnormal = this for males, = that for femalesâ, etc.) - useful whether or not we also do the following structured part
For structured flagging of abnormals, modify the reference range parameter so that it can be fixed (same low, hi, very low, very hi for all groups) or complex/parametric
Define the parametric reference ranges in a separate, fairly simple structure, where each subgroup would be defined by parameter type (Age Range, gender, ethnicity, etc.), parameter value 1 and value 2 (e.g., low and high age values; or for a gender parameter just one value is used to specify Male or Female), and the various reference range boundary values that are already in use for the fixed case
â I suppose that âvalue 1â and âvalue 2â also have to have typing, as they could be numbers or enums