def test_copy(sinusoid): y1 = Signal1D(sinusoid) y2 = y1.copy() y2._z *= 0 assert np.all(y2._z == 0) assert not (np.all(y1._z == 0))
def __call__(self, x, snr=np.inf, dist=np.random.normal): """ self(x) will give a Signal1D of the parametric model evaluate at x Args: x: the points to evaluate expr over. can be a pint array snr: signal to noise ratio in dB dist: noise distribution Returns: Signal1D: the parametric model evaluated for parameter setpoints and x, with noise added if snr is specified. noise is useful for algorithm testing """ parameters = [k for k in self.v] values = [self.v[k] for k in self.v] if not (hasattr(x, '__iter__')): x = np.array([x]) # make x look iterable if it isn't for Signal1D f = sympy.lambdify(parameters + [self._free_var], self.expr, "numpy") z = f(*(values + [x])) if not (hasattr(z, '__iter__')): # we have unintentionally simplified self.expr to a constant z = np.array(len(x) * [z]) z = z.astype('complex128') if snr < np.inf: noise = dist(size=len(z)) + 1j * dist(size=len(z)) noise *= 10**(-snr / 10) * np.std(z)**2 / np.std(noise)**2 z += noise return Signal1D(z, xraw=x)
def decimate_by_derivative(sig1d, N, tform = lambda z : np.abs(z)): """ [EXPERIMENTAL] draws N random samples from sig1d about points of change Args: sig1d: the input Signal1D type to decimate N: the number of points to sample tform: a transformation to apply to the sig1d to generate real sample values used in the decimation procedure. np.abs is applied by default Returns: sig1d: a Signal1D type of length N containing samples that occur in the input sig1d """ if N > len(sig1d): return sig1d real = np.array(tform(sig1d.values), dtype = np.float64) # the thinking here is that if we increase sparsity between points where the # derrivative is 0, then we can safely interpolate between them probs = np.abs(np.diff(real))**.5 probs /= np.sum(probs) # NOTE: the last sample can never be chosen since probs is derrived from a diff idxs = np.random.choice(range(len(probs)), size = N, p = probs, replace = False) idxs.sort() return Signal1D(sig1d.values[idxs], xraw = sig1d.x[idxs])
def test_fft(sinusoid): y = Signal1D(sinusoid, xlims=(0 * ureg('s'), 0.1 * ureg('s'))) fft = y.fft() # make sure that the peak frequency is at 1kHz as specified assert np.abs(fft.abs().idxmax()).to('kHz').magnitude == pytest.approx(1.0) assert y.pwr == pytest.approx(fft.pwr)
def test_samples_above_below(sinusoid): y = Signal1D(sinusoid) y1 = y.samples_above(0.5, tform='real') y2 = y.samples_below(0.5, tform='abs') assert np.all(y1.real().values > 0.5) assert np.all(y2.abs().values < 0.5) assert len(y1.samples_below(0.5)) == 0
def test_arithmetic(sinusoid): y = Signal1D(sinusoid) assert np.all((y + 5)._z == y._z + 5) assert np.all((5 + y)._z == y._z + 5) assert np.all((y - 6)._z == y._z - 6) assert np.all((7 - y)._z == y._z - 7) assert np.all((y * 20)._z == y._z * 20) assert np.all((15 * y)._z == y._z * 15) assert np.all((y / .1)._z == y._z / .1) assert np.all((.1 / (y + 3))._z == .1 / (y._z + 3)) # test equality operator assert np.all(6 * y + 4 != y)
def resonators_w_line_delays(): fc = 5 * ureg('GHz') nch = ideal_notch(b_fr=(fc, fc, fc)) env = pm_line_delay() resonances, taus = [], [] x = np.linspace(fc - 50 * ureg('MHz'), fc + 50 * ureg('MHz'), 1000) np.random.seed(40) for (s21, m1), (ld, m2) in zip(sample(nch, 5, x), sample(env, 5, x)): # sample each resonance with centre frequency fc and span 20*fwhm fwhm_samples = s21.samples_below(s21.min() + np.ptp(s21.values) / 2) fwhm = np.ptp(fwhm_samples.x) f = np.linspace(fc - 10 * fwhm, fc + 10 * fwhm, 1000) model = nch(f).values * env(f).values # inject some magnitude only noise. XXX: build this into fitkit mags = np.abs(model) + np.random.normal(scale=2e-3, size=len(f)) resonances += [Signal1D(mags * np.exp(1j * np.angle(model)), xraw=f)] taus += [env.v['tau']] return zip(taus, resonances)
def test_correct_init(sinusoid): y = Signal1D(sinusoid) y = Signal1D(sinusoid, xlims=(-1 * ureg('us'), 10 * ureg('us'))) y = Signal1D(sinusoid, xcentspan=(0 * ureg('Hz'), 10 * ureg('Hz')))
def sinusoid(): fs = 20e3 t = np.arange(0, 0.1, 1 / fs) return Signal1D(np.sin(2 * np.pi * 1e3 * t), xlims=(0 * ureg('s'), 1 * ureg('s')))
def test_bad_xdef(sinusoid): with pytest.raises(Exception) as e_info: y = Signal1D(sinusoid, xlims=(0, 50), xcentspan=(25, 10)) with pytest.raises(Exception) as e_info: y = Signal1D(sinusoid, xlims=(50, 0))
def test_plot(sinusoid): y = Signal1D(sinusoid, xlims=(0 * ureg('s'), 1 * ureg('s'))) y.plot() plt.show() y.plot(style='abs') plt.show()
def test_plotz(sinusoid): y = Signal1D(sinusoid) y.plotz() plt.show()
def test_metric(sinusoid, dc): y1 = Signal1D(sinusoid[:len(dc)]) y2 = Signal1D(dc) assert y1 @ y1 == pytest.approx(0.0) assert y1 @ y2 == pytest.approx(1500)
def test_fs(sinusoid): y = Signal1D(sinusoid, xlims=(0 * ureg('s'), 0.1 * ureg('s'))) assert y.fs.to('Hz').magnitude == pytest.approx(20e3)
def test_pwr(dc): y = Signal1D(dc) assert y.pwr == pytest.approx(len(dc))
def test_len(dc): y = Signal1D(dc) assert len(y) == len(dc)
def test_x_init(sinusoid): y = Signal1D(sinusoid, xlims=(0 * ureg('s'), 1 * ureg('s'))) assert np.all(y.x == np.linspace(0, 1, len(y), endpoint=False) * ureg('s')) y = Signal1D(sinusoid, xcentspan=(0, 2)) assert np.all(y.x == np.linspace(-1, 1, len(y)))