82 lines
3.0 KiB
Python
Executable File
82 lines
3.0 KiB
Python
Executable File
#!/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()
|