Source code for nilmtk.appliance

from __future__ import print_function, division
from warnings import warn
from collections import namedtuple
from copy import deepcopy
from .hashable import Hashable
from .utils import flatten_2d_list
from nilm_metadata import get_appliance_types

ApplianceID = namedtuple('ApplianceID', ['type', 'instance'])
DEFAULT_ON_POWER_THRESHOLD = 10

[docs]class Appliance(Hashable): """Represents an appliance instance. Attributes ---------- metadata : dict See here metadata attributes: http://nilm-metadata.readthedocs.org/en/latest/dataset_metadata.html#appliance """ #: Static (AKA class) variable. Maps from appliance_type (string) to a dict #: describing metadata about each appliance type. appliance_types = {} def __init__(self, metadata=None): self.metadata = {} if metadata is None else metadata # Instantiate static appliance_types if not Appliance.appliance_types: Appliance.appliance_types = get_appliance_types() # Check appliance type if (self.identifier.type and not Appliance.appliance_types.has_key(self.identifier.type)): warn("'{}' is not a recognised appliance type." .format(self.identifier.type), RuntimeWarning) @property
[docs] def identifier(self): """Return ApplianceID""" md = self.metadata return ApplianceID(md.get('type'), md.get('instance'))
@property
[docs] def type(self): """Return deepcopy of dict describing appliance type.""" return deepcopy(Appliance.appliance_types[self.identifier.type])
@property
[docs] def n_meters(self): """Return number of meters (int) to which this appliance is connected""" return len(self.metadata['meters'])
[docs] def on_power_threshold(self): threshold_from_appliance_type = self.type.get('on_power_threshold', DEFAULT_ON_POWER_THRESHOLD) return self.metadata.get('on_power_threshold', threshold_from_appliance_type)
[docs] def label(self, pretty=False): """Return string '(<type>, <identifier>)' e.g. '(fridge, 1)' if `pretty=False` else if `pretty=True` then return a string like 'Fridge' or 'Fridge 2'. If type == 'unknown' then appends `original_name` to end of label.""" if pretty: label = str(self.identifier.type) label = label.capitalize() if self.identifier.instance > 1: label += " {}".format(self.identifier.instance) else: label = str(tuple(self.identifier)) if self.identifier.type is 'unknown': label += ', original name = {}'.format( self.metadata.get('original_name')) return label
[docs] def categories(self): """Return 1D list of category names (strings).""" return flatten_2d_list(self.type.get('categories').values())
[docs] def matches(self, key): """ Parameters ---------- key : dict Returns ------- Bool True if all key:value pairs in `key` match `appliance.metadata` or `Appliance.appliance_types[appliance.metadata['type']]`. Returns True if key is empty dict. """ if not key: return True if not isinstance(key, dict): raise TypeError() match = True for k, v in key.iteritems(): if hasattr(self.identifier, k): if getattr(self.identifier, k) != v: match = False elif self.metadata.has_key(k): if self.metadata[k] != v: match = False elif k == 'category': if v not in self.categories(): match = False elif self.type.has_key(k): metadata_value = self.type[k] if (isinstance(metadata_value, list) and not isinstance(v, list)): # for example, 'control' is a list in metadata if v not in metadata_value: match = False elif metadata_value != v: match = False else: raise KeyError("'{}' not a valid key.".format(k)) return match