|
- #!/usr/bin/python
-
- import nilmtools.filter
- import nilmdb.client
- import numpy as np
- import operator
-
- def main():
- 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()
- 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.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 create", 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": args.srcpath,
- "decimate_factor": args.factor })
-
- # If source is decimated, we have to decimate a bit differently
- if "decimate_source" in f.client.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()
|