EnVar microschema · class
Variable Identity
VariableIdentity
The identity and semantics of an environmental exposure variable — what physical quantity is being captured, in what units, and how it binds to community vocabularies. One per record.
Where it sits
Composed intoEnvironmentalExposureRecord
Fields
Data tools give each measurement a short nickname, like tmax for maximum temperature. This is that nickname, written down exactly as the tool spells it, so you can go back to the source and find the same measurement again.
Short machine-readable name for the variable, usually the name the upstream tool uses for it (e.g. tmax, tmmx, air.2m). Identity only — not necessarily the column header in the companion data file; that binding lives in DataLayout.value_column (see envar_layout).
Example
tmax — Daymet daily maximum air temperature variable
Covered by — 5 standards
Why it matters & mappings
This is the handle under which the upstream product knows the variable (Daymet tmax vs gridMET tmmx). Without it the record cannot be traced back to the source product's variable, and a rerun cannot request the same quantity from the tool.
Different tools use different nicknames for the same thing, so scientific communities maintain shared official names for physical quantities (like "air_temperature"). Tagging the record with the official name lets computers tell that two datasets measure the same thing, no matter what each dataset called it.
The standard-name identifier for the physical quantity, as a CURIE so the schema privileges no single naming authority. Use a CF Convention Standard Name where one exists (CF:air_temperature, CF:relative_humidity); for health-relevant quantities CF does not define (e.g. Heat Index, WBGT), mint a term in the project registry (ENVAR:heat_index) or reuse an ontology term (ECTO:...). The prefix carries the authority; the slot name does not. Mandatory.
Examples
CF:air_temperature — CF Standard Name for the Daymet daily Tmax scenario
CF:mass_concentration_of_pm2p5_ambient_aerosol_particles_in_air — CF Standard Name for the ACAG PM2.5 scenario
Covered by — 5 standards
Why it matters & mappings
This is the cross-agency identifier that makes the variable interoperable: without it, tmax from one product and tmmx from another cannot be recognised by machines as the same physical quantity, so records cannot be pooled or harmonised across studies.
UCUM is a compact, machine-readable spelling of the unit — Cel for degrees Celsius, ug/m3 for micrograms per cubic metre — so software can convert °C to °F or check units automatically without guessing what a human-written unit string means.
The unit expressed in UCUM syntax, e.g. Cel for degrees Celsius, K for Kelvin, ug/m3 for PM2.5 mass concentration.
Examples
Cel — degrees Celsius (Daymet Tmax)
ug/m3 — micrograms per cubic metre (PM2.5 mass concentration)
Covered by — 5 standards
Why it matters & mappings
A number without units is uninterpretable — a value of 35 could be °C or °F, a factor-of-1.8 error in an exposure analysis. UCUM is the machine-readable form that health-data layers (e.g. OMOP's unit_concept_id) align to, so omitting it also blocks automated unit conversion and downstream integration.
See also: https://ucum.org/
A simple status flag saying whether the health-data catalogue already has a code for this measurement, has one in the works, or has nothing yet. It turns a silent gap into an explicit, reportable fact.
Status of this variable's coverage in the target health-data vocabulary (existing / proposed / gap). Makes the vocabulary gap explicit rather than silent. Required.
Example
gap — no OMOP concept exists yet for daily Tmax
Allowed values
existing A concept id is available in the target vocabulary
proposed A concept submission is in flight
gap No concept exists yet and none is yet proposed
Covered by — 5 standards
Why it matters & mappings
A downstream system must know whether to expect a concept id. The explicit existing/proposed/gap status makes vocabulary gaps visible and countable rather than silently null — which is what drives vocabulary-extension requests for environmental variables.
Says what kind of value to expect: a decimal number that can take any value (like a temperature), a yes/no flag, or a category. Software needs this to know how to read and summarise the data correctly.
The data type of the stored exposure value.
Example
continuous_numeric
Allowed values
continuous_numeric Continuous numeric value (e
categorical Categorical value (e
binary_flag Binary flag (e
count Integer count (e
event_marker Date-stamped event (e
Covered by — 5 standards
examples/scenarios/standards/omop_gaia_daymet_tmax.yaml (value_data_type)Why it matters & mappings
Tells consumers how to parse and analyse the values — continuous numbers, categories, and flags need different statistics and storage. Omitting it forces guessing from the data, which fails on ambiguous cases like 0/1 columns (count, flag, or category?).
A "daily temperature" value could be the day's highest reading, its average, or its lowest — very different numbers. This short standard phrase (like "time: maximum") records which one it is, in the exact wording that climate-data software already understands.
CF cell_methods string describing how the value summarises sub-period values, e.g. time: maximum for Tmax, time: mean for daily mean.
Examples
time: maximum — daily maximum (Tmax)
time: mean — mean over the aggregation period (e.g. annual-mean PM2.5)
Why it matters & mappings
A daily maximum and a daily mean of the same quantity carry the same standard name and units; only the aggregation statement tells them apart. Keeping the verbatim CF string also enables round-tripping against CF/NetCDF source products and the CF-consistency triple check over standard_name + cf_cell_methods + units_ucum. Conditionally-Core because the slot is CF-specific by design: it is mandatory when standard_name uses the CF: prefix (the context of SPEC.md validation rule 5), while a non-CF product genuinely has no verbatim cell_methods string to preserve — its vocabulary-neutral aggregation semantics live in the required temporal_aggregation_method.
When the original data used different units, this spells out the exact arithmetic that turned them into the numbers in the data file — like showing your work in a calculation, so others can check it.
The conversion from the source's native representation to the values in the companion data file, written out, e.g. Cel = K - 273.15 or K = stored × 0.1 + 220.0; Cel = K - 273.15. Required whenever native_units_ucum is declared.
Example
K = stored * 0.1 + 220.0; Cel = K - 273.15 — gridMET tmmx unpack-then-convert chain in the Amadeus scenario
Why it matters & mappings
Twin value columns and silent container conversions are how factor-of-1.8 unit errors enter exposure analyses undetected. Once native units are declared, the bridging math is the only record of how the file's values relate to the source's — it is what makes the conversion checkable rather than trusted.
A friendly, spelled-out name for the measurement — like "daily maximum air temperature at 2 m" instead of the cryptic code tmax — so anyone reading the record knows what it is without decoding jargon.
Human-readable label, e.g. "daily maximum air temperature at 2 m".
Example
daily maximum air temperature at 2 m
Covered by — 5 standards
Why it matters & mappings
Terse tool codes like tmmx are easy to misread (maximum vs mean) and force readers to consult external tool documentation. A plain-language label lets a human verify at a glance that the record describes the intended quantity.
Data producers often store numbers in different units than the ones shown to users — Kelvin instead of Celsius, or compressed integers that need unpacking. This field records the unit the source actually uses, so anyone going back to the original files knows what the raw numbers mean.
UCUM unit of the values as the source product stores them, when that differs from units_ucum (the unit of the values in the companion data file). Omit when the source already stores values in units_ucum — absence means "no conversion happened". Declaring it makes unit_conversion_formula required.
Example
K — gridMET tmmx stores Kelvin; the Amadeus scenario emits Celsius
Covered by — 5 standards
Why it matters & mappings
A value of 308 and a value of 35 can be the same temperature. When the source stores different units (or packed integers) than the companion file carries, the native unit is the anchor that lets a consumer check the conversion and re-read the source bytes; without it the sidecar's values cannot be traced back to the product.
See also: https://ucum.org/
Health databases each keep their own catalogue of codes for the things they record. This slot says which catalogue the record's health-data code (and its status) comes from — for example the OMOP catalogue used by many hospital research databases.
The downstream health-data vocabulary that target_concept_id and concept_status refer to, e.g. omop (OHDSI Standardised Vocabulary), bdc (BioData Catalyst). Names the vocabulary so the schema privileges no single health-data layer.
Example
omop — OHDSI Standardised Vocabulary (OMOP CDM)
Covered by — 5 standards
Why it matters & mappings
target_concept_id and concept_status are meaningless without knowing which vocabulary they refer to; naming it explicitly keeps the record portable across health-data layers (OMOP, BDC, ...) instead of silently assuming one.
Health databases store everything under numeric codes from a shared catalogue. This is that code for the environmental measurement, when one exists, so the exposure value can sit alongside clinical data under an identifier the database already knows.
Concept identifier for the variable in the vocabulary named by target_concept_vocabulary (e.g. an OHDSI concept_id). Nullable with reason for environmental variables that lack coverage today.
Example
2005200123 — illustrative OHDSI concept_id; in the canonical Tmax and PM2.5 scenarios this slot is null with a missing reason
Covered by — 5 standards
Why it matters & mappings
This is the hook that lets the environmental value land in a health database as a recognised concept. Recording it — or its documented absence — shows whether the vocabulary binding was attempted and against what, instead of leaving the linkage silent and unreproducible.
See also: https://athena.ohdsi.org/
The lowest value that would still make physical sense — for example -50 °C for outdoor air temperature. Anything below it is probably an error; this is a warning signal, not a hard rule.
Physical / domain lower bound for plausible values (e.g. -50 °C for ambient Tmax). Not a hard validation bound; sanity-check signal.
Example
-50 — plausible lower bound for ambient Tmax in °C
Covered by — 5 standards
Why it matters & mappings
Gives automated quality checks a sanity band: without it, unit mix-ups and corrupted values (e.g. a Tmax of 350 from unconverted Kelvin) pass silently into downstream analyses.
The highest value that would still make physical sense — for example 60 °C for outdoor air temperature. Anything above it likely signals a unit mix-up or a data error worth investigating.
Physical / domain upper bound for plausible values (e.g. 60 °C for ambient Tmax).
Example
60 — plausible upper bound for ambient Tmax in °C
Covered by — 5 standards
Why it matters & mappings
Together with the plausible minimum, this gives automated quality checks a sanity band: without it, unit mix-ups and corrupted values slip silently past validation into exposure analyses.
The pretty version of the unit for people to read, like "°C". The machine version (Cel) is stored separately; this one exists purely for showing on screen or in print.
Human-readable unit string for display purposes, e.g. °C.
Example
°C
Why it matters & mappings
Keeps human-facing output (tables, plots, reports) readable without every consumer having to translate UCUM codes; omitting it risks each tool rendering the unit differently or mislabelling axes.
Big datasets often save space by storing small whole numbers that must be multiplied by a constant to get the real measurement. This is that constant.
CF-style packing multiplier applied when decoding the source's stored integers to physical values (physical = stored × scale_factor + add_offset). Only meaningful alongside native_units_ucum.
Example
0.1 — gridMET tmmx packs Kelvin as unsigned int16 with scale 0.1
Why it matters & mappings
Anyone re-reading the source grid directly (rather than the companion file) must unpack stored integers with exactly this factor; a wrong or missing factor yields physically plausible but wrong values, the worst kind of error.
The second constant in the space-saving trick: after multiplying the stored number, add this to get the real measurement.
CF-style packing offset applied when decoding the source's stored integers to physical values (physical = stored × scale_factor + add_offset). Only meaningful alongside native_units_ucum.
Example
220.0 — gridMET tmmx packing offset (unpacks to true Kelvin)
Why it matters & mappings
The offset half of the unpacking convention; without it the scale factor alone still decodes to the wrong physical value.
When a code is missing, it matters why. This slot records the reason — for example that no such code has been invented yet — so an empty field is not mistaken for a processing mistake.
Reason target_concept_id is null. Distinguishes "no concept yet exists in the target vocabulary" from "the pipeline did not resolve it".
Example
not_provided_by_source
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
Without a stated reason, a null target_concept_id is ambiguous: downstream users cannot tell a genuine vocabulary gap from a pipeline that simply failed to look the concept up, and so cannot decide whether to fix the data or request a new concept.
Different scientific communities keep different dictionaries of concepts. This is a list of "also known as" links pointing to the matching entries in those dictionaries, so people searching any of them can still find this measurement.
Cross-references binding this variable to other vocabularies and ontologies, each as a CURIE. One generic list rather than a slot per standard, so adding a vocabulary is a new prefix, not a schema change. Examples: ECTO:0000012 (Environmental Conditions, Treatments and Exposures Ontology — cross-Monarch / cross-CHORDS alignment), ENVO:01000339 (Environment Ontology — material or process exposed to), LOINC:... / SNOMED:... (where the variable has clinical coverage). Note: the primary downstream health-data binding, with its existing / proposed / gap status, stays in the structured target_concept_* slots — this list is for additional, status-free cross-references.
Examples
ECTO:0000012 — exposure to temperature (ECTO) — one element of the cross-reference list for the Daymet daily Tmax scenario
ENVO:03000049 — temperature of air (ENVO) — a second element of the same cross-reference list
Why it matters & mappings
Cross-references to ontologies (ECTO, ENVO) and clinical codes (LOINC, SNOMED) let the variable be found and aligned across projects and communities; without them, cross-study harmonisation has to be redone by hand. Enrichment only — not needed to reproduce the value.
Full field reference — every slot, cardinality & inheritance
| Field | Name | Tier | Cardinality / Range | Description |
|---|---|---|---|---|
| Variable Name | variable_name |
core | 1 String |
Short machine-readable name for the variable, usually the name the upstream t... |
| Variable Label | variable_label |
recommended | 0..1 String |
Human-readable label, e |
| Standard Name | standard_name |
core | 1 Uriorcurie |
The standard-name identifier for the physical quantity, as a CURIE so the sch... |
| CF Cell Methods | cf_cell_methods |
conditionally core | 0..1 String |
CF cell_methods string describing how the value summarises sub-period value... |
| Units (UCUM) | units_ucum |
core | 1 String |
The unit expressed in UCUM syntax, e |
| Display Units | units_display |
optional | 0..1 String |
Human-readable unit string for display purposes, e |
| Native Units (UCUM) | native_units_ucum |
recommended | 0..1 String |
UCUM unit of the values as the source product stores them, when that differ... |
| Native Value Scale Factor | native_value_scale_factor |
optional | 0..1 Float |
CF-style packing multiplier applied when decoding the source's stored integer... |
| Native Value Offset | native_value_offset |
optional | 0..1 Float |
CF-style packing offset applied when decoding the source's stored integers to... |
| Unit Conversion Formula | unit_conversion_formula |
conditionally core | 0..1 String |
The conversion from the source's native representation to the values in the c... |
| Target Concept Vocabulary | target_concept_vocabulary |
recommended | 0..1 String |
The downstream health-data vocabulary that target_concept_id and `concept_s... |
| Target Concept Identifier | target_concept_id |
recommended | 0..1 String |
Concept identifier for the variable in the vocabulary named by `target_concep... |
| Reason Concept ID Is Missing | target_concept_id_missing_reason |
optional | 0..1 MissingReasonEnum |
Reason target_concept_id is null |
| Concept Status | concept_status |
core | 1 ConceptStatusEnum |
Status of this variable's coverage in the target health-data vocabulary (`exi... |
| Concept Cross-References | concept_mappings |
optional | * Uriorcurie |
Cross-references binding this variable to other vocabularies and ontologies, ... |
| Value Data Type | value_data_type |
core | 1 DataTypeEnum |
The data type of the stored exposure value |
| Plausible Minimum Value | value_range_plausible_min |
recommended | 0..1 Float |
Physical / domain lower bound for plausible values (e |
| Plausible Maximum Value | value_range_plausible_max |
recommended | 0..1 Float |
Physical / domain upper bound for plausible values (e |
Conditional rules on this class
| Rule Applied | Preconditions | Postconditions |
|---|---|---|
| slot_conditions | {'standard_name': {'pattern': '^CF:'}} |
{'cf_cell_methods': {'required': True}} |
| Rule Applied | Preconditions | Postconditions |
|---|---|---|
| slot_conditions | {'native_units_ucum': {'value_presence': 'PRESENT'}} |
{'unit_conversion_formula': {'required': True}} |
Diagram & LinkML source
classDiagram
class VariableIdentity
click VariableIdentity href "../../classes/VariableIdentity/"
VariableIdentity : cf_cell_methods
VariableIdentity : concept_mappings
VariableIdentity : concept_status
VariableIdentity --> "1" ConceptStatusEnum : concept_status
click ConceptStatusEnum href "../../enums/ConceptStatusEnum/"
VariableIdentity : native_units_ucum
VariableIdentity : native_value_offset
VariableIdentity : native_value_scale_factor
VariableIdentity : standard_name
VariableIdentity : target_concept_id
VariableIdentity : target_concept_id_missing_reason
VariableIdentity --> "0..1" MissingReasonEnum : target_concept_id_missing_reason
click MissingReasonEnum href "../../enums/MissingReasonEnum/"
VariableIdentity : target_concept_vocabulary
VariableIdentity : unit_conversion_formula
VariableIdentity : units_display
VariableIdentity : units_ucum
VariableIdentity : value_data_type
VariableIdentity --> "1" DataTypeEnum : value_data_type
click DataTypeEnum href "../../enums/DataTypeEnum/"
VariableIdentity : value_range_plausible_max
VariableIdentity : value_range_plausible_min
VariableIdentity : variable_label
VariableIdentity : variable_name
name: VariableIdentity
annotations:
domain_of_use:
tag: domain_of_use
value: environmental_exposure
description: The identity and semantics of an environmental exposure variable — what
physical quantity is being captured, in what units, and how it binds to community
vocabularies. One per record.
title: Variable Identity
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://cfconventions.org/standard-names.html
- https://ucum.org/
rank: 1000
slot_usage:
variable_name:
name: variable_name
required: true
standard_name:
name: standard_name
required: true
units_ucum:
name: units_ucum
required: true
concept_status:
name: concept_status
required: true
value_data_type:
name: value_data_type
required: true
attributes:
variable_name:
name: variable_name
annotations:
tier:
tag: tier
value: core
justification:
tag: justification
value: This is the handle under which the upstream product knows the variable
(Daymet `tmax` vs gridMET `tmmx`). Without it the record cannot be traced
back to the source product's variable, and a rerun cannot request the same
quantity from the tool.
explanation:
tag: explanation
value: Data tools give each measurement a short nickname, like `tmax` for
maximum temperature. This is that nickname, written down exactly as the
tool spells it, so you can go back to the source and find the same measurement
again.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: gaia_db/variable_source.variable_name; DeGAUSS/Amadeus emit
the short name only as a bare column header (tmax / tmmx)
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §F (Variable short name —
✅ for GAIA)
note:
tag: note
value: GAIA carries the variable short name first-class in variable_source.variable_name;
the combined stack surfaces it as a named slot.
degauss:
tag: degauss
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: cohort_addresses_geocoded_daymet CSV column header `tmax`
note:
tag: note
value: 'DeGAUSS carries the short name only as the value column header,
not as a first-class named slot. Conservative: partial.'
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: gridmet_tmmx.csv column header `tmmx`; thredds_dataset.xml
long_name/standard_name = tmmx
note:
tag: note
value: 'Amadeus carries the short name as a column header and in the
THREDDS long_name, not as a portable variable-name slot. Conservative:
partial.'
cher:
tag: cher
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: table_column_dictionary.column_name (literal column name)
note:
tag: note
value: 'C-HER records each resource''s literal column_name, which
serves as the variable''s machine-readable handle; not a portable
sidecar short-name. 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: A tool-specific short name is an instance-layer handle; the
CODATA/I-ADOPT conceptual layer names the property canonically,
not the upstream tool's nickname.
description: Short machine-readable name for the variable, usually the name the
upstream tool uses for it (e.g. `tmax`, `tmmx`, `air.2m`). Identity only — not
necessarily the column header in the companion data file; that binding lives
in `DataLayout.value_column` (see envar_layout).
title: Variable Name
examples:
- value: tmax
description: Daymet daily maximum air temperature variable
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
required: true
variable_label:
name: variable_label
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: Terse tool codes like `tmmx` are easy to misread (maximum vs mean)
and force readers to consult external tool documentation. A plain-language
label lets a human verify at a glance that the record describes the intended
quantity.
explanation:
tag: explanation
value: A friendly, spelled-out name for the measurement — like "daily maximum
air temperature at 2 m" instead of the cryptic code `tmax` — so anyone reading
the record knows what it is without decoding jargon.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: gaia_db/variable_source.variable_description; JSON-LD variableMeasured.description
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §F (Variable description
/ long name — ✅ for GAIA)
note:
tag: note
value: GAIA carries a variable long name / description first-class
in variable_source.variable_description and the JSON-LD.
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 CSVs carry no variable description / long name — only
the bare `tmax` column header.
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: thredds_dataset.xml description = "Daily Maximum Temperature
(2m)"; grid named daily_maximum_temperature
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §F (Variable description
/ long name — ✅ for Amadeus)
note:
tag: note
value: Amadeus's THREDDS metadata carries a human-readable variable
description first-class.
cher:
tag: cher
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: table_column_dictionary.name (human-readable, optional) / description
note:
tag: note
value: 'C-HER''s optional `name` and required column `description`
carry a human-readable label, though `name` is optional. 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: A display label is instance-layer presentation; CODATA's conceptual
layer names the property via I-ADOPT Object/Property, not a free-text
label.
description: Human-readable label, e.g. "daily maximum air temperature at 2 m".
title: Variable Label
examples:
- value: daily maximum air temperature at 2 m
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
standard_name:
name: standard_name
annotations:
tier:
tag: tier
value: core
justification:
tag: justification
value: 'This is the cross-agency identifier that makes the variable interoperable:
without it, `tmax` from one product and `tmmx` from another cannot be recognised
by machines as the same physical quantity, so records cannot be pooled or
harmonised across studies.'
explanation:
tag: explanation
value: Different tools use different nicknames for the same thing, so scientific
communities maintain shared official names for physical quantities (like
"air_temperature"). Tagging the record with the official name lets computers
tell that two datasets measure the same thing, no matter what each dataset
called it.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: gaia_db/variable_source.property_id and JSON-LD variableMeasured.propertyID
→ vocab.nerc.ac.uk/standard_name/air_temperature (NERC/CF mirror)
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §F (CF standard name — ✅
for GAIA)
note:
tag: note
value: GAIA is the only stack carrying a real CF standard name, via
the hand-authored NERC propertyID in variable_source / JSON-LD.
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 carries no standard-name identifier — the quantity
is implicit in the `tmax` column name.
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: thredds_dataset.xml standard_name = "tmmx" (gridMET shortcode
overloaded, not a real CF term)
note:
tag: note
value: 'Amadeus populates a standard_name slot but with the gridMET
shortcode rather than a CF term, so a CF lookup fails. Conservative:
partial.'
cher:
tag: cher
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: table_column_dictionary.column_tag_id (ontology tag planned
§8)
note:
tag: note
value: 'C-HER''s column_tag / planned ontology encoding will tag columns
to its MORPH-built ontology, but no CF/standard-name binding exists
today. Conservative: partial.'
codata:
tag: codata
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: I-ADOPT Object + Property decomposition; DDI-CDI RepresentedVariable
(value domain + units)
note:
tag: note
value: Naming the physical quantity canonically is exactly CODATA's
RepresentedVariable / I-ADOPT layer — its strongest zone — but it
names the concept, not this run's specific CURIE.
description: The standard-name identifier for the physical quantity, as a CURIE
so the schema privileges no single naming authority. Use a CF Convention Standard
Name where one exists (`CF:air_temperature`, `CF:relative_humidity`); for health-relevant
quantities CF does not define (e.g. Heat Index, WBGT), mint a term in the project
registry (`ENVAR:heat_index`) or reuse an ontology term (`ECTO:...`). The prefix
carries the authority; the slot name does not. Mandatory.
title: Standard Name
examples:
- value: CF:air_temperature
description: CF Standard Name for the Daymet daily Tmax scenario
- value: CF:mass_concentration_of_pm2p5_ambient_aerosol_particles_in_air
description: CF Standard Name for the ACAG PM2.5 scenario
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://cfconventions.org/standard-names.html
- https://obofoundry.org/ontology/ecto.html
slot_uri: dcterms:subject
owner: VariableIdentity
domain_of:
- VariableIdentity
range: uriorcurie
required: true
cf_cell_methods:
name: cf_cell_methods
annotations:
tier:
tag: tier
value: conditionally_core
justification:
tag: justification
value: 'A daily maximum and a daily mean of the same quantity carry the same
standard name and units; only the aggregation statement tells them apart.
Keeping the verbatim CF string also enables round-tripping against CF/NetCDF
source products and the CF-consistency triple check over `standard_name`
+ `cf_cell_methods` + `units_ucum`. Conditionally-Core because the slot
is CF-specific by design: it is mandatory when `standard_name` uses the
`CF:` prefix (the context of SPEC.md validation rule 5), while a non-CF
product genuinely has no verbatim `cell_methods` string to preserve — its
vocabulary-neutral aggregation semantics live in the required `temporal_aggregation_method`.'
explanation:
tag: explanation
value: 'A "daily temperature" value could be the day''s highest reading, its
average, or its lowest — very different numbers. This short standard phrase
(like "time: maximum") records which one it is, in the exact wording that
climate-data software already understands.'
description: 'CF `cell_methods` string describing how the value summarises sub-period
values, e.g. `time: maximum` for Tmax, `time: mean` for daily mean.'
title: CF Cell Methods
comments:
- 'Deliberately CF-specific — do not generalise. The vocabulary-neutral capture
of aggregation semantics already exists as the required `TemporalReference.temporal_aggregation_method`
enum (envar_temporal), which maps 1:1 to the temporal part of `cell_methods`;
that enum is what machines should reason over. This slot instead preserves the
*verbatim* CF expression. `cell_methods` is a structured mini-language (multi-axis
forms like `area: mean time: maximum`, `within`/`over` qualifiers, `where` clauses)
with no cross-vocabulary equivalent, so a "generalised" slot would be either
a free string of unspecified syntax (losing machine-readability) or a newly
minted EnVar aggregation grammar with no tooling support. Keeping the literal
string also enables round-tripping against CF/NetCDF source products and the
CF-consistency triple check over `standard_name` + `cf_cell_methods` + `units_ucum`
(SPEC.md, validation rule 5). Contrast `standard_name`, which *was* generalised
to a CURIE — that works because it is an identifier, and prefixes provide a
standard generalisation mechanism; no such mechanism exists for expressions.'
examples:
- value: 'time: maximum'
description: daily maximum (Tmax)
- value: 'time: mean'
description: mean over the aggregation period (e.g. annual-mean PM2.5)
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://cfconventions.org/cf-conventions/cf-conventions.html#cell-methods
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
units_ucum:
name: units_ucum
annotations:
tier:
tag: tier
value: core
justification:
tag: justification
value: A number without units is uninterpretable — a value of 35 could be
°C or °F, a factor-of-1.8 error in an exposure analysis. UCUM is the machine-readable
form that health-data layers (e.g. OMOP's unit_concept_id) align to, so
omitting it also blocks automated unit conversion and downstream integration.
explanation:
tag: explanation
value: UCUM is a compact, machine-readable spelling of the unit — `Cel` for
degrees Celsius, `ug/m3` for micrograms per cubic metre — so software can
convert °C to °F or check units automatically without guessing what a human-written
unit string means.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: gaia_db/variable_source.unit_code (UCUM `CEL`) + unit_text;
JSON-LD variableMeasured.unitCode; external_exposure.unit_concept_id
8653
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §E (Native unit declared
— ✅ for GAIA)
note:
tag: note
value: GAIA carries the unit as a first-class UCUM code (CEL) plus
the OMOP unit_concept_id.
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: thredds_dataset.xml units = "K"; gridmet_tmmx.cf_metadata.json
mirrors it
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §E (Native unit declared
— ✅ for Amadeus)
note:
tag: note
value: Amadeus declares the native unit K in a machine-readable CF
metadata slot (though not in UCUM syntax).
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's `tmax` column has no unit annotation; °C is only
a container convention.
cher:
tag: cher
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: table_column_dictionary.column_unit_id (required for Value-tagged
columns)
note:
tag: note
value: 'C-HER requires column_unit on Value-tagged columns, but the
unit vocabulary is not asserted to be UCUM. Conservative: partial.'
codata:
tag: codata
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: DDI-CDI RepresentedVariable (value domain + units); I-ADOPT
decomposition
note:
tag: note
value: Units live at CODATA's RepresentedVariable layer — canonical
unit semantics — but not the specific UCUM string of this run's
file.
description: The unit expressed in UCUM syntax, e.g. `Cel` for degrees Celsius,
`K` for Kelvin, `ug/m3` for PM2.5 mass concentration.
title: Units (UCUM)
examples:
- value: Cel
description: degrees Celsius (Daymet Tmax)
- value: ug/m3
description: micrograms per cubic metre (PM2.5 mass concentration)
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://ucum.org/
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
required: true
units_display:
name: units_display
annotations:
tier:
tag: tier
value: optional
justification:
tag: justification
value: Keeps human-facing output (tables, plots, reports) readable without
every consumer having to translate UCUM codes; omitting it risks each tool
rendering the unit differently or mislabelling axes.
explanation:
tag: explanation
value: The pretty version of the unit for people to read, like "°C". The machine
version (`Cel`) is stored separately; this one exists purely for showing
on screen or in print.
description: Human-readable unit string for display purposes, e.g. `°C`.
title: Display Units
examples:
- value: °C
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
native_units_ucum:
name: native_units_ucum
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: A value of 308 and a value of 35 can be the same temperature. When
the source stores different units (or packed integers) than the companion
file carries, the native unit is the anchor that lets a consumer check the
conversion and re-read the source bytes; without it the sidecar's values
cannot be traced back to the product.
explanation:
tag: explanation
value: Data producers often store numbers in different units than the ones
shown to users — Kelvin instead of Celsius, or compressed integers that
need unpacking. This field records the unit the source actually uses, so
anyone going back to the original files knows what the raw numbers mean.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: GAIA stores °C as if it were always °C; only the OMOP-side
unit lands in value_as_number and the upstream native unit is not
on the row.
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: thredds_dataset.xml units = "K" (native) alongside the derived
value_celsius; gridmet_tmmx.csv value_kelvin column
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §D/§E (Value in native source
units — ✅ for Amadeus)
note:
tag: note
value: Amadeus ships the native Kelvin value and its unit declaration
side by side with the converted Celsius.
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 does the K→°C conversion inside the container, so the
native unit never appears in any output.
cher:
tag: cher
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: C-HER records one column_unit per column; it has no notion
of a distinct source-native unit and conversion.
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: A source-native unit and its packing are instance-layer decode
details; CODATA's conceptual/represented layers do not carry per-run
storage conventions.
description: UCUM unit of the values as the *source product stores them*, when
that differs from `units_ucum` (the unit of the values in the companion data
file). Omit when the source already stores values in `units_ucum` — absence
means "no conversion happened". Declaring it makes `unit_conversion_formula`
required.
title: Native Units (UCUM)
comments:
- 'Added after the reverse gap survey (docs/reverse-gap-survey.md, 2026-07): all
three worked pipelines surfaced the same gap independently — Amadeus ships `value_kelvin`/`value_celsius`
twin columns, GAIA stores °C with no record of the K→°C math, and DeGAUSS converts
inside the container so the native unit never appears in any output. The Amadeus
translation had to park the native unit in a YAML comment because the schema
had no slot for it; the GAIA scenario prototyped exactly this key as a hand-added
`envar:*` PropertyValue in its JSON-LD catalog entry before it existed here.'
examples:
- value: K
description: gridMET tmmx stores Kelvin; the Amadeus scenario emits Celsius
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://ucum.org/
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
native_value_scale_factor:
name: native_value_scale_factor
annotations:
tier:
tag: tier
value: optional
justification:
tag: justification
value: Anyone re-reading the source grid directly (rather than the companion
file) must unpack stored integers with exactly this factor; a wrong or missing
factor yields physically plausible but wrong values, the worst kind of error.
explanation:
tag: explanation
value: Big datasets often save space by storing small whole numbers that must
be multiplied by a constant to get the real measurement. This is that constant.
description: CF-style packing multiplier applied when decoding the source's stored
integers to physical values (`physical = stored × scale_factor + add_offset`).
Only meaningful alongside `native_units_ucum`.
title: Native Value Scale Factor
comments:
- 'Added after the reverse gap survey (docs/reverse-gap-survey.md, 2026-07): the
THREDDS metadata the Amadeus flow fetches declares `scale_factor = 0.1`, `add_offset
= 220.0`, `_Unsigned` — the packed int16 → Kelvin decode convention. The survey
rated this the single most load-bearing no-home field it found: mis-decoding
produces garbage temperatures, and nothing in the sidecar recorded it.'
examples:
- value: '0.1'
description: gridMET tmmx packs Kelvin as unsigned int16 with scale 0.1
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://cfconventions.org/cf-conventions/cf-conventions.html#packed-data
owner: VariableIdentity
domain_of:
- VariableIdentity
range: float
native_value_offset:
name: native_value_offset
annotations:
tier:
tag: tier
value: optional
justification:
tag: justification
value: The offset half of the unpacking convention; without it the scale factor
alone still decodes to the wrong physical value.
explanation:
tag: explanation
value: 'The second constant in the space-saving trick: after multiplying the
stored number, add this to get the real measurement.'
description: CF-style packing offset applied when decoding the source's stored
integers to physical values (`physical = stored × scale_factor + add_offset`).
Only meaningful alongside `native_units_ucum`.
title: Native Value Offset
comments:
- Added after the reverse gap survey (docs/reverse-gap-survey.md, 2026-07) together
with `native_value_scale_factor` — the other half of the packed-value decode
convention the Amadeus THREDDS metadata declares and the sidecar previously
lost.
examples:
- value: '220.0'
description: gridMET tmmx packing offset (unpacks to true Kelvin)
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://cfconventions.org/cf-conventions/cf-conventions.html#packed-data
owner: VariableIdentity
domain_of:
- VariableIdentity
range: float
unit_conversion_formula:
name: unit_conversion_formula
annotations:
tier:
tag: tier
value: conditionally_core
justification:
tag: justification
value: Twin value columns and silent container conversions are how factor-of-1.8
unit errors enter exposure analyses undetected. Once native units are declared,
the bridging math is the only record of how the file's values relate to
the source's — it is what makes the conversion checkable rather than trusted.
explanation:
tag: explanation
value: When the original data used different units, this spells out the exact
arithmetic that turned them into the numbers in the data file — like showing
your work in a calculation, so others can check it.
description: The conversion from the source's native representation to the values
in the companion data file, written out, e.g. `Cel = K - 273.15` or `K = stored
× 0.1 + 220.0; Cel = K - 273.15`. Required whenever `native_units_ucum` is declared.
title: Unit Conversion Formula
comments:
- 'Added after the reverse gap survey (docs/reverse-gap-survey.md, 2026-07): the
Amadeus translation carried this exact math only as a YAML comment ("the schema
has no slot for it"), and the GAIA scenario hand-added it as an `envar:unit_conversion`
PropertyValue. The comparison table in the EnVar pipeline repo lists "K→°C conversion
math recorded: ❌" for every pipeline — this slot is the fix.'
examples:
- value: K = stored * 0.1 + 220.0; Cel = K - 273.15
description: gridMET tmmx unpack-then-convert chain in the Amadeus scenario
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
target_concept_vocabulary:
name: target_concept_vocabulary
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: '`target_concept_id` and `concept_status` are meaningless without knowing
which vocabulary they refer to; naming it explicitly keeps the record portable
across health-data layers (OMOP, BDC, ...) instead of silently assuming
one.'
explanation:
tag: explanation
value: Health databases each keep their own catalogue of codes for the things
they record. This slot says which catalogue the record's health-data code
(and its status) comes from — for example the OMOP catalogue used by many
hospital research databases.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: external_exposure.exposure_concept_id + exposure_type_concept_id
(32885) + unit_concept_id (8653) — OMOP vocabulary is the implicit
target
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §D (Exposure concept / variable
identity — ✅ for GAIA)
note:
tag: note
value: The OMOP CDM is the target vocabulary itself; the concept slots
land the value against OHDSI concept ids.
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 emits a bare `tmax` value with no target-vocabulary
binding.
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 carries no target-vocabulary binding; the variable
is implicit in the `tmmx` column name.
cher:
tag: cher
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: C-HER's controlled vocabs (DCMI Type, IANA media types) describe
resource type/format, not a downstream health-data target vocabulary
for the variable.
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: Binding to a downstream health-data layer is an instance/target
concern; CODATA aligns concepts across standards but names no single
target vocabulary.
description: The downstream health-data vocabulary that `target_concept_id` and
`concept_status` refer to, e.g. `omop` (OHDSI Standardised Vocabulary), `bdc`
(BioData Catalyst). Names the vocabulary so the schema privileges no single
health-data layer.
title: Target Concept Vocabulary
examples:
- value: omop
description: OHDSI Standardised Vocabulary (OMOP CDM)
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://athena.ohdsi.org/
- https://biodatacatalyst.nhlbi.nih.gov/
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
target_concept_id:
name: target_concept_id
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: This is the hook that lets the environmental value land in a health
database as a recognised concept. Recording it — or its documented absence
— shows whether the vocabulary binding was attempted and against what, instead
of leaving the linkage silent and unreproducible.
explanation:
tag: explanation
value: Health databases store everything under numeric codes from a shared
catalogue. This is that code for the environmental measurement, when one
exists, so the exposure value can sit alongside clinical data under an identifier
the database already knows.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: external_exposure.exposure_concept_id (placeholder concept
present) + exposure_type_concept_id 32885
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §D (Exposure concept / variable
identity — ✅ for GAIA)
note:
tag: note
value: GAIA fills the concept-id slot even though no real OMOP concept
is yet minted for daily-max-air-temperature; the binding exists.
degauss:
tag: degauss
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: No concept-id column in DeGAUSS output.
amadeus:
tag: amadeus
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: No concept-id column in Amadeus output.
cher:
tag: cher
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: C-HER binds no downstream concept id for the variable; only
planned ontology tags on columns (§8).
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: A concrete concept id in a target vocabulary is instance-layer;
CODATA names the concept, not this run's downstream id.
description: Concept identifier for the variable in the vocabulary named by `target_concept_vocabulary`
(e.g. an OHDSI concept_id). Nullable with reason for environmental variables
that lack coverage today.
title: Target Concept Identifier
examples:
- value: '2005200123'
description: illustrative OHDSI concept_id; in the canonical Tmax and PM2.5
scenarios this slot is null with a missing reason
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://athena.ohdsi.org/
owner: VariableIdentity
domain_of:
- VariableIdentity
range: string
target_concept_id_missing_reason:
name: target_concept_id_missing_reason
annotations:
tier:
tag: tier
value: optional
justification:
tag: justification
value: 'Without a stated reason, a null `target_concept_id` is ambiguous:
downstream users cannot tell a genuine vocabulary gap from a pipeline that
simply failed to look the concept up, and so cannot decide whether to fix
the data or request a new concept.'
explanation:
tag: explanation
value: When a code is missing, it matters why. This slot records the reason
— for example that no such code has been invented yet — so an empty field
is not mistaken for a processing mistake.
description: Reason `target_concept_id` is null. Distinguishes "no concept yet
exists in the target vocabulary" from "the pipeline did not resolve it".
title: Reason Concept ID Is Missing
examples:
- value: not_provided_by_source
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: MissingReasonEnum
concept_status:
name: concept_status
annotations:
tier:
tag: tier
value: core
justification:
tag: justification
value: A downstream system must know whether to expect a concept id. The explicit
existing/proposed/gap status makes vocabulary gaps visible and countable
rather than silently null — which is what drives vocabulary-extension requests
for environmental variables.
explanation:
tag: explanation
value: A simple status flag saying whether the health-data catalogue already
has a code for this measurement, has one in the works, or has nothing yet.
It turns a silent gap into an explicit, reportable fact.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: GAIA fills a placeholder exposure_concept_id but carries no
existing/proposed/gap status flag saying whether a real OMOP concept
exists — an EnVar-novel slot.
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 has no concept binding and so no coverage-status flag.
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 has no concept binding and so no coverage-status flag.
cher:
tag: cher
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: C-HER carries no existing/proposed/gap coverage status for
a target vocabulary.
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: A gap-status flag against a target vocabulary is instance/target
bookkeeping, outside CODATA's conceptual-alignment layer.
description: Status of this variable's coverage in the target health-data vocabulary
(`existing` / `proposed` / `gap`). Makes the vocabulary gap explicit rather
than silent. Required.
title: Concept Status
examples:
- value: gap
description: no OMOP concept exists yet for daily Tmax
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: ConceptStatusEnum
required: true
concept_mappings:
name: concept_mappings
annotations:
tier:
tag: tier
value: optional
justification:
tag: justification
value: Cross-references to ontologies (ECTO, ENVO) and clinical codes (LOINC,
SNOMED) let the variable be found and aligned across projects and communities;
without them, cross-study harmonisation has to be redone by hand. Enrichment
only — not needed to reproduce the value.
explanation:
tag: explanation
value: Different scientific communities keep different dictionaries of concepts.
This is a list of "also known as" links pointing to the matching entries
in those dictionaries, so people searching any of them can still find this
measurement.
description: 'Cross-references binding this variable to other vocabularies and
ontologies, each as a CURIE. One generic list rather than a slot per standard,
so adding a vocabulary is a new prefix, not a schema change. Examples: `ECTO:0000012`
(Environmental Conditions, Treatments and Exposures Ontology — cross-Monarch
/ cross-CHORDS alignment), `ENVO:01000339` (Environment Ontology — material
or process exposed to), `LOINC:...` / `SNOMED:...` (where the variable has clinical
coverage). Note: the *primary* downstream health-data binding, with its `existing`
/ `proposed` / `gap` status, stays in the structured `target_concept_*` slots
— this list is for additional, status-free cross-references.'
title: Concept Cross-References
examples:
- value: ECTO:0000012
description: exposure to temperature (ECTO) — one element of the cross-reference
list for the Daymet daily Tmax scenario
- value: ENVO:03000049
description: temperature of air (ENVO) — a second element of the same cross-reference
list
from_schema: https://w3id.org/linkml/microschemas/envar
see_also:
- https://obofoundry.org/ontology/ecto.html
- https://obofoundry.org/ontology/envo.html
- https://loinc.org/
owner: VariableIdentity
domain_of:
- VariableIdentity
range: uriorcurie
multivalued: true
value_data_type:
name: value_data_type
annotations:
tier:
tag: tier
value: core
justification:
tag: justification
value: Tells consumers how to parse and analyse the values — continuous numbers,
categories, and flags need different statistics and storage. Omitting it
forces guessing from the data, which fails on ambiguous cases like 0/1 columns
(count, flag, or category?).
explanation:
tag: explanation
value: 'Says what kind of value to expect: a decimal number that can take
any value (like a temperature), a yes/no flag, or a category. Software needs
this to know how to read and summarise the data correctly.'
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: gaia_catalog meta_etl_*.json qudt:dataType (numeric/float4)
evidence:
tag: evidence
value: examples/scenarios/standards/omop_gaia_daymet_tmax.yaml (value_data_type)
note:
tag: note
value: GAIA registers the attribute's numeric qudt:dataType at dataset-registration
time; the EnVar translation carries it first-class as value_data_type.
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 emits a numeric `tmax` column but declares no explicit
value data type; the type is implicit in the data.
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 emits numeric value_kelvin/value_celsius columns with
no explicit value-data-type declaration.
cher:
tag: cher
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: table_column_dictionary.column_tag (Value) + column_unit (unit
present ⇒ numeric)
note:
tag: note
value: 'C-HER''s Value tag plus the presence/absence of a column_unit
distinguishes numeric from free-text value columns, but not the
full continuous/categorical/flag taxonomy. Conservative: partial.'
codata:
tag: codata
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: DDI-CDI RepresentedVariable value domain (numeric vs categorical
value domain)
note:
tag: note
value: A value domain is exactly what CDI's RepresentedVariable carries,
so the numeric/categorical distinction lives at CODATA's represented
layer.
description: The data type of the stored exposure value.
title: Value Data Type
examples:
- value: continuous_numeric
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: DataTypeEnum
required: true
value_range_plausible_min:
name: value_range_plausible_min
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: 'Gives automated quality checks a sanity band: without it, unit mix-ups
and corrupted values (e.g. a Tmax of 350 from unconverted Kelvin) pass silently
into downstream analyses.'
explanation:
tag: explanation
value: The lowest value that would still make physical sense — for example
-50 °C for outdoor air temperature. Anything below it is probably an error;
this is a warning signal, not a hard rule.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: gaia_db/variable_source.min_value (−50); also JSON-LD variableMeasured
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §F (Variable valid range
min/max — ✅ for GAIA)
note:
tag: note
value: GAIA carries a first-class min_value (−50) as variable metadata.
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 carries no plausible-range metadata.
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 carries no plausible-range bounds; only a _FillValue
sentinel.
cher:
tag: cher
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: C-HER column metadata carries no per-variable plausible min/max.
codata:
tag: codata
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: I-ADOPT Constraint on the Property; DDI-CDI value-domain bounds
note:
tag: note
value: Plausible domain bounds are naturally an I-ADOPT Constraint
on the property / a CDI value-domain restriction at the conceptual
layer.
description: Physical / domain lower bound for plausible values (e.g. -50 °C for
ambient Tmax). Not a hard validation bound; sanity-check signal.
title: Plausible Minimum Value
examples:
- value: '-50'
description: plausible lower bound for ambient Tmax in °C
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: float
value_range_plausible_max:
name: value_range_plausible_max
annotations:
tier:
tag: tier
value: recommended
justification:
tag: justification
value: 'Together with the plausible minimum, this gives automated quality
checks a sanity band: without it, unit mix-ups and corrupted values slip
silently past validation into exposure analyses.'
explanation:
tag: explanation
value: The highest value that would still make physical sense — for example
60 °C for outdoor air temperature. Anything above it likely signals a unit
mix-up or a data error worth investigating.
covered_by:
tag: covered_by
annotations:
omop_gaia:
tag: omop_gaia
annotations:
extent:
tag: extent
value: full
status:
tag: status
value: verified
where:
tag: where
value: gaia_db/variable_source.max_value (60); also JSON-LD variableMeasured
evidence:
tag: evidence
value: EnVar/examples/heat/COMPARISON.md §F (Variable valid range
min/max — ✅ for GAIA)
note:
tag: note
value: GAIA carries a first-class max_value (60) as variable metadata.
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 carries no plausible-range metadata.
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 carries no plausible-range bounds; only a _FillValue
sentinel.
cher:
tag: cher
annotations:
extent:
tag: extent
value: absent
status:
tag: status
value: asserted
where:
tag: where
value: no column
note:
tag: note
value: C-HER column metadata carries no per-variable plausible min/max.
codata:
tag: codata
annotations:
extent:
tag: extent
value: partial
status:
tag: status
value: asserted
where:
tag: where
value: I-ADOPT Constraint on the Property; DDI-CDI value-domain bounds
note:
tag: note
value: Plausible domain bounds are naturally an I-ADOPT Constraint
on the property / a CDI value-domain restriction at the conceptual
layer.
description: Physical / domain upper bound for plausible values (e.g. 60 °C for
ambient Tmax).
title: Plausible Maximum Value
examples:
- value: '60'
description: plausible upper bound for ambient Tmax in °C
from_schema: https://w3id.org/linkml/microschemas/envar
owner: VariableIdentity
domain_of:
- VariableIdentity
range: float
rules:
- preconditions:
slot_conditions:
standard_name:
name: standard_name
pattern: '^CF:'
postconditions:
slot_conditions:
cf_cell_methods:
name: cf_cell_methods
required: true
description: CF-based products (a `CF:`-prefixed `standard_name`) must preserve
the verbatim `cell_methods` string — the context of SPEC.md validation rule 5
and of the `conditionally_core` tier on `cf_cell_methods`. Non-CF products are
exempt; their aggregation semantics live in the required `temporal_aggregation_method`.
- preconditions:
slot_conditions:
native_units_ucum:
name: native_units_ucum
value_presence: PRESENT
postconditions:
slot_conditions:
unit_conversion_formula:
name: unit_conversion_formula
required: true
description: 'Declaring native units is declaring a conversion: once `native_units_ucum`
says the source stored something other than `units_ucum`, the math that bridged
them must be written down or the sidecar''s values cannot be traced back to the
source bytes (tier conditionally_core context "native units declared").'
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:VariableIdentity |
| native | envar:VariableIdentity |