openrvdas.logger.transforms.delta_transform

No module-level documentation available.
  1import logging
  2from typing import Union
  3
  4from logger.utils.das_record import DASRecord  # noqa: E402
  5from logger.transforms.transform import Transform
  6
  7KNOWN_FIELD_TYPES = ['polar']
  8
  9
 10################################################################################
 11def polar_diff(last_value, value):
 12    return ((value - last_value) + 180) % 360 - 180
 13
 14
 15################################################################################
 16class DeltaTransform(Transform):
 17    def __init__(self, rate=False, field_type=None, **kwargs):
 18        """Return a DASRecord (or dict, depending on input record type) with
 19        each field's delta in value from it's previous value. If a field
 20        is absent, it will be omitted. The first time a field appears, it
 21        will be omitted (as there is no previous value to delta from). If
 22        no deltas are available, None will be returned.
 23
 24        rate — If True, return the rate of change (delta/second). If a
 25               list of field names, return rate of change for field names
 26               in the list, simple delta for all others.  fields, or just
 27               return the delta.
 28
 29        field_type — if not None, should be a dict mapping field names to
 30               special field types, if any. Currently, only 'polar' is
 31               implemented.
 32        """
 33        super().__init__(**kwargs)  # processes 'quiet' and type hints
 34
 35        if type(rate) not in [bool, list]:
 36            raise ValueError('"rate" argument in DeltaTransform must be either '
 37                             'a list or Boolean. Found type %s' % type(rate))
 38        if field_type:
 39            if not type(field_type) is dict:
 40                raise ValueError('"field_type" argument in DeltaTransform must be '
 41                                 ' either None or a dict. Found "%s"' %
 42                                 type(field_type))
 43            # Check that any specified field types are ones we know about.
 44            for field_name, this_field_type in field_type.items():
 45                if this_field_type not in KNOWN_FIELD_TYPES:
 46                    raise ValueError('Unknown field_type specified for field %s: %s. '
 47                                     'Known field types are: %s' %
 48                                     (field_name, this_field_type, KNOWN_FIELD_TYPES))
 49        self.rate = rate
 50        self.field_type = field_type
 51
 52        # Dict of {field_name: (previous_timestamp, previous_value)} pairs
 53        self.last_value_dict = {}
 54
 55    ############################
 56    def transform(self, record: Union[DASRecord, dict]) -> Union[DASRecord, dict]:
 57
 58        # See if it's something we can process, and if not, try digesting
 59        if not self.can_process_record(record):  # BaseModule
 60            return self.digest_record(record)  # BaseModule
 61
 62        if type(record) is DASRecord:
 63            fields = record.fields
 64            timestamp = record.timestamp
 65
 66        elif type(record) is dict:
 67            fields = record.get('fields')
 68            timestamp = record.get('timestamp')
 69        else:
 70            logging.info('Record passed to DeltaTransform was neither a dict nor a '
 71                         'DASRecord. Type was %s: %s' % (type(record), str(record)[:80]))
 72            return None
 73
 74        if fields is None:
 75            logging.info('Record passed to DeltaTransform does not have "fields": %s', record)
 76            return None
 77
 78        if timestamp is None:
 79            logging.info('Record passed to DeltaTransform does not have "timestamp": %s', record)
 80            return None
 81
 82        delta_values = {}
 83
 84        for key, value in fields.items():
 85            # If we don't have a previous value for this field, store the
 86            # current one and move on to the next field.
 87            if key not in self.last_value_dict:
 88                self.last_value_dict[key] = (timestamp, value)
 89                continue
 90
 91            last_timestamp, last_value = self.last_value_dict.get(key, (None, None))
 92
 93            # Does this field have a special type?
 94            if type(self.field_type) is dict:
 95                this_field_type = self.field_type.get(key)
 96            else:
 97                this_field_type = self.field_type
 98
 99            # What do we do with this field_type? 'None' is a simple diff
100            if this_field_type == 'polar':
101                delta_values[key] = polar_diff(last_value, value)
102            elif this_field_type is None:
103                delta_values[key] = value - last_value
104            else:
105                raise ValueError('DeltaTransform configured with unrecognized '
106                                 'field type for %s: "%s"', key, this_field_type)
107
108            # Are we doing rate or simple diff for this field?
109            if self.rate is True or type(self.rate) is list and key in self.rate:
110                time_diff = timestamp - last_timestamp
111                # If rate, make sure it's a valid time difference. Bail if it isn't.
112                if time_diff <= 0:
113                    logging.warning('Invalid difference in successive timestamps for '
114                                    'field %s:  %g -> %g', key, last_timestamp, timestamp)
115                    return None
116                delta_values[key] = delta_values[key] / time_diff
117
118            # Finally, save the current values for next time
119            self.last_value_dict[key] = (timestamp, value)
120
121        # If, at the end of it all, we don't have any fields, return None
122        if not delta_values:
123            return None
124
125        # If they gave us a dict, return a dict; if they gave us a
126        # DASRecord, return a DASRecord.
127        if type(record) is dict:
128            return {'timestamp': timestamp, 'fields': delta_values}
129
130        return DASRecord(timestamp=timestamp, fields=delta_values)
KNOWN_FIELD_TYPES = ['polar']
def polar_diff(last_value, value):
12def polar_diff(last_value, value):
13    return ((value - last_value) + 180) % 360 - 180
class DeltaTransform(logger.transforms.transform.Transform):
 17class DeltaTransform(Transform):
 18    def __init__(self, rate=False, field_type=None, **kwargs):
 19        """Return a DASRecord (or dict, depending on input record type) with
 20        each field's delta in value from it's previous value. If a field
 21        is absent, it will be omitted. The first time a field appears, it
 22        will be omitted (as there is no previous value to delta from). If
 23        no deltas are available, None will be returned.
 24
 25        rate — If True, return the rate of change (delta/second). If a
 26               list of field names, return rate of change for field names
 27               in the list, simple delta for all others.  fields, or just
 28               return the delta.
 29
 30        field_type — if not None, should be a dict mapping field names to
 31               special field types, if any. Currently, only 'polar' is
 32               implemented.
 33        """
 34        super().__init__(**kwargs)  # processes 'quiet' and type hints
 35
 36        if type(rate) not in [bool, list]:
 37            raise ValueError('"rate" argument in DeltaTransform must be either '
 38                             'a list or Boolean. Found type %s' % type(rate))
 39        if field_type:
 40            if not type(field_type) is dict:
 41                raise ValueError('"field_type" argument in DeltaTransform must be '
 42                                 ' either None or a dict. Found "%s"' %
 43                                 type(field_type))
 44            # Check that any specified field types are ones we know about.
 45            for field_name, this_field_type in field_type.items():
 46                if this_field_type not in KNOWN_FIELD_TYPES:
 47                    raise ValueError('Unknown field_type specified for field %s: %s. '
 48                                     'Known field types are: %s' %
 49                                     (field_name, this_field_type, KNOWN_FIELD_TYPES))
 50        self.rate = rate
 51        self.field_type = field_type
 52
 53        # Dict of {field_name: (previous_timestamp, previous_value)} pairs
 54        self.last_value_dict = {}
 55
 56    ############################
 57    def transform(self, record: Union[DASRecord, dict]) -> Union[DASRecord, dict]:
 58
 59        # See if it's something we can process, and if not, try digesting
 60        if not self.can_process_record(record):  # BaseModule
 61            return self.digest_record(record)  # BaseModule
 62
 63        if type(record) is DASRecord:
 64            fields = record.fields
 65            timestamp = record.timestamp
 66
 67        elif type(record) is dict:
 68            fields = record.get('fields')
 69            timestamp = record.get('timestamp')
 70        else:
 71            logging.info('Record passed to DeltaTransform was neither a dict nor a '
 72                         'DASRecord. Type was %s: %s' % (type(record), str(record)[:80]))
 73            return None
 74
 75        if fields is None:
 76            logging.info('Record passed to DeltaTransform does not have "fields": %s', record)
 77            return None
 78
 79        if timestamp is None:
 80            logging.info('Record passed to DeltaTransform does not have "timestamp": %s', record)
 81            return None
 82
 83        delta_values = {}
 84
 85        for key, value in fields.items():
 86            # If we don't have a previous value for this field, store the
 87            # current one and move on to the next field.
 88            if key not in self.last_value_dict:
 89                self.last_value_dict[key] = (timestamp, value)
 90                continue
 91
 92            last_timestamp, last_value = self.last_value_dict.get(key, (None, None))
 93
 94            # Does this field have a special type?
 95            if type(self.field_type) is dict:
 96                this_field_type = self.field_type.get(key)
 97            else:
 98                this_field_type = self.field_type
 99
100            # What do we do with this field_type? 'None' is a simple diff
101            if this_field_type == 'polar':
102                delta_values[key] = polar_diff(last_value, value)
103            elif this_field_type is None:
104                delta_values[key] = value - last_value
105            else:
106                raise ValueError('DeltaTransform configured with unrecognized '
107                                 'field type for %s: "%s"', key, this_field_type)
108
109            # Are we doing rate or simple diff for this field?
110            if self.rate is True or type(self.rate) is list and key in self.rate:
111                time_diff = timestamp - last_timestamp
112                # If rate, make sure it's a valid time difference. Bail if it isn't.
113                if time_diff <= 0:
114                    logging.warning('Invalid difference in successive timestamps for '
115                                    'field %s:  %g -> %g', key, last_timestamp, timestamp)
116                    return None
117                delta_values[key] = delta_values[key] / time_diff
118
119            # Finally, save the current values for next time
120            self.last_value_dict[key] = (timestamp, value)
121
122        # If, at the end of it all, we don't have any fields, return None
123        if not delta_values:
124            return None
125
126        # If they gave us a dict, return a dict; if they gave us a
127        # DASRecord, return a DASRecord.
128        if type(record) is dict:
129            return {'timestamp': timestamp, 'fields': delta_values}
130
131        return DASRecord(timestamp=timestamp, fields=delta_values)

Base class Transform about which we know nothing else.

Passes arguments quiet, encoding and encoding_errors up to BaseModule

DeltaTransform(rate=False, field_type=None, **kwargs)
18    def __init__(self, rate=False, field_type=None, **kwargs):
19        """Return a DASRecord (or dict, depending on input record type) with
20        each field's delta in value from it's previous value. If a field
21        is absent, it will be omitted. The first time a field appears, it
22        will be omitted (as there is no previous value to delta from). If
23        no deltas are available, None will be returned.
24
25        rate — If True, return the rate of change (delta/second). If a
26               list of field names, return rate of change for field names
27               in the list, simple delta for all others.  fields, or just
28               return the delta.
29
30        field_type — if not None, should be a dict mapping field names to
31               special field types, if any. Currently, only 'polar' is
32               implemented.
33        """
34        super().__init__(**kwargs)  # processes 'quiet' and type hints
35
36        if type(rate) not in [bool, list]:
37            raise ValueError('"rate" argument in DeltaTransform must be either '
38                             'a list or Boolean. Found type %s' % type(rate))
39        if field_type:
40            if not type(field_type) is dict:
41                raise ValueError('"field_type" argument in DeltaTransform must be '
42                                 ' either None or a dict. Found "%s"' %
43                                 type(field_type))
44            # Check that any specified field types are ones we know about.
45            for field_name, this_field_type in field_type.items():
46                if this_field_type not in KNOWN_FIELD_TYPES:
47                    raise ValueError('Unknown field_type specified for field %s: %s. '
48                                     'Known field types are: %s' %
49                                     (field_name, this_field_type, KNOWN_FIELD_TYPES))
50        self.rate = rate
51        self.field_type = field_type
52
53        # Dict of {field_name: (previous_timestamp, previous_value)} pairs
54        self.last_value_dict = {}

Return a DASRecord (or dict, depending on input record type) with each field's delta in value from it's previous value. If a field is absent, it will be omitted. The first time a field appears, it will be omitted (as there is no previous value to delta from). If no deltas are available, None will be returned.

rate — If True, return the rate of change (delta/second). If a list of field names, return rate of change for field names in the list, simple delta for all others. fields, or just return the delta.

field_type — if not None, should be a dict mapping field names to special field types, if any. Currently, only 'polar' is implemented.

rate
field_type
last_value_dict
def transform( self, record: Union[logger.utils.das_record.DASRecord, dict]) -> Union[logger.utils.das_record.DASRecord, dict]:
 57    def transform(self, record: Union[DASRecord, dict]) -> Union[DASRecord, dict]:
 58
 59        # See if it's something we can process, and if not, try digesting
 60        if not self.can_process_record(record):  # BaseModule
 61            return self.digest_record(record)  # BaseModule
 62
 63        if type(record) is DASRecord:
 64            fields = record.fields
 65            timestamp = record.timestamp
 66
 67        elif type(record) is dict:
 68            fields = record.get('fields')
 69            timestamp = record.get('timestamp')
 70        else:
 71            logging.info('Record passed to DeltaTransform was neither a dict nor a '
 72                         'DASRecord. Type was %s: %s' % (type(record), str(record)[:80]))
 73            return None
 74
 75        if fields is None:
 76            logging.info('Record passed to DeltaTransform does not have "fields": %s', record)
 77            return None
 78
 79        if timestamp is None:
 80            logging.info('Record passed to DeltaTransform does not have "timestamp": %s', record)
 81            return None
 82
 83        delta_values = {}
 84
 85        for key, value in fields.items():
 86            # If we don't have a previous value for this field, store the
 87            # current one and move on to the next field.
 88            if key not in self.last_value_dict:
 89                self.last_value_dict[key] = (timestamp, value)
 90                continue
 91
 92            last_timestamp, last_value = self.last_value_dict.get(key, (None, None))
 93
 94            # Does this field have a special type?
 95            if type(self.field_type) is dict:
 96                this_field_type = self.field_type.get(key)
 97            else:
 98                this_field_type = self.field_type
 99
100            # What do we do with this field_type? 'None' is a simple diff
101            if this_field_type == 'polar':
102                delta_values[key] = polar_diff(last_value, value)
103            elif this_field_type is None:
104                delta_values[key] = value - last_value
105            else:
106                raise ValueError('DeltaTransform configured with unrecognized '
107                                 'field type for %s: "%s"', key, this_field_type)
108
109            # Are we doing rate or simple diff for this field?
110            if self.rate is True or type(self.rate) is list and key in self.rate:
111                time_diff = timestamp - last_timestamp
112                # If rate, make sure it's a valid time difference. Bail if it isn't.
113                if time_diff <= 0:
114                    logging.warning('Invalid difference in successive timestamps for '
115                                    'field %s:  %g -> %g', key, last_timestamp, timestamp)
116                    return None
117                delta_values[key] = delta_values[key] / time_diff
118
119            # Finally, save the current values for next time
120            self.last_value_dict[key] = (timestamp, value)
121
122        # If, at the end of it all, we don't have any fields, return None
123        if not delta_values:
124            return None
125
126        # If they gave us a dict, return a dict; if they gave us a
127        # DASRecord, return a DASRecord.
128        if type(record) is dict:
129            return {'timestamp': timestamp, 'fields': delta_values}
130
131        return DASRecord(timestamp=timestamp, fields=delta_values)