Ejemplo n.º 1
0
    def freqz(self, worN, fs):
        """

        Returns an audioSample of the frequency response corresponding to 
        the zpk filter. Inputs are the same as scipy.signal.freqz_zpk

        ---------------------------------------------------------------------
        INPUTS
        ---------------------------------------------------------------------
        worN			| (int) length of the frequency response (assumes
                        | single-sided)
        ---------------------------------------------------------------------
        fs  			| (int) sampling frequency
        ---------------------------------------------------------------------
        
        ---------------------------------------------------------------------
        OUTPUTS
        ---------------------------------------------------------------------
        (audioSample) containing the frequency response (frequency domain)
        of the filter
        ---------------------------------------------------------------------

        """

        if isinstance(worN, float):
            print(
                "Float given instead of integer for length of freqz. This will be converted to an integer"
            )
            worN = int(worN)

        w, h = sig.freqz_zpk(self.get_zs(), self.get_ps(answer_complex=True), \
            self.get_k(), worN=worN)

        return audioSample(h, type="f", Fs=fs)
Ejemplo n.º 2
0
def plot_zpk(system, fp, fs, Amax, Amin, sample_rate=48e3, num_samples=1024, ax=None, plot_focus='all'):

    fmin = np.floor(np.log10(fp))-1
    fmax = np.ceil(np.log10(fs))

    f = np.logspace(fmin, fmax, num_samples)
    f, h = signal.freqz_zpk(*system, fs=sample_rate, worN=f)

    if ax is None:
        fig, ax = plt.subplots()
    
    if plot_focus == 'all':
        axis_focus = [1e2, 10**fmax, -50, 1]
        ax.set_xscale('log')
    elif plot_focus == 'pass':
        axis_focus = [1000, 2500, -5, 0]
    elif plot_focus == 'stop':
        axis_focus = [3000, 5000, -50, -35]

    # Plot data
    ax.plot(f, 20 * np.log10(np.abs(h)), linewidth=2)

    # Plot boxes
    box_style = dict(linewidth=2, linestyle='--', edgecolor='k', facecolor='0.9')
    ax.fill([10**fmin, 10**fmin,  fp,  fp], [-Amin*2, -Amax, -Amax, -Amin*2], **box_style) # pass
    ax.fill([fs, fs,  10**fmax,  10**fmax], [-Amin, Amax, Amax, -Amin], **box_style) # stop

    # Set plot properties
    ax.set_title('Lowpass filter')
    ax.set_xlabel('Frequency [Hz]')
    ax.set_ylabel('Amplitude [dB]')
    ax.grid(True, which='both', axis='both')
    ax.axis(axis_focus)
Ejemplo n.º 3
0
def test__get_causal_signal_preserves_roots_inside_unit_circle():
    n_signals = 1
    _, transfer_function = freqz_zpk(0.25, 0.5, 1.00, whole=True)
    n_fft_samples = transfer_function.shape[0]
    linear_predictor = np.zeros((1, n_fft_samples, n_signals, n_signals),
                                dtype=np.complex)
    linear_predictor[0, :, 0, 0] = transfer_function

    _, expected_transfer_function = freqz_zpk(0.25, 0.5, 1.00, whole=True)
    linear_coef = ifft(expected_transfer_function)
    linear_coef[0] *= 0.5

    expected_causal_signal = np.zeros((1, n_fft_samples, n_signals, n_signals),
                                      dtype=np.complex)
    expected_causal_signal[0, :, 0, 0] = fft(linear_coef)

    causal_signal = _get_causal_signal(linear_predictor)

    assert np.allclose(causal_signal, expected_causal_signal)
Ejemplo n.º 4
0
def test_minimum_phase_decomposition():
    n_signals = 1
    # minimum phase is all poles and zeros inside the unit circle
    _, transfer_function = freqz_zpk(0.25, 0.50, 1.00, whole=True)
    n_fft_samples = transfer_function.shape[0]
    expected_minimum_phase_factor = np.zeros(
        (2, n_fft_samples, n_signals, n_signals), dtype=np.complex)
    expected_minimum_phase_factor[0, :, 0, 0] = transfer_function

    _, transfer_function2 = freqz_zpk(0.125, 0.25, 1.00, whole=True)
    expected_minimum_phase_factor[1, :, 0, 0] = transfer_function2

    expected_cross_spectral_matrix = np.matmul(
        expected_minimum_phase_factor,
        _conjugate_transpose(expected_minimum_phase_factor))
    minimum_phase_factor = minimum_phase_decomposition(
        expected_cross_spectral_matrix)
    cross_spectral_matrix = (minimum_phase_factor *
                             _conjugate_transpose(minimum_phase_factor))

    assert np.allclose(minimum_phase_factor, expected_minimum_phase_factor)
    assert np.allclose(cross_spectral_matrix, expected_cross_spectral_matrix)
    def test_freq_resp_zpk(self):
        # Test that frequency response meets tolerance from ITU-R BS.468-4
        fs = 270000
        z, p, k = ITU_R_468_weighting(fs, 'zpk')
        w, h = signal.freqz_zpk(z, p, k, 2*pi*frequencies/fs)
        levels = 20 * np.log10(abs(h))

        if mpl:
            plt.figure('468')
            plt.semilogx(frequencies, levels, alpha=0.7, label='zpk')
            plt.legend()

        assert all(np.less_equal(levels, responses + upper_limits))
        assert all(np.greater_equal(levels, responses + lower_limits))
Ejemplo n.º 6
0
def test__get_causal_signal_removes_roots_outside_unit_circle():
    n_signals = 1
    _, transfer_function = freqz_zpk(4, 2, 1.00, whole=True)
    n_fft_samples = transfer_function.shape[0]
    linear_predictor = np.zeros((1, n_fft_samples, n_signals, n_signals),
                                dtype=np.complex)
    linear_predictor[0, :, 0, 0] = transfer_function

    expected_causal_signal = np.ones((1, n_fft_samples, n_signals, n_signals),
                                     dtype=np.complex)

    causal_signal = _get_causal_signal(linear_predictor)

    assert np.allclose(causal_signal, expected_causal_signal)
Ejemplo n.º 7
0
    def test_freq_resp_zpk(self):
        # Test that frequency response meets tolerance from ANSI S1.4-1983
        fs = 270000
        z, p, k = A_weighting(fs, 'zpk')
        w, h = signal.freqz_zpk(z, p, k, 2 * pi * frequencies / fs)
        levels = 20 * np.log10(abs(h))

        if mpl:
            plt.figure('A')
            plt.semilogx(frequencies, levels, alpha=0.7, label='zpk')
            plt.legend()

        assert all(np.less_equal(levels, responses['A'] + upper_limits))
        assert all(np.greater_equal(levels, responses['A'] + lower_limits))
Ejemplo n.º 8
0
def plot_zpk(z, p, k, fp, fs, Amax, Amin, sample_rate=48e3):
    f, h = signal.freqz_zpk(z, p, k, fs=sample_rate)

    plt.plot(f, 20 * np.log10(abs(h)))
    plt.xscale('log')
    plt.title('Lowpass filter fit to constraints')
    plt.xlabel('Frequency [Hz]')
    plt.ylabel('Amplitude [dB]')
    plt.grid(True, which='both', axis='both')
    plt.fill([1e2, 1e2, fp, fp], [-Amin * 2, -Amax, -Amax, -Amin * 2],
             '0.9',
             lw=0)  # pass
    plt.fill([fs, fs, 1e4, 1e4], [-Amin, Amax, Amax, -Amin], '0.9',
             lw=0)  # stop
    plt.axis([1e2, 1e4, -50, 1])
Ejemplo n.º 9
0
def get_specbasis(bandpass):

    low = bandpass[0]
    high = bandpass[1]
    corners = bandpass[2]

    low = low / (0.5*df)
    high = high / (0.5*df)

    z, p, k = iirfilter(corners, [low, high], btype='band',
                        ftype='butter', output='zpk')
    w, h = freqz_zpk(z,p,k, worN=len(freq))
    
    # always zerophase
    h2 = h*np.conjugate(h)
    
    return np.real(h2)
Ejemplo n.º 10
0
def PinkNoise(fs, fstart=10, fend=None, N=3):
    """
    Creates SOS filter for pink noise. The filter has a flat response below
    fstart, and rolls of close to Nyquist, or flattens out above fend. The
    ripple (i.e.) closeness the filter rolls of depends on the number of
    sections. The default, N=3 results in

    Args:
        fs: Sampling frequency [Hz]
        fstart: Frequency of first pole of the filter
        fend: Frequency of last pole of the filter, if not given, set to 5/6th
        of the Nyquist frequency.
        N: Number of sections.

    Returns:
        sos: Array of digital filter coefficients

    """
    order = N * 2
    if fend is None:
        fend = 5 * fs / 6 / 2
    # Not the fastest implementation, but this will not be the bottleneck
    # anyhow.
    fpoles = np.array(
        [fstart * (fend / fstart)**(n / (order - 1)) for n in range(order)])

    # Put zeros inbetween poles
    fzeros = np.sqrt(fpoles[1:] * fpoles[:-1])

    poles = -2 * np.pi * fpoles
    zeros = -2 * np.pi * fzeros

    z, p, k = bilinear_zpk(zeros, poles, 1, fs=fs)

    # Compute the frequency response and search for the gain at fstart, we
    # normalize such that this gain is ~ 0 dB. Rounded to an integer frequency
    # in Hz.
    Omg, h = freqz_zpk(z, p, k, worN=int(fs / 2), fs=fs)
    h_fstart = np.abs(h[int(fstart)])
    k *= 1 / h_fstart

    sos = zpk2sos(z, p, k)

    return sos
Ejemplo n.º 11
0
def check_limits(system, spec, num_samples=1000):
    # fp, fs, Amax=1, Amin=42, sample_rate=48e3

    f1 = np.logspace(np.floor(np.log10(spec['fp']))-1, np.log10(spec['fp']), 2*num_samples)
    f2 = np.logspace(np.log10(spec['fs']), np.log10(spec['sample_rate']/2), num_samples)
    # f1 = np.linspace(0, spec['fp'], 2*num_samples)
    # f2 = np.linspace(spec['fs'], spec['sample_rate']/2, num_samples)
    f = np.hstack([f1, f2])

    f, h = signal.freqz_zpk(*system, fs=spec['sample_rate'], worN=f)
    Hdb = 20 * np.log10(np.abs(h))

    pass_band = Hdb[f <= spec['fp']]
    pass_band_faults = (pass_band < -spec['Amax']).sum() + (pass_band > 0).sum()
    stop_band_faults = (Hdb[f >= spec['fs']] > -spec['Amin']).sum()

    total_faults = pass_band_faults + stop_band_faults + system[1].size

    return total_faults
Ejemplo n.º 12
0
def get_specbasis(bandpass):

    low = bandpass[0]
    high = bandpass[1]
    corners = bandpass[2]

    low = low / (0.5 * df)
    high = high / (0.5 * df)

    z, p, k = iirfilter(corners, [low, high],
                        btype='band',
                        ftype='butter',
                        output='zpk')
    w, h = freqz_zpk(z, p, k, worN=len(freq))

    # always zerophase
    h2 = h * np.conjugate(h)

    return np.real(h2)
Ejemplo n.º 13
0
def Z2(w3,n):
	#Krok 1
	wc = 2*np.tan(w3/2)
	poles = np.array([])
	#Krok 2
	for k in range(0,n):
		sk = wc*(np.exp(1j*np.pi*(1+2*k)/(2*n)))*np.exp(1j*np.pi/2)
		poles = np.append(poles,sk)
		plt.figure(2)
		plt.plot(np.real(sk),np.imag(sk),marker = 'x')
	plt.title('Położenie biegunów filtru analogowego')
	plt.xlabel('Real part')
	plt.ylabel('Imaginary part')
	plt.show()

	#Krok 3
	G0_num,G0_den = 1,1
	for k in range(0,n):
		G0_num = G0_num*(-poles[k]) 
		G0_den = G0_den*(2-poles[k]) 
	G0 = G0_num/G0_den
	poles_digital = (2+poles)/(2-poles)
	for n in poles_digital:
		plt.figure(3)
		plt.scatter(np.real(poles_digital),np.imag(poles_digital),marker='x')
	plt.xlim((-1.5,1.5))
	plt.title('Położenie zer oraz biegunów filtru cyfrowego')
	plt.ylabel('Imaginary part')
	plt.xlabel('Real part')
	plt.plot(-1,0,marker = 'o')
	plt.show()

	#Krok 4
	w,h = signal.freqz_zpk([-1,-1,-1], poles_digital, G0)
	fig = plt.figure(4)
	print(np.where(np.isclose(w, 2.50959257)))
	print(abs(h)[409])
	plt.title('Digital filter frequency response')
	plt.plot(w, (abs(h)), 'b')
	plt.xlabel('Frequency [rad/s]')
	plt.grid()
	plt.show()
Ejemplo n.º 14
0
def plotFilterResponse(zpk, fs):
    """
    Plot the filter frequency response.

    Parameters
    ----------
    zpk : array-like
        The 3 parameters of the filter [z, p, k].
    fs : float
        Sampling frequency in Hz.

    Returns:

    fig : instance of matplotlib.figure.Figure
        The figure of the filter response.
    """

    z, p, k = zpk
    w, h = freqz_zpk(z, p, k, worN=8000)

    plt.plot(0.5 * fs * w / np.pi, 20 * np.log10(abs(h)), 'b')
    plt.title('Chebyshev II bandstop filter')
    plt.xlabel('Normalized frequency')
    plt.ylabel('Amplitude [dB]')
from scipy import signal
z, p, k = signal.butter(4, 0.2, output='zpk')
w, h = signal.freqz_zpk(z, p, k)

import matplotlib.pyplot as plt
fig = plt.figure()
plt.title('Digital filter frequency response')
ax1 = fig.add_subplot(111)

plt.plot(w, 20 * np.log10(abs(h)), 'b')
plt.ylabel('Amplitude [dB]', color='b')
plt.xlabel('Frequency [rad/sample]')

ax2 = ax1.twinx()
angles = np.unwrap(np.angle(h))
plt.plot(w, angles, 'g')
plt.ylabel('Angle (radians)', color='g')
plt.grid()
plt.axis('tight')
plt.show()
Ejemplo n.º 16
0
 def get_respuesta_frecuencial(self, cantidad_muestras, filtro):
     z = filtro[0]
     p = filtro[1]
     k = filtro[2]
     return signal.freqz_zpk(z, p, k, worN=cantidad_muestras)
Ejemplo n.º 17
0
def s2z_zpk(s_zeros, s_poles, s_gain, s2z, fs, f0):
    z_zeros, z_poles, z_gain = s2z(s_zeros, s_poles, s_gain, fs=fs)
    z_gain *= _np.abs(_sig.freqs_zpk(s_zeros, s_poles, s_gain, worN=[2*_np.pi*f0])[1])\
        / _np.abs(_sig.freqz_zpk(z_zeros, z_poles, z_gain, worN=[f0], fs=fs)[1])
    return z_zeros, z_poles, z_gain
Ejemplo n.º 18
0
# Design a 4th-order digital Butterworth filter with cut-off of 100 Hz in a
# system with sample rate of 1000 Hz, and plot the frequency response:

from scipy import signal

z, p, k = signal.butter(4, 100, output='zpk', fs=1000)
w, h = signal.freqz_zpk(z, p, k, fs=1000)

import matplotlib.pyplot as plt

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_title('Digital filter frequency response')

ax1.plot(w, 20 * np.log10(abs(h)), 'b')
ax1.set_ylabel('Amplitude [dB]', color='b')
ax1.set_xlabel('Frequency [Hz]')
ax1.grid()

ax2 = ax1.twinx()
angles = np.unwrap(np.angle(h))
ax2.plot(w, angles, 'g')
ax2.set_ylabel('Angle [radians]', color='g')

plt.axis('tight')
plt.show()
Ejemplo n.º 19
0
def plot_zpk(z, p, k, worN=5000, fs=44.1e3, show=True):
    """

    Visualize a system given the a list of zeros, poles and a gain
    
    
    ---------------------------------------------------------------------
    INPUTS
    ---------------------------------------------------------------------
    z			| (1-d iterable) of zeros of the system
    ---------------------------------------------------------------------
    p			| (1-d iterable) of poles of the system
    ---------------------------------------------------------------------
    k			| (float) gain of the system
    ---------------------------------------------------------------------
    worN		| as required by scipy.signal.freqz_zpk, list of 
                | frequencies or number of frequencies to calculate the 
                | reponse at
    ---------------------------------------------------------------------
    fs  		| (float) sampling frequency used to calculate the 
                | frequencies in Hz
    ---------------------------------------------------------------------
    show		| whether or not to display the resulting graph using 
                | plt.show()
    ---------------------------------------------------------------------
    
    """

    if isinstance(worN, float):
        print(
            "Float given instead of integer for length of freqz. This will be converted to an integer"
        )
        worN = int(worN)

    # int casting to ensure supplied the number of frequencies to calculate
    w, h = sig.freqz_zpk(z, p, k, worN=worN)  # rad/samp, magnitudes

    fig = plt.figure(figsize=(20, 4))
    gs = GridSpec(2, 2, width_ratios=[1, 2])

    #plot poles/zeros
    ax1 = fig.add_subplot(gs[0:, 0])

    #gives the unit circle
    unit_circle = patches.Circle((0, 0),
                                 radius=1,
                                 fill=False,
                                 color='grey',
                                 ls='dotted',
                                 alpha=0.5)
    ax1.add_patch(unit_circle)

    # plot poles and zeros
    for pole in p:
        plt.plot(pole.real,
                 pole.imag,
                 'x',
                 markersize=7,
                 alpha=0.7,
                 color='blue')
    for zero in z:
        plt.plot(zero.real,
                 zero.imag,
                 'o',
                 markersize=7,
                 markerfacecolor='none',
                 markeredgecolor=colorConverter.to_rgba('mediumseagreen',
                                                        alpha=0.7))
    ax1.grid(True)
    ax1.set_xlim(-1.2, 1.2)
    ax1.set_ylim(-1.2, 1.2)
    ax1.set_title('Z domain Poles/Zeros')

    #plot mag/phase
    ax2 = fig.add_subplot(gs[0, 1:])
    db = 20 * np.log10(np.abs(h))
    ax2.plot(w / np.pi * fs / 2, db)
    ax2.set_xscale('symlog')
    spacing = octaves_to(fs / 2)
    ax2.set_xticks(spacing)
    ax2.set_xticklabels(spacing, rotation=30)
    ax2.set_ylim(-75, 5)
    ax2.grid(True)
    ax2.set_yticks([0, -20, -40, -60])
    ax2.set_ylabel('Gain [dB]')
    ax2.set_title('Frequency Response')

    ax3 = fig.add_subplot(gs[1, 1:])
    ax3.plot(w / np.pi * fs / 2, np.angle(h))
    ax3.set_xscale('symlog')
    ax3.set_xticks(spacing)
    ax3.set_xticklabels(spacing, rotation=30)
    ax3.grid(True)
    ax3.set_yticks([-np.pi, -0.5 * np.pi, 0, 0.5 * np.pi, np.pi],
                   [r'$-\pi$', r'$-\pi/2$', '0', r'$\pi/2$', r'$\pi$'])
    ax3.set_ylabel('Phase [rad]')
    ax3.set_xlabel('Frequency (Hz)')

    if show: plt.show()
from scipy import signal
import matplotlib.pyplot as plt

fs = 100
bf = 2 * np.pi * np.array([7, 13])
filts = signal.lti(*signal.butter(4, bf, btype='bandpass', analog=True, output='zpk'))
filtz = signal.lti(*signal.bilinear_zpk(filts.zeros, filts.poles, filts.gain, fs))
wz, hz = signal.freqz_zpk(filtz.zeros, filtz.poles, filtz.gain)
ws, hs = signal.freqs_zpk(filts.zeros, filts.poles, filts.gain, worN=fs*wz)
plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hz).clip(1e-15)), label=r'$|H(j \omega)|$')
plt.semilogx(wz*fs/(2*np.pi), 20*np.log10(np.abs(hs).clip(1e-15)), label=r'$|H_z(e^{j \omega})|$')
plt.legend()
plt.xlabel('Frequency [Hz]')
plt.ylabel('Magnitude [dB]')
plt.grid()