openrvdas.logger.utils.subsample
No module-level documentation available.
1#!/usr/bin/env python3 2""" 3""" 4import logging 5 6 7def subsample(algorithm, values, latest_timestamp, now): 8 """An omnibus routine for taking a list of timestamped values, a 9 specification of an averaging algorithm, and returning a list of 10 zero, one or more timestamped "averaged" output values. 11 12 algorithm The name of the algorithm to be used 13 14 values List of values to be averaged in format of 15 [(timestamp, value), (timestamp, value),...] 16 17 latest_timestamp 18 Timestamp of the last value that was output 19 20 now Timestamp now 21 """ 22 if not isinstance(algorithm, dict): 23 logging.warning('Function subsample() handed non-dict algorithm ' 24 'specification: %s', algorithm) 25 return None 26 if not values: 27 logging.info('Function subsample() handed empty values list') 28 return None 29 30 alg_type = algorithm.get('type') 31 32 ################## 33 # Select algorithm 34 35 # boxcar_average: all values within symmetric interval window get 36 # same weight. 37 if alg_type == 'boxcar_average': 38 interval = algorithm.get('interval', 10) # How often to output 39 window = algorithm.get('window', 10) # How far back to average 40 41 # Which timestamps are we going to emit as averages? Start at 42 # 'interval' seconds after the last timestamp we emitted and end 43 # at 'window/2' seconds before now, because we want to have a full 44 # 'window' seconds available for most recent point. 45 ts = max(latest_timestamp + interval, values[0][0] + window / 2) 46 ts_list = [] 47 while ts <= now - window / 2: 48 ts_list.append(ts) 49 ts += interval 50 51 if not ts_list: 52 logging.debug('No timestamps to emit this time') 53 return None 54 55 # Start and end intervals for data for each timestamp 56 ts_start = {ts: (ts - window / 2) for ts in ts_list} 57 ts_end = {ts: (ts + window / 2) for ts in ts_list} 58 ts_data = {ts: [] for ts in ts_list} 59 60 # Iterate through values backwards until we're outside the window 61 # of the first output ts. 62 earliest_ts_of_interest = ts_list[0] - window / 2 63 for v_index in range(len(values) - 1, -1, -1): 64 (value_ts, value) = values[v_index] 65 if value_ts < earliest_ts_of_interest: 66 break 67 68 # Does this ts,value pair belong in any of our averages? 69 for ts in ts_list: 70 if value_ts > ts_start[ts] and value_ts < ts_end[ts]: 71 ts_data[ts].append(value) 72 73 # Assemble averages for all timestamps we're going to emit 74 results = [] 75 for ts in ts_list: 76 if type(ts) not in [int, float, bool]: 77 logging.warning('Trying to subsample non-numeric value "%s"', ts) 78 continue 79 if len(ts_data[ts]): 80 try: 81 results.append((ts, sum(ts_data[ts]) / len(ts_data[ts]))) 82 except TypeError: 83 logging.warning('Non-numeric input in subsample: %s, in %s, list: %s', 84 ts_data[ts], ts_data, ts_list) 85 86 return results 87 88 else: 89 logging.warning('Function subsample() received unrecognized algorithm ' 90 'type: %s', alg_type) 91 return None
def
subsample(algorithm, values, latest_timestamp, now):
8def subsample(algorithm, values, latest_timestamp, now): 9 """An omnibus routine for taking a list of timestamped values, a 10 specification of an averaging algorithm, and returning a list of 11 zero, one or more timestamped "averaged" output values. 12 13 algorithm The name of the algorithm to be used 14 15 values List of values to be averaged in format of 16 [(timestamp, value), (timestamp, value),...] 17 18 latest_timestamp 19 Timestamp of the last value that was output 20 21 now Timestamp now 22 """ 23 if not isinstance(algorithm, dict): 24 logging.warning('Function subsample() handed non-dict algorithm ' 25 'specification: %s', algorithm) 26 return None 27 if not values: 28 logging.info('Function subsample() handed empty values list') 29 return None 30 31 alg_type = algorithm.get('type') 32 33 ################## 34 # Select algorithm 35 36 # boxcar_average: all values within symmetric interval window get 37 # same weight. 38 if alg_type == 'boxcar_average': 39 interval = algorithm.get('interval', 10) # How often to output 40 window = algorithm.get('window', 10) # How far back to average 41 42 # Which timestamps are we going to emit as averages? Start at 43 # 'interval' seconds after the last timestamp we emitted and end 44 # at 'window/2' seconds before now, because we want to have a full 45 # 'window' seconds available for most recent point. 46 ts = max(latest_timestamp + interval, values[0][0] + window / 2) 47 ts_list = [] 48 while ts <= now - window / 2: 49 ts_list.append(ts) 50 ts += interval 51 52 if not ts_list: 53 logging.debug('No timestamps to emit this time') 54 return None 55 56 # Start and end intervals for data for each timestamp 57 ts_start = {ts: (ts - window / 2) for ts in ts_list} 58 ts_end = {ts: (ts + window / 2) for ts in ts_list} 59 ts_data = {ts: [] for ts in ts_list} 60 61 # Iterate through values backwards until we're outside the window 62 # of the first output ts. 63 earliest_ts_of_interest = ts_list[0] - window / 2 64 for v_index in range(len(values) - 1, -1, -1): 65 (value_ts, value) = values[v_index] 66 if value_ts < earliest_ts_of_interest: 67 break 68 69 # Does this ts,value pair belong in any of our averages? 70 for ts in ts_list: 71 if value_ts > ts_start[ts] and value_ts < ts_end[ts]: 72 ts_data[ts].append(value) 73 74 # Assemble averages for all timestamps we're going to emit 75 results = [] 76 for ts in ts_list: 77 if type(ts) not in [int, float, bool]: 78 logging.warning('Trying to subsample non-numeric value "%s"', ts) 79 continue 80 if len(ts_data[ts]): 81 try: 82 results.append((ts, sum(ts_data[ts]) / len(ts_data[ts]))) 83 except TypeError: 84 logging.warning('Non-numeric input in subsample: %s, in %s, list: %s', 85 ts_data[ts], ts_data, ts_list) 86 87 return results 88 89 else: 90 logging.warning('Function subsample() received unrecognized algorithm ' 91 'type: %s', alg_type) 92 return None
An omnibus routine for taking a list of timestamped values, a specification of an averaging algorithm, and returning a list of zero, one or more timestamped "averaged" output values.
algorithm The name of the algorithm to be used
values List of values to be averaged in format of [(timestamp, value), (timestamp, value),...]
latest_timestamp Timestamp of the last value that was output
now Timestamp now