def __pow__(self, other): if not is_integer(other): return NotImplemented n, d = self.tf if other > 0: return LinearSystem(normalize(n**other, d**other), self.analog) elif other < 0: return LinearSystem(normalize(d**-other, n**-other), self.analog) else: assert other == 0 return LinearSystem(1., self.analog)
def sys_equal(sys1, sys2, rtol=1e-05, atol=1e-08): """Returns true iff sys1 and sys2 have the same transfer functions.""" # TODO: doesn't do pole-zero cancellation sys1 = LinearSystem(sys1) sys2 = LinearSystem(sys2) if sys1.analog != sys2.analog: raise ValueError("Cannot compare analog with digital system") tf1 = normalize(*sys2tf(sys1)) tf2 = normalize(*sys2tf(sys2)) for t1, t2 in zip(tf1, tf2): if len(t1) != len(t2) or not np.allclose(t1, t2, rtol=rtol, atol=atol): return False return True
def pink(N, state=None): """ Pink noise. :param N: Amount of samples. :param state: State of PRNG. :type state: :class:`np.random.RandomState` Pink noise has equal power in bands that are proportionally wide. Power density decreases with 3 dB per octave. """ # This method uses the filter with the following coefficients. #b = np.array([0.049922035, -0.095993537, 0.050612699, -0.004408786]) #a = np.array([1, -2.494956002, 2.017265875, -0.522189400]) #return lfilter(B, A, np.random.randn(N)) # Another way would be using the FFT #x = np.random.randn(N) #X = rfft(x) / N state = np.random.RandomState() if state is None else state uneven = N % 2 X = state.randn(N // 2 + 1 + uneven) + 1j * state.randn(N // 2 + 1 + uneven) S = np.sqrt(np.arange(len(X)) + 1.) # +1 to avoid divide by zero y = (irfft(X / S)).real if uneven: y = y[:-1] return normalize(y, 1)
def __add__(self, other): self._check_other(other) n1, d1 = self.tf n2, d2 = LinearSystem(other, self.analog).tf if len(d1) == len(d2) and np.allclose(d1, d2): # short-cut to avoid needing pole-zero cancellation return LinearSystem((n1 + n2, d1), self.analog) return LinearSystem(normalize(n1*d2 + n2*d1, d1*d2), self.analog)
def test_allclose(self): """Test for false positive on allclose in normalize() in filter_design.py""" # Test to make sure the allclose call within signal.normalize does not # choose false positives. Then check against a known output from MATLAB # to make sure the fix doesn't break anything. # These are the coefficients returned from # `[b,a] = cheby1(8, 0.5, 0.048)' # in MATLAB. There are at least 15 significant figures in each # coefficient, so it makes sense to test for errors on the order of # 1e-13 (this can always be relaxed if different platforms have # different rounding errors) b_matlab = np.array([ 2.150733144728282e-11, 1.720586515782626e-10, 6.022052805239190e-10, 1.204410561047838e-09, 1.505513201309798e-09, 1.204410561047838e-09, 6.022052805239190e-10, 1.720586515782626e-10, 2.150733144728282e-11 ]) a_matlab = np.array([ 1.000000000000000e+00, -7.782402035027959e+00, 2.654354569747454e+01, -5.182182531666387e+01, 6.334127355102684e+01, -4.963358186631157e+01, 2.434862182949389e+01, -6.836925348604676e+00, 8.412934944449140e-01 ]) # This is the input to signal.normalize after passing through the # equivalent steps in signal.iirfilter as was done for MATLAB b_norm_in = np.array([ 1.5543135865293012e-06, 1.2434508692234413e-05, 4.3520780422820447e-05, 8.7041560845640893e-05, 1.0880195105705122e-04, 8.7041560845640975e-05, 4.3520780422820447e-05, 1.2434508692234413e-05, 1.5543135865293012e-06 ]) a_norm_in = np.array([ 7.2269025909127173e+04, -5.6242661430467968e+05, 1.9182761917308895e+06, -3.7451128364682454e+06, 4.5776121393762771e+06, -3.5869706138592605e+06, 1.7596511818472347e+06, -4.9409793515707983e+05, 6.0799461347219651e+04 ]) b_output, a_output = normalize(b_norm_in, a_norm_in) # The test on b works for decimal=14 but the one for a does not. For # the sake of consistency, both of these are decimal=13. If something # breaks on another platform, it is probably fine to relax this lower. assert_array_almost_equal(b_matlab, b_output, decimal=13) assert_array_almost_equal(a_matlab, a_output, decimal=13)
def violet(N, state=None): """ Violet noise. Power increases with 6 dB per octave. :param N: Amount of samples. :param state: State of PRNG. :type state: :class:`np.random.RandomState` Power increases with +9 dB per octave. Power density increases with +6 dB per octave. """ state = np.random.RandomState() if state is None else state uneven = N % 2 X = state.randn(N // 2 + 1 + uneven) + 1j * state.randn(N // 2 + 1 + uneven) S = (np.arange(len(X))) # Filter y = (irfft(X * S)).real if uneven: y = y[:-1] return normalize(y, 1)
def test_allclose(self): """Test for false positive on allclose in normalize() in filter_design.py""" # Test to make sure the allclose call within signal.normalize does not # choose false positives. Then check against a known output from MATLAB # to make sure the fix doesn't break anything. # These are the coefficients returned from # `[b,a] = cheby1(8, 0.5, 0.048)' # in MATLAB. There are at least 15 significant figures in each # coefficient, so it makes sense to test for errors on the order of # 1e-13 (this can always be relaxed if different platforms have # different rounding errors) b_matlab = np.array([2.150733144728282e-11, 1.720586515782626e-10, 6.022052805239190e-10, 1.204410561047838e-09, 1.505513201309798e-09, 1.204410561047838e-09, 6.022052805239190e-10, 1.720586515782626e-10, 2.150733144728282e-11]) a_matlab = np.array([1.000000000000000e+00, -7.782402035027959e+00, 2.654354569747454e+01, -5.182182531666387e+01, 6.334127355102684e+01, -4.963358186631157e+01, 2.434862182949389e+01, -6.836925348604676e+00, 8.412934944449140e-01]) # This is the input to signal.normalize after passing through the # equivalent steps in signal.iirfilter as was done for MATLAB b_norm_in = np.array([1.5543135865293012e-06, 1.2434508692234413e-05, 4.3520780422820447e-05, 8.7041560845640893e-05, 1.0880195105705122e-04, 8.7041560845640975e-05, 4.3520780422820447e-05, 1.2434508692234413e-05, 1.5543135865293012e-06]) a_norm_in = np.array([7.2269025909127173e+04, -5.6242661430467968e+05, 1.9182761917308895e+06, -3.7451128364682454e+06, 4.5776121393762771e+06, -3.5869706138592605e+06, 1.7596511818472347e+06, -4.9409793515707983e+05, 6.0799461347219651e+04]) b_output, a_output = normalize(b_norm_in, a_norm_in) # The test on b works for decimal=14 but the one for a does not. For # the sake of consistency, both of these are decimal=13. If something # breaks on another platform, it is probably fine to relax this lower. assert_array_almost_equal(b_matlab, b_output, decimal=13) assert_array_almost_equal(a_matlab, a_output, decimal=13)
def _override_tf(b, a): b, a = signal.normalize(b, a) Rs_, Rct_, Cdl_ = tf_to_circuit(b, a) b, a = circuit_to_tf((Rs if Rs else Rs_), (Rct if Rct else Rct_), (Cdl if Cdl else Cdl_)) return b, a
def tf_to_circuit(b, a): b, a = signal.normalize(b, a) Rs = b[0] Rct = (b[1] / a[1]) - Rs Cdl = (a[1] * Rct)**-1 return (Rs, Rct, Cdl)
def tf(self): b_hi, a_hi = self.tf_high b_lo, a_lo = self.tf_low b = polymul(b_hi, b_lo) a = polymul(a_hi, a_lo) return normalize(b, a)
def __hash__(self): num, den = normalize(*self.tf) return hash((tuple(num), tuple(den), self.analog))
def __mul__(self, other): self._check_other(other) n1, d1 = self.tf n2, d2 = LinearSystem(other, self.analog).tf return LinearSystem(normalize(n1*n2, d1*d2), self.analog)