#!/usr/bin/python import nilmtools.filter import nilmdb.client import numpy as np import operator def main(argv = None): f = nilmtools.filter.Filter() parser = f.setup_parser("Decimate a stream") group = parser.add_argument_group("Decimate options") group.add_argument('-f', '--factor', action='store', default=4, type=int, help='Decimation factor (default: %(default)s)') # Parse arguments try: args = f.parse_args(argv) except nilmtools.filter.MissingDestination as e: # If no destination, suggest how to create it by figuring out # a recommended layout. src = e.src dest = e.dest print "Source is %s (%s)" % (src.path, src.layout) print "Destination %s doesn't exist" % (dest.path) if "decimate_source" in f.client_src.stream_get_metadata(src.path): rec = src.layout elif 'int32' in src.layout_type or 'float64' in src.layout_type: rec = 'float64_' + str(src.layout_count * 3) else: rec = 'float32_' + str(src.layout_count * 3) print "You could make it with a command like:" print " nilmtool -u %s create %s %s" % (e.dest.url, e.dest.path, rec) raise SystemExit(1) if not (args.factor >= 2): raise Exception("factor needs to be 2 or more") f.check_dest_metadata({ "decimate_source": f.src.path, "decimate_factor": args.factor }) # If source is decimated, we have to decimate a bit differently if "decimate_source" in f.client_src.stream_get_metadata(args.srcpath): again = True else: again = False f.process_numpy(decimate, args = (args.factor, again)) def decimate(data, interval, args, insert_function, final): """Decimate data""" (factor, again) = args (n, m) = data.shape # Figure out which columns to use as the source for mean, min, and max, # depending on whether this is the first decimation or we're decimating # again. Note that we include the timestamp in the means. if again: c = (m - 1) // 3 # e.g. c = 3 # ts mean1 mean2 mean3 min1 min2 min3 max1 max2 max3 mean_col = slice(0, c + 1) min_col = slice(c + 1, 2 * c + 1) max_col = slice(2 * c + 1, 3 * c + 1) else: mean_col = slice(0, m) min_col = slice(1, m) max_col = slice(1, m) # Discard extra rows that aren't a multiple of factor n = n // factor * factor data = data[:n,:] # Reshape it into 3D so we can process 'factor' rows at a time data = data.reshape(n // factor, factor, m) # Fill the result out = np.c_[ np.mean(data[:,:,mean_col], axis=1), np.min(data[:,:,min_col], axis=1), np.max(data[:,:,max_col], axis=1) ] insert_function(out) return n if __name__ == "__main__": main()