Usage¶
Prerequisites¶
Typical runtime usage assumes:
omop-alchemyis installed and can import the OMOP CDM modelsomop-semanticsruntime value sets are availableorm_loader.helpers.Baseresolves in the active environment- a PostgreSQL database is available for materialized view creation and refresh
If you use the semantics-backed modifier layer, database-backed resolver setup must also be available at import time.
Importing Construct Families¶
Constructs are registered via the @register_construct decorator when their modules are imported.
That means this:
from omop_constructs.core import get_construct_registry
registry = get_construct_registry()
is not enough on its own in a fresh process.
Import the families you want first:
from omop_constructs.alchemy import events, episodes, modifiers, demography # noqa: F401
from omop_constructs.core import get_construct_registry
registry = get_construct_registry()
If you only need a subset, import only those modules. The registry will then contain only the imported construct classes.
Inspecting The Registry¶
from omop_constructs.alchemy import events, episodes, modifiers, demography # noqa: F401
from omop_constructs.core import get_construct_registry
registry = get_construct_registry()
print(registry.describe())
print(registry.plan())
Useful inspection methods:
registry.describe()Human-readable dependency overviewregistry.plan()Dependency-sorted construct planregistry.build_plan_json()JSON-serializable version of the planregistry.explain(bind)SQL length plus existence and optional row countsregistry.validate(bind)Database schema vs mapper comparison
Creating And Refreshing Materialized Views¶
registry.create_all(engine)
registry.refresh_all(engine)
Safer operational variants are also available:
registry.create_missing(bind)Only create views that do not yet existregistry.refresh_existing(bind)Only refresh views that already exist
These helpers assume PostgreSQL materialized views and use pg_matviews for existence checks.
Direct Use Of Materialized View Classes¶
Every registered construct class exposes its __mv_select__ and mapped columns, so you can compose on top of them with SQLAlchemy.
from omop_constructs.alchemy.episodes import TreatmentEnvelopeMV
import sqlalchemy as sa
stmt = (
sa.select(
TreatmentEnvelopeMV.person_id,
TreatmentEnvelopeMV.condition_episode,
TreatmentEnvelopeMV.days_from_dx_to_treatment,
)
.where(TreatmentEnvelopeMV.days_from_dx_to_treatment > 30)
)
Current Semantics-Driven Behavior¶
The modifier and staging layer depends on runtime concept resolvers from omop_constructs.semantics.
In practice this means:
- importing
omop_constructs.alchemy.modifiersis not a pure no-op - stage and modifier query fragments can depend on resolver-backed concept expansion
- environment loading for the resolver engine may happen if
ENGINEis not already configured
If you want a lighter import path for event or episode constructs only, avoid importing modifier modules unless you need them.
Current Episode-Linkage Patterns¶
The codebase currently uses three main episode-linkage strategies:
- explicit
Episode_Eventlinkage where available - time-window attachment to
ConditionEpisodeMVfor observations, procedures, and measurements - specialty-specific visit ranking for
DxRelevantVisitMV
The consult-window path combines:
DxObservationMVDxRelevantVisitMVTreatmentEnvelopeMV
to compute episode-level referral-to-specialist and referral-to-treatment windows.
Common Pitfalls¶
- Empty registry after startup:
import the construct families before calling
get_construct_registry() - Import-time resolver errors: check semantics runtime configuration before importing modifier-heavy modules
- Schema mismatch during validation: the mapped class and underlying materialized view definition have drifted
- Missing construct in downstream code: confirm the module containing that construct class has actually been imported