Index: common/monsoon/monsoon/monsoon_utils.py |
diff --git a/common/monsoon/monsoon/monsoon_utils.py b/common/monsoon/monsoon/monsoon_utils.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..905792f2a12afb1f19695bb6a648b2add7d2a93f |
--- /dev/null |
+++ b/common/monsoon/monsoon/monsoon_utils.py |
@@ -0,0 +1,62 @@ |
+# Copyright 2017 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+import collections |
+import re |
+ |
+# Named tuple for all monsoon samples. |
+MonsoonSample = collections.namedtuple('MonsoonSample', 'Timestamp Amps') |
+ |
+# Regular expression to extract timestamp and amperage from Monsoon's log. |
+SampleRegex = re.compile(r"(\d+)\s+(?<![a-zA-Z:])([-+]?\d*\.?\d+)") |
+ |
+def ReadSamplesFromFile(file): |
+ """ Reads raw samples from a file in the form 'Timestamp Amps', returning |
+ a list of MonsoonSample tuples. |
+ """ |
+ samples = [] |
+ for line in file: |
+ value_match = SampleRegex.match(line) |
+ # Sometimes there can be transient USB communication errors. They can be |
+ # safely ignored. |
+ if value_match is not None: |
+ # Some versions of monsoon.py supply timestamp in integer. Some later |
+ # versions could in theory supply timestamp as a float. Collapse all |
+ # and treat timestamps as if they were integer seconds. |
+ timestamp_second = int(value_match.group(1)) |
+ amps = float(value_match.group(2)) |
+ samples.append(MonsoonSample(Timestamp = timestamp_second, Amps = amps)) |
+ return samples |
+ |
+def TransformSamplesWithFrequency(samples, frequency): |
+ """ Transforms a list of MonsoonSample (with integer second accuracy) into a |
+ list of MonsoonSample with fractional accuracy, assuming a fixed frequency. |
+ """ |
+ result = [] |
+ second_samples = [] |
+ second = -1 |
+ last_index = len(samples) - 1 |
+ for i,source_sample in enumerate(samples): |
+ if second == -1: |
+ second = source_sample.Timestamp |
+ if (source_sample.Timestamp != second) or (i == last_index): |
+ # Now and then the data may have more samples than the given frequency |
+ # (a desktop OS isn't an RTOS after all). Lets allow it and average out |
+ # the samples. |
+ if len(second_samples) > frequency: |
+ second_frequency = len(second_samples) |
+ else: |
+ second_frequency = frequency |
+ period = 1.0 / second_frequency |
+ # Samples are represented as halfway through the period. |
+ time_offset = -(period / 2.0) |
+ if len(result) == 0: |
+ time_offset += (second_frequency - len(second_samples) - 1) * period |
+ for second_sample in second_samples: |
+ result.append(MonsoonSample(Timestamp = second + time_offset, Amps = |
+ second_sample.Amps)) |
+ time_offset += period |
+ del second_samples[:] |
+ second = source_sample.Timestamp |
+ second_samples.append(source_sample) |
+ return result |