def statistics_get(self, t1, t2): """Get the statistics for the collected sample data over a time range. :param t1: The starting time in seconds relative to the streaming start time. :param t2: The ending time in seconds. :return: The statistics data structure. See :meth:`joulescope.driver.Driver.statistics_get` for details. """ log.debug('statistics_get(%s, %s)', t1, t2) s1 = self.time_to_sample_id(t1) s2 = self.time_to_sample_id(t2) if s1 is None or s2 is None: return None (k1, k2), s = self._get_reduction_stats(s1, s2) if s1 < k1: length = k1 - s1 s_start = self.get(s1, k1, increment=length) s.combine(Statistics(length=length, stats=s_start[0, :, :])) if s2 > k2: length = s2 - k2 s_stop = self.get(k2, s2, increment=length) s.combine(Statistics(length=length, stats=s_stop[0, :, :])) t_start = s1 / self.sampling_frequency t_stop = s2 / self.sampling_frequency return stats_to_api(s.value, t_start, t_stop)
def statistics_get(self, t1, t2): """Get the statistics for the collected sample data over a time range. :param t1: The starting time in seconds relative to the streaming start time. :param t2: The ending time in seconds. :return: The statistics data structure. Here is an example: { "time": { "range": [4.2224105, 4.7224105], "delta": 0.5, "units": "s" }, "signals": { "current": { "statistics": { "μ": 1.1410409683776379e-07, "σ": 3.153094851882088e-08, "min": 2.4002097531727884e-10, "max": 2.77493541034346e-07, "p2p": 2.772535200590287e-07 }, "units": "A", "integral_units": "C" }, "voltage": { "statistics": { "μ": 3.2984893321990967, "σ": 0.0010323672322556376, "min": 3.293551445007324, "max": 3.3026282787323, "p2p": 0.009076833724975586 }, "units": "V", "integral_units": null }, "power": { "statistics": { "μ": 3.763720144434046e-07, "σ": 1.0400773930996365e-07, "min": 7.916107769290193e-10, "max": 9.155134534921672e-07, "p2p": 9.147218427152382e-07 }, "units": "W", "integral_units": "J" } } } Note: this same format is used by the :meth:`statistics_callback`. """ v = self.view s1 = v.time_to_sample_id(t1) s2 = v.time_to_sample_id(t2) log.info('buffer %s, %s => %s, %s : %s', t1, t2, s1, s2, v.span) d = self.stream_buffer.stats_get(start=s1, stop=s2) t_start = s1 / self.sampling_frequency t_stop = s2 / self.sampling_frequency return stats_to_api(d, t_start, t_stop)
def _statistics_get(self, start=None, stop=None, units=None): """Get the statistics for the collected sample data over a time range. :return: The statistics data structure. Here is an example: """ s1, s2 = self._convert_time_range_to_samples(start, stop, units) # self._log.debug('buffer %s, %s, %s => %s, %s', start, stop, units, s1, s2) d = self._stream_buffer.stats_get(start=s1, stop=s2) t_start = s1 / self.sampling_frequency t_stop = s2 / self.sampling_frequency return stats_to_api(d, t_start, t_stop)
def _statistics_get(self, start=None, stop=None, units=None): """Get the statistics for the collected sample data over a time range. :return: The statistics data structure. See the :`statistics documentation <statistics.html>`_ for details on the data format. """ s1, s2 = self._convert_time_range_to_samples(start, stop, units) # self._log.debug('buffer %s, %s, %s => %s, %s', start, stop, units, s1, s2) d, x_range = self._stream_buffer.statistics_get(start=s1, stop=s2) t_start = x_range[0] / self.sampling_frequency t_stop = x_range[1] / self.sampling_frequency return stats_to_api(d, t_start, t_stop)
def data_array_to_update(x_limits, x, data_array): """Convert raw data buffer to a view update. :param x_limits: The list of [x_min, x_max] or None if unknown. :param x: The np.ndarray of x-axis times. :param data_array: The np.ndarray((N, STATS_FIELD_COUNT), dtype=STATS_DTYPE) """ if len(x): s = stats_to_api(data_array[0, :], float(x[0]), float(x[-1])) else: s = stats_to_api(None, 0.0, 0.0) s['time']['x'] = {'value': x, 'units': 's'} s['time']['limits'] = {'value': x_limits, 'units': 's'} s['state'] = {'source_type': 'buffer'} # ['realtime', 'buffer'] for idx, signal in enumerate(s['signals'].values()): signal['µ']['value'] = data_array[:, idx]['mean'].copy() length = data_array[:, idx]['length'] - 1 length[length < 1] = 1.0 signal['σ2']['value'] = data_array[:, idx]['variance'] / length signal['min']['value'] = data_array[:, idx]['min'].copy() signal['max']['value'] = data_array[:, idx]['max'].copy() signal['p2p']['value'] = signal['max']['value'] - signal['min']['value'] return s
def _process(self, stream_buffer, start_id, end_id): d_id = end_id - start_id if d_id < SAMPLE_COUNT_MIN: return # too short, debounced s = stream_buffer.statistics_get(start_id, end_id)[0] t_start = start_id / stream_buffer.output_sampling_frequency t_end = end_id / stream_buffer.output_sampling_frequency s = stats_to_api(s, t_start, t_end) duration = s['time']['delta']['value'] charge = s['signals']['current']['∫']['value'] energy = s['signals']['power']['∫']['value'] timestamp = datetime.datetime.utcfromtimestamp(self.timestamp) timestamp_str = timestamp.isoformat() line = f'{timestamp_str},{duration:.6f},{charge},{energy}' print(line) if self._filehandle is not None: self._filehandle.write(line + '\n') self._filehandle.flush()
def statistics_get(self, start=None, stop=None, units=None): """Get the statistics for the collected sample data over a time range. :param start: The starting time relative to the first sample. :param stop: The ending time. :param units: The units for start and stop. 'seconds' is in floating point seconds relative to the view. 'samples' or None is in stream buffer sample indices. :return: The statistics data structure. See :meth:`joulescope.driver.Driver.statistics_get` for details. """ log.debug('statistics_get(%s, %s, %s)', start, stop, units) s1, s2 = self.normalize_time_arguments(start, stop, units) if s1 == s2: s2 = s1 + 1 # always try to produce valid statistics s = self._stats_get(s1, s2) t_start = s1 / self.sampling_frequency t_stop = s2 / self.sampling_frequency return stats_to_api(s.value, t_start, t_stop)