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.
 
 
 
 

113 lines
4.0 KiB

  1. #!/usr/bin/env python3
  2. import os
  3. import nilmtools.filter
  4. import nilmtools.decimate
  5. import nilmdb.client
  6. import argparse
  7. import fnmatch
  8. def main(argv=None):
  9. parser = argparse.ArgumentParser(
  10. formatter_class=argparse.RawDescriptionHelpFormatter,
  11. description="""\
  12. Automatically create multiple decimations from a single source
  13. stream, continuing until the last decimated level contains fewer
  14. than 500 points total.
  15. Wildcards and multiple paths are accepted. Decimated paths are
  16. ignored when matching wildcards.
  17. """)
  18. def_url = os.environ.get("NILMDB_URL", "http://localhost/nilmdb/")
  19. parser.add_argument("-u", "--url", action="store", default=def_url,
  20. help="NilmDB server URL (default: %(default)s)")
  21. parser.add_argument("-f", "--factor", action="store", default=4, type=int,
  22. help='Decimation factor (default: %(default)s)')
  23. parser.add_argument("-m", "--max", action="store", default=500, type=int,
  24. help='Maximum number of points in last level ' +
  25. '(default: %(default)s)')
  26. parser.add_argument("-F", "--force-metadata", action="store_true",
  27. default=False,
  28. help="Force metadata changes if the dest "
  29. "doesn't match")
  30. parser.add_argument("-v", "--version", action="version",
  31. version=nilmtools.__version__)
  32. parser.add_argument("path", action="store", nargs='+',
  33. help='Path of base stream')
  34. args = parser.parse_args(argv)
  35. if args.max < 0:
  36. print("error: bad max, must be nonnegative")
  37. raise SystemExit(1)
  38. # Pull out info about the base stream
  39. client = nilmdb.client.Client(args.url)
  40. # Find list of paths to process
  41. streams = [str(s[0]) for s in client.stream_list()]
  42. streams = [s for s in streams if "~decim-" not in s]
  43. paths = []
  44. for path in args.path:
  45. new = fnmatch.filter(streams, str(path))
  46. if not new:
  47. print("error: no stream matched path:", path)
  48. raise SystemExit(1)
  49. paths.extend(new)
  50. for path in paths:
  51. do_decimation(client, args, path)
  52. def do_decimation(client, args, path):
  53. print("Decimating", path)
  54. info = nilmtools.filter.get_stream_info(client, path)
  55. if not info: # pragma: no cover (only good paths passed above)
  56. raise Exception("path " + path + " not found")
  57. meta = client.stream_get_metadata(path)
  58. if "decimate_source" in meta:
  59. print("Stream", path, "was decimated from", meta["decimate_source"])
  60. print("You need to pass the base stream instead")
  61. raise SystemExit(1)
  62. # Figure out the type we should use for decimated streams
  63. if ('int32' in info.layout_type or
  64. 'int64' in info.layout_type or
  65. 'float64' in info.layout_type):
  66. decimated_type = 'float64_' + str(info.layout_count * 3)
  67. else:
  68. decimated_type = 'float32_' + str(info.layout_count * 3)
  69. # Now do the decimations until we have few enough points
  70. factor = 1
  71. while True:
  72. print("Level", factor, "decimation has", info.rows, "rows")
  73. if info.rows <= args.max:
  74. break
  75. factor *= args.factor
  76. new_path = "%s~decim-%d" % (path, factor)
  77. # Create the stream if needed
  78. new_info = nilmtools.filter.get_stream_info(client, new_path)
  79. if not new_info:
  80. print("Creating stream", new_path)
  81. client.stream_create(new_path, decimated_type)
  82. # Run the decimation as if it were run from the commandline
  83. new_argv = ["-u", args.url,
  84. "-f", str(args.factor)]
  85. if args.force_metadata:
  86. new_argv.extend(["--force-metadata"])
  87. new_argv.extend([info.path, new_path])
  88. nilmtools.decimate.main(new_argv)
  89. # Update info using the newly decimated stream
  90. info = nilmtools.filter.get_stream_info(client, new_path)
  91. return
  92. if __name__ == "__main__":
  93. main()