def test_pop_empty_array(): tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="array") result = tsb.pop() assert isinstance(result, np.ndarray) assert result.shape == (0, 4) assert result.size == 0
def test_pop_empty_uarray(): tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="uarray") result = tsb.show(n_samples=n_samples) assert isinstance(result, np.ndarray) assert result.shape == (0, 2) assert result.size == 0
def test_add_arrays(): tsb = TimeSeriesBuffer(maxlen=maxlen) M = 4 data = np.random.random((N, M)) t = data[:, 0] ut = data[:, 1] v = data[:, 2] uv = data[:, 3] # add data to buffer in different combinations # and check if latest element of buffer corresponds to latest element of data ignore = tsb.empty_unc # no uncertainty information tsb.add(time=t, val=v) assert tsb.buffer[-1] == (data[-1, 0], ignore, data[-1, 2], ignore) # typical uncertainty information tsb.add(time=t, val=v, val_unc=uv) assert tsb.buffer[-1] == (data[-1, 0], ignore, data[-1, 2], data[-1, 3]) # full uncertainty information tsb.add(time=t, time_unc=ut, val=v, val_unc=uv) assert tsb.buffer[-1] == (data[-1, 0], data[-1, 1], data[-1, 2], data[-1, 3]) # untypical uncertainty information tsb.add(time=t, time_unc=ut, val=v) assert tsb.buffer[-1] == (data[-1, 0], data[-1, 1], data[-1, 2], ignore)
def test_pop_empty_uarrays(): tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="uarrays") t, v = tsb.show(n_samples=n_samples) assert isinstance(t, np.ndarray) assert isinstance(v, np.ndarray) assert t.size == 0 assert v.size == 0
def test_return_format_list(): M = 4 tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="list") data = np.random.random((N, M)) tsb.add(data=data) result = tsb.show(n_samples=n_samples) assert isinstance(result, list) assert isinstance(result[0], tuple) assert isinstance(result[0][0], float)
def test_return_format_array(): M = 4 tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="array") data = np.random.random((N, M)) tsb.add(data=data) result = tsb.show(n_samples=n_samples) assert isinstance(result, np.ndarray) assert isinstance(result[0], np.ndarray) assert isinstance(result[0][0], float)
def test_return_format_uarrays(): M = 4 tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="uarrays") data = np.random.random((N, M)) tsb.add(data=data) t, v = tsb.show(n_samples=n_samples) assert isinstance(t, np.ndarray) assert isinstance(v, np.ndarray) assert isinstance(t[0], uncertainties.core.Variable) assert isinstance(v[0], uncertainties.core.Variable)
def test_return_format_arrays(): M = 4 tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="arrays") data = np.random.random((N, M)) tsb.add(data=data) t, ut, v, uv = tsb.show(n_samples=n_samples) assert isinstance(t, np.ndarray) assert isinstance(ut, np.ndarray) assert isinstance(v, np.ndarray) assert isinstance(uv, np.ndarray) assert isinstance(t[0], float) assert isinstance(ut[0], float) assert isinstance(v[0], float) assert isinstance(uv[0], float)
def test_show_all(): M = 4 tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="array") data = np.random.random((N, M)) tsb.add(data=data) # return some buffer elements without pop result = tsb.show(n_samples=-1) # check that show does not alter the buffer assert len(result) == N # check if newest elements are received and order is as expected assert np.all(result == data)
def test_add_uarray(): tsb = TimeSeriesBuffer(maxlen=maxlen) M = 4 data = np.random.random((N, M)) udata = unumpy.uarray(data[:, [0, 2]], data[:, [1, 3]]) # add data to buffer tsb.add(data=udata) # check if number of buffer elements increased accordingly assert len(tsb) == min(N, maxlen) # check if latest element of buffer corresponds to latest element of data assert tsb.buffer[-1] == tuple(data[-1, :])
def test_show_size_and_order(): n_samples = 7 M = 4 tsb = TimeSeriesBuffer(maxlen=maxlen, return_type="array") data = np.random.random((N, M)) tsb.add(data=data) # return some buffer elements without pop length_before_show = len(tsb) result = tsb.show(n_samples=n_samples) length_after_show = len(tsb) # check that show does not alter the buffer assert length_before_show == length_after_show # check if newest elements are received and order is as expected assert np.all(result == data[-n_samples:, :])
def test_add_array(): # init the buffer tsb = TimeSeriesBuffer(maxlen=maxlen) counter = 0 # fill buffer with arrays of different shape for M in [2, 3, 4]: data = np.random.random((N, M)) # add data to buffer tsb.add(data=data) # check if number of buffer elements increased accordingly counter += len(data) assert len(tsb) == min(counter, maxlen) # check if latest element of buffer corresponds to latest element of data # (because M changes, we only check if the timestamp (index=0) matches) assert tsb.buffer[-1][0] == data[-1, 0]
def test_pop_size_and_order(): n_samples = 7 M = 4 tsb = TimeSeriesBuffer(maxlen=maxlen) data = np.random.random((N, M)) tsb.add(data=data) # pop some buffer elements length_before_pop = len(tsb) result = tsb.pop(n_samples=n_samples) length_after_pop = len(tsb) # check output length and buffer size after pop if n_samples > length_before_pop: assert 0 == length_after_pop else: assert length_before_pop - n_samples == length_after_pop # check if really oldest elements are received assert np.all(result == data[0:n_samples, :])
def set_output_data(self, channel, data=None, metadata=None): # create storage for new output channels if channel not in self._output_data.keys(): self._output_data[channel] = { "metadata": metadata, "buffer": TimeSeriesBuffer(maxlen=self._output_data_maxlen), } if metadata is not None: # update received metadata self._output_data[channel]["metadata"] = metadata if data is not None: # append received data self._output_data[channel]["buffer"].add(data=data)
def _set_input_data(self, sender, data=None, metadata=None): # create storage for new senders if sender not in self._input_data.keys(): self._input_data[sender] = { "metadata": metadata, "buffer": TimeSeriesBuffer(maxlen=self._input_data_maxlen), } if metadata is not None: # update received metadata self._input_data[sender]["metadata"] = metadata if data is not None: # append received data self._input_data[sender]["buffer"].add(data=data)
def test_error_on_shape_mismatch(): tsb = TimeSeriesBuffer(maxlen=maxlen) M = 4 data = np.random.random((N, M)) t = data[:, 0] ut = data[:, 1] v = data[:, 2] uv = data[:, 3] with pytest.raises(ValueError): tsb.add(time=t, time_unc=ut[:-2], val=v, val_unc=uv) with pytest.raises(ValueError): tsb.add(time=t, time_unc=ut, val=v[:-2], val_unc=uv) with pytest.raises(ValueError): tsb.add(time=t, time_unc=ut, val=v, val_unc=uv[:-2])
def main(): # basics buffer_length = 120 signal = Buffer(maxlen=buffer_length, return_type="arrays") cycle_duration = 0.1 # seconds plot_counter = 0 dwt_counter = 0 cycle_counter = 0 # init wavelet stuff ld, hd, _, _ = wavelet.filter_design("db2") dwt_length = 21 # init multi level wavelet stuff n_levels = 4 output_multi_level = [n_levels] + [ level for level in list(range(1, n_levels + 1))[::-1] ] # highest level twice because we store detail + approx output_multi_buffer_maxlen = [ buffer_length // 2 ** level for level in output_multi_level ] output_multi = [ Buffer(maxlen=maxlen, return_type="arrays") for maxlen in output_multi_buffer_maxlen ] # list of buffer (different lengths to approximately cover the same timespan) level_states = None # init plot plt.ion() fig = plt.figure() ax = fig.subplots(nrows=1 + len(output_multi), ncols=1, sharex=True) # init signal plot ax[0].set_ylabel("$x^{(0)}$") ax[0].set_ylim([-2, 2]) (sm,) = ax[0].plot(0, 0, "-k") # signal (su,) = ax[0].plot(0, 0, ":k", linewidth=0.8) # upper unc (sl,) = ax[0].plot(0, 0, ":k", linewidth=0.8) # lower unc # init coefficient plots c_lines = [] for i, (level, _ax) in enumerate(zip(output_multi_level[::-1], ax[1:])): if i == len(ax[1:]) - 1: _ax.set_ylabel("$a^{{({0})}}$".format(level)) else: _ax.set_ylabel("$d^{{({0})}}$".format(level)) _ax.set_ylim(auto=True) ce = _ax.errorbar( 0, 0, yerr=0, linewidth=0, elinewidth=2, color="gray", capsize=5 ) cm = _ax.scatter([0], [0], c="r", s=10) # (detail) coeffs c_lines.append([cm, ce]) _ax.set_ylim([-3, 3]) # simulate infinite stream of data while True: cycle_counter += 1 # ti = tm.time() ti = cycle_counter * cycle_duration ui = 0.15 * (np.sin(2 * ti) + 2) xi = np.sin(ti) + np.random.randn() * ui signal.add(time=ti, val=xi, val_unc=ui) # run DWT every <dwt_length> iterations dwt_counter += 1 if dwt_counter % dwt_length == 0: t, _, v, u = signal.show(dwt_length) # multi level dwt with uncertainty coeffs, Ucoeffs, _, level_states = wavelet.wave_dec_realtime( v, u, ld, hd, n=n_levels, level_states=level_states ) # assign correct timestamps to the coefficients i0_old = (level_states["counter"] - len(t)) % 2 ** n_levels time_indices = np.arange(i0_old, i0_old + len(t)) # save results to data structure for c, u, buffer, level in zip( coeffs, Ucoeffs, output_multi, output_multi_level ): time_indices_level = (time_indices + 1) % 2 ** level == 0 if ( time_indices_level.sum() > 0 ): # otherwise error from time-series-buffer buffer.add(time=t[time_indices_level], val=c, val_unc=u) dwt_counter = 0 # set dwt length until next cycle dwt_length = random.choice( [1, 2, 10, 21] ) # could also be constant, e.g. dwt_length = 20 print(dwt_length) # update plot every 5 iterations plot_counter += 1 if ( plot_counter % 5 == 0 and cycle_counter > buffer_length ): # skip plotting at startup, when buffer is still not fully filled # update plot # get data to plot t_signal, _, v_signal, u_signal = signal.show(-1) # update signal lines sm.set_xdata(t_signal) su.set_xdata(t_signal) sl.set_xdata(t_signal) sm.set_ydata(v_signal) su.set_ydata(v_signal + u_signal) sl.set_ydata(v_signal - u_signal) ax[0].set_xlim([min(t_signal), max(t_signal)]) # update dwt lines for buffer, _ax, c_line in zip(output_multi[::-1], ax[1:], c_lines): if len(buffer) > 0: # otherwise error from time-series-buffer t_coeff, _, v_coeff, u_coeff = buffer.show(-1) # change the scatter data = np.c_[t_coeff, v_coeff] c_line[0].set_offsets(data) c_line[0].set_facecolor(["r"] * len(t_coeff)) # change the error bars c_line[1].remove() c_line[1] = _ax.errorbar( t_coeff, v_coeff, yerr=u_coeff, linewidth=0, elinewidth=1.5, color="gray", capsize=3, zorder=0, ) upper_unc = v_coeff + u_coeff lower_unc = v_coeff - u_coeff if v_coeff.size != 0: lim = [np.min(lower_unc), np.max(upper_unc)] _ax.set_ylim(lim) # finally update the plot itself fig.tight_layout() fig.align_ylabels(ax) fig.canvas.draw() fig.canvas.flush_events() # reset plot counter plot_counter = 0