Skip to content

Columns & Structural Mixins

OMOP Alchemy provides a small set of column helpers and mixins that encode recurring OMOP CDM patterns directly into ORM structure.

These utilities exist to:

  • reduce boilerplate
  • make OMOP semantics explicit
  • keep table definitions readable
  • align ORM structure with CDM specifications

They are structural, not analytical: they describe how data is shaped, not what it means.


Column helper functions

Column helpers wrap common OMOP column patterns into small, intention-revealing factory functions.

They are thin wrappers around sqlalchemy.orm.mapped_column with defaults chosen to match the CDM Field-Level specifications.

Concept foreign keys

OMOP relies heavily on concept identifiers, with specific semantics around nullability and unknown values.

required_concept_fk

OMOP-required concept foreign key.

This pattern is used when the CDM requires a concept reference, but allows an explicit “unknown” value (concept_id = 0).

Semantics:

  • Must exist
  • Unknown allowed (concept_id = 0)
  • Matches CDM Field-Level spec
  • foreign key to concept.concept_id

optional_concept_fk

Used when a concept reference is genuinely optional.


Convenience wrappers

These helpers exist primarily for consistency and readability when defining large tables with many fields.

optional_fk

Optional foreign keys to non-concept tables.

required_int

Required integer column.

optional_int

Optional integer column.


Structural mixins

Structural mixins encode table-level OMOP patterns that recur across multiple CDM tables.

PersonScoped

Used for tables that are fundamentally scoped to a person.

Encodes the standard person_id foreign key and indexing pattern.

ConceptTyped

Mixin for tables whose primary meaning is encoded by a concept_id.

Subclasses MUST define something_concept_id.

Not currently used, but intention to build out logic for generic EAV queries & timeline projections.

ValueMixin

Encodes the OMOP pattern where a value may be represented either numerically or categorically.

Structural guarantees:

  • at least one value must be present
  • enforced via a check constraint
  • validated at assignment time

This helps when building generic tooling that needs to handle values flexibly but then normalise for analysis.

Examples:

>>> from omop_alchemy.cdm.model.clinical.measurement import Measurement
>>> m = Measurement()
>>> m.value_as_number = 42.0
>>> m.value_as_concept_id = None  # OK
>>> m.value_as_number = None  # Raises ValueError

DatedEvent

Mixin for tables with start/end date and datetime pairs.

This mixin does not enforce temporal logic (e.g. start ≤ end); it only defines the shape, but this may be integrated with the event timeline machinery in future.

HealthSystemContext

Encodes attribution to providers and visits.

Used across many clinical event tables to provide consistent join points into the health system structure.

SourceAttribution

Mixin for _source_value and _source_concept_id patterns.

UnitConcept

Mixin for unit_concept_id.


Marker mixins

Some mixins exist purely to label intent. They do not add columns or behavior. We don't currently do anything with these.

FactTable

Marker mixin for OMOP fact tables.

Used for introspection, tooling, and documentation only.

ReferenceTable

Marker mixin for OMOP reference tables.