Source code for otestpoint.labtools.transform

#
# Copyright (c) 2016-2017 - Adjacent Link LLC, Bridgewater, New Jersey
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#  * Neither the name of Adjacent Link LLC nor the names of its
#    contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

"""Produce a transformed labtools variable instance using a callable.

"""

from subject import Subject
from observer import Observer
import numpy as np
import pandas as pd
import traceback

[docs]class Transform(Subject,Observer): """ Transform subject data using a callable. """ def __init__(self,variable,transform,**kwargs): """Creates a Transform instance. Transform instances work on subjects with single value state or list of values state: val [val_0,val_1,...val_N] Args: variable (str) - Vairable instance to transform. transform (callable) - Callable python object. Kwargs: name (str): Subject name. Default: Transform(transform(variable)). Raises: KeyError """ Subject.__init__(self,variable.stream()) Observer.__init__(self) self._transform = transform self._cache = {} self._tags = set() self._updated = set() self._name = kwargs.pop('name',None) if self._name == None: name = "" try: name = self._transform.__name__ except: name = self._transform.__class__.__name__ self._name = "Transform(%s(%s))" % (name,variable.name()) if kwargs: raise KeyError("Unknown key(s): %s" % ", ".join(kwargs.keys())) variable.attach(self)
[docs] def name(self): """Gets the name of this subject. Returns: Subject name (str). """ return self._name
[docs] def notify(self,subject): """Processes subject update to produce new state.""" data,updated = subject.state() if not data and not updated: self._cache.clear() self._tags.clear() self._updated.clear() self.notify_observers() return # remove values in cache and previous data no longer available # in subject for purge in set(self._cache.keys()).difference(data.keys()): del self._cache[purge] # update tags and existing cache with nan for any new tag entries for tags in data.values(): for tag in tags: if tag not in self._tags: # update existing cache/previous with np.nan subject values for timestamp in self._cache: self._cache[timestamp][tag] = np.nan # update tags self._tags.update(set(tags.keys())) # update cache to include np.nan data for new timestamps for timestamp in updated: if timestamp not in self._cache: self._cache[timestamp] = {} for tag in self._tags: if tag not in self._cache[timestamp]: self._cache[timestamp][tag] = np.nan for timestamp in updated: for tag in data[timestamp]: try: self._cache[timestamp][tag] = self._transform(data[timestamp][tag]) except: print traceback.format_exc() self._cache[timestamp][tag] = np.nan self._updated = updated self.notify_observers() self._updated = set()
[docs] def state(self): """Gets the state. Returns: A dict of with timestamp (int) keys and dict values. Where each dict value has tag name (str) keys and the transformed value. Depending on the subject, that can be a single value, a list of values. """ return self._cache,self._updated