OpenSRP / FHIR-Core Export¶
TRICC can export draw.io clinical decision support diagrams to a full FHIR R4 bundle compatible with OpenSRP 2 / FHIR-Core.
Overview¶
The OpenSRPStrategy extends the base FHIRStrategy and produces:
| Resource | Description |
|---|---|
Questionnaire |
SDC-profiled questionnaire with enableWhenExpression / calculatedExpression |
Library |
CQL logic library (one per cpg-common-process + shared helper) |
StructureMap |
Extraction map (Questionnaire → FHIR resources) |
ValueSet |
One per select_one / select_multiple question |
PlanDefinition |
One per cpg-common-process; named-event trigger + applicability condition |
Composition |
Manifest listing all resources for the form package |
Binary |
App config JSON (base64) + image binaries |
| FSH files | FHIR Shorthand for all of the above (SUSHI-ready) |
Quick Start¶
```bash
Convert a draw.io file to OpenSRP FHIR-Core output¶
python tests/build.py \ -i tests/data/demo.drawio \ -o tests/output/opensrp/ \ -O OpenSRPStrategy \ -d my_form_id ```
Output directory layout¶
tests/output/opensrp/
├── questionnaire/
│ └── Questionnaire-<process>.json
├── library/
│ ├── Library-<form_id>-<process>.json
│ └── Library-<form_id>Helper.json
├── structure-map/
│ └── StructureMap-<process>.json
├── ValueSet/
│ └── ValueSet-<node_id>.json
├── plan-definition/
│ └── PlanDefinition-<process>.json
├── binary/
│ ├── Binary-config.json
│ └── Binary-<node_id>.json # images
├── Composition.json
└── fsh/
├── Questionnaire-<process>.fsh
├── Library-<form_id>-<process>.fsh
├── PlanDefinition-<process>.fsh
├── Composition.fsh
└── ...
Architecture¶
Class hierarchy¶
BaseOutPutStrategy
└── FHIRStrategy (standard FHIR SDC — Questionnaire, Library, StructureMap, ValueSet, Binary)
└── OpenSRPStrategy (adds PlanDefinition, Composition, Binary config, FSH, openSRP wiring)
Processing pipeline¶
execute()
├── process_base() → generate_base(node) builds Questionnaire items
├── process_relevance() → generate_relevance(node) adds enableWhenExpression (FHIRPath)
├── process_calculate() → generate_calculate(node) adds CQL defines + calculatedExpression
├── process_export() → generate_export(node) builds StructureMap rules
└── export()
├── [FHIRStrategy] write questionnaire/, library/, structure-map/, ValueSet/, binary/
└── [OpenSRPStrategy]
├── generate_plandefinition(process) → plan-definition/
├── _wire_questionnaire_extensions() → cqlInputResources + planDefinitions on Q
├── generate_composition() → Composition.json
├── generate_binary_config() → binary/Binary-config.json
└── _write_fsh_files() → fsh/
cpg-common-process Mapping¶
Each draw.io activity is mapped to a
cpg-common-process
named event via the process attribute on TriccNodeMainStart.
The get_process(node) function (in tricc_oo/visitors/tricc.py) walks the
TRICC graph upward to find the process name for any node:
- If the node itself is a
TriccNodeMainStart→ returnnode.process - If the node's activity root is a
TriccNodeMainStart→ returnroot.process - Recurse on the activity
- Fallback: walk
prev_nodes
Supported process names (from tricc_oo/visitors/utils.py):
registration, triage, clinical-assessment, determine-diagnosis,
guideline-based-care, dispense-medications, discharge-referral-of-patient,
record-and-report, monitor-and-follow-up-of-patient,
alert-reminder-education-of-patient, guideline-based-care,
dispense-medications, discharge-referral-of-patient,
record-and-report, monitor-and-follow-up-of-patient
Expression System¶
Relevance (enableWhen)¶
Relevance conditions from the TRICC graph are converted to FHIRPath using
convert_expression_to_fhirpath() and attached as an SDC
enableWhenExpression extension:
json
{
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-enableWhenExpression",
"valueExpression": {
"language": "text/fhirpath",
"expression": "%resource.item.where(linkId='age').answer.value >= 18"
}
}
Calculations (calculatedExpression / initialExpression)¶
Calculate nodes (and some relevance logic) are converted to CQL using
convert_expression_to_cql(). A shared Helper library provides data
access via FHIR resources (e.g. GetObsValue("concept.code")). Per-process
libraries are thin wrappers that expose named defines.
In the Questionnaire, expressions use simple define names (the Questionnaire declares its library/libraries at the top level):
json
{
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-calculatedExpression",
"valueExpression": {
"language": "text/cql-identifier",
"expression": "Calc_bmi"
}
}
Example generated CQL style (segment library):
```cql include fhir_formHelper version '1.0.0' called Helper
define Calc_bmi: Helper.GetObsValue("weight") / (Helper.GetObsValue("height") * Helper.GetObsValue("height")) ```
PlanDefinition¶
Each cpg-common-process gets a PlanDefinition with:
- trigger:
named-event→cpg-common-process-<process> - condition: CQL applicability expression
"Is Applicable" - action:
definitionCanonicalpointing to the Questionnaire
json
{
"resourceType": "PlanDefinition",
"id": "pd-registration",
"status": "active",
"trigger": [{ "type": "named-event", "name": "cpg-common-process-registration" }],
"action": [{
"title": "Fill registration form",
"definitionCanonical": "http://example.org/Questionnaire/registration",
"condition": [{
"kind": "applicability",
"expression": { "language": "text/cql", "expression": "Is Applicable" }
}]
}]
}
Questionnaire Extensions (openSRP wiring)¶
The _wire_questionnaire_extensions() method adds two openSRP-specific
extensions to each Questionnaire:
cqlInputResources¶
Points to the CQL Library for this process:
json
{
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext",
"extension": [
{ "url": "name", "valueId": "<form_id>-<process>" },
{ "url": "type", "valueCode": "Library" }
]
}
planDefinitions¶
References the PlanDefinition for this process:
json
{
"url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-planDefinition",
"valueCanonical": "http://example.org/PlanDefinition/pd-<process>"
}
StructureMap (Extraction)¶
Each node with a concept attribute generates a StructureMap rule that
extracts the answer into the appropriate FHIR resource:
| TRICC concept type | FHIR resource | Profile |
|---|---|---|
diagnosis |
Condition |
http://hl7.org/fhir/StructureDefinition/Condition |
proposed_diagnosis |
Condition |
http://hl7.org/fhir/StructureDefinition/Condition |
observation |
Observation |
http://hl7.org/fhir/StructureDefinition/Observation |
medication |
MedicationRequest |
http://hl7.org/fhir/StructureDefinition/MedicationRequest |
procedure |
Procedure |
http://hl7.org/fhir/StructureDefinition/Procedure |
encounter |
Encounter |
http://hl7.org/fhir/StructureDefinition/Encounter |
FSH Output¶
All resources are also serialized to
FHIR Shorthand (FSH)
in the fsh/ subdirectory, ready for compilation with
SUSHI.
The FSH serializer (tricc_oo/converters/fhir/fsh_serializer.py) supports:
Questionnaire→Instance: … InstanceOf: SDCQuestionnaireExtractLibrary→Instance: … InstanceOf: LibraryStructureMap→Instance: … InstanceOf: StructureMapValueSet→ValueSet: …with concept includesPlanDefinition→Instance: … InstanceOf: PlanDefinitionComposition→Instance: … InstanceOf: CompositionBinary→Instance: … InstanceOf: Binary- Any other resource type → generic
Instancewith JSON comments
Testing¶
```bash
Run all strategy tests¶
python -m pytest tests/test_strategies/ -v
Run a specific test class¶
python -m pytest tests/test_strategies/test_opensrp_strategy.py::TestFshSerializer -v
Full integration test (requires a draw.io file)¶
python tests/build.py \ -i tests/data/demo.drawio \ -o tests/output/opensrp/ \ -O OpenSRPStrategy \ -l d ```
Key Files¶
| File | Purpose |
|---|---|
tricc_oo/strategies/output/opensrp.py |
OpenSRPStrategy class |
tricc_oo/strategies/output/fhir_form.py |
FHIRStrategy base class |
tricc_oo/converters/fhir/questionnaire_item_mapper.py |
Node type → FHIR item type mapping |
tricc_oo/converters/fhir/concept_mapper.py |
Concept type → FHIR resource mapping |
tricc_oo/converters/fhir/fsh_serializer.py |
FHIR dict → FSH text serializer |
tricc_oo/visitors/tricc.py |
get_process() graph walker |
tests/test_strategies/test_opensrp_strategy.py |
Unit tests |