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.
 
 
 
 

89 lines
2.9 KiB

  1. #!/usr/bin/env python3
  2. import nilmtools.filter
  3. import numpy as np
  4. def main(argv=None):
  5. f = nilmtools.filter.Filter()
  6. parser = f.setup_parser("Decimate a stream")
  7. group = parser.add_argument_group("Decimate options")
  8. group.add_argument('-f', '--factor', action='store', default=4, type=int,
  9. help='Decimation factor (default: %(default)s)')
  10. # Parse arguments
  11. try:
  12. args = f.parse_args(argv)
  13. except nilmtools.filter.MissingDestination as e:
  14. # If no destination, suggest how to create it by figuring out
  15. # a recommended layout.
  16. src = e.src
  17. dest = e.dest
  18. print("Source is %s (%s)" % (src.path, src.layout))
  19. print("Destination %s doesn't exist" % (dest.path))
  20. if "decimate_source" in f.client_src.stream_get_metadata(src.path):
  21. rec = src.layout
  22. elif ('int32' in src.layout_type or
  23. 'int64' in src.layout_type or
  24. '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. again = True
  39. else:
  40. again = False
  41. f.process_numpy(decimate, args=(args.factor, again))
  42. def decimate(data, interval, args, insert_function, final):
  43. """Decimate data"""
  44. (factor, again) = args
  45. (n, m) = data.shape
  46. # Figure out which columns to use as the source for mean, min, and max,
  47. # depending on whether this is the first decimation or we're decimating
  48. # again. Note that we include the timestamp in the means.
  49. if again:
  50. c = (m - 1) // 3
  51. # e.g. c = 3
  52. # ts mean1 mean2 mean3 min1 min2 min3 max1 max2 max3
  53. mean_col = slice(0, c + 1)
  54. min_col = slice(c + 1, 2 * c + 1)
  55. max_col = slice(2 * c + 1, 3 * c + 1)
  56. else:
  57. mean_col = slice(0, m)
  58. min_col = slice(1, m)
  59. max_col = slice(1, m)
  60. # Discard extra rows that aren't a multiple of factor
  61. n = n // factor * factor
  62. data = data[:n, :]
  63. # Reshape it into 3D so we can process 'factor' rows at a time
  64. data = data.reshape(n // factor, factor, m)
  65. # Fill the result
  66. out = np.c_[np.mean(data[:, :, mean_col], axis=1),
  67. np.min(data[:, :, min_col], axis=1),
  68. np.max(data[:, :, max_col], axis=1)]
  69. insert_function(out)
  70. return n
  71. if __name__ == "__main__":
  72. main()