Source code for smif.metadata

# -*- coding: utf-8 -*-
"""Encapsulates the input or output parameters of a sector model,
for example::

        - name: petrol_price
          spatial_resolution: GB
          temporal_resolution: annual
          units: £/l
        - name: diesel_price
          spatial_resolution: GB
          temporal_resolution: annual
          units: £/l
        - name: LPG_price
          spatial_resolution: GB
          temporal_resolution: annual
          units: £/l

"""
from __future__ import absolute_import, division, print_function

import collections.abc
import logging

from smif.convert.unit import get_register as get_unit_register

__author__ = "Will Usher, Tom Russell"
__copyright__ = "Will Usher, Tom Russell, University of Oxford 2017"
__license__ = "mit"


[docs]class Metadata(object): """All metadata about a single dataset, typically model input or output Arguments ========= name: str The dataset name spatial_resolution: :class:`smif.convert.region.RegionSet` The region set that defines the spatial resolution temporal_resolution: :class:`smif.convert.interval.IntervalSet` The interval set that defines the temporal resolution units: str Name of the units for the dataset values """ def __init__(self, name, spatial_resolution, temporal_resolution, units): self.unit_register = get_unit_register() self.logger = logging.getLogger(__name__) self.name = name self.spatial_resolution = spatial_resolution self.temporal_resolution = temporal_resolution self.units = self.normalise_unit(units, name) def __repr__(self): return repr(self.as_dict()) def __eq__(self, other): return self.name == other.name \ and self.spatial_resolution == other.spatial_resolution \ and self.temporal_resolution == other.temporal_resolution \ and self.units == other.units
[docs] def as_dict(self): config = { 'name': self.name, 'spatial_resolution': self.spatial_resolution.name, 'temporal_resolution': self.temporal_resolution.name, 'units': self.units }
return config
[docs] def normalise_unit(self, unit_string, param_name): """Parse unit and return standard string representation """ unit = self.unit_register.parse_unit(unit_string) if unit is not None: # if parsed successfully normalised = str(unit) else: normalised = unit_string self.logger.debug("Using unit for %s: %s", param_name, normalised)
return normalised
[docs] def get_region_names(self): """The list of region names for this spatial resolution """
return self.spatial_resolution.get_entry_names()
[docs] def get_interval_names(self): """The list of interval names for this temporal resolution """
return self.temporal_resolution.get_entry_names()
[docs]class MetadataSet(collections.abc.Mapping): """A container for metadata about model inputs or outputs Arguments ========= metadata: list A list of dicts like :: { 'name': 'heat_demand' 'spatial_resolution': smif.convert.ResolutionSet 'temporal_resolution': smif.convert.ResolutionSet 'units': 'kW' } Or, a list of smif.metadata.Metadata Metadata('heat_demand', smif.convert.area.RegionSet, smif.convert.interval.IntervalSet, 'kW') """ def __init__(self, metadata_list=None): self._metadata = {} if metadata_list is not None: for metadata_item in metadata_list: self.add_metadata(metadata_item) def __repr__(self): return "MetadataSet({})".format(repr(list(self._metadata.values()))) @property def metadata(self): """A list of the model parameters Returns ======= parameters: list A list of :class:`smif.Metadata`, sorted by name """ sorted_keys = sorted(list(self._metadata.keys())) return [self._metadata[key] for key in sorted_keys] def __len__(self): return len(self._metadata) def __getitem__(self, name): if name in self._metadata: metadata_item = self._metadata[name] else: raise KeyError("No metadata found for name '{}'".format(name)) return metadata_item def __iter__(self): for item in self._metadata: yield item
[docs] def add_metadata(self, item): """Add an item to the set Arguments --------- item: Metadata or dict Metadata object or dictionary with keys 'name', 'spatial_resolution', 'temporal_resolution' and 'units' """ if isinstance(item, dict): item = Metadata( item['name'], item['spatial_resolution'], item['temporal_resolution'], item['units'] ) assert isinstance(item, Metadata)
self._metadata[item.name] = item
[docs] def get_spatial_res(self, name): """The spatial resolution for parameter `name` Arguments --------- name: str The name of a model parameter """
return self[name].spatial_resolution
[docs] def get_temporal_res(self, name): """The temporal resolution for parameter `name` Arguments --------- name: str The name of a model parameter """
return self[name].temporal_resolution
[docs] def get_units(self, name): """The units used for parameter 'name' Arguments --------- name: str The name of a model parameter """
return self[name].units @property def spatial_resolutions(self): """A list of the spatial resolutions Returns ------- list A list of the spatial resolutions associated with the model parameters """ return [parameter.spatial_resolution for parameter in self._metadata.values()] @property def temporal_resolutions(self): """A list of the temporal resolutions Returns ------- list A list of the temporal resolutions associated with the model parameters """ return [parameter.temporal_resolution for parameter in self._metadata.values()] @property def names(self): """A list of the parameter names """ return [parameter.name for parameter in self._metadata.values()] @property def units(self): """A list of the units Returns ------- list A list of the units associated with the model parameters """
return [parameter.units for parameter in self._metadata.values()]