Relationship Between Concepts and Observations

Observations vs. Concepts

An observation is any clinical measurement acquired and observable in a clinical setting. If you use your imagination, just about anything can be an observation. For example, a hemoglobin test, a patient's weight, an answer to a question, or a physical exam finding. In short, any piece of data collected in a clinical setting (a patient's demographic information being a notable exception) is considered to be an observation. Note that if a clinician decides to order a hemoglobin, the order itself isn't observational: this is a clinician action, not something measured or acquired directly from the patient. More information on observations can be found elsewhere on the wiki.

concept is a means of describing observational information within our system.  Inherent within the data model is a collection of definitions for any concept that's collected within the repository: the concept dictionary.  The concept dictionary defines the name, code, and appropriate attributes for any observations or data collected (including medical tests, drugs, results, symptoms and conditions).  Nearly every medical concept used is defined within the dictionary, which is done in lieu of hard-coding concepts into tables.  More information on concepts and the concept dictionary is available elsewhere on the wiki.

Options for Storing Observations

For example, consider the following format of data:

Date

Patient

Sodium

Creatinine

Date

Patient

Sodium

Creatinine

Monday

Smith

 

1.5

Wednesday

Jones

142

0.7

This is easy to understand, but what happens when you decide to store glucose levels? You must change the structure of your table. And – heaven forbid – what if the lab starts reporting creatinines with a new reference range? Do you throw the new creatinine values in the same column and worry about it later? Or do you end up a second creatinine column for the new values?  Now consider the same data in the following format:

Date

Patient

Observation

Value

Date

Patient

Observation

Value

Monday

Smith

Creatinine

1.5

Wednesday

Jones

Sodium

142

Wednesday

Jones

Creatinine

0.7

Now there is one row per value instead of one per patient. Rather than being text, the various observations are actually referenced from a central concept dictionary. If the lab starts reporting a new type of creatinine, you no longer have to change the structure of the table. You simple add a concept for the new creatinine into your concept dictionary and you are done.

Observations in OpenMRS

Let's look at this portion of the OpenMRS data model, or the obs table:


Each observation noted during a clinical evaluation is stored as a row within this table. The obs_id is the unique identifier of the table, and should be a simple autonumbered field. Many of the subsequent attributes seen to the right are "meta data" related to the particular visit.

  • patient_id is a foreign key to patient.patient_id, and should include the internal patient identifier number for the patient (not the medical record number). 

  • concept_id is another foreign key which refers to the concept being collected by the system. 

  • location_id describes where the observation was collected, it will typically be a clinical setting such as a clinic or a laboratory.  

  • encounter_id refers to the particular patient visit. As you might assume, many observations are collected during the course of a given clinical visit. Each visit's "meta data" is contained within this encounter table. You might wonder what the point of location_id is, after seeing what is stored within an encounter. In short, observations on a patient can be made outside of an encounter, or outside of the purview of our system. For example, a patient could bring copies of their medical record, or observations could be made during a home visit, etc. Therefore, encounter_id is not a required field.

Observation Values

How the value of the observation is stored depends of the data type of the concept as defined by it's term definition. You'll notice that there are numerous different fields to store values. You'll only use one of these for each row. More information on datatypes is available elsewhere on the wiki.

Here is a quick over of how data is stored based on the datatype of the concept used to collect the information: 

  • Responses to boolean concepts are stored in the value_boolean column

  • Responses to coded concepts are stored in the value_coded column

  • Responses to numeric concepts are stored in the value_numeric column

  • Responses to datetime concepts are stored in the value_datetime column

Examples

Here are a few actual examples to provide a finer point.

Patient: Jenny D. Patient

MRN: 99TU-2, which corresponds to patient_id: 123

Clinic Vist Date: 1/14/05 @ 2:30pm

Location: Mosoriot Medical Center

Hemoglobin: 11.5

Weight: 45 kg

Date of TB treatment: 1/1/2002

Gastrointestinal Exam: Hepatomegaly...

 

 

As you can see, this patient has a number of observations ready for storage. The name, and medical record number aren't important for the obs table, but you can see a patient_id, and a location. You also see a datetime for the visit. The third and fourth bits of information will give you enough information to build an encounter within the ''
encounter table. Mosoriot has a corresponding location_id of "2". Following the demographics are four separate observations to be recorded: hemoglobin, a numeric value; weight, a numeric vital sign; date of TB treatment, a datetime; and gastrointestinal exam finding, a coded answer. If you look at this concept, hepatomegaly is one of the possible answers, and it's the corresponding concept 5008. Knowing all of this, filling in the table is pretty straightforward. Based on the data to the left, you would store 4 rows of data within the obs table with the following information...

obs_id

pat_id

trm_id

lctn_id

encntr_id

sub_id

val_bool

val_cod

val_dt

val_num

num_mod

val_txt

d_e_t

enterer

comment

obs_id

pat_id

trm_id

lctn_id

encntr_id

sub_id

val_bool

val_cod

val_dt

val_num

num_mod

val_txt

d_e_t

enterer

comment

1

123

21

2

345

 

 

 

 

11.5

 

 

1/15/2005

2

 

2

123

5089

2

345

 

 

 

 

45

 

 

1/15/2005

2

 

3

123

1113

2

345

 

 

 

1/1/2002

 

 

 

1/15/2005

2

 

4

123

1125

2

345

 

 

5008

 

 

 

 

1/15/2005

2