Cohort Modules Categorization/Typing

Use of dates is optional. A cohort service that accepts period of membership or can answer “who was in the cohort on YYYY-MM-DD” can be used like a list of people and the dates ignored.

Great point. Example is static via dynamic as definition rather than “type” discriminator. FHIR is using “type” to specify the type of members in the cohort anyway (meaning we probably shouldn’t be using cohort type for another purpose).

Some of the features of the cohort module are worth keeping and others could be removed and brought back again some day. More details below.

To ensure we’re evolving toward FHIR (not diverging or creating new incompatibilities with FHIR), let’s start with what FHIR Group offers:

FHIR Group

property description notes
active active / inactive All cohorts will be seen in FHIR as “active” until we decide we want/need to add the capability to disable cohorts (without voiding/deleting them).
actual “actual” list of people vs. “descriptive” list of “types” of intended individuals From the documentation, I’m not sure FHIR’s “actual vs. descriptive” is precisely our static vs. dynamic. But maybe. This seems like a FHIR property we could infer when exposing an OpenMRS cohort as a FHIR Group.
type kind of members (e.g., people, cows, syringes, etc.) We can focus on people and leave grouping of cows & syringes to farming and inventory systems.
managingEntity ownership We’ll want to have owners, editors, viewers.
characteristic a simplified set of key/value pairs defining include or exclude criteria This looks like one approach to a cohort definition hardcoded into the FHIR group. We need more flexibility.
member members are anything (people, cows, syringes, etc.) We’ll focus on people.
member.active active / inactive membership For FHIR, we would infer inactive for any member who doesn’t have a membership with start & end dates covering the time of interest.
member.period period of membership Same as our membership start date & end date.

Next, let’s consider what we have in core:

OpenMRS core

  • members are patients
  • period of membership (start date & end date)

And then there’s the Cohort Module (wiki page), which was initial intended to enhance our cohorts in a way that could be re-introduced to core:

Cohort Module

  • members are persons
  • cohort attributes
  • membership attributes
  • membership role (e.g., head of household)
  • obs, program, visit & encounter for cohorts

So, let’s imagine bringing these together into a way that helps align us with FHIR and focuses on the things we need now (e.g., we need to support patient lists asap):

Target state (what we want now)

  • Use cohort definition to define how cohort is determined
    • Doesn’t translate to FHIR Group (which only supports include/exclude list of key/value pairs)
  • Support attributes of cohorts & memberships to empower local & module needs through extension
property notes
cohort.definition Take the reporting approach of providing a definition of how a cohort is achieved. The definition might specify the cohort is manually managed or it could point to a handler that can return the cohort. We’ll probably want a definition_handler property to avoid having to pre-define all types of definitions; rather, have the API persist the definition and where to go to turn the definition into an actual list of people. The API would provide common use cases out of the box, but custom cohort-generating algorithms with their own definition schema could be supplied by add-ons.
date_members_updated The UTC timestamp of when the cohort was last updated (whether manually or through a calculation)
public Some mechanism to support visibility (e.g., public vs private)
ownership / access Like FHIR has managingEntity, we want to track ownership. We’ll want more than ownership; rather, we want to be able to relate users to a cohort with access levels (e.g., owner, editor, viewer).
cohort.attribute
cohort_member.attribute
Attributes allow implementations and add-ons to innovate without having to fork the code. So, I would favor supporting the OpenMRS attributes pattern for both cohorts and cohort memberships.
cohort.type == Person We should probably migrate away from using cohort.type for other purposes (e.g., static vs. dynamic), since FHIR defines their type as the type of members. In our cases, this will always be persons – not just patients (like we currently have in core), but not cows (like FHIR supports). The idea of static (manually managed) vs. dynamic (calculated) cohorts can be absorbed into support for definitions (since these are definitions of how the cohort is realized).
cohort_member.start_date
cohort_member.end_date
We continue to support periods of membership. The API is (or can be) designed so cohorts can be used as a simple list of persons and the start & end dates ignored if they aren’t needed.

The type of contract with a definition handler could be include methods like:

public interface CohortDefinitionHandler {
  boolean needsUpdate(cohort); // True if cohort needs to be updated
  void update(cohort); // Update cohort using definition
  boolean supportsManualChanges(cohort); // allow manual changes?
}

This means we put the obs/program/visit/encounter for cohorts along with membership roles aside for now (pull them out of the cohort module) and focus the cohort module on cohorts of persons, user access to cohorts, cohort definitions, and continue supporting cohort/member attributes. This would allow us to support most/all of the needs for OpenMRS 3.0’s patient lists.

Future state

  • Add membership roles
  • Add membership sort weight
  • Support obs, program, visit & encounter for cohorts (like FHIR does) in core, so reporting and the rest of OpenMRS API can leverage them

I haven’t addressed this requirement – i.e., mutually exclusive cohorts. I’d suggest we could work through design ideas for supporting mutually exclusive cohorts in a separate Talk topic.

1 Like