You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

82 lines
3.0 KiB

  1. #!/usr/bin/python
  2. import nilmtools.filter
  3. import nilmdb.client
  4. import numpy as np
  5. import operator
  6. def main(argv = None):
  7. f = nilmtools.filter.Filter()
  8. parser = f.setup_parser("Decimate a stream")
  9. group = parser.add_argument_group("Decimate options")
  10. group.add_argument('-f', '--factor', action='store', default=4, type=int,
  11. help='Decimation factor (default: %(default)s)')
  12. # Parse arguments
  13. try:
  14. args = f.parse_args(argv)
  15. except nilmtools.filter.MissingDestination as e:
  16. # If no destination, suggest how to create it by figuring out
  17. # a recommended layout.
  18. src = e.src
  19. dest = e.dest
  20. print "Source is %s (%s)" % (src.path, src.layout)
  21. print "Destination %s doesn't exist" % (dest.path)
  22. if "decimate_source" in f.client_src.stream_get_metadata(src.path):
  23. rec = src.layout
  24. elif 'int32' in src.layout_type or 'float64' in src.layout_type:
  25. rec = 'float64_' + str(src.layout_count * 3)
  26. else:
  27. rec = 'float32_' + str(src.layout_count * 3)
  28. print "You could make it with a command like:"
  29. print " nilmtool -u %s create %s %s" % (e.dest.url,
  30. e.dest.path, rec)
  31. raise SystemExit(1)
  32. if not (args.factor >= 2):
  33. raise Exception("factor needs to be 2 or more")
  34. f.check_dest_metadata({ "decimate_source": f.src.path,
  35. "decimate_factor": args.factor })
  36. # If source is decimated, we have to decimate a bit differently
  37. if "decimate_source" in f.client_src.stream_get_metadata(args.srcpath):
  38. n = f.src.layout_count // 3
  39. f.process_python(function = decimate_again, rows = args.factor,
  40. args = (n,))
  41. else:
  42. n = f.src.layout_count
  43. f.process_python(function = decimate_first, rows = args.factor,
  44. args = (n,))
  45. def decimate_first(data, n):
  46. """Decimate original data -- result has 3 times as many columns"""
  47. # For this simple calculation, converting to a Numpy array
  48. # and doing the math is slower than just doing it directly.
  49. rows = iter(data)
  50. r_sum = r_min = r_max = rows.next()
  51. for row in rows:
  52. r_sum = map(operator.add, r_sum, row)
  53. r_min = map(min, r_min, row)
  54. r_max = map(max, r_max, row)
  55. r_mean = [ x / len(data) for x in r_sum ]
  56. return [ [ r_mean[0] ] + r_mean[1:] + r_min[1:] + r_max[1:] ]
  57. def decimate_again(data, n):
  58. """Decimate already-decimated data -- result has the same number
  59. of columns"""
  60. rows = iter(data)
  61. r = rows.next()
  62. r_sum = r[0:(n+1)]
  63. r_min = r[(n+1):(2*n+1)]
  64. r_max = r[(2*n+1):(3*n+1)]
  65. for r in rows:
  66. r_sum = map(operator.add, r_sum, r[0:(n+1)])
  67. r_min = map(min, r_min, r[(n+1):(2*n+1)])
  68. r_max = map(max, r_max, r[(2*n+1):(3*n+1)])
  69. r_mean = [ x / len(data) for x in r_sum ]
  70. return [ r_mean + r_min + r_max ]
  71. if __name__ == "__main__":
  72. main()