Skip to content

Layered Architecture

OMOP Alchemy is built as a deliberately layered system.

Each layer adds capability while preserving the guarantees of the layers beneath it. The core layers build upward from generic infrastructure to OMOP-aware views; Toolkit and Semantic Validation build on those views independently.

The result is a system that is:

  • composable
  • inspectable
  • safe for both ETL and analytics

The Layer Stack

flowchart BT subgraph L0["orm-loader"] L0a["CSVLoadableTableInterface"] L0b["SerialisableTableInterface"] L0c["Bulk load & casting helpers"] L0d["Materialized-view lifecycle"] end subgraph CDM["omop_alchemy.cdm"] direction BT subgraph L1["cdm.base"] L1a["CDMTableBase"] L1b["Column helpers"] L1c["Structural mixins"] L1d["ReferenceContext"] L1e["DomainValidation primitives"] end subgraph L2["cdm.models"] L2a["Concrete CDM tables"] L2b["@cdm_table"] L2c["OMOP-compliant schemas"] end subgraph L3["Views & Contexts"] L3a["Reference contexts"] L3b["Derived properties"] L3c["Hybrid expressions"] end end subgraph L4["Toolkit"] L4a["Standard queries, composition & exploration"] end subgraph L5["Semantic Validation"] L5a["ExpectedDomain"] L5b["DomainRule"] L5c["Runtime domain checks"] end L0 -->|infrastructure| L1 L1 -->|OMOP structure| L2 L2 -->|views & navigation| L3 L3 -->|reusable queries| L4 L3 -->|semantic checks| L5 classDef infrastructure fill:#e8f1fb,stroke:#2b6cb0,stroke-width:1.5px,color:#17324d classDef cdmLayer fill:#eaf6ef,stroke:#2f855a,stroke-width:1.5px,color:#193b29 classDef toolkitLayer fill:#fff6df,stroke:#b7791f,stroke-width:1.5px,color:#4a3210 classDef validationLayer fill:#f3eaff,stroke:#805ad5,stroke-width:1.5px,color:#33224d class L0a,L0b,L0c,L0d infrastructure class L1a,L1b,L1c,L1d,L1e,L2a,L2b,L2c,L3a,L3b,L3c cdmLayer class L4a toolkitLayer class L5a,L5b,L5c validationLayer style CDM fill:#f8fafc,stroke:#64748b,stroke-width:2px,stroke-dasharray:5 5 style L0 fill:#f5faff,stroke:#2b6cb0,stroke-width:1.5px style L1 fill:#f3fbf5,stroke:#2f855a,stroke-width:1.5px style L2 fill:#f3fbf5,stroke:#2f855a,stroke-width:1.5px style L3 fill:#f3fbf5,stroke:#2f855a,stroke-width:1.5px style L4 fill:#fffaf0,stroke:#b7791f,stroke-width:1.5px style L5 fill:#faf7ff,stroke:#805ad5,stroke-width:1.5px

Layer responsibilities

Layer Purpose Responsibilities Boundary and examples
orm-loader (L0) Ingestion and infrastructure CSV loading; bulk inserts; type casting; serialization; materialized-view definition and lifecycle operations Domain-agnostic: it does not understand OMOP concepts, vocabularies, or clinical meaning. OMOP Alchemy may provide a selectable and logical row identity, while applications own view collections, dependency policy, and deployment. CSVLoadableTableInterface
SerialisableTableInterface
Materialized views
cdm.base (L1) Structural OMOP semantics Common table structure; required and optional column patterns; reusable mixins; reference relationship mechanics; domain validation primitives Defines OMOP’s shape, not its analytical meaning. Answers: “What does a valid OMOP table look like?” CDMTableBase; PersonScoped; ReferenceContext
cdm.models (L2) Concrete OMOP tables Actual CDM tables; exact column layouts; primary and foreign keys; official OMOP schemas Safe for ETL and bulk loading; avoids eager relationships and analytical helpers. Example: Person
Views & Contexts (L3) Navigation and analysis Reference relationships; derived properties; hybrid expressions; query-friendly helpers Designed for interactive use, not ingestion: tables are for pipelines; views are for people. PersonContext; PersonView
Toolkit (L4) Reusable clinical queries and composition Standard query contracts; vocabulary and concept resolution; event and episode composition; reusable analytical projections Consumes CDM models and views, adding interpretation and retrieval rules without replacing models or hiding database access. Toolkit overview; Query contracts
Semantic Validation (L5) Explicit semantic expectations Declared domain expectations; inspectable rules; runtime advisory checks Non-blocking and non-mutating; safe to skip or run interactively. Answers: “Does this object reference the kinds of concepts I think it does?” ExpectedDomain

Directional guarantees

The dependency direction is intentionally one-way: higher layers may use lower layers, but lower layers never import higher layers. In the diagram, arrows show capability building upward from the foundation; Toolkit and Semantic Validation are peers rather than dependencies of one another.

  • lower layers never import higher layers
  • ETL code never depends on analytical helpers
  • validation never mutates state

This guarantees:

  • predictable ingestion
  • expressive analysis
  • minimal coupling
  • documentation that stays aligned with code

Why this separation matters

Implementations that collapse these concerns into a single ORM layer will tend to produce:

  • accidental joins in ETL
  • brittle analytical code
  • hard-to-debug semantics
  • documentation drift