hdhelpers

Introduction

hdhelpers is a package designed for and included in the standard installation of the hetida designer.

It contains functions that streamline plotting components, especially those that are used in the hetida platform, by

  • accessing series metadata that complies with the hetida platform metadata scheme,

  • aditional helper functions like adjusting the timezone of timestamps, series, and dataframes,

  • accessing metadata that the hetida platform writes into the hetida designer’s plot_target_settings context variable (tbd),

  • providing toggleable standardized styling options and json serialization for plotly plots (tbd).

Further Information

Functions

metadata

Collection of functions to access metadata information from timeseries objects. Metadata information can follow varying conventions as the package glom is used to extract the requested information.

hdhelpers.metadata.get_display_names(multitsframe)

Gets display names of the MTSF metrics from the metadata

Parameters:

multitsframe (pd.DataFrame) – MTSF with metadata following the convention.

Returns:

Dictionary of metrics containing the display names. If the display name of the metrics is not present it returns the result of hdhelpers.metadata.get_names().

Return type:

defaultdict[str, defaultdict[str, str | None]]

Raises:

TypeError – If multitsframe is not a DataFrame.

Code example:

>>> attr = { "by_metric": { "metric1": {"metric": {"display_name": "display_name_of_metric1"}},
...                         "metric2": {"metric": {"name": "name_of_metric2"}}}}
>>> dataframe.attrs = attr
>>> result = get_display_names(dataframe)
>>> result["metric1"]["value"]
'display_name_of_metric1'
>>> result["metric2"]["value"]
'name_of_metric2'

Lets try another MTSF format:

>>> attr = { "dataset_metadata": {"metric_key": "external_id"},
...          "metrics": [{"external_id": "ruhr-temperature",
...                       "name": "Ruhr temperature [°C]",
...                       "display_name": "temperature [°C]",
...                       "short_display_name": "[°C]",
...                       "value_dimensions": [{"column": "temp", "measurement": "temperature", "unit": "°C"}]}]}
>>> dataframe.attrs = attr
>>> result = get_display_names(dataframe)
>>> result["ruhr-temperature"]["value"]
'temperature [°C]'
hdhelpers.metadata.get_measurements(multitsframe)

Gets measurement (type) of the MTSF metrics from the metadata

Parameters:

multitsframe (pd.DataFrame) – MTSF with metadata following the convention.

Returns:

Dictionary of metrics containing the measurement (type) of the MTSF metrics. If the short measurement (type) of the MTSF metrics is not present it returns None.

Return type:

defaultdict[str, defaultdict[str, str | None]]

Raises:

TypeError – If multitsframe is not a DataFrame.

Code example:

>>> attr = { "dataset_metadata": {"metric_key": "external_id"},
...          "metrics": [{"external_id": "column_name", "value_dimensions": [{"column": "temp", "measurement": "temperature"}]}]}
>>> dataframe.attrs = attr
>>> result = get_measurements(dataframe)
>>> result["column_name"]["temp"]
'temperature'
hdhelpers.metadata.get_metric_info(multitsframe, metric_info)

Gets a dictionary of metadata associated to metrics.

In contrast to metadata associated to concrete value dimensions, this function abstracts access to metadata associated to the underlying metric.

Parameters:
  • multitsframe (pd.DataFrame) – MTSF with metadata following the convention.

  • metric_info (str | Spec) – Name of information to retrieve. Note that metric_info is interpreted as a glom Spec.

Returns:

Dictionary, where keys are the entries of the metrics metadata specified via “metric_key” in “dataset_metadata” and values are the entries specified via “metric_info” in the metrics metadata

Return type:

defaultdict[str, Any]

Code example:

>>> multitsframe.attrs = {
...    "dataset_metadata": {
...        "metric_key": "id"
...    },
...    "metrics": [
...        {
...            "id": "first",
...            "external_id": "external_first",
...            "unit": "m",
...            "display_name": "first display name",
...            "value_dimensions": [
...                {
...                    "column": "temp",
...                    "unit": "C",
...                    "measurement": "temperature"
...                }
...            ]
...        },
...        {
...            "id": "second",
...            "name": "second name",
...            "external_id": "external_second",
...            "value_dimensions": [
...                {
...                    "column": "temp",
...                    "unit": "C"
...                }
...            ]
...        }
...    ]
... }
>>> result = get_metric_info(multitsframe, "external_id")
>>> result["first"]
'external_first'
>>> result["second"]
'external_second'
>>> result["not-given"] is None
True
hdhelpers.metadata.get_names(multitsframe)

Gets names of the MTSF metrics from the metadata

Parameters:

multitsframe (pd.DataFrame) – MTSF with metadata following the convention.

Returns:

Dictionary of metrics containing the names. If the name is not present for a metric the corresponding value is None.

Return type:

dict[str, str | None]

Raises:

TypeError – If multitsframe is not a DataFrame.

Code example:

>>> attr = { "by_metric": { "metric1": {"metric": {"name": "name_of_metric1"}},
...                        "metric2": {"metric": {"name": None }} }}
>>> dataframe.attrs = attr
>>> result = get_names(dataframe)
>>> result["metric1"]["value"]
'name_of_metric1'
>>> result["metric2"]["value"] is None
True

Lets try another MTSF format:

>>> attr = { "dataset_metadata": {"metric_key": "external_id"},
...          "metrics": [{"external_id": "ruhr-temperature",
...                       "name": "Ruhr temperature [°C]",
...                       "display_name": "temperature [°C]",
...                       "short_display_name": "[°C]",
...                       "value_dimensions": [{"column": "temp", "measurement": "temperature", "unit": "°C"}]}]}
>>> dataframe.attrs = attr
>>> result = get_names(dataframe)
>>> result["ruhr-temperature"]["value"]
'Ruhr temperature [°C]'
hdhelpers.metadata.get_queried_interval(data)

Get queried interval from metadata

Parameters:

data (pd.Series | pd.DataFrame) – Series or Dataframe with metadata following the convention

Returns:

Tuple of available start and end date of requested interval.

Return type:

tuple[datetime.datetime | None, datetime.datetime | None]

Raises:
  • ValueError – If metadata of data is not None and not convertible to a datetime-object (ISO-format is expected).

  • TypeError – If data is not a Series or Dataframe.

Code example:

>>> attr = {
...        "dataset_metadata": {
...        "ref_interval_start_timestamp": "2025-11-05T13:28:00Z",
...        "ref_interval_end_timestamp": "2025-11-06T13:28:00Z"
...    }
... }
>>> series.attrs = attr
>>> start, end = get_queried_interval(series)
>>> start.isoformat()
'2025-11-05T13:28:00+00:00'
>>> end.isoformat()
'2025-11-06T13:28:00+00:00'
hdhelpers.metadata.get_series_display_name(series)

Gets display name of the series from metadata

Parameters:

series (pd.Series) – Series with metadata following the convention.

Returns:

Returns the display name of the value. If the display name of the metric is not present it returns the display name of the value. If the metric display name is not present it returns the result of hdhelpers.metadata.get_series_name().

Return type:

str | None

Raises:

TypeError – If series is not a Series.

Code example:

>>> attr = { "by_metric": { "series": {"metric": {"display_name": "display_name_of_series"}}}}
>>> series.attrs = attr
>>> get_series_display_name(series)
'display_name_of_series'
hdhelpers.metadata.get_series_info(series, value_dim_info)

Gets an arbitrary series info

Since a series has only one value dimension named “value”, this information is equivalent to information on the metric.

Parameters:
  • series (pd.Series) – Series with metadata following the convention.

  • value_dim_info (str | Spec) – Name of information to retrieve. Note that value_dim_info is interpreted as a glom Spec.

Returns:

Retrieved information defined by value_dim_info

Return type:

Any

Code example:

>>> attr = { "by_metric": { "series": {"value_dimensions": {"value": {"unit": "m"}}}}}
>>> series.attrs = attr
>>> get_series_info(series, "unit")
'm'
>>> get_series_info(series, "not-given") is None
True
hdhelpers.metadata.get_series_measurement(series)

Gets measurement (type) of the Series from metadata

Parameters:

series (pd.Series) – Series with metadata following the convention.

Returns:

Returns the measurement (type) of the value. If “measurement” is not given in the metadata, None is returned.

Return type:

str | None

Raises:

TypeError – If series is not a Series.

Code example:

>>> attr = { "by_metric": { "series": { "metric": {"measurement": "temperature"}}}}
>>> series.attrs = attr
>>> get_series_measurement(series)
'temperature'
hdhelpers.metadata.get_series_name(series)

Gets name of the series from metadata

Parameters:

series (pd.Series) – Series with metadata following the convention.

Returns:

Returns the name of the value. If the name of the metric is not present it returns the name of the value. If the value name is not present it returns None.

Return type:

str | None

Raises:

TypeError – If series is not a Series.

Let’s test what happens if series has name in value_dimensions:

>>> attr = { "by_metric": { "series": {"value_dimensions": {"value": {"name": "value_name_of_series"}}}}}
>>> series.attrs = attr
>>> get_series_name(series)
'value_name_of_series'

Let’s test what happens if series has name in metric:

>>> attr = { "by_metric": { "series": {"metric": {"name": "name_of_series_1"}}}}
>>> series.attrs = attr
>>> get_series_name(series)
'name_of_series_1'

Let’s test what happens if series has name in metric and value_dimensions:

>>> attr = { "single_metric_metadata": { "structured_metadata": {"metric": {"name": "name_of_series_2"}},
...                                                              "value_dimensions": {"value": {"name": "value_name_of_series"}}}}
>>> series.attrs = attr
>>> get_series_name(series)
'name_of_series_2'
hdhelpers.metadata.get_series_short_display_name(series)

Gets short display name of the Series from metadata

Parameters:

series (pd.Series) – Series with metadata following the convention.

Returns:

Returns the short display name of the value. If the short display name of the metric is not present it returns the short display name of the value. If the metric short display name is not present it returns the result of hdhelpers.metadata.get_series_display_name().

Return type:

str | None

Raises:

TypeError – If series is not a Series.

Code example:

>>> attr = { "by_metric": { "series": { "metric": {"short_display_name": "short_display_name_of_series"}}}}
>>> series.attrs = attr
>>> get_series_short_display_name(series)
'short_display_name_of_series'
hdhelpers.metadata.get_series_unit(series)

Gets name of the series from metadata

Parameters:

series (pd.Series) – Series with metadata following the convention.

Returns:

Returns the unit of series. If the unit of the series is not present it returns None.

Return type:

str | None

Raises:

TypeError – If series is not a Series.

Let’s test what happens if series has no attr:

>>> series.attrs = {}
>>> get_series_unit(series) is None
True

Let’s test what happens if series has attr but no entry for unit:

>>> attr = { "by_metric": { "series": {"value_dimensions": {"value": {"unit":None}}}}}
>>> series.attrs = attr
>>> get_series_unit(series) is None
True

Let’s test what happens if series has unit in attr:

>>> attr = { "by_metric": { "series": {"value_dimensions": {"value": {"unit":"m/s"}}}}}
>>> series.attrs = attr
>>> get_series_unit(series)
'm/s'
hdhelpers.metadata.get_short_display_names(multitsframe)

Gets short display names of the MTSF metrics from the metadata

Parameters:

multitsframe (pd.DataFrame) – MTSF with metadata following the convention.

Returns:

Dictionary of metrics containing the short display names. If the short display name of the metrics is not present it returns the result of hdhelpers.metadata.get_display_names().

Return type:

defaultdict[str, defaultdict[str, str | None]]

Raises:

TypeError – If multitsframe is not a DataFrame.

Code example:

>>> attr = { "by_metric": { "metric1": {"metric": {"short_display_name": "short_display_name_of_metric1"}},
...                         "metric2": {"metric": {"name": "name_of_metric2"}},
...                         "metric3": {"metric": {"name": None}} }}
>>> dataframe.attrs = attr
>>> result = get_short_display_names(dataframe)
>>> result["metric1"]["value"]
'short_display_name_of_metric1'
>>> result["metric2"]["value"]
'name_of_metric2'
>>> result["metric3"]["value"] is None
True

Lets try another MTSF format:

>>> attr = { "dataset_metadata": {"metric_key": "external_id"},
...          "metrics": [{"external_id": "ruhr-temperature",
...                       "name": "Ruhr temperature [°C]",
...                       "display_name": "temperature [°C]",
...                       "short_display_name": "temp. [°C]",
...                       "value_dimensions": [{"column": "temp", "measurement": "temperature", "unit": "°C"}]}]}
>>> dataframe.attrs = attr
>>> result = get_short_display_names(dataframe)
>>> result["ruhr-temperature"]["value"]
'temp. [°C]'
hdhelpers.metadata.get_units(multitsframe)

Gets unit of value dimensions in MTSF metrics from Metadata

Parameters:

multitsframe (pd.DataFrame) – MTSF with metadata following the convention.

Returns:

Dictionary of metrics containing the names of the value dimensions. If the short display name of the value_dimension is not present it returns the result of get_value_dimension_info().

Return type:

dict[str, dict[str | None] | None]

Raises:

TypeError – If multitsframe is not a DataFrame.

Code example:

>>> attr = {
...    "by_metric": {
...        "metric1": {
...           "value_dimensions": {
...                "value_dim_1": {
...                    "unit": "m"
...                }
...            }
...        },
...        "metric3": {
...            "value_dimensions": {
...                 "value_dim_1": {
...                     "unit": None,
...                 }
...            }
...        }
...    }
... }
>>> dataframe.attrs = attr
>>> result = get_units(dataframe)
>>> result["metric1"]['value_dim_1']
'm'
>>> result["metric3"]['value_dim_1'] is None
True
>>> result["metric2"]['value_dim_1'] is None
True

helpers

Collection of useful functions to ease some operations in hetida designer code.

hdhelpers.helpers.modify_timezone(object_to_convert, to_timezone=None, column_names=None, convert_index=True)

Converts time information of pandas objects to a certain timezone

This function is applicable to index and/or columns of pd.Series or pd.DataFrame as well as for single pd.Timestamp objects.

Parameters:
  • object_to_convert (pd.Timestamp | pd.Series | pd.DataFrame) – Timestamp, Series or DataFrame where timezone is modified

  • to_timezone (str | None) – Timezone to convert to, e.g. for German time use “Europe/Berlin”. See possible timezone strings in pandas’ tz_convert method or pytz all_timezones list. If to_timezone is not defined, the global timezone from plot_target_settings is used. .

  • column_names (str | None) – List of column_names to modify. For pd.Series the default behaviour is modifying the index and for pd.DataFrame the default behaviour is modifying the column “timestamp”. This option is not applicable in case object_to_convert is a pd.Timestamp.

  • convert_index (bool | None) – Boolean that controls whether the index of pd.Dataframe or pd.Series should be transformed. Note that for a pd.Series setting this option to true results in the same output as using column_names=None. This option is not applicable in case object_to_convert is a pd.Timestamp.

Returns:

Returns the modified timezone object.

Return type:

pd.Timestamp | pd.Series | pd.DataFrame

Raises:

TypeError – If object_to_convert is not a pd.Series, pd.Timestamp, pd.DataFrame.

Code example:

>>> from hdhelpers.helpers import modify_timezone
>>> modified_timezone = modify_timezone(pd.to_datetime("2025-01-01T01:00:00+05:00"), to_timezone="Europe/Berlin")
>>> int(modified_timezone.utcoffset().total_seconds())
3600

exceptions

exception hdhelpers.exceptions.HelperException(*args, error_code='', extra_information=None, **kwargs)

Bases: Exception

Exception to re-raise exceptions with error code raised in the code of the hdhelpers package.

Parameters:
  • args (Any)

  • error_code (int | str)

  • extra_information (dict | None)

  • kwargs (Any)

Return type:

None

exception hdhelpers.exceptions.InsufficientPlottingData(*args, error_code='', extra_information=None, **kwargs)

Bases: HelperException

A plot component has insufficient data to generate a meaningful plot

This exception class should be used when custom plots generated by hetida designer are integrated in other frontends. This allows the frontend to handle the case of e.g. no data to show in a sensible way, surpressing an empty plot and showing an adequate message instead.

Parameters:
  • args (Any)

  • error_code (int | str)

  • extra_information (dict | None)

  • kwargs (Any)

Return type:

None