Metadata model reference

Read models with hdhelpers.metadata.read_metadata(). The returned type depends on the metadata’s data type; see Automatic metadata type selection. All three root models are immutable, allow additional fields and provide the same reading and update methods.

Root models

Model

Data

Value dimensions

SeriesMetadata

One metric in a pandas Series

One, named value

SingleTSFrameMetadata

One metric in a pandas DataFrame

One or more value columns

MultiTSFrameMetadata

Metrics identified by a DataFrame’s metric column

Value columns for each metric

The root fields are dataset_metadata (settings for the dataset), metrics (metric descriptions) and optional value_dimensions_shared (column defaults). See Metadata lookup basics for storage, missing values and shared field rules.

Reading and updating

Using Shared data setup, read a model and attach changed metadata to a converted result. Updates return a new model; the original remains unchanged.

>>> meta = md.read_metadata(series, required=True)
>>> meta.unit()
'm'
>>> result = series * 100
>>> changed = meta.with_value_dimension(None, "value", unit="cm")
>>> md.set_metadata(result, changed)
>>> md.get_series_unit(result), meta.unit()
('cm', 'm')
>>> multi = md.read_metadata(multitsframe, required=True)
>>> multi.unit("plant_a.pressure")
'bar'
>>> multi.narrowed_to("plant_a.pressure").unit()
'bar'

metric_id is the value of the field selected by dataset_metadata.metric_key. It can be omitted for SeriesMetadata and SingleTSFrameMetadata; MultiTSFrameMetadata requires it for methods reading one metric, even if only one metric is present. column selects a value dimension and defaults to "value".

Methods in the plural return dictionaries by metric ID; value-dimension methods return nested dictionaries as result[metric_id][column]. Missing fields return None; metric() raises KeyError for an unknown metric. See Default time zones, Recording information and Default aggregation methods for their specific defaults.

with_metric, with_value_dimension and with_dataset_metadata accept field changes as keyword arguments and validate the changed metadata. Use these methods for updates; model_copy(update=...) does not validate replacement values. Use hdhelpers.metadata.attrs_to_json() when exporting pandas attrs, or model_dump(mode="json") to obtain the model’s convention fields directly.

Root classes and methods

The shared methods are documented once under SeriesMetadata below. They are also available on SingleTSFrameMetadata and MultiTSFrameMetadata. Conversion methods change only metadata; convert the pandas data separately to match it.

class hdhelpers.metadata.conventions.SeriesMetadata(**data)[source]

Immutable metadata for a SERIES: one metric with a single “value” dimension.

Read from a pandas Series with read_metadata. See the module documentation for storage, adapter exchange and common field rules.

as_singletsframe(column: str = 'value') → SingleTSFrameMetadata[source]

The metadata of the SINGLETSFRAME with the values of the SERIES in column

Renames the value dimension “value” of the metric and the shared one to column.

default_aggregation_method(metric_id: str | None = None) → str

The default aggregation method of the metric, see the module docstring

default_aggregation_methods() → dict[str, str]
default_timezone(metric_id: str | None = None) → str | None

The default time zone of the metric, otherwise the one of the dataset metadata

default_timezones() → dict[str, str | None]
display_name(metric_id: str | None = None, column: str = 'value', *, include_inherited: bool = False) → str | None

The display name, falling back to the name

display_names(*, include_inherited: bool = False) → dict[str, dict[str, str | None]]
measurement(metric_id: str | None = None, column: str = 'value', *, include_inherited: bool = False) → str | None
measurements(*, include_inherited: bool = False) → dict[str, dict[str, str | None]]
metric(metric_id: str | None = None) → MetricMetadata

The metadata of a metric, KeyError if there is none

metric_ids() → list[str]

The ids of the metrics, i.e. their values of the field named by the metric key

metric_info(field: str, metric_id: str | None = None, *, include_inherited: bool = True) → Any

Information of a metric, see the module docstring for the fallbacks

metric_infos(field: str, *, include_inherited: bool = True) → dict[str, Any]
name(metric_id: str | None = None, column: str = 'value', *, include_inherited: bool = False) → str | None
names(*, include_inherited: bool = False) → dict[str, dict[str, str | None]]
queried_interval() → tuple[datetime | None, datetime | None]

Start and end of the queried interval (the ref interval), None if missing

recording(metric_id: str | None = None) → Recording

How the values of the metric are recorded

The frequency with its offset and time zone falls back to the ones of the dataset metadata as a whole.

recordings() → dict[str, Recording]
short_display_name(metric_id: str | None = None, column: str = 'value', *, include_inherited: bool = False) → str | None

The short display name, falling back to the display name and the name

short_display_names(*, include_inherited: bool = False) → dict[str, dict[str, str | None]]
unit(metric_id: str | None = None, column: str = 'value', *, include_inherited: bool = False) → str | None
units(*, include_inherited: bool = False) → dict[str, dict[str, str | None]]
value_dimension_info(fields: str | Sequence[str], metric_id: str | None = None, column: str = 'value', *, include_inherited: bool = False) → Any

Information of a value dimension, trying the fields in turn

value_dimension_infos(fields: str | Sequence[str], *, include_inherited: bool = False) → dict[str, dict[str, Any]]

Information of the value dimensions by column by metric

The value dimensions of a metric are its own ones, “value” and the shared ones.

with_dataset_metadata(**changes: Any) → Self

A version with fields of the dataset metadata changed, the metrics are shared

Validated including all rules of the conventions, since the dataset metadata concerns all metrics.

with_metric(metric_id: str | None = None, /, **changes: Any) → Self

A version with fields of a metric changed, the other metrics are shared

The changed metric is validated, including the rules of the conventions which concern it.

with_value_dimension(metric_id: str | None = None, column: str = 'value', /, **changes: Any) → Self

A version with fields of a value dimension of a metric changed, see with_metric

class hdhelpers.metadata.conventions.SingleTSFrameMetadata(**data)[source]

Immutable metadata for a SINGLETSFRAME: one metric with one or more value columns.

Read from a pandas DataFrame with read_metadata. See the module documentation for storage, adapter exchange and common field rules.

as_series(column: str = 'value') → SeriesMetadata[source]

The metadata of the SERIES with the values of column

Keeps only the value dimensions of column, renamed to “value”. KeyError if the metric has no value dimension of column.

as_multitsframe(metric_id: str | None = None) → MultiTSFrameMetadata[source]

The metadata of the MULTITSFRAME of the single metric, named metric_id if given

If metric_id differs from the id of the metric, it becomes its id: in the field named by the metric key if the metric does not have it, otherwise in the field “metric”, which then becomes the metric key.

class hdhelpers.metadata.conventions.MultiTSFrameMetadata(**data)[source]

Immutable metadata for a MULTITSFRAME: multiple metrics identified by a metric column.

Each metric can have several value dimensions; a MULTITSFRAME may also hold one metric. Read from a pandas DataFrame with read_metadata. See the module documentation for storage, adapter exchange and common field rules.

narrowed_to(metric_id: str) → SingleTSFrameMetadata[source]

The metadata of the SINGLETSFRAME of one metric, KeyError if it has no metadata

The metric is shared, not copied. It becomes the single and only queried metric.

Reading method guide

Shared methods

Methods

Purpose

SeriesMetadata.metric_ids(), metric()

List metric identifiers or retrieve a metric’s metadata.

SeriesMetadata.value_dimension_info(), value_dimension_infos()

Read a field or dotted path for one value dimension, or for all metrics and columns. An ordered sequence of fields specifies fallbacks, e.g. ("display_name", "name").

SeriesMetadata.unit(), units(), measurement(), measurements()

Read units or measured quantities, e.g. "°C" or "temperature".

SeriesMetadata.name(), names(), display_name(), display_names(), short_display_name(), short_display_names()

Read names or labels with the documented fallbacks.

SeriesMetadata.metric_info(), metric_infos()

Read a field or dotted path, searching the metric before its value dimension. Inherited properties are a final fallback when enabled.

SeriesMetadata.default_timezone(), default_timezones()

Read the time zone for calculations, falling back to the dataset default.

SeriesMetadata.recording(), recordings()

Read Recording objects describing how values are recorded.

SeriesMetadata.default_aggregation_method(), default_aggregation_methods()

Read explicit or inferred aggregation methods, normalizing AVG to MEAN.

SeriesMetadata.queried_interval()

Read the requested interval as UTC datetimes.

Nested metadata

These classes describe the root models’ fields. Construct them from convention fields with ModelName.model_validate(mapping), or access them through a root model, e.g. meta.metric().value_dimensions. Required fields may accept None where the conventions permit unknown values.

class hdhelpers.metadata.conventions.MetricMetadata(**data)[source]

Metadata of a metric, i.e. of a single, possibly multidimensional timeseries

A metric is identified by its field named by dataset_metadata.metric_key, whose values occur in the metric column of a MULTITSFRAME. Every metric must have this field as a string, unique among the metrics.

Required fields include id, name and value_dimensions. Other fields describe labels, recording, default time zone, aggregation, comments and inherited properties.

class hdhelpers.metadata.conventions.ValueDimensionMetadata(**data)[source]

Metadata for one metric’s value column, such as its unit and measured quantity.

Each metric describes its value columns; a SERIES uses “value”. Non-null fields take precedence over shared metadata for the same column. Unit and measurement are required fields, but may be None if unknown.

Required fields are column, unit and measurement. Unit and measurement may be None. Optional fields include names, data type, deadband and display precision.

class hdhelpers.metadata.conventions.SharedValueDimensionMetadata(**data)[source]

Default metadata for a value column shared across metrics.

Matched by column name (“value” for a SERIES) and used when the corresponding field is missing from metric-specific metadata.

column identifies the value dimension. Its other fields supply shared defaults.

class hdhelpers.metadata.conventions.SingleMetricDatasetMetadata(**data)[source]

Metadata associated with a SERIES or SINGLETSFRAME as a whole

E.g. the queried time interval or how existing data should be handled when the dataset is sent to an adapter. The fields concerning invalidation and deletion are only relevant for adapters actually supporting these operations, like the built-in SQL adapter. Other adapters may ignore them.

Start and end of an interval must be provided together.

single_metric identifies the sole metric using metric_key.

class hdhelpers.metadata.conventions.MultiTSFrameDatasetMetadata(**data)[source]

Metadata associated with a MULTITSFRAME as a whole

E.g. the queried time interval or how existing data should be handled when the dataset is sent to an adapter. The fields concerning invalidation and deletion are only relevant for adapters actually supporting these operations, like the built-in SQL adapter. Other adapters may ignore them.

Start and end of an interval must be provided together.

Both dataset models include metric_key, queried_metrics, the requested interval, default settings and adapter invalidation settings. Here single_metric is optional and applies only to a dataset containing one metric.

class hdhelpers.metadata.conventions.InheritedMetricMetadata(**data)[source]

Properties supplied by a source system for a metric and its parent assets.

Stores already-resolved values, e.g. a plant’s latitude; the source system resolves the hierarchy. Metadata lookups use these properties as fallbacks only with include_inherited=True. Convention-defined fields such as name, id and unit belong in the metric or value-dimension metadata.

Use JSON types matching each value’s meaning: numbers, booleans and UTC ISO timestamp strings for points in time. For example, hetida platform supplies properties by label, using a signal’s own value or that of the nearest parent asset providing one.

class hdhelpers.metadata.conventions.MetricComment(**data)[source]

A comment attached to a metric, describing a time range of its timeseries data

E.g. the hetida platform provides the comments on a signal whose time range overlaps the queried interval and which existed at query time, newest first.

Start and end of the time range must be provided together. They are equal for a comment on a single point in time.

class hdhelpers.metadata.conventions.MetricCommentReply(**data)[source]

A reply to a comment attached to a metric

class hdhelpers.metadata.conventions.SignalGroupMetadata(**data)[source]

A group of signals a dataset was read from

E.g. the hetida platform provides the signal group a MULTITSFRAME was read from.

Allowed values and validation issues

class hdhelpers.metadata.conventions.IntervalType(*values)[source]

Which boundaries belong to a time interval

closed: both, open: none, left_closed / right_open: only the start, right_closed / left_open: only the end.

class hdhelpers.metadata.conventions.AggregationMethod(*values)[source]

Method for aggregating timeseries values into coarser intervals.

Metadata lookups normalize AVG to MEAN; they are distinct enum values.

class hdhelpers.metadata.conventions.ValueDataType(*values)[source]

Data type of the values of a value dimension

class hdhelpers.metadata.conventions.RecordingMode(*values)[source]

When the values of a timeseries are recorded

periodic: one value per interval of data_frequency, timestamped with the start of the interval. A missing value is a gap. on_change: a value is recorded when it changes (by more than the deadband of its value dimension) and holds until the next one. Missing timestamps are no gaps, as long as data_frequency (the heartbeat) is not exceeded. irregular: values at arbitrary points in time.

class hdhelpers.metadata.conventions.MetadataIssueSeverity(*values)[source]

Severity of an issue found when checking metadata against the metadata conventions

error: Violates the conventions, so helpers and components may misinterpret the metadata. warning: Likely a mistake, e.g. metadata not matching the data.

class hdhelpers.metadata.conventions.MetadataConventionIssue(**data)[source]

A metadata validation problem, reported as an error or warning.

severity

Error for a violation; warning for a likely mistake.

Type:

MetadataIssueSeverity

location

Path to the affected field, e.g. “metrics[0].name”; empty for the metadata as a whole.

Type:

str

message

Explanation of the problem.

Type:

str

Obtain validation issues with hdhelpers.metadata.check_metadata_conventions(). When required metadata cannot be read, hdhelpers.metadata.read_metadata() raises MetadataConventionError, whose issues attribute contains these issue objects.