PSDL Execution Architecture¶
Overview¶
PSDL separates clinical logic (scenarios) from data binding (datasetSpec). This document describes how these layers connect to enable portable, executable clinical algorithms.
Layer Architecture¶
┌─────────────────────────────────────────────────────────────────────────────┐
│ EXECUTION CHAIN │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────┐ │
│ │ PSDL Scenario │ WHAT to detect (pure clinical logic) │
│ │ │ Signals use semantic refs only │
│ │ signals: │ e.g., ref: creatinine │
│ │ cr: │ │
│ │ ref: creat │ NO physical bindings here │
│ └────────┬─────────┘ │
│ │ │
│ │ Inspector validates + enriches │
│ ↓ │
│ ┌──────────────────┐ │
│ │ Certified │ Contains: │
│ │ Bundle │ - Validated scenario │
│ │ │ - terminologyAnchors (OMOP vocabulary binding) │
│ │ terminologyAnchors│ - Checksum, audit info │
│ │ creatinine: │ │
│ │ concept_id │ Anchors semantic refs to standard vocabulary │
│ │ concept_code│ │
│ │ vocabulary │ │
│ └────────┬─────────┘ │
│ │ │
│ │ Runtime pairs with site's datasetSpec │
│ ↓ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ datasetSpec (same schema) │ │
│ │ │ │
│ │ Maps semantic refs → physical data locations │ │
│ │ Defines: table, column, concept_id filter, units, timestamps │ │
│ │ │ │
│ │ ┌────────────────┐ ┌────────────────┐ ┌────────────────────────┐ │ │
│ │ │ omop_cdm_v54 │ │ mimic_iv │ │ hospital_xyz │ │ │
│ │ │ (standard) │ │ (PhysioNet) │ │ (custom institution) │ │ │
│ │ └────────────────┘ └────────────────┘ └────────────────────────┘ │ │
│ │ │ │
│ │ All follow the PSDL dataset spec │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ↓ │
│ ┌──────────────────┐ │
│ │ Local Database │ Actual patient data │
│ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Layer Responsibilities¶
| Layer | Purpose | Who Creates | Schema |
|---|---|---|---|
| Scenario | Clinical logic (WHAT to detect) | Clinician/Author | PSDL spec — see the PSDL repo |
| terminologyAnchors | Standard vocabulary binding (OMOP) | Inspector (auto) | backend/app/models/schemas.py (TerminologyAnchors) |
| datasetSpec | Physical data binding (WHERE data lives) | Site data analyst | PSDL dataset spec — see the PSDL repo |
Scenario Layer¶
Defined by the PSDL spec (in the PSDL repo). Contains:
- signals: Semantic references (e.g.,
ref: creatinine) - trends: Computed values from signals
- logic: Boolean predicates (clinical rules)
- audit: Intent, rationale, provenance
Key principle: NO physical bindings. Signals use semantic refs only.
# Example scenario (pure logic)
signals:
cr:
ref: creatinine
# NO concept_id, table, or column here
trends:
cr_delta_48h:
expr: delta(cr, 48h)
logic:
aki_stage1:
when: cr_delta_48h >= 0.3
severity: high
terminologyAnchors Layer (Inspector's Contribution)¶
Added by Inspector at export time. Anchors semantic refs to standard vocabulary:
terminologyAnchors:
creatinine:
concept_id: 3016723
concept_code: "2160-0"
vocabulary_id: LOINC
concept_name: "Creatinine [Mass/volume] in Serum or Plasma"
standard_unit: mg/dL
match_confidence: high # or medium, low, unanchored
heart_rate:
concept_id: 3027018
concept_code: "8867-4"
vocabulary_id: LOINC
concept_name: "Heart rate"
standard_unit: /min
match_confidence: high
Purpose: 1. Validates scenario uses standard terminology 2. Provides vocabulary metadata for governance 3. Helps sites create their datasetSpec (they know what concept_ids to map) 4. Enables cross-site scenario portability
Unanchored signals: Logged with warnings in bundle. Sites can still execute if they provide custom mapping in their datasetSpec.
datasetSpec Layer¶
Defined by the PSDL dataset spec (see the PSDL repo). Maps semantic refs to physical data:
# Example: omop_cdm_v54.yaml
psdl_version: "0.4"
dataset:
name: omop_cdm_v54
version: "1.0.0"
data_model: omop
conventions:
patient_id_field: person_id
default_timestamp_field: measurement_datetime
timezone: UTC
unit_strategy: strict
elements:
creatinine:
table: measurement
value_field: value_as_number
time_field: measurement_datetime
patient_field: person_id
filter:
concept_id: 3016723
unit: mg/dL
Key point: All datasetSpecs (standard OMOP, MIMIC-IV, custom institution) follow the SAME schema. They're just different instances with different values.
Execution Flow¶
1. Author writes PSDL scenario (pure logic, semantic refs)
↓
2. Inspector validates + generates terminologyAnchors (OMOP binding)
↓
3. Export certified bundle (scenario + terminologyAnchors + audit)
↓
4. Site has datasetSpec (maps refs → their physical data)
↓
5. Runtime: Bundle + datasetSpec → Execute against local data
terminologyAnchors Implementation¶
Schema Definition¶
class TerminologyAnchor(BaseModel):
"""Single terminology anchor for a semantic reference."""
concept_id: Optional[int] = None
concept_code: Optional[str] = None
vocabulary_id: Optional[str] = None
concept_name: Optional[str] = None
standard_unit: Optional[str] = None
match_confidence: Literal["high", "medium", "low", "unanchored"]
class TerminologyAnchors(BaseModel):
"""All terminology anchors for a scenario."""
anchors: Dict[str, TerminologyAnchor]
unanchored_refs: List[str] # Refs that couldn't be matched
anchor_timestamp: str # When anchoring was performed
vocabulary_version: Optional[str] = None # OMOP vocabulary version
Confidence Levels¶
| Level | Criteria | Action |
|---|---|---|
| high | Exact match or known alias | Auto-accept |
| medium | Fuzzy match >80% similarity | Include with note |
| low | Fuzzy match 60-80% similarity | Include with warning |
| unanchored | No match found | Log warning, allow custom mapping |
Implementation Location¶
- Service:
backend/app/services/terminology_anchoring.py - Called from:
backend/app/services/exporter.pyat bundle export - Uses:
backend/app/services/vocabulary.pyfor OMOP lookup
Bundle Structure with terminologyAnchors¶
{
"bundle_version": "1.2",
"certified_at": "2026-01-23T12:00:00Z",
"checksum": "sha256:...",
"scenario": { ... },
"terminology_anchors": {
"anchors": {
"creatinine": {
"concept_id": 3016723,
"concept_code": "2160-0",
"vocabulary_id": "LOINC",
"concept_name": "Creatinine [Mass/volume] in Serum or Plasma",
"standard_unit": "mg/dL",
"match_confidence": "high"
}
},
"unanchored_refs": [],
"anchor_timestamp": "2026-01-23T12:00:00Z"
},
"validation": { ... },
"audit": { ... }
}
References¶
- PSDL Scenario & Dataset Spec schemas — the PSDL spec repo
- Execution contract — how execution platforms consume certified bundles
- API & bundle reference — the canonical certified-bundle schema