EnVar microschema · class
Health-Layer Linkage
HealthLayerLinkage
Hooks the sidecar uses to be findable from a downstream health-data layer (OMOP, BioData Catalyst, …). These are not clinical metadata — they are the hooks the exposure record needs so a health-side row can resolve back to its provenance. The target layer is named in health_layer_target, so no single model is privileged. One per record.
Where it sits
Composed intoEnvironmentalExposureRecord
Fields
Health records are stored in different standard formats — for example OMOP, a widely used common format for health records, so tools written for one hospital's data work on another's. This slot simply says which of those formats this exposure record is meant to plug into.
The downstream health-data layer this sidecar links into. Names the target so health_layer_link_field is interpreted against the right model.
Example
omop_external_exposure — OMOP CDM via the OHDSI GIS external_exposure table extension
Allowed values
omop_external_exposure OMOP CDM, via the OHDSI GIS `external_exposure` table extension
bdc BioData Catalyst (BDC) harmonised model
other Another health-data layer named out of band
Covered by — 5 standards
Why it matters & mappings
Without naming the target layer, health_layer_link_field is ambiguous — a consumer cannot know which data model the link field belongs to, so the exposure record cannot be reliably resolved from the health side. Naming the target in a slot (rather than baking it into slot names) is also what keeps the schema neutral across health data models.
See also: https://ohdsi.github.io/CommonDataModel/
Think of the exposure record and the patient database as two spreadsheets that need to be matched up. This slot names the column in the patient-side spreadsheet that holds the matching ID, so anyone can connect the two tables without guessing.
Name of the field in the target health-data layer that carries provenance_id. For OMOP this is external_exposure.exposure_source_value (the default); other layers name their own field.
Example
exposure_source_value — the OMOP external_exposure field that carries provenance_id
Covered by — 5 standards
Why it matters & mappings
This is the join key declaration: it names the exact field in the health-data layer that holds this record's provenance_id. Without it, exposure rows cannot be joined back to patients in the health data model, and a health-side row cannot resolve to its exposure provenance.
See also: https://ohdsi.github.io/CommonDataModel/
This is simply a head count: how many different people this exposure record covers. It lets whoever receives the data check that nothing went missing along the way.
Number of distinct persons this exposure record was extracted for. Helps downstream estimate the volume of health-layer rows the sidecar describes.
Example
3 — three cohort members in the worked Phoenix example
Why it matters & mappings
Gives downstream consumers a volume expectation: without it, a health-layer loader cannot sanity-check whether the number of exposure rows it receives matches the number of persons the record was extracted for, so silent truncation or duplication goes unnoticed.
When the head count is missing, this slot says why — for example, the tool could have counted but did not, or counting simply does not apply. An explained blank is far more useful than a silent one.
Reason cohort_size_anchored is null.
Example
available_but_not_extracted — the pipeline could count anchored persons but does not yet surface it
Allowed values
not_provided_by_source Source product does not produce this information
available_but_not_extracted Source produces this information but the current pipeline does not surface it
upstream_data_not_propagated An upstream tool emitted this information but the current pipeline dropped it...
under_investigation We are working on populating this slot
not_applicable This slot does not apply to this variable / record
Why it matters & mappings
Distinguishes "the cohort size is genuinely unknown" from "the pipeline just did not record it". Without the reason, a null count is uninterpretable and downstream users cannot tell whether to chase the number or accept its absence.
Full field reference — every slot, cardinality & inheritance
| Field | Name | Tier | Cardinality / Range | Description |
|---|---|---|---|---|
| Target Health-Data Layer | health_layer_target |
recommended | 0..1 HealthLayerTargetEnum |
The downstream health-data layer this sidecar links into |
| Health-Layer Link Field | health_layer_link_field |
recommended | 0..1 String |
Name of the field in the target health-data layer that carries `provenance_id... |
| Anchored Cohort Size | cohort_size_anchored |
optional | 0..1 Integer |
Number of distinct persons this exposure record was extracted for |
| Reason Cohort Size Is Missing | cohort_size_anchored_missing_reason |
optional | 0..1 MissingReasonEnum |
Reason cohort_size_anchored is null |
Diagram & LinkML source
classDiagram
class HealthLayerLinkage
click HealthLayerLinkage href "../../classes/HealthLayerLinkage/"
HealthLayerLinkage : cohort_size_anchored
HealthLayerLinkage : cohort_size_anchored_missing_reason
HealthLayerLinkage --> "0..1" MissingReasonEnum : cohort_size_anchored_missing_reason
click MissingReasonEnum href "../../enums/MissingReasonEnum/"
HealthLayerLinkage : health_layer_link_field
HealthLayerLinkage : health_layer_target
HealthLayerLinkage --> "0..1" HealthLayerTargetEnum : health_layer_target
click HealthLayerTargetEnum href "../../enums/HealthLayerTargetEnum/"
name: HealthLayerLinkage
annotations:
domain_of_use:
tag: domain_of_use
value: environmental_exposure
description: Hooks the sidecar uses to be findable from a downstream health-data layer
(OMOP, BioData Catalyst, …). These are *not* clinical metadata — they are the hooks
the exposure record needs so a health-side row can resolve back to its provenance.
The target layer is named in `health_layer_target`, so no single model is privileged.
One per record.
title: Health-Layer Linkage
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://ohdsi.github.io/CommonDataModel/
- https://biodatacatalyst.nhlbi.nih.gov/
rank: 1000
attributes:
health_layer_target:
name: health_layer_target
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: Without naming the target layer, `health_layer_link_field` is ambiguous
— a consumer cannot know which data model the link field belongs to, so
the exposure record cannot be reliably resolved from the health side. Naming
the target in a slot (rather than baking it into slot names) is also what
keeps the schema neutral across health data models.
explanation:
tag: explanation
value: Health records are stored in different standard formats — for example
OMOP, a widely used common format for health records, so tools written for
one hospital's data work on another's. This slot simply says which of those
formats this exposure record is meant to plug into.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: external_exposure table (OMOP CDM GIS extension) — the target
is OMOP but is implicit, not a named slot
note:
tag: note
value: 'Gaia lands values into OMOP external_exposure, so the target
layer is effectively OMOP, but it is baked into the pipeline rather
than declared in a target field. Conservative: partial.'
degauss:
tag: degauss
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: DeGAUSS appends columns to the cohort CSV and names no downstream
health-layer target.
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: Amadeus names no downstream health-layer target.
cher:
tag: cher
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: PostgreSQL schema=health (health-resource bucket)
note:
tag: note
value: 'C-HER has a health schema for health resources, but does not
name a downstream health-data model as an exposure-record target.
Conservative: partial.'
codata:
tag: codata
annotations:
extent:
tag: extent
value: out_of_layer
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: Health-layer target naming is instance/integration-layer; out
of scope for CODATA.
description: The downstream health-data layer this sidecar links into. Names the
target so `health_layer_link_field` is interpreted against the right model.
title: Target Health-Data Layer
examples:
- value: omop_external_exposure
description: OMOP CDM via the OHDSI GIS `external_exposure` table extension
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://ohdsi.github.io/CommonDataModel/
owner: HealthLayerLinkage
domain_of:
- HealthLayerLinkage
range: HealthLayerTargetEnum
health_layer_link_field:
name: health_layer_link_field
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: 'This is the join key declaration: it names the exact field in the
health-data layer that holds this record''s `provenance_id`. Without it,
exposure rows cannot be joined back to patients in the health data model,
and a health-side row cannot resolve to its exposure provenance.'
explanation:
tag: explanation
value: Think of the exposure record and the patient database as two spreadsheets
that need to be matched up. This slot names the column in the patient-side
spreadsheet that holds the matching ID, so anyone can connect the two tables
without guessing.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: external_exposure.exposure_source_value (the OMOP field that
would carry a provenance id)
note:
tag: note
value: 'The OMOP external_exposure.exposure_source_value field exists
and is the natural provenance-id carrier, but gaia does not populate
it with a sidecar provenance id. Conservative: partial.'
degauss:
tag: degauss
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: DeGAUSS declares no health-layer join field.
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: Amadeus declares no health-layer join field.
cher:
tag: cher
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: table_column_dictionary.reference_column_id (FK to a column
in another resource, e.g. the health schema)
note:
tag: note
value: 'C-HER models a cross-resource reference-column mechanism that
could carry such a join, but declares no exposure-record-to-health-layer
link field. Conservative: partial.'
codata:
tag: codata
annotations:
extent:
tag: extent
value: out_of_layer
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: Health-layer join-field declaration is instance/integration-layer;
out of scope for CODATA.
description: Name of the field in the target health-data layer that carries `provenance_id`.
For OMOP this is `external_exposure.exposure_source_value` (the default); other
layers name their own field.
title: Health-Layer Link Field
examples:
- value: exposure_source_value
description: the OMOP `external_exposure` field that carries `provenance_id`
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://ohdsi.github.io/CommonDataModel/
owner: HealthLayerLinkage
domain_of:
- HealthLayerLinkage
range: string
cohort_size_anchored:
name: cohort_size_anchored
annotations:
tier:
tag: tier
value: optional
justification:
tag: justification
value: 'Gives downstream consumers a volume expectation: without it, a health-layer
loader cannot sanity-check whether the number of exposure rows it receives
matches the number of persons the record was extracted for, so silent truncation
or duplication goes unnoticed.'
explanation:
tag: explanation
value: 'This is simply a head count: how many different people this exposure
record covers. It lets whoever receives the data check that nothing went
missing along the way.'
description: Number of distinct persons this exposure record was extracted for.
Helps downstream estimate the volume of health-layer rows the sidecar describes.
title: Anchored Cohort Size
examples:
- value: '3'
description: three cohort members in the worked Phoenix example
from_schema: https://w3id.org/linkml/microschemas/envar
owner: HealthLayerLinkage
domain_of:
- HealthLayerLinkage
range: integer
cohort_size_anchored_missing_reason:
name: cohort_size_anchored_missing_reason
annotations:
tier:
tag: tier
value: optional
justification:
tag: justification
value: Distinguishes "the cohort size is genuinely unknown" from "the pipeline
just did not record it". Without the reason, a null count is uninterpretable
and downstream users cannot tell whether to chase the number or accept its
absence.
explanation:
tag: explanation
value: When the head count is missing, this slot says why — for example, the
tool could have counted but did not, or counting simply does not apply.
An explained blank is far more useful than a silent one.
description: Reason `cohort_size_anchored` is null.
title: Reason Cohort Size Is Missing
examples:
- value: available_but_not_extracted
description: the pipeline could count anchored persons but does not yet surface
it
from_schema: https://w3id.org/linkml/microschemas/envar
owner: HealthLayerLinkage
domain_of:
- HealthLayerLinkage
range: MissingReasonEnum
See Also
Identifier and Mapping Information
Annotations
| property | value |
|---|---|
| domain_of_use | environmental_exposure |
Schema Source
- from schema: https://w3id.org/linkml/microschemas/envar
Mappings
| Mapping Type | Mapped Value |
|---|---|
| self | envar:HealthLayerLinkage |
| native | envar:HealthLayerLinkage |