Observation template

Observation templates are used to capture observations during an encounter in a pre-defined format. You could define observation templates to capture both general/non-disease-specific (e.g. Operation notes) information and condition/disease specific (e.g. Anaemia)  information.

To the user, an observation template shows up as an input form in the "Consultation" user interface. While in the back end, the observation template is modelled as a concept set. The form fields can be customised by defining/modifying concepts within the concept set.

Finally, to display an observation template on the Consultation UI, add the new concept set to the "All Observation Templates" concept set.

 

Disease template

A disease template can be defined by using one or more observation templates, one observation template each for a type of encounter.

For example, a disease template for Diabetes can be composed of 2 observation templates : "Diabetes intake" and "Diabetes follow-up".

To the user, a disease template looks like a set of UI forms in the "Consultation" user interface. You can configure the patient dashboard or visit page to display the observations captured using a disease template. In the back end, disease template is modelled as a concept set with the observation templates as the set members.

To make the disease template appear on the patient dashboard, add that concept set to the "All Disease Templates" concept set and modify the dashboard configurations.


General guidelines to define observation templates and concepts


Naming Convention

Disease Template Concept Sets

Example:
Fully Specified Name = Anaemia Templates, Short Name = Anaemia
Fully Specified Name = Anaemia Intake Template, Short Name = Anaemia - Intake (note there is no comma in FN)

Fully Specified Name = Anaemia Progress Template, Short Name = Anaemia - Progress (note there is no comma in FN)

Concept Data Types

 TypeExample
1Coded - Autocomplete with only coded values

Usage:
Use it when you have fixed set of answers for a concept
"Death Note, Primary Cause of Death": {
          "required": true,
          "answersConceptName": "Death Note, Cause, Answers",
          "autocomplete": true
}

Where,

  "Death Note, Primary Cause of Death" = Concept which has answers
2Coded - Autocomplete with coded values and non-coded values
You need to define following hierarchy of concepts (taking example of Chief Complaints here).
Here's the OpenMRS concept structure level.

  • Chief Complaint Data (Is Set=true, class=Concept Details)
    • Chief Complaint (DataType=Coded)
    • Non-Coded Chief Complaint (DataType=Text)
  • Chief Complaint Answers (DataType=Coded)
 


You can add Chief Complaint data to a concept-set which you are using for your form to show in Observations tab

 

All the coded answers should be added to Chief Complaint Answers and not Chief Complaint. This is a hack for now because of inability to ignore loading of children when loading a concept. When we load children it slows down the loading of the form

 
"Chief Complaint Data": {
"answersConceptName": "Chief Complaint Answers",
"autocomplete": true,
"codedConceptName": "Chief Complaint",
"nonCodedConceptName": "Non-Coded Chief Complaint",
"durationRequired": false,
"allowAddMore" : true
}
 

If either of codedConceptName or nonCodedConceptName is not given, It will be treated as autocomplete with only coded values.
The name of this configuration can be either "Chief Complaint Data" or "Chief Complaint"
which is the name of <Concept Set> or <Concept Set Member whose DataType is coded>.

For multiselect configuration, Add the following to the config map

 
"multiSelect": true instead of "autocomplete": true 
3Text - Free text type
"Chief Complaint Notes: {
"conciseText": true 
}
4Boolean - For Yes/No type
"Posture" : {
"buttonSelect" : true
}
5Numeric - For numerical values

Usage: Recommended to be configured only when the numbers would be small like number of children, pregnancies etc 
"No of children" : {
"stepper": true
6Date - For dates (without time) 
7Datetime - For dates with time 
8N/A - No data type

Usage: This is used for concepts which are used as answer to some other concept
 

 


Concept Data Conditions

Any concept in the parent concept set can be enabled / disabled conditionally based on the other concepts value. This makes the long forms usable and intuitive to use. These conditions can also be used to show errors on the forms as well.

Example:

In the below example, "Chief Complaint Notes" is editable only if the "Chief Complaint" concept is filled.

 

The configuration to enable the sample condition is shown below

File: /openmrs/apps/clinical/formConditions.js

// Bahmni.ConceptSet.FormConditions.rules is a map with key as the <concept name> that matches with the currently changed element in the observation form
Bahmni.ConceptSet.FormConditions.rules = {
  '<concept name>': function(formName, formFieldValues) {
		// This function gets 2 parameters
		// 'formName' will be the concept name of the form in which a value has been changed. ("History and Examination" in the above gif)
		// 'formFieldValues' is a map with key as concept name and value as its current value
		//    All the editable fields like 'Chief Complaint', 'Chief Complaint Notes', 'History Notes' will be present with their values as seen on the screen
 
		return {enable: [], disable: [], error: ""};
		// This method SHOULD return a map with two keys 'enable' and 'disable' with string array containing the concept names that needs to be enabled or disabled. You can return an error message to display in the UI with the 'error' variable.
  }



 

Example

Bahmni.ConceptSet.FormConditions.rules = {		//This is a constant that Bahmni expects
  'Chief Complaint Data': function(formName, formFieldValues) {//'Chief Complaint Data' concept when edited, triggers this function
        var conditions = {enable: [], disable: []};
        var chiefComplaint = formFieldValues['Chief Complaint'];
        var nonCodedChiefComplaint = formFieldValues['Non-Coded Chief Complaint'];
        if(chiefComplaint || nonCodedChiefComplaint) {
            conditions.enable.push("Chief Complaint Notes")
        } else {
			conditions.error = "Chief Complaint is not entered."
            conditions.disable.push("Chief Complaint Notes")
        }
        return conditions; //Return object SHOULD be a map with 'enable' and 'disable' arrays having the concept names
  }
    
};

The configuration to enable or disable form based on multiselect

Example:

Bahmni.ConceptSet.FormConditions.rules = {	
  'Tuberculosis, Type': function(formName, formFieldValues) {
	var conditions = {enable: [], disable: []};
	var selectedValues = formFieldValues['Tuberculosis, Type'];
	var found = _.contains(selectedValues, "Pulmonary") && _.contains(selectedValues, "Extrapulmonary")
	if(found) {
		//conditions
	} else {
		//conditions
	}
  }    
};

 


Concept Classes

While in most cases you can choose you class yourself, Bahmni recognises some classes for its functionality.

Computed - When this class is used then field would show up as read-only in the observations tab of clinical module the,  which can be overridden manually.

Concept Details -


CSV Upload feature for creating templates


Steps:

  1. Create and upload a concept CSV file. (Choose the option- concept while uploading the CSV)
    Sample concept CSV file: Delivery_concepts.csv
  2. Create and upload a concept set CSV file. (Choose the option- concept set while uploading the CSV)
    Sample concept CSV file: Delivery_concept_sets.csv

 

Naming convention for CSV files:

  1. Concept CSV file: <Disease>_concepts.csv
    Example: Anaemia_concepts.csv
  2. Concept set CSV file: <Disease>_concept_sets.csv
    Example: Anaemia_concept_sets.csv
  3. Avoid using short forms in filename like - TB_concepts.csv , use Tuberculosis_concepts.csv instead. 

CSV examples for Observation Templates and generic concepts can be found at:

https://github.com/Bhamni/default-config/tree/master/openmrs/templates

https://github.com/Bhamni/possible-config/tree/master/openmrs/templates