#!/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): n = f.src.layout_count // 3 f.process_python(function = decimate_again, rows = args.factor, args = (n,)) else: n = f.src.layout_count f.process_python(function = decimate_first, rows = args.factor, args = (n,)) def decimate_first(data, n): """Decimate original data -- result has 3 times as many columns""" # For this simple calculation, converting to a Numpy array # and doing the math is slower than just doing it directly. rows = iter(data) r_sum = r_min = r_max = rows.next() for row in rows: r_sum = map(operator.add, r_sum, row) r_min = map(min, r_min, row) r_max = map(max, r_max, row) r_mean = [ x / len(data) for x in r_sum ] return [ [ r_mean[0] ] + r_mean[1:] + r_min[1:] + r_max[1:] ] def decimate_again(data, n): """Decimate already-decimated data -- result has the same number of columns""" rows = iter(data) r = rows.next() r_sum = r[0:(n+1)] r_min = r[(n+1):(2*n+1)] r_max = r[(2*n+1):(3*n+1)] for r in rows: r_sum = map(operator.add, r_sum, r[0:(n+1)]) r_min = map(min, r_min, r[(n+1):(2*n+1)]) r_max = map(max, r_max, r[(2*n+1):(3*n+1)]) r_mean = [ x / len(data) for x in r_sum ] return [ r_mean + r_min + r_max ] if __name__ == "__main__": main()