def _aggregation_value(self, values_to_aggregate, func=None): """Get the aggregated value related to input values_to_aggregate, a specific function and a timestamp. """ if func is None: func = get_aggregation(name=self.aggregation) if len(values_to_aggregate) > 0: result = round(func(values_to_aggregate), 2) else: result = 0 if self.fill else None return result
def calculate(self, points, timewindow, meta=None, usenan=True): """Do an operation on all points with input timewindow. :param bool usenan: if False (True by default) remove nan point values. :return: points such as follow: Let func self aggregation function and input points of the form: [(T0, V0), ..., (Tn, Vn)] then the result is [(T0, func(V0, V1)), (T2, func(V2, V3), ...]. """ result = [] # start to exclude points not in timewindow # in taking care about round time if self.round_time: period = self._get_period(timewindow) round_starttimestamp = period.round_timestamp( timestamp=timewindow.start() ) timewindow = timewindow.reduce( start=round_starttimestamp, stop=timewindow.stop() ) # start to exclude points which are not in timewindow points = [ point for point in points if point[0] in timewindow and (usenan or not isnan(point[1])) ] if not meta: meta = {} transform_method = meta.get('type') points = apply_transform(points, method=transform_method) points_len = len(points) func = None no_aggregation = get_aggregation(self.aggregation) is None too_much = (not points) or self.period is None and self.max_points > points_len if (no_aggregation or too_much): result = points # result is points else: # else calculate points with the right aggregation function func = get_aggregation(name=self.aggregation) # get timesteps timesteps = self.timesteps(timewindow)[:-1] # initialize variables for loop i = 0 values_to_aggregate = [] last_point = None len_timesteps = len(timesteps) # iterate on timesteps to get points in [prev_ts, timestamp[ for index, timestamp in enumerate(timesteps): # initialize values_to_aggregate values_to_aggregate = [] # set timestamp and previous_timestamp if index < (len_timesteps - 1): # calculate the upper bound next_timestamp = timesteps[index + 1] else: next_timestamp = None # fill the values_to_aggregate array for i in range(i, points_len): # while points to process pt_ts, pt_val = points[i] # leave the loop if _timestamp is for a future aggregation if next_timestamp is not None and pt_ts >= next_timestamp: break else: # add value to list of values to aggregate values_to_aggregate.append(pt_val) else: # leave the loop whatever timesteps i += 1 # TODO: understand what it means :D if self.aggregation == DELTA and last_point: values_to_aggregate.insert(0, last_point) if values_to_aggregate: # get the aggregated value related to values_to_aggregate aggregation_value = self._aggregation_value( values_to_aggregate, func ) # new point to add to result if usenan or not isnan(aggregation_value): aggregation_point = timestamp, aggregation_value result.append(aggregation_point) # save last_point for future DELTA checking last_point = aggregation_point[-1] elif usenan: result.append((timestamp, float('nan'))) return result
def calculate(self, points, timewindow, meta=None, usenan=True): """Do an operation on all points with input timewindow. :param bool usenan: if False (True by default) remove nan point values. :return: points such as follow: Let func self aggregation function and input points of the form: [(T0, V0), ..., (Tn, Vn)] then the result is [(T0, func(V0, V1)), (T2, func(V2, V3), ...]. """ result = [] # start to exclude points not in timewindow # in taking care about round time if self.round_time: period = self._get_period(timewindow) round_starttimestamp = period.round_timestamp( timestamp=timewindow.start()) timewindow = timewindow.reduce(start=round_starttimestamp, stop=timewindow.stop()) # start to exclude points which are not in timewindow points = [ point for point in points if point[0] in timewindow and (usenan or not isnan(point[1])) ] if not meta: meta = {} transform_method = meta.get('type') points = apply_transform(points, method=transform_method) points_len = len(points) func = None no_aggregation = get_aggregation(self.aggregation) is None too_much = ( not points) or self.period is None and self.max_points > points_len if (no_aggregation or too_much): result = points # result is points else: # else calculate points with the right aggregation function func = get_aggregation(name=self.aggregation) # get timesteps timesteps = self.timesteps(timewindow)[:-1] # initialize variables for loop i = 0 values_to_aggregate = [] last_point = None len_timesteps = len(timesteps) # iterate on timesteps to get points in [prev_ts, timestamp[ for index, timestamp in enumerate(timesteps): # initialize values_to_aggregate values_to_aggregate = [] # set timestamp and previous_timestamp if index < (len_timesteps - 1): # calculate the upper bound next_timestamp = timesteps[index + 1] else: next_timestamp = None # fill the values_to_aggregate array for i in range(i, points_len): # while points to process pt_ts, pt_val = points[i] # leave the loop if _timestamp is for a future aggregation if next_timestamp is not None and pt_ts >= next_timestamp: break else: # add value to list of values to aggregate values_to_aggregate.append(pt_val) else: # leave the loop whatever timesteps i += 1 # TODO: understand what it means :D if self.aggregation == DELTA and last_point: values_to_aggregate.insert(0, last_point) if values_to_aggregate: # get the aggregated value related to values_to_aggregate aggregation_value = self._aggregation_value( values_to_aggregate, func) # new point to add to result if usenan or not isnan(aggregation_value): aggregation_point = timestamp, aggregation_value result.append(aggregation_point) # save last_point for future DELTA checking last_point = aggregation_point[-1] elif usenan: result.append((timestamp, float('nan'))) return result