Пример #1
0
def iir_bandstops(fstops, fs, order=4):
    import numpy as np
    from scipy.signal import iirdesign, zpk2tf, freqz
    nyq = 0.5 * fs
    # Zeros zd, poles pd, and gain kd for the digital filter
    zd = np.array([])
    pd = np.array([])
    kd = 1

    # Notches
    for fstopData in fstops:
        fstop = fstopData[0]
        df = fstopData[1]
        df2 = fstopData[2]
        low = (fstop - df) / nyq
        high = (fstop + df) / nyq
        low2 = (fstop - df2) / nyq
        high2 = (fstop + df2) / nyq
        z, p, k = iirdesign([low,high], [low2,high2], gpass=1, gstop=6,
                            ftype='ellip', output='zpk')
        zd = np.append(zd,z)
        pd = np.append(pd,p)

    # Set gain to one at 100 Hz...better not notch there
    bPrelim,aPrelim = zpk2tf(zd, pd, 1)
    outFreq, outg0 = freqz(bPrelim, aPrelim, 100/nyq)

    # Return the numerator and denominator of the digital filter
    b,a = zpk2tf(zd,pd,k)
    return b, a
Пример #2
0
def ITU_R_468_weighting(fs):
    """
    Return ITU-R 468 digital weighting filter transfer function
 
    fs : float
        Sampling frequency
 
    Example:
 
    >>> from scipy.signal import freqz
    >>> import matplotlib.pyplot as plt
    >>> fs = 200000
    >>> b, a = ITU_R_468_weighting(fs)
    >>> f = np.logspace(np.log10(10), np.log10(fs/2), 1000)
    >>> w = 2*pi * f / fs
    >>> w, h = freqz(b, a, w)
    >>> plt.semilogx(w*fs/(2*pi), 20*np.log10(abs(h)))
    >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
    >>> plt.axis([10, 100e3, -50, 20])
 
    """
 
    z, p, k = ITU_R_468_weighting_analog()
 
    # Use the bilinear transformation to get the digital filter.
    try:
        # Currently private but more accurate
        from scipy.signal.filter_design import _zpkbilinear
        zz, pz, kz = _zpkbilinear(z, p, k, fs)
        return zpk2tf(zz, pz, kz)
    except ImportError:
        b, a = zpk2tf(z, p, k)
        return bilinear(b, a, fs)
def iir_bandstops(fstops, fs, order=4):
    """ellip notch filter
    fstops is a list of entries of the form [frequency (Hz), df, df2]                           
    where df is the pass width and df2 is the stop width (narrower                              
    than the pass width). Use caution if passing more than one freq at a time,                  
    because the filter response might behave in ways you don't expect.
    """
    nyq = 0.5 * fs

    # Zeros zd, poles pd, and gain kd for the digital filter
    zd = np.array([])
    pd = np.array([])
    kd = 1

    # Notches
    for fstopData in fstops:
        fstop = fstopData[0]
        df = fstopData[1]
        df2 = fstopData[2]
        low = (fstop - df) / nyq
        high = (fstop + df) / nyq
        low2 = (fstop - df2) / nyq
        high2 = (fstop + df2) / nyq
        z, p, k = iirdesign([low,high], [low2,high2], gpass=1, gstop=6,
                            ftype='ellip', output='zpk')
        zd = np.append(zd,z)
        pd = np.append(pd,p)

    # Set gain to one at 100 Hz...better not notch there                                        
    bPrelim,aPrelim = zpk2tf(zd, pd, 1)
    outFreq, outg0 = freqz(bPrelim, aPrelim, 100/nyq)

    # Return the numerator and denominator of the digital filter                                
    b,a = zpk2tf(zd,pd,k)
    return b, a
Пример #4
0
def ITU_R_468_weighting(fs):
    """
    Return ITU-R 468 digital weighting filter transfer function

    fs : float
        Sampling frequency

    Example:

    >>> from scipy.signal import freqz
    >>> import matplotlib.pyplot as plt
    >>> fs = 200000
    >>> b, a = ITU_R_468_weighting(fs)
    >>> f = np.logspace(np.log10(10), np.log10(fs/2), 1000)
    >>> w = 2*pi * f / fs
    >>> w, h = freqz(b, a, w)
    >>> plt.semilogx(w*fs/(2*pi), 20*np.log10(abs(h)))
    >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
    >>> plt.axis([10, 100e3, -50, 20])

    """

    z, p, k = ITU_R_468_weighting_analog()

    # Use the bilinear transformation to get the digital filter.
    try:
        # Currently private but more accurate
        from scipy.signal.filter_design import _zpkbilinear

        zz, pz, kz = _zpkbilinear(z, p, k, fs)
        return zpk2tf(zz, pz, kz)
    except ImportError:
        b, a = zpk2tf(z, p, k)
        return bilinear(b, a, fs)
Пример #5
0
def prepare_video_filters():
	# TODO:  test these CLV+innerCAV parameters.  Should be same on PAL+NTSC 
	t1 = 25
	t2 = 13.75
	
	[tf_b, tf_a] = sps.zpk2tf(-t2*(10**-8), -t1*(10**-8), t1 / t2)
	SP['f_emp'] = sps.bilinear(tf_b, tf_a, 1/(freq_hz/2))

	# RF BPF and analog audio cut filters
	SP['f_videorf_bpf'] = sps.butter(1, [SP['vbpf'][0]/(freq_hz/2), SP['vbpf'][1]/(freq_hz/2)], btype='bandpass')

	if SP['analog_audio'] == True:
		SP['f_aleft_stop'] = sps.butter(1, [(SP['audio_lfreq'] - 750000)/(freq_hz/2), (SP['audio_lfreq'] + 750000)/(freq_hz/2)], btype='bandstop')
		SP['f_aright_stop'] = sps.butter(1, [(SP['audio_rfreq'] - 750000)/(freq_hz/2), (SP['audio_rfreq'] + 750000)/(freq_hz/2)], btype='bandstop')

	# standard post-demod LPF
	lowpass_filter_b, lowpass_filter_a = sps.butter(SP['vlpf_order'], SP['vlpf_freq']/(freq_hz/2), 'low')
	
	# post-demod deemphasis filter
	[tf_b, tf_a] = sps.zpk2tf(-SP['deemp'][1]*(10**-8), -SP['deemp'][0]*(10**-8), SP['deemp'][0] / SP['deemp'][1])
	SP['f_deemp'] = sps.bilinear(tf_b, tf_a, 1/(freq_hz/2))

	# if AC3:
	#SP['f_arightcut'] = sps.butter(1, [(2650000)/(freq_hz/2), (3150000)/(freq_hz/2)], btype='bandstop')

	# prepare for FFT: convert above filters to FIR using FDLS techniques first
	forder = 256 
	forderd = 0 

	[Bbpf_FDLS, Abpf_FDLS] = fdls.FDLS_fromfilt(SP['f_videorf_bpf'][0], SP['f_videorf_bpf'][1], forder, forderd, 0, phasemult = 1.00)
	[Bemp_FDLS, Aemp_FDLS] = fdls.FDLS_fromfilt(SP['f_emp'][0], SP['f_emp'][1], forder, forderd, 0)
	[Bdeemp_FDLS, Adeemp_FDLS] = fdls.FDLS_fromfilt(SP['f_deemp'][0], SP['f_deemp'][1], forder, forderd, 0)
	[Bplpf_FDLS, Aplpf_FDLS] = fdls.FDLS_fromfilt(lowpass_filter_b, lowpass_filter_a, forder, forderd, 0)

	Fbpf = np.fft.fft(Bbpf_FDLS, blocklen)
	Femp = np.fft.fft(Bemp_FDLS, blocklen)

	SP['fft_video'] = Fbpf * fft_hilbert

	if SP['analog_audio'] == True:
		[Bcutl_FDLS, Acutl_FDLS] = fdls.FDLS_fromfilt(SP['f_aleft_stop'][0], SP['f_aleft_stop'][1], forder, forderd, 0, phasemult = 1.00)
		[Bcutr_FDLS, Acutr_FDLS] = fdls.FDLS_fromfilt(SP['f_aright_stop'][0], SP['f_aright_stop'][1], forder, forderd, 0, phasemult = 1.00)
		Fcutl = np.fft.fft(Bcutl_FDLS, blocklen)
		Fcutr = np.fft.fft(Bcutr_FDLS, blocklen)
		SP['fft_video'] *= (Fcutl * Fcutr)
	
	SP['fft_video_inner'] = SP['fft_video'] * Femp

	# Post processing:  lowpass filter + deemp
	Fplpf = np.fft.fft(Bplpf_FDLS, blocklen)
	Fdeemp = np.fft.fft(Bdeemp_FDLS, blocklen)
	SP['fft_post'] = Fplpf * Fdeemp	

	# determine freq offset and mult for output stage	
	hz_ire_scale = (SP['videorf_100ire'] - SP['videorf_0ire']) / 100
	minn = SP['videorf_0ire'] + (hz_ire_scale * -60)
	SP['output_minfreq'] = sminn = minn / (freq_hz / tau)

	out_scale = 65534.0 / (SP['ire_max'] - SP['ire_min'])
	SP['output_scale'] = (freq_hz / tau) * (out_scale / hz_ire_scale)
Пример #6
0
def iir_bandstops(fstops, fs, order=4):
    """ellip notch filter
    fstops is a list of entries of the form [frequency (Hz), df, df2]                           
    where df is the pass width and df2 is the stop width (narrower                              
    than the pass width). Use caution if passing more than one freq at a time,                  
    because the filter response might behave in ways you don't expect.
    """
    nyq = 0.5 * fs

    # Zeros zd, poles pd, and gain kd for the digital filter
    zd = np.array([])
    pd = np.array([])
    kd = 1

    # Notches
    for fstopData in fstops:
        fstop = fstopData[0]
        df = fstopData[1]
        df2 = fstopData[2]
        low = (fstop - df) / nyq
        high = (fstop + df) / nyq
        low2 = (fstop - df2) / nyq
        high2 = (fstop + df2) / nyq
        z, p, k = iirdesign([low,high], [low2,high2], gpass=1, gstop=6,
                            ftype='ellip', output='zpk')
        zd = np.append(zd,z)
        pd = np.append(pd,p)

    # Set gain to one at 100 Hz...better not notch there                                        
    bPrelim,aPrelim = zpk2tf(zd, pd, 1)
    outFreq, outg0 = freqz(bPrelim, aPrelim, 100/nyq)

    # Return the numerator and denominator of the digital filter                                
    b,a = zpk2tf(zd,pd,k)
    return b, a
def find_sysd_prew(sys,f,Ts): #Find the discrete-time transfer function for the Bilinear transform with prewarping
    #Convert the continuous time system to a form so we can substitute s with factor*(z-1)/(z+1)
    s = Symbol('s')
    zer = sys.zero()
    pol = sys.pole()
    teller = 1
    noemer = 1
    for k in range(len(zer)):
        teller = teller * (s-zer[k])
    for k in range(len(pol)):
        noemer = noemer*(s-pol[k])
    sys_cont = teller/noemer
    val1 = sys.horner(0)[0][0]
    val2 = sys_cont.subs(s,0)
    K = val1/val2
    sys_cont = simplify(K*teller/noemer)
    #Substitute s
    z = Symbol('z')
    factor = float(f)/(math.tan(float(f)*Ts/2))
    ssys = simplify(sys_cont.subs(s,factor*(z-1)/(z+1)))
    omgekeerd = simplify(1/ssys)
    #Compute zeros and poles
    zeros = solve(ssys, z)
    poles = solve(omgekeerd,z)
    #Compute gain
    num,den = signal.zpk2tf(zeros,poles,1)
    num = num.tolist()
    den = den.tolist()
    for k in range(len(num)):
        try:
            num[k] = float(num[k])
        except:
            num[k] = num[k]
    for k in range(len(den)):
        try:
            den[k] = float(den[k])
        except:
            den[k] = den[k]
    system = TransferFunction(num,den,Ts)
    gain = sys.horner(0)[0][0]/(system.horner(1)[0][0])
    #Convert it to a transferfunction
    num,den = signal.zpk2tf(zeros,poles,gain)
    num = num.tolist()
    den = den.tolist()
    for k in range(len(num)):
        try:
            num[k] = float(num[k])
        except:
            num[k] = num[k]
    for k in range(len(den)):
        try:
            den[k] = float(den[k])
        except:
            den[k] = den[k]
    system = TransferFunction(num,den,Ts)
    return system
Пример #8
0
def prepare_video_filters(SP):
    # TODO:  test these CLV+innerCAV parameters.  Should be same on PAL+NTSC
    t1 = 25
    t2 = 13.75

    [tf_b, tf_a] = sps.zpk2tf(-t2 * (10 ** -8), -t1 * (10 ** -8), t1 / t2)
    Femp = filtfft(sps.bilinear(tf_b, tf_a, 1 / (freq_hz / 2)))

    # RF BPF and analog audio cut filters
    Fbpf = filtfft(sps.butter(1, [SP["vbpf"][0] / (freq_hz / 2), SP["vbpf"][1] / (freq_hz / 2)], btype="bandpass"))

    # standard post-demod LPF
    Fplpf = filtfft(sps.butter(SP["vlpf_order"], SP["vlpf_freq"] / (freq_hz / 2), "low"))

    # post-demod deemphasis filter
    [tf_b, tf_a] = sps.zpk2tf(
        -SP["deemp"][1] * (10 ** -8), -SP["deemp"][0] * (10 ** -8), SP["deemp"][0] / SP["deemp"][1]
    )
    Fdeemp = filtfft(sps.bilinear(tf_b, tf_a, 1.0 / (freq_hz / 2)))

    SP["fft_video"] = Fbpf * fft_hilbert

    if SP["analog_audio"] == True:
        Fcutl = filtfft(
            sps.butter(
                1,
                [(SP["audio_lfreq"] - 750000) / (freq_hz / 2), (SP["audio_lfreq"] + 750000) / (freq_hz / 2)],
                btype="bandstop",
            )
        )
        Fcutr = filtfft(
            sps.butter(
                1,
                [(SP["audio_rfreq"] - 750000) / (freq_hz / 2), (SP["audio_rfreq"] + 750000) / (freq_hz / 2)],
                btype="bandstop",
            )
        )
        # if AC3:
        # SP['f_arightcut'] = sps.butter(1, [(2650000)/(freq_hz/2), (3150000)/(freq_hz/2)], btype='bandstop')

        SP["fft_video"] *= Fcutl * Fcutr

    SP["fft_video_inner"] = SP["fft_video"] * Femp

    # Post processing:  lowpass filter + deemp
    SP["fft_post"] = Fplpf * Fdeemp

    # determine freq offset and mult for output stage
    hz_ire_scale = (SP["videorf_100ire"] - SP["videorf_0ire"]) / 100
    minn = SP["videorf_0ire"] + (hz_ire_scale * -60)
    SP["output_minfreq"] = sminn = minn / (freq_hz / tau)

    out_scale = 65534.0 / (SP["ire_max"] - SP["ire_min"])
    SP["output_scale"] = (freq_hz / tau) * (out_scale / hz_ire_scale)
def iir(c,N,fs,fc=0,wc=0,fc1=0,fc2=0,wc1=0,wc2=0):
    if c==1:
        b,a = signal.butter(N,wc,btype = 'low',analog=True,output='ba')#Design an Nth order digital or analog Butterworth filter and return the filter coefficients in (B,A) or (Z,P,K) form.
        za,pa,ka = signal.butter(N,wc,btype = 'low',analog=True,output='zpk')
        num,den = signal.zpk2tf(za,pa,ka)
    elif c==2:
        b,a = signal.butter(N,wc,btype = 'high',analog=True,output='ba')#Design an Nth order digital or analog Butterworth filter and return the filter coefficients in (B,A) or (Z,P,K) form.
        za,pa,ka = signal.butter(N,wc,btype = 'high',analog=True,output='zpk')
        num,den = signal.zpk2tf(za,pa,ka)
    elif c==3:
        b,a = signal.butter(N,[wc1,wc2],btype = 'bandpass',analog=True,output='ba')#Design an Nth order digital or analog Butterworth filter and return the filter coefficients in (B,A) or (Z,P,K) form.
        za,pa,ka = signal.butter(N,[wc1,wc2],btype = 'bandpass',analog=True,output='zpk')
        num,den = signal.zpk2tf(za,pa,ka)
    elif c==4:
        b,a = signal.butter(N,[wc1,wc2],btype = 'bandstop',analog=True,output='ba')#Design an Nth order digital or analog Butterworth filter and return the filter coefficients in (B,A) or (Z,P,K) form.
        za,pa,ka = signal.butter(N,[wc1,wc2],btype = 'bandstop',analog=True,output='zpk')
        num,den = signal.zpk2tf(za,pa,ka)
    #Compute frequency response of analog filter.
    w, h = signal.freqs(b,a)#h->frequency response
    plt.semilogx(w, 20 * np.log10(abs(h)))
    plt.xlabel('Frequency')
    plt.ylabel('Amplitude response [dB]')
    plt.grid()
    plt.show()
    
    fig = plt.figure()
    ax1 = fig.add_subplot(1, 1, 1)
    ax1.set_title('Analog 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()
    
    #to plot the poles and zeros in z-plane
    plt.figure()
    plt.plot(np.real(za), np.imag(za), 'xb')
    plt.plot(np.real(pa), np.imag(pa), 'or')
    plt.legend(['Zeros', 'Poles'], loc=2)
    plt.title('Pole / Zero Plot')
    plt.ylabel('Real')
    plt.xlabel('Imaginary')
    plt.grid()
    plt.show()
    
    print("Num: ");print(num)
    print("Den: ");print(den)
Пример #10
0
def prepare_video_filters(SP):
    # TODO:  test these CLV+innerCAV parameters.  Should be same on PAL+NTSC
    t1 = 25
    t2 = 13.75

    [tf_b, tf_a] = sps.zpk2tf(-t2 * (10**-8), -t1 * (10**-8), t1 / t2)
    Femp = filtfft(sps.bilinear(tf_b, tf_a, 1 / (freq_hz / 2)))

    # RF BPF and analog audio cut filters
    Fbpf = filtfft(
        sps.butter(
            1, [SP['vbpf'][0] / (freq_hz / 2), SP['vbpf'][1] / (freq_hz / 2)],
            btype='bandpass'))

    # standard post-demod LPF
    Fplpf = filtfft(
        sps.butter(SP['vlpf_order'], SP['vlpf_freq'] / (freq_hz / 2), 'low'))

    # post-demod deemphasis filter
    [tf_b,
     tf_a] = sps.zpk2tf(-SP['deemp'][1] * (10**-8), -SP['deemp'][0] * (10**-8),
                        SP['deemp'][0] / SP['deemp'][1])
    Fdeemp = filtfft(sps.bilinear(tf_b, tf_a, 1.0 / (freq_hz / 2)))

    SP['fft_video'] = Fbpf * fft_hilbert

    if SP['analog_audio'] == True:
        Fcutl = filtfft(
            sps.butter(1, [(SP['audio_lfreq'] - 750000) / (freq_hz / 2),
                           (SP['audio_lfreq'] + 750000) / (freq_hz / 2)],
                       btype='bandstop'))
        Fcutr = filtfft(
            sps.butter(1, [(SP['audio_rfreq'] - 750000) / (freq_hz / 2),
                           (SP['audio_rfreq'] + 750000) / (freq_hz / 2)],
                       btype='bandstop'))
        # if AC3:
        #SP['f_arightcut'] = sps.butter(1, [(2650000)/(freq_hz/2), (3150000)/(freq_hz/2)], btype='bandstop')

        SP['fft_video'] *= (Fcutl * Fcutr)

    SP['fft_video_inner'] = SP['fft_video'] * Femp

    # Post processing:  lowpass filter + deemp
    SP['fft_post'] = Fplpf * Fdeemp

    # determine freq offset and mult for output stage
    hz_ire_scale = (SP['videorf_100ire'] - SP['videorf_0ire']) / 100
    minn = SP['videorf_0ire'] + (hz_ire_scale * -60)
    SP['output_minfreq'] = sminn = minn / (freq_hz / tau)

    out_scale = 65534.0 / (SP['ire_max'] - SP['ire_min'])
    SP['output_scale'] = (freq_hz / tau) * (out_scale / hz_ire_scale)
Пример #11
0
    def __init__(self, Gp, Time, Input):
        while (True):
            # Try random parameter values
            self.DP1 = np.random.uniform(0, DAMPING_MAX)
            self.WN1 = np.random.uniform(0, WN_MAX)
            self.DP2 = np.random.uniform(0, DAMPING_MAX)
            self.WN2 = np.random.uniform(0, WN_MAX)

            # Compute location of zeros
            (self.Z1,
             self.Z2) = np.roots([1, 2 * self.DP1 * self.WN1, self.WN1**2])
            (self.Z3,
             self.Z4) = np.roots([1, 2 * self.DP2 * self.WN2, self.WN2**2])

            # Create test PI controller (used to calculate the maximum K for closed loop stable)
            (self.Gc_num, self.Gc_den) = zpk2tf(
                [self.Z1, self.Z2, self.Z3, self.Z4], [0],
                1)  # Controller with one pole in origin and 2 pair of zeros
            self.Gc = ctrl.tf(self.Gc_num, self.Gc_den)

            # Evaluate closed loop stability
            self.gm, self.pm, self.Wcg, self.Wcp = ctrl.margin(self.Gc * Gp)

            # Dischard solutions with no gain margin
            if self.Wcg == None or (self.Wcp != None and self.Wcg >= self.Wcp):
                continue

            if self.gm == None:  # None = inf
                self.gm = K_MAX

            # If K < gm => closed loop stable (gm > 0dB)
            self.K = np.random.uniform(0, self.gm)

            # Create PI controller for closed loop stable system
            (self.Gc_num, self.Gc_den) = zpk2tf(
                [self.Z1, self.Z2, self.Z3, self.Z4], [0], self.K
            )  # Controller with one pole in origin and 2 pair of zeros
            self.Gc = ctrl.tf(self.Gc_num, self.Gc_den)

            # Closed loop system
            self.M = ctrl.feedback(self.Gc * Gp, 1)

            # Closed loop step response
            self.y, self.t, self.xout = ctrl.lsim(self.M, Input, Time)

            # Evaluate fitness
            self.fitness = evaluate(Input, self.y)

            break
Пример #12
0
def step_resp_SecondOrder2(t=None, Q=None, w0=None, Amp=None):

    if t is None:
        tt = np.array([])
        y_out = np.array([])

    else:
        if Q is None:
            tt = np.array([])
            y_out = np.array([])

        else:
            if w0 is None:  # w0 = 1 [rad/seg] "Normalizado"
                NUM = [1]
                DEN = [1, 1 / Q, 1]

            else:
                z = np.array([])
                p = np.roots([1, w0 / Q, w0**2])
                k = w0**2
                NUM, DEN = sig.zpk2tf(z, p, k)

                if Amp is None:
                    u = 1 * esc(t)

                else:
                    u = Amp * esc(t)

                tt, y_out, x = sig.lsim2((NUM, DEN), u, t)

    return tt, y_out
Пример #13
0
    def fitness_calc(self, Gp, Time, Input):

        # Compute location of zeros
        (self.Z1,
         self.Z2) = np.roots([1, 2 * self.DP1 * self.WN1, self.WN1**2])
        (self.Z3,
         self.Z4) = np.roots([1, 2 * self.DP2 * self.WN2, self.WN2**2])

        # Create PI controller
        (self.Gc_num, self.Gc_den) = zpk2tf(
            [self.Z1, self.Z2, self.Z3, self.Z4], [0],
            self.K)  # Controller with one pole in origin and 2 pair of zeros
        self.Gc = ctrl.tf(self.Gc_num, self.Gc_den)

        # Evaluate closed loop stability
        self.gm, self.pm, self.Wcg, self.Wcp = ctrl.margin(self.Gc * Gp)

        # Dischard solutions with no gain margin
        if self.gm == None or self.gm <= 1:
            self.fitness = 999
            return

        # Closed loop system
        self.M = ctrl.feedback(self.Gc * Gp, 1)

        # Closed loop step response
        self.y, self.t, self.xout = ctrl.lsim(self.M, Input, Time)

        # Evaluate fitness
        self.fitness = evaluate(Input, self.y)
Пример #14
0
def mirroredNTF(ntf):
    """Creates a symmetric noise transfer function from a prototype.

    This function takes a prototype single band NTF for a LP modulator
    and returns a symmetric NTF with signal bands at the bottom and at
    the top of the available frequency ranges.

    Note that the way in which the mirroring happens make the resulting
    NTF peak at about the squared value as the peak of the original
    prototype. Hence the prototype should be designed with an H_inf value
    that is the square root of the desired one.

    Parameters
    ----------
    ntf : tuple
        input noise tranfer function in zpk form

    Returns
    -------
    ntf2 : tuple
        output noise transfer function in zpk form
    """
    zpk_mode = True
    if len(ntf) != 3:
        zpk_mode = False
        ntf = tf2zpk(*ntf)
    # Take the opposite of poles and zeros to get an HP filter
    ntf_flipped = (-ntf[0], -ntf[1], ntf[2])
    # Take the product of the two
    ntf_mirrored = (np.hstack((ntf[0], ntf_flipped[0])),
                    np.hstack((ntf[1], ntf_flipped[1])), 1)
    if not zpk_mode:
        ntf_mirrored = zpk2tf(*ntf_mirrored)
    return ntf_mirrored
Пример #15
0
def _design_iir(wp, ws, sample_rate, gpass, gstop,
                analog=False, ftype='cheby1', output='zpk'):
    # pylint: disable=invalid-name
    nyq = sample_rate / 2.
    wp = numpy.atleast_1d(wp)
    ws = numpy.atleast_1d(ws)
    if analog:  # convert Hz to rad/s
        wp *= TWO_PI
        ws *= TWO_PI
    else:  # convert Hz to half-cycles / sample
        wp /= nyq
        ws /= nyq
    z, p, k = signal.iirdesign(wp, ws, gpass, gstop, analog=analog,
                               ftype=ftype, output='zpk')
    if analog:  # convert back to Hz
        z /= -TWO_PI
        p /= -TWO_PI
        k *= TWO_PI ** z.size / -TWO_PI ** p.size
    if output == 'zpk':
        return z, p, k
    elif output == 'ba':
        return signal.zpk2tf(z, p, k)
    elif output == 'sos':
        return signal.zpk2sos(z, p, k)
    else:
        raise ValueError("'%s' is not a valid output form." % output)
def integrate(data, sample_frequency, integration_time):
    """Integrate the sound pressure squared using exponential integration.
    
    :param data: Energetic quantity, e.g. :math:`p^2`.
    :param sample_frequency: Sample frequency.
    :param integration_time: Integration time.
    :returns: 
    
    Time weighting is applied by applying a low-pass filter with one real pole at :math:`-1/\\tau`.
    
    .. note:: Because :math:`f_s \\cdot t_i` is generally not an integer, samples are discarded. This results in a drift of samples for longer signals (e.g. 60 minutes at 44.1 kHz).
    
    """
    integration_time = np.asarray(integration_time)
    sample_frequency = np.asarray(sample_frequency)
    samples = data.shape[-1]
    b, a  = zpk2tf([1.0], [1.0, integration_time], [1.0])
    b, a = bilinear(b, a, fs=sample_frequency)
    #b, a = bilinear([1.0], [1.0, integration_time], fs=sample_frequency) # Bilinear: Analog to Digital filter.
    n = np.floor(integration_time * sample_frequency).astype(int)
    data = data[..., 0:n*(samples//n)]
    newshape = list(data.shape[0:-1])
    newshape.extend([-1, n])
    data = data.reshape(newshape)
    #data = data.reshape((-1, n)) # Divide in chunks over which to perform the integration.
    return lfilter(b, a, data)[...,n-1] / integration_time # Perform the integration. Select the final value of the integration.
Пример #17
0
def zpk_tf1(zeros_tf, poles_tf, gain):
    zeros = getzeros(zeros_tf)
    poles = getzeros(poles_tf)
    num, den = zpk2tf(zeros, poles, gain)
    #    sys = matlab.zpk(zeros, poles, gain)
    sys = matlab.tf(num, den)
    return sys
Пример #18
0
def _design_iir(wp,
                ws,
                sample_rate,
                gpass,
                gstop,
                analog=False,
                ftype='cheby1',
                output='zpk'):
    nyq = sample_rate / 2.
    wp = atleast_1d(wp)
    ws = atleast_1d(ws)
    if analog:
        wp *= TWO_PI
        ws *= TWO_PI
    else:
        wp /= nyq
        ws /= nyq
    z, p, k = signal.iirdesign(wp,
                               ws,
                               gpass,
                               gstop,
                               analog=analog,
                               ftype=ftype,
                               output='zpk')
    if analog:
        z /= -TWO_PI
        p /= -TWO_PI
    if output == 'zpk':
        return z, p, k
    elif output == 'ba':
        return signal.zpk2tf(z, p, k)
    elif output == 'sos':
        return signal.zpk2sos(z, p, k)
    else:
        raise ValueError("'%s' is not a valid output form." % output)
Пример #19
0
def mirroredNTF(ntf):
    """Creates a symmetric noise transfer function from a prototype.

    This function takes a prototype single band NTF for a LP modulator
    and returns a symmetric NTF with signal bands at the bottom and at
    the top of the available frequency ranges.

    Note that the way in which the mirroring happens make the resulting
    NTF peak at about the squared value as the peak of the original
    prototype. Hence the prototype should be designed with an H_inf value
    that is the square root of the desired one.

    Parameters
    ----------
    ntf : tuple
        input noise tranfer function in zpk form

    Returns
    -------
    ntf2 : tuple
        output noise transfer function in zpk form
    """
    zpk_mode = True
    if len(ntf) != 3:
        zpk_mode = False
        ntf = tf2zpk(*ntf)
    # Take the opposite of poles and zeros to get an HP filter
    ntf_flipped = (-ntf[0], -ntf[1], ntf[2])
    # Take the product of the two
    ntf_mirrored = (np.hstack((ntf[0], ntf_flipped[0])),
                    np.hstack((ntf[1], ntf_flipped[1])), 1)
    if not zpk_mode:
        ntf_mirrored = zpk2tf(*ntf_mirrored)
    return ntf_mirrored
Пример #20
0
def for_matti(kirjain, tyyppi, fs):
    F = np.array(
        formantit2.formantit[tyyppi][kirjain][0:4])  #4 ensimmäistä formanttia
    Ba = np.array([20, 30, 50, 60])  #Bandwith formanteille

    dur = formantit2.formantit[tyyppi][kirjain][4]  #kesto
    nsamps = int(math.floor(dur * fs))  #Näytteiden määrä
    R = np.exp(-np.pi * Ba / fs)  #naparadius
    theta = (2 * np.pi * F) / fs  #napakulma
    poles = R * np.exp(1j * theta)  #Navat
    [B, A] = sg.zpk2tf(0, poles, 1)  #Kontrolli

    f0 = 105  #pitch
    w0T = 2 * np.pi * f0 / fs  #normalisoitu

    nharm = int(math.floor((fs / 2) / f0))
    sig = np.zeros(nsamps)
    n = np.arange(nsamps)

    if F[0] != 0 and F[1] != 0 and F[2] != 0 and F[3] != 0:
        for i in range(nharm):
            #sig += np.sin(i*w0T*n)
            sig += sg.sawtooth(i * w0T * n)

    sig = sig / np.max(sig)

    speech = sg.lfilter(np.array([1.0]), A, sig)
    return speech
def return_trans_func(f, sensor_name, coil_name, sample_rate, nd=16, debug=0):
    try:
        sk, sp, sz, Afit, Bfit, np, nz = get_hdf5values(f, sensor_name, coil_name, nd, debug=debug)
        print 'obtained hdf data'
        data_found = 1
    except:
        print 'failed to get data - coupling not recorded because its too weak?'
        data_found = 2
        return 0, 0, 0

    #convert zero-pole-gain representation to polynomial representation
    b_s, a_s = scipy_signal.zpk2tf(sz,sp,sk)
    if debug==1:
        print 'b_s:', ['%.2e'%(i_tmp) for i_tmp in b_s]
        print 'a_s:', ['%.2e'%(i_tmp) for i_tmp in a_s]
        print 'zpk2tf finished'

    #convert from s-domain -> z-domain using bilinear transform
    #note this uses a modified version of the scipy function
    #b_z, a_z = scipy_signal.bilinear(b_s, a_s,fs=sample_rate)
    b_z, a_z = bilinear(b_s, a_s, fs=sample_rate)
    if debug==1:
        print 'b_z:', ['%.2e'%(i_tmp) for i_tmp in b_z]
        print 'a_z:', ['%.2e'%(i_tmp) for i_tmp in a_z]
        print 'bz and az found'
    return a_z, b_z, 1
Пример #22
0
def butter_test(order, range, capacity):

    range = numpy.core.numeric.asarray(range)

    z, p = compute_butterworth(order)

    fs = 2.0
    warped = 2 * fs * numpy.tan(numpy.pi * range / fs)

    if capacity in ('lowpass', 'highpass'):

        if capacity == 'lowpass':
            z, p, k = capacity_filters._zpklp2lp(z, p, 1, wo=warped)
        elif capacity == 'highpass':
            z, p, k = capacity_filters._zpklp2hp(z, p, 1, wo=warped)
    elif capacity in ('bandpass', 'bandstop'):

        bw = warped[1] - warped[0]
        wo = numpy.sqrt(warped[0] * warped[1])

        if capacity == 'bandpass':
            z, p, k = capacity_filters._zpklp2bp(z, p, 1, wo=wo, bw=bw)
        elif capacity == 'bandstop':
            z, p, k = capacity_filters._zpklp2bs(z, p, 1, wo=wo, bw=bw)

    z, p, k = capacity_filters._zpkbilinear(z, p, 1, fs=fs)
    return signal.zpk2tf(z, p, k)
Пример #23
0
def make_biquads(filterset, fs=FS):
    ZPK = list(generate_filter_coeffs(filterset, fs, output='zpk'))

    biquads = []
    singles = []

    # pair off zeros/poles from each filter set and convert to transfer func
    for Z, P, K in ZPK:
        zeros = sorted(Z, key=lambda x: -abs(x.imag))
        poles = sorted(P, key=lambda x: -abs(x.imag))

        for zz, pp in zip(grouper(2, zeros), grouper(2, poles)):
            ba = sig.zpk2tf(zz, pp, K)
            if len(zz) == 2:
                biquads.append(ba)
            else:
                singles.append(ba)

    # convolve the spare singles together to make biquads
    for BA in grouper(2, singles):
        (b1, a1), (b2, a2) = BA
        b = sig.convolve(b1, b2)
        a = sig.convolve(a1, a2)
        biquads.append((b, a))

    return np.array(biquads)
Пример #24
0
def save_fil(fil_dict, arg, out_format, sender, DEBUG = False):
    """
    Convert between poles / zeros / gain, filter coefficients (polynomes)
    and second-order sections and store all available formats in the passed
    dictionary 'fil_dict'.
    """
    if DEBUG: print("saveFil: arg = ",arg)
    if out_format == 'zpk': # arg = [z,p,k]
        (b, a) = sig.zpk2tf(arg[0], arg[1], arg[2])
        zpk = arg
    elif out_format == 'ba': # arg = [b,a]
        if np.ndim(arg) == 1:
#            print(len(arg))
            b = np.asarray(arg)
            a = np.zeros(len(arg))
            a[0] = 1
        else:
            b = arg[0]
            a = arg[1]
#        print("saveFil: b, a = ",b , a)
        zpk = sig.tf2zpk(b, a)#[np.roots(arg), [1, np.zeros(len(arg)-1)],1]
    else:
        raise ValueError("Unknown output format {0:s}".format(out_format))
    fil_dict['ba'] = [b, a]
    fil_dict['zpk'] = [zpk[0], zpk[1], zpk[2]]#zpk
    fil_dict['sos'] = None
    fil_dict['creator'] = (out_format, sender)
Пример #25
0
def iir_bp(fstops, fs, order=4):
    """
    the opposite of a notch filter: return coefficients to add a spectral line
    """
    nyq = 0.5 * fs

    # Zeros zd, poles pd, and gain kd for the digital filter
    zd = np.array([])
    pd = np.array([])

    # Lines
    for fstopData in fstops:
        fstop = fstopData[0]
        df = fstopData[1]
        df2 = fstopData[2]
        low = (fstop - df) / nyq
        high = (fstop + df) / nyq
        low2 = (fstop - df2) / nyq
        high2 = (fstop + df2) / nyq
        z, p, k = sig.iirdesign([low2, high2], [low, high],
                                gpass=1,
                                gstop=6,
                                ftype='ellip',
                                output='zpk')
        zd = np.append(zd, z)
        pd = np.append(pd, p)

    # Return the numerator and denominator of the digital filter
    b, a = sig.zpk2tf(zd, pd, k)
    return b, a
Пример #26
0
    def _normalize_gain(self):
        """
        Normalize the gain factor so that the maximum of |H(f)| stays 1 or a
        previously stored maximum value of |H(f)|. Do this every time a P or Z
        has been change.

        Called by _copy_item()
        """
        if not np.isfinite(self.zpk[2]):
            self.zpk[2] = 1.

        norm = self.cmbNorm.currentText()
        if norm != "None":
            b, a = zpk2tf(self.zpk[0], self.zpk[1], self.zpk[2])
            [w, H] = freqz(b, a)
            Hmax = max(abs(H))
            if not np.isfinite(Hmax) or Hmax > 1e4 or Hmax < 1e-4:
                Hmax = 1.
            if norm == "1":
                self.zpk[2] = self.zpk[2] / Hmax  # normalize to 1
            elif norm == "Max":
                if norm != self.norm_last:  # setting has been changed -> 'Max'
                    self.Hmax_last = Hmax  # use current design to set Hmax_last
                self.zpk[2] = self.zpk[2] / Hmax * self.Hmax_last
            self.norm_last = norm  # store current setting of combobox

        self._restore_gain()
Пример #27
0
def filter_arma(data, rate, verbose=False):
    """Filter using a preset ARMA system"""
    #Place poles by hand, it doesn't matter much. Values should be in hz
    #I can't be bothered playing with the radius.
    zeros = np.array([100, 2000, 400, 412, 2500, 3500, 4000])
    poles = np.array([200, 2000, 3000, 8000])
    z = 0.99 * np.exp(2j * np.pi * (zeros / (2 * rate)))
    p = 0.99 * np.exp(2j * np.pi * (poles / (2 * rate)))
    #Make the filter use real transfer function values!
    z = np.append(z, z.conj())
    p = np.append(p, p.conj())

    if (verbose):
        plt.figure()
        plt.title("Zero locations")
        plt.scatter(z.real, z.imag)
        print("Zero freqs as multiple of pi", np.angle(z) / np.pi)
        print("Zero mags", np.abs(z))
        plt.figure()
        plt.title("Pole locations")
        plt.scatter(p.real, p.imag)
        print("Pole freqs as multiple of pi", np.angle(p) / np.pi)
        print("Pole mags", np.abs(p))

    b, a = sig.zpk2tf(z, p, 1)
    output = sig.lfilter(b, a, data)
    if (verbose):
        h, w = sig.freqz(b, a, fs=rate)
        plt.figure()
        plt.title("test_function")
        plt.plot(h)
        plt.plot(w)
    return output
Пример #28
0
    def _normalize_gain(self):
        """
        Normalize the gain factor so that the maximum of |H(f)| stays 1 or a
        previously stored maximum value of |H(f)|. Do this every time a P or Z
        has been changed.
        Called by setModelData() and when cmbNorm is activated

        """
        norm = qget_cmb_box(self.ui.cmbNorm, data=False)
        self.ui.ledGain.setEnabled(norm == 'None')
        if norm != self.norm_last:
            qstyle_widget(self.ui.butSave, 'changed')
        if not np.isfinite(self.zpk[2]):
            self.zpk[2] = 1.
        self.zpk[2] = np.real_if_close(self.zpk[2]).item()
        if np.iscomplex(self.zpk[2]):
            logger.warning("Casting complex to real for gain k!")
            self.zpk[2] = np.abs(self.zpk[2])

        if norm != "None":
            b, a = zpk2tf(self.zpk[0], self.zpk[1], self.zpk[2])
            [w, H] = freqz(b, a, whole=True)
            Hmax = max(abs(H))
            if not np.isfinite(Hmax) or Hmax > 1e4 or Hmax < 1e-4:
                Hmax = 1.
            if norm == "1":
                self.zpk[2] = self.zpk[2] / Hmax # normalize to 1
            elif norm == "Max":
                if norm != self.norm_last: # setting has been changed -> 'Max'
                    self.Hmax_last = Hmax # use current design to set Hmax_last
                self.zpk[2] = self.zpk[2] / Hmax * self.Hmax_last
        self.norm_last = norm # store current setting of combobox

        self._restore_gain()
Пример #29
0
def integrate(data, sample_frequency, integration_time):
    """Integrate the sound pressure squared using exponential integration.
    
    :param data: Energetic quantity, e.g. :math:`p^2`.
    :param sample_frequency: Sample frequency.
    :param integration_time: Integration time.
    :returns: 
    
    Time weighting is applied by applying a low-pass filter with one real pole at :math:`-1/\\tau`.
    
    .. note:: Because :math:`f_s \\cdot t_i` is generally not an integer, samples are discarded. This results in a drift of samples for longer signals (e.g. 60 minutes at 44.1 kHz).
    
    """
    integration_time = np.asarray(integration_time)
    sample_frequency = np.asarray(sample_frequency)
    samples = data.shape[-1]
    b, a = zpk2tf([1.0], [1.0, integration_time], [1.0])
    b, a = bilinear(b, a, fs=sample_frequency)
    #b, a = bilinear([1.0], [1.0, integration_time], fs=sample_frequency) # Bilinear: Analog to Digital filter.
    n = np.floor(integration_time * sample_frequency).astype(int)
    data = data[..., 0:n * (samples // n)]
    newshape = list(data.shape[0:-1])
    newshape.extend([-1, n])
    data = data.reshape(newshape)
    #data = data.reshape((-1, n)) # Divide in chunks over which to perform the integration.
    return lfilter(
        b, a, data
    )[..., n -
      1] / integration_time  # Perform the integration. Select the final value of the integration.
Пример #30
0
def zpk_120qa(flat=True):
    ''' Trillium 120QA TransferFunction

    Transfer function from Velocity to Voltage.

    Retrun
    ------
    H : matlab.tf
    
    '''
    z = np.array([0, 0, -31.63, -160, -350, -3177])  # rad/sec
    p = np.array([
        -0.03661 + 0.037059j, -0.03661 - 0.037059j, -32.55, -142, -364 + 404j,
        -364 - 404j, -1260, -4900 + 5200j, -4900 - 5200j, -7100 + 1700j,
        -7100 - 1700j
    ])  # rad/sec
    k = 8.31871 * 10e17  # f=1Hzで1202.5になるように規格化した。だめだけども。
    S = 1202.5 / 9.99999845
    if False:
        z, p, k = trillium.zpk_120qa()
        num, den = zpk2tf(z, p, k)
        w, h = freqs(num, den, worN=np.logspace(-2, 3, 1e5))
        f = w / np.pi / 2.0
        df = f[1] - f[0]
        idx = np.where(np.isclose(f, 1.0, atol=df) == True)[0]
        print(abs(h[idx]))
        plt.loglog(f, abs(h))
        plt.savefig('hoge.png')
    return z, p, k * S
Пример #31
0
    def _normalize_gain(self):
        """
        Normalize the gain factor so that the maximum of |H(f)| stays 1 or a
        previously stored maximum value of |H(f)|. Do this every time a P or Z
        has been changed.
        Called by setModelData() and when cmbNorm is activated

        """
        norm = qget_cmb_box(self.ui.cmbNorm, data=False)
        self.ui.ledGain.setEnabled(norm == 'None')
        if norm != self.norm_last:
            qstyle_widget(self.ui.butSave, 'changed')
        if not np.isfinite(self.zpk[2]):
            self.zpk[2] = 1.
        self.zpk[2] = np.real_if_close(self.zpk[2]).item()
        if np.iscomplex(self.zpk[2]):
            logger.warning("Casting complex to real for gain k!")
            self.zpk[2] = np.abs(self.zpk[2])

        if norm != "None":
            b, a = zpk2tf(self.zpk[0], self.zpk[1], self.zpk[2])
            [w, H] = freqz(b, a, whole=True)
            Hmax = max(abs(H))
            if not np.isfinite(Hmax) or Hmax > 1e4 or Hmax < 1e-4:
                Hmax = 1.
            if norm == "1":
                self.zpk[2] = self.zpk[2] / Hmax  # normalize to 1
            elif norm == "Max":
                if norm != self.norm_last:  # setting has been changed -> 'Max'
                    self.Hmax_last = Hmax  # use current design to set Hmax_last
                self.zpk[2] = self.zpk[2] / Hmax * self.Hmax_last
        self.norm_last = norm  # store current setting of combobox

        self._restore_gain()
Пример #32
0
    def _process_waveforms(self, waveforms):
        """Process the waveforms with the DataLogger information."""
        # Correcting electric Field with actual length of dipole
        for runid in self.runlist:
            try:
                mask = ((waveforms.index > self.runinfo[runid]['Start']) &
                        (waveforms.index < self.runinfo[runid]['End']))
                waveforms["QN"].loc[mask] *= (100.0/self.runinfo[runid]['Ex'])  # mV/km
                waveforms["QE"].loc[mask] *= (100.0/self.runinfo[runid]['Ey'])  # mV/km

            # If there's no info about length, then use default length.
            except KeyError:
                pass

        if self.zpk is None:
            return waveforms

        # Filtering waveforms by NIMS system response
        for channel in waveforms:   # loop for FE, FN, FZ, QN, QE
            for filt in self.zpk[channel]:   # loop for filter
                zval = self.zpk[channel][filt]['z']
                pval = self.zpk[channel][filt]['p']
                kval = self.zpk[channel][filt]['k']

                # convert analog zpk to digital filter
                zval, pval, kval = bilinear_zpk(zval, pval, kval, self.samplingrate)
                b, a = zpk2tf(zval, pval, kval)

                waveforms[channel] = filtfilt(b, a, waveforms[channel].interpolate())
        return waveforms
Пример #33
0
def frequency_response_analog(poles, zeros):
    k = 1.
    poles = map(freq2omega, poles)
    zeros = map(freq2omega, zeros)
    ac = sigpy.zpk2tf(zeros, poles, k)
    w, h = sigpy.freqs(ac[0], ac[1], 2**20)
    w = w / (2 * np.pi)
    return w, h
Пример #34
0
def calcFiltros(A1,A2,Wc,Wp):
    plt.figure()
    Nb, Wnb = signal.buttord(Wp,Wc,A1,A2,True)  
    Nc, Wnc = signal.cheb1ord(Wp,Wc,A1,A2,True)
    Ne, Wne = signal.ellipord(Wp,Wc,A1,A2,True)

    print('Butterbord Wp =' + str(Wp))
    print("N = "+ str(Nb) )
    print("Wn = "+ str(Wnb) )
    Zb,Pb,Kb = signal.buttap(Nb)
    ab,bb = signal.zpk2tf(Zb,Pb,Kb)
    print("H(s) = ")
    strFunTrans = funTrans([ab,bb])
    print(strFunTrans)
    print("\n")
    wb, hb = freqs(ab, bb)
    plt.semilogx(wb, abs(hb))

    print('Chebychev Wp =' + str(Wp))
    print("N = "+ str(Nc) )
    print("Wn = "+ str(Wnc) )
    Zc,Pc,Kc = signal.buttap(Nc)
    ac,bc = signal.zpk2tf(Zc,Pc,Kc)
    print("H(s) = ")
    strFunTrans = funTrans([ac,bc])
    print(strFunTrans)
    print("\n")
    wc, hc = freqs(ac, bc)  
    plt.semilogx(wc, abs(hc))

    print('Eliptica Wp =' + str(Wp))
    print("N = "+ str(Ne) )
    print("Wn = "+ str(Wne) )
    Ze,Pe,Ke = signal.buttap(Ne)
    ae,be = signal.zpk2tf(Ze,Pe,Ke)
    print("H(s) = ")
    strFunTrans = funTrans([ae,be])
    print(strFunTrans)
    print("\n")  
    we, he = freqs(ae, be)
    plt.semilogx(we, abs(he))

    plt.xlabel('Frequency')
    plt.ylabel('Amplitude response')
    plt.grid()
Пример #35
0
 def test_filter(self):
     array = self.create()
     a2 = array.filter([100], [1], 1e-2)
     self.assertIsInstance(a2, type(array))
     self.assertArraysEqual(a2.frequencies, array.frequencies)
     # manually rebuild the filter to test it works
     b, a, = signal.zpk2tf([100], [1], 1e-2)
     fresp = abs(signal.freqs(b, a, array.frequencies.value)[1])
     nptest.assert_array_equal(a2.value, fresp * array.value)
Пример #36
0
    def test_filter(self, array):
        a2 = array.filter([100], [1], 1e-2)
        assert isinstance(a2, type(array))
        utils.assert_quantity_equal(a2.frequencies, array.frequencies)

        # manually rebuild the filter to test it works
        b, a, = signal.zpk2tf([100], [1], 1e-2)
        fresp = abs(signal.freqs(b, a, array.frequencies.value)[1])
        utils.assert_array_equal(a2.value, fresp * array.value)
Пример #37
0
 def test_filter(self):
     array = self.create()
     a2 = array.filter([100], [1], 1e-2)
     self.assertIsInstance(a2, type(array))
     self.assertArraysEqual(a2.frequencies, array.frequencies)
     # manually rebuild the filter to test it works
     b, a, = signal.zpk2tf([100], [1], 1e-2)
     fresp = abs(signal.freqs(b, a, array.frequencies.value)[1])
     nptest.assert_array_equal(a2.value, fresp * array.value)
Пример #38
0
    def test_filter(self, array):
        a2 = array.filter([100], [1], 1e-2)
        assert isinstance(a2, type(array))
        utils.assert_quantity_equal(a2.frequencies, array.frequencies)

        # manually rebuild the filter to test it works
        b, a, = signal.zpk2tf([100], [1], 1e-2)
        fresp = abs(signal.freqs(b, a, array.frequencies.value)[1])
        utils.assert_array_equal(a2.value, fresp * array.value)
Пример #39
0
def crossCalib(monitor_trace, response_trace, **kwargs):
	
	m_trace=monitor_trace.copy()
	r_trace=response_trace.copy()

	if 'demean' in kwargs and kwargs['demean']:
		m_trace.detrend('demean')
		r_trace.detrend('demean')

	if 'taper' in kwargs and kwargs['taper']:
		m_trace.taper(0.05)
		r_trace.taper(0.05)

	#Paramètres des PSD
	if 'nfft' in kwargs:
		n_fft=kwargs['nfft']
	else:
		n_fft=1024

	if 'npad' in kwargs:
		n_pad=kwargs['npad']
	else:
		n_pad=n_fft*4

	if 'noverlap' in kwargs:
		n_overlap=kwargs['noverlap']
	else:
		n_overlap=int(n_fft*0.90)

	#paz par défaut: chaine générique
	if 'paz' in kwargs:
		paz=kwargs['paz']
	else:
		paz=dict()
		paz['zeros']=np.array([])
		paz['poles']=np.array([])
		paz['gain']=1
		paz['seismometer_gain']=1
		paz['datalogger_gain']=1
		paz['sensitivity']=paz['seismometer_gain']*paz['datalogger_gain']*paz['gain']

	
	fs=m_trace.stats.sampling_rate
	(P00,f)=mlab.psd(m_trace.data,Fs=fs,NFFT=n_fft,noverlap=n_overlap,pad_to=n_pad,detrend=mlab.detrend_mean,window=mlab.window_hanning)
	(P01,f)=mlab.csd(m_trace.data,r_trace.data,Fs=fs,NFFT=n_fft,noverlap=n_overlap,pad_to=n_pad,detrend=mlab.detrend_mean,window=mlab.window_hanning)
	(C,f)=mlab.cohere(m_trace.data,r_trace.data,Fs=fs,NFFT=n_fft,noverlap=n_overlap,pad_to=n_pad,detrend=mlab.detrend_mean,window=mlab.window_hanning)
	
	(b,a)=sp.zpk2tf(paz['zeros'],paz['poles'],paz['sensitivity'])
	(_w,H0)=sp.freqs(b,a,f*2*np.pi)

	H1=P01*H0/P00
	H1=H1[1:]
	C=C[1:]
	f=f[1:]

	return (H1,C,f)
Пример #40
0
def get_fitted_tf(omega_measured,tf_measured,coh_measured,_exc,dof):
    _tf = control.tf(*zpk2tf([],[],0))
    print(_exc,dof)    
    for i in range(5):
        try:
            w0,Q0,k0 = params[_exc][dof][i]
            __tf = control.tf(*zpk2tf([],p(w0,Q0),k0))
            _tf += __tf            
        except:
            pass
            #
    if dof not in _exc:
        _tf = _tf*(blend(lp='low')+blend(lp='high'))
        #_tf = _tf*(blend(lp='low'))
    mag, phase, omega = _tf.freqresp(omega_measured)
    _w = omega
    h = mag*np.exp(1j*phase)#*np.exp(1j*10)
    h = np.squeeze(h)
    return _w,h
Пример #41
0
def emphasis_iir(t1, t2, fs):
    """Generate an IIR filter for 6dB/octave pre-emphasis (t1 > t2) or
    de-emphasis (t1 < t2), given time constants for the two corners."""

    # Convert time constants to frequencies, and pre-warp for bilinear transform
    w1 = 2 * fs * np.tan((1 / t1) / (2 * fs))
    w2 = 2 * fs * np.tan((1 / t2) / (2 * fs))

    # Zero at t1, pole at t2
    tf_b, tf_a = sps.zpk2tf([-w1], [-w2], w2 / w1)
    return sps.bilinear(tf_b, tf_a, fs)
Пример #42
0
def random_arma(p, q, k = 1, z_radius = 1, p_radius = 0.75):
  '''
  Returns a random ARMA(p, q) filter.  The parameters p and q define
  the order of the filter where p is the number of AR coefficients
  (poles) and q is the number of MA coefficients (zeros).  k is the
  gain of the filter.  The z_radius and p_radius paramters specify the
  maximum magnitude of the zeros and poles resp.  In order for the
  filter to be stable, we should have p_radius < 1.  The poles and
  zeros will be placed uniformly at random inside a disc of the
  specified radius.

  We also force the coefficients to be real.  This is done by ensuring
  that for every complex pole or zero, it's recipricol conjugate is
  also present.  If p and q are even, then all the poles/zeros could
  be complex.  But if p or q is odd, then one of the poles and or
  zeros will be purely real.

  The filter must be causal.  That is, we assert p >= q.

  Finally, note that in order to generate complex numbers uniformly
  over the disc we can't generate R and theta uniformly then transform
  them.  This will give a distribution concentrated near (0, 0).  We
  need to generate u uniformly [0, 1] then take R = sqrt(u).  This can
  be seen by starting with a uniform joint distribution f(x, y) =
  1/pi, then applying a transform to (r, theta) with x = rcos(theta),
  y = rsin(theta), calculating the distributions of r and theta, then
  applying inverse transform sampling.
  '''
  assert(p >= q), 'System is not causal'
  P = []
  Z = []
  for i in range(p % 2):
    pi_r = stats.uniform.rvs(loc = -p_radius, scale = 2*p_radius)
    P.append(pi_r)
    
  for i in range((p - (p % 2)) / 2):
    pi_r = sqrt(stats.uniform.rvs(loc = 0, scale = p_radius))
    pi_ang = stats.uniform.rvs(loc = -np.pi, scale = 2*np.pi)
    P.append(cmath.rect(pi_r, pi_ang))
    P.append(cmath.rect(pi_r, -pi_ang))

  for i in range(q % 2):
    zi_r = stats.uniform.rvs(loc = -z_radius, scale = 2*z_radius)
    Z.append(zi_r)

  for i in range((q - (q % 2)) / 2):
    zi_r = stats.uniform.rvs(loc = 0, scale = z_radius)
    zi_ang = stats.uniform.rvs(loc = -np.pi, scale = 2*np.pi)
    Z.append(cmath.rect(zi_r, zi_ang))
    Z.append(cmath.rect(zi_r, -zi_ang))

  b, a = signal.zpk2tf(Z, P, k)

  return b, a
Пример #43
0
    def setRandomFIR(self, order=2):
        """ generates minimum-phase FIR filters with random zeros
		for each neuron
		order = nr of zeros in one filter
		"""
        size = self.getSize()
        zeros = (N.random.rand(size, order) * 2 - 1) + (N.random.rand(size, order) * 2 - 1) * 1j
        k = 1.0
        self.B = N.zeros((size, order + 1))
        self.A = N.zeros((size, order + 1))
        for n in range(size):
            self.B[n], self.A[n] = signal.zpk2tf(zeros[n], [], k)
def test_ITU_R_468_weight(fs=None):
    """
    Test that frequency response meets tolerance from Rec. ITU-R BS.468-4
    """
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.signal import freqz

    frequencies = np.array((
        31.5, 63, 100, 200, 400, 800, 1000, 2000, 3150, 4000, 5000,
        6300,
        7100, 8000, 9000, 10000, 12500, 14000, 16000, 20000, 31500
        ))

    responses = np.array((
        -29.9, -23.9, -19.8, -13.8, -7.8, -1.9, 0, +5.6, +9.0, +10.5, +11.7,
        +12.2,
        +12.0, +11.4, +10.1, +8.1, 0, -5.3, -11.7, -22.2, -42.7
        ))

    upper_limits = np.array((
        +2.0, +1.4, +1.0, +0.85, +0.7, +0.55, +0.5, +0.5, +0.5, +0.5, +0.5,
        +0.01,   # Actually 0 tolerance, but specified as "+12.2" dB
        +0.2, +0.4, +0.6, +0.8, +1.2, +1.4, +1.6, +2.0, +2.8
        ))

    lower_limits = np.array((
        -2.0, -1.4, -1.0, -0.85, -0.7, -0.55, -0.5, -0.5, -0.5, -0.5, -0.5,
        -0.01,   # Actually 0 tolerance, but specified as "+12.2" dB
        -0.2, -0.4, -0.6, -0.8, -1.2, -1.4, -1.6, -2.0, -float('inf')
        ))

    if fs is None:
        z, p, k = ITU_R_468_weighting_analog()
        b, a = zpk2tf(z, p, k)
        w, h = freqs(b, a, 2*pi*frequencies)
    else:
        # Passes if fs >= 180000 Hz but not at typical audio fs
        b, a = ITU_R_468_weighting(fs)
        w = 2*pi * frequencies / fs
        w, h = freqz(b, a, w)

    levels = 20 * np.log10(abs(h))

    plt.semilogx(frequencies, levels)
    plt.semilogx(frequencies, responses + upper_limits, 'r--')
    plt.semilogx(frequencies, responses + lower_limits, 'r--')

    assert all(np.less_equal(levels, responses + upper_limits))
    assert all(np.greater_equal(levels, responses + lower_limits))
Пример #45
0
def dcgain(*args):
    '''
    Compute the gain of the system in steady state.

    The function takes either 1, 2, 3, or 4 parameters:

    Parameters
    ----------
    A, B, C, D: array-like
        A linear system in state space form.
    Z, P, k: array-like, array-like, number
        A linear system in zero, pole, gain form.
    num, den: array-like
        A linear system in transfer function form.
    sys: LTI (StateSpace or TransferFunction)
        A linear system object.

    Returns
    -------
    gain: ndarray
        The gain of each output versus each input:
        :math:`y = gain \cdot u`

    Notes
    -----
    This function is only useful for systems with invertible system
    matrix ``A``.

    All systems are first converted to state space form. The function then
    computes:

    .. math:: gain = - C \cdot A^{-1} \cdot B + D
    '''
    #Convert the parameters to state space form
    if len(args) == 4:
        A, B, C, D = args
        return ss(A, B, C, D).dcgain()
    elif len(args) == 3:
        Z, P, k = args
        num, den = zpk2tf(Z, P, k)
        return tf(num, den).dcgain()
    elif len(args) == 2:
        num, den = args
        return tf(num, den).dcgain()
    elif len(args) == 1:
        sys, = args
        return sys.dcgain()
    else:
        raise ValueError("Function ``dcgain`` needs either 1, 2, 3 or 4 "
                         "arguments.")
Пример #46
0
 def test_identity(self):
     """Test the identity transfer function."""
     z = []
     p = []
     k = 1.
     b, a = zpk2tf(z, p, k)
     b_r = np.array([1.])  # desired result
     a_r = np.array([1.])  # desired result
     # The test for the *type* of the return values is a regression
     # test for ticket #1095.  In the case p=[], zpk2tf used to
     # return the scalar 1.0 instead of array([1.0]).
     assert_array_equal(b, b_r)
     assert_(isinstance(b, np.ndarray))
     assert_array_equal(a, a_r)
     assert_(isinstance(a, np.ndarray))
Пример #47
0
def A_weighting(fs, output='ba'):
    """
    Design of a digital A-weighting filter.

    Designs a digital A-weighting filter for
    sampling frequency `fs`.
    Warning: fs should normally be higher than 20 kHz. For example,
    fs = 48000 yields a class 1-compliant filter.

    Parameters
    ----------
    fs : float
        Sampling frequency
    output : {'ba', 'zpk', 'sos'}, optional
        Type of output:  numerator/denominator ('ba'), pole-zero ('zpk'), or
        second-order sections ('sos'). Default is 'ba'.

    Examples
    --------
    Plot frequency response

    >>> from scipy.signal import freqz
    >>> import matplotlib.pyplot as plt
    >>> fs = 200000
    >>> b, a = A_weighting(fs)
    >>> f = np.logspace(np.log10(10), np.log10(fs/2), 1000)
    >>> w = 2*pi * f / fs
    >>> w, h = freqz(b, a, w)
    >>> plt.semilogx(w*fs/(2*pi), 20*np.log10(abs(h)))
    >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
    >>> plt.axis([10, 100e3, -50, 20])

    Since this uses the bilinear transform, frequency response around fs/2 will
    be inaccurate at lower sampling rates.
    """
    z, p, k = ABC_weighting('A')

    # Use the bilinear transformation to get the digital filter.
    z_d, p_d, k_d = _zpkbilinear(z, p, k, fs)

    if output == 'zpk':
        return z_d, p_d, k_d
    elif output in {'ba', 'tf'}:
        return zpk2tf(z_d, p_d, k_d)
    elif output == 'sos':
        return zpk2sos(z_d, p_d, k_d)
    else:
        raise ValueError("'%s' is not a valid output form." % output)
Пример #48
0
    def _save(self, fil_dict, arg):
        """
        First design initial elliptic filter meeting sqRoot Amp specs;
         - Then create residue vector from poles/zeros;
         - Then square filter (k,p,z and dc,p,r) to get zero phase filter;
         - Then Convert results of filter design to all available formats (pz, pr, ba, sos)
        and store them in the global filter dictionary.

        Corner frequencies and order calculated for minimum filter order are
        also stored to allow for an easy subsequent manual filter optimization.
        """
        fil_save(fil_dict, arg, self.FRMT, __name__)

        # For min. filter order algorithms, update filter dict with calculated
        # new values for filter order N and corner frequency(s) F_PBC

        fil_dict['N'] = self.N
        if str(fil_dict['fo']) == 'min':
            if str(fil_dict['rt']) == 'LP' or str(fil_dict['rt']) == 'HP':
#               HP or LP - single  corner frequency
                fil_dict['F_PB'] = self.F_PBC / 2.
            else: # BP or BS - two corner frequencies
                fil_dict['F_PB'] = self.F_PBC[0] / 2.
                fil_dict['F_PB2'] = self.F_PBC[1] / 2.

#       Now generate poles/residues for custom file save of new parameters
        if (not self.manual):
            z = fil_dict['zpk'][0]
            p = fil_dict['zpk'][1]
            k = fil_dict['zpk'][2]
            n = len(z)
            gain, residues = self._partial (k, p, z, n)

            pA, zA, gn, pC, rC = self._sqCausal (k, p, z, gain, residues, n)
            fil_dict['rpk'] = [rC, pC, gn]

#           save antiCausal b,a (nonReciprocal) also [easier to compute h(n)
            try:
               fil_dict['baA'] = sig.zpk2tf(zA, pA, k)
            except Exception as e:
               logger.error(e)

#       'rpk' is our signal that this is a non-Causal filter with zero phase
#       inserted into fil dictionary after fil_save and convert
        # sig_tx -> select_filter -> filter_specs   
        self.sig_tx.emit({'sender':__name__, 'filt_changed':'ellip_zero'})
Пример #49
0
def compute_coeffs(z, z1):
    """ function computes the filter coefficients of decomposition low pass filter
        given zeros at pi and zeros of trigonmonetric polynomial 
        for daubach filter """

    # adding poles for causal system
    zeros = len(z)
    p = np.zeros(zeros - 1)
    p = np.array(p)
    z = np.append(z, z1)

    h = zpk2tf(z, p, [1])
    h = np.array(h[0])

    # normalizing the filter coefficients
    h = h / math.sqrt(np.sum(h ** 2))
    return h, z, p
def ITU_R_468_weighting_analog():
    """
    Return ITU-R 468 analog weighting filter zeros, poles, and gain
    """

    z = [0]
    p = [-25903.70104781628,
         +36379.90893732929j-23615.53521363528,
         -36379.90893732929j-23615.53521363528,
         +62460.15645250649j-18743.74669072136,
         -62460.15645250649j-18743.74669072136,
         -62675.1700584679]

    # Normalize to +12.2 dB at 6.3 kHz, numerically
    b, a = zpk2tf(z, p, 1)
    w, h = freqs(b, a, 2*pi*6300)
    k = 10**(+12.2/20) / abs(h[0])

    return z, p, k
Пример #51
0
 def test_mapCtoD_1(self):
     """Test function for mapCtoD() 1/6"""
     # The first test comes straight from the DSToolbox doc
     # We map the standard continuous time DS modulator to its DT counterpart
     # and we check whether the TF is (1 - 1/z)**2
     LFc = (np.array([[0., 0.], [1., 0.]]),
            np.array([[1., -1.], [0., -1.5]]),
            np.array([[0., 1.]]),
            np.array(([[0., 0.]]))
           )
     tdac = [0, 1]
     LF, Gp = ds.mapCtoD(LFc, tdac)
     ABCD = np.vstack((np.hstack((LF[0], LF[1])),
                       np.hstack((LF[2], LF[3]))
                     ))
     H = ds.calculateTF(ABCD)
     num, den = zpk2tf(*H[0])
     self.assertTrue(np.allclose(num, [ 1., -2.,  1.], atol=1e-8, rtol=1e-5))
     self.assertTrue(np.allclose(den, [1., 0., 0.], atol=1e-8, rtol=1e-5))
Пример #52
0
def _c2dmatched(sysC, Ts):
    # Pole-zero match method of continuous to discrete time conversion
    szeros, spoles, sgain = tf2zpk(sysC.num[0][0], sysC.den[0][0])
    zzeros = [0] * len(szeros)
    zpoles = [0] * len(spoles)
    pregainnum = [0] * len(szeros)
    pregainden = [0] * len(spoles)
    for idx, s in enumerate(szeros):
        sTs = s*Ts
        z = exp(sTs)
        zzeros[idx] = z
        pregainnum[idx] = 1-z
    for idx, s in enumerate(spoles):
        sTs = s*Ts
        z = exp(sTs)
        zpoles[idx] = z
        pregainden[idx] = 1-z
    zgain = np.multiply.reduce(pregainnum)/np.multiply.reduce(pregainden)
    gain = sgain/zgain
    sysDnum, sysDden = zpk2tf(zzeros, zpoles, gain)
    return TransferFunction(sysDnum, sysDden, Ts)
Пример #53
0
 def __init__(self, source, gain=1, **kwds):
     # Automatically duplicate mono input to fit the desired output shape
     gain = np.atleast_1d(gain)
     if len(gain) != source.nchannels and len(gain) != 1:
         if source.nchannels != 1:
             raise ValueError('Can only automatically duplicate source '
                              'channels for mono sources, use '
                              'RestructureFilterbank.')
         source = RestructureFilterbank(source, len(gain))
     samplerate = source.samplerate
     zeros = np.array([-200, -200])
     poles = np.array([-250 + 400j, -250 - 400j,
                       -2000 + 6000j, -2000 - 6000j])
     # use an arbitrary gain here, will be normalized afterwards
     b, a = signal.zpk2tf(zeros, poles * 2 * np.pi, 1.5e9)
     # normalize the response at 1000Hz (of the analog filter)
     resp = np.abs(signal.freqs(b, a, [1000*2*np.pi])[1])  # response magnitude
     b /= resp
     bd, ad = signal.bilinear(b, a, samplerate)
     bd = (np.tile(bd, (source.nchannels, 1)).T * gain).T
     ad = np.tile(ad, (source.nchannels, 1))
     LinearFilterbank.__init__(self, source, bd, ad, **kwds)
def ITU_R_468_weighting(fs, output='ba'):
    """
    Return ITU-R 468 digital weighting filter transfer function

    Parameters
    ----------
    fs : float
        Sampling frequency

    Examples
    --------

    >>> from scipy.signal import freqz
    >>> import matplotlib.pyplot as plt
    >>> fs = 200000
    >>> b, a = ITU_R_468_weighting(fs)
    >>> f = np.logspace(np.log10(10), np.log10(fs/2), 1000)
    >>> w = 2*pi * f / fs
    >>> w, h = freqz(b, a, w)
    >>> plt.semilogx(w*fs/(2*pi), 20*np.log10(abs(h)))
    >>> plt.grid(True, color='0.7', linestyle='-', which='both', axis='both')
    >>> plt.axis([10, 100e3, -50, 20])
    """

    z, p, k = ITU_R_468_weighting_analog()

    # Use the bilinear transformation to get the digital filter.
    zz, pz, kz = _zpkbilinear(z, p, k, fs)

    if output == 'zpk':
        return zz, pz, kz
    elif output in {'ba', 'tf'}:
        return zpk2tf(zz, pz, kz)
    elif output == 'sos':
        return zpk2sos(zz, pz, kz)
    else:
        raise ValueError("'%s' is not a valid output form." % output)
Пример #55
0
def _design_iir(wp, ws, sample_rate, gpass, gstop,
                analog=False, ftype='cheby1', output='zpk'):
    nyq = sample_rate / 2.
    wp = atleast_1d(wp)
    ws = atleast_1d(ws)
    if analog:
        wp *= TWO_PI
        ws *= TWO_PI
    else:
        wp /= nyq
        ws /= nyq
    z, p, k = signal.iirdesign(wp, ws, gpass, gstop, analog=analog,
                               ftype=ftype, output='zpk')
    if analog:
        z /= -TWO_PI
        p /= -TWO_PI
    if output == 'zpk':
        return z, p, k
    elif output == 'ba':
        return signal.zpk2tf(z, p, k)
    elif output == 'sos':
        return signal.zpk2sos(z, p, k)
    else:
        raise ValueError("'%s' is not a valid output form." % output)
Пример #56
0
z, p, k = tf2zpk(c, [1])
zplane(z, p)

c = np.convolve(c, np.flipud(c))
print c
figure()
z, p, k = tf2zpk(c, [1])
zplane(z, p)

print z

s1 = math.sqrt(2)
s2 = 1.0 / s1
z = [s1, s2, -s1, -s2]

h = zpk2tf(z, p, k)
print h, k


show()
dd
dim = 2 + w.vanishing_moments_psi
dim1 = w.vanishing_moments_psi + 1
print dim, dim1, w.dec_lo, w.vanishing_moments_psi

A = np.zeros((dim, dim1))
c = np.zeros(dim1)

P = 2 * np.eye(dim)
P[dim - 1, dim - 1] = -2
q = np.zeros(dim)
Пример #57
0
    def filter(self, *filt):
        """Apply the given filter to this `TimeSeries`.

        All recognised filter arguments are converted either into cascading
        second-order sections (if scipy >= 0.16 is installed), or into the
        ``(numerator, denominator)`` representation before being applied
        to this `TimeSeries`.

        .. note::

           All filters are presumed to be digital (Z-domain), if you have
           an analog ZPK (in Hertz or in rad/s) you should be using
           `TimeSeries.zpk` instead.

        .. note::

           When using `scipy` < 0.16 some higher-order filters may be
           unstable. With `scipy` >= 0.16 higher-order filters are
           decomposed into second-order-sections, and so are much more stable.

        Parameters
        ----------
        *filt
            one of:

            - :class:`scipy.signal.lti`
            - `MxN` `numpy.ndarray` of second-order-sections
              (`scipy` >= 0.16 only)
            - ``(numerator, denominator)`` polynomials
            - ``(zeros, poles, gain)``
            - ``(A, B, C, D)`` 'state-space' representation

        Returns
        -------
        result : `TimeSeries`
            the filtered version of the input `TimeSeries`

        See also
        --------
        TimeSeries.zpk
            for instructions on how to filter using a ZPK with frequencies
            in Hertz
        scipy.signal.sosfilter
            for details on the second-order section filtering method
            (`scipy` >= 0.16 only)
        scipy.signal.lfilter
            for details on the filtering method

        Raises
        ------
        ValueError
            If ``filt`` arguments cannot be interpreted properly
        """
        sos = None
        # single argument given
        if len(filt) == 1:
            filt = filt[0]
            # detect LTI
            if isinstance(filt, signal.lti):
                filt = filt
                a = filt.den
                b = filt.num
            # detect SOS
            elif isinstance(filt, numpy.ndarray) and filt.ndim == 2:
                sos = filt
            # detect taps
            else:
                b = filt
                a = [1]
        # detect TF
        elif len(filt) == 2:
            b, a = filt
        elif len(filt) == 3:
            try:
                sos = signal.zpk2sos(*filt)
            except AttributeError:
                b, a = signal.zpk2tf(*filt)
        elif len(filt) == 4:
            try:
                zpk = signal.ss2zpk(*filt)
                sos = signal.zpk2sos(zpk)
            except AttributeError:
                b, a = signal.ss2tf(*filt)
        else:
            raise ValueError("Cannot interpret filter arguments. Please "
                             "give either a signal.lti object, or a "
                             "tuple in zpk or ba format. See "
                             "scipy.signal docs for details.")
        if sos is not None:
            new = signal.sosfilt(sos, self, axis=0).view(self.__class__)
        else:
            new = signal.lfilter(b, a, self, axis=0).view(self.__class__)
        new.__dict__ = self.copy_metadata()
        return new
Пример #58
0
def test_detector():
  fitSamples = 100

#  Prepare detector
  zero_1 = -5.56351644e+07
  pole_1 = -1.38796386e+04
  pole_real = -2.02559385e+07
  pole_imag = 9885315.37450211
  
  gain = 2./1e-8
  
  zeros = [zero_1,0. ]
  poles = [ pole_real+pole_imag*1j, pole_real-pole_imag*1j, pole_1]
  system = signal.lti(zeros, poles, gain )
  
  system.to_tf()
  num = system.num
  den = system.den
  
  print "original num: " + str(num)
  print "original den" + str(den)
  
  system.to_zpk()
  print "back to the zpk"
  print system.zeros
  print system.poles
  print system.gain

#  num = np.array((3478247474.8078203, 1.9351287044375424e+17, 6066014749714584.0)) 
#  den = [1, 40525756.715025946, 508584795912802.44, 7.0511687850000589e+18]
#  system = signal.lti(num, den)
#
#  zeros = system.zeros
#  poles = system.poles
#  gain = system.gain

  new_num, new_den, dt = signal.cont2discrete((num, den), 1E-8, method="bilinear")
#  new_num /= 1.05836038e-08
  print "new discrete tf representation"
  print new_num
  print new_den
  print dt

  new_z, new_p, new_k, dt = signal.cont2discrete((zeros, poles, gain), 1E-8, method="bilinear" )
  print "new discrete zpk representation"
  print new_z
  print new_p
  print new_k
  print dt
  
  print "...and back to tf"
  dis_num, dis_den = signal.zpk2tf(new_z, new_p, new_k)
  print dis_num
  print dis_den

  tempGuess = 77.89
  gradGuess = 0.0483
  pcRadGuess = 2.591182
  pcLenGuess = 1.613357

  #Create a detector model
  detName = "conf/P42574A_grad%0.2f_pcrad%0.2f_pclen%0.2f.conf" % (0.05,2.5, 1.65)
  det =  Detector(detName, temperature=tempGuess, timeStep=10., numSteps=fitSamples, )
  det.LoadFields("P42574A_fields_v3.npz")
  det.SetFields(pcRadGuess, pcLenGuess, gradGuess)

  print "time steps out number is %d" % det.siggenInst.GetSafeConfiguration()['ntsteps_out']
  print "time steps calc number is %d" % det.siggenInst.GetSafeConfiguration()['time_steps_calc']
  print "step size out is %f" % det.siggenInst.GetSafeConfiguration()['step_time_out']
  print "step size calc is %f" % det.siggenInst.GetSafeConfiguration()['step_time_calc']


  sig_array = det.GetRawSiggenWaveform( 0.174070, 0.528466, 10.755795)
  
  t, sig_array2, x = signal.lsim(system, sig_array, det.time_steps, interp=False)
  
  
  sig_array1 = signal.lfilter(new_num[0], new_den, sig_array)
  sig_array4 = signal.lfilter(dis_num, dis_den, sig_array)
  
#  dissystem = system.to_discrete(1E-8)
#  
##  new_k = dissystem.zeros
##  new_p = dissystem.poles
##  new_k = dissystem.gain
##  dis_num, dis_den = signal.zpk2tf(new_z, new_p, new_k)
##  sig_array5 = signal.lfilter(dis_num, dis_den, sig_array)


#
#
  plt.figure()
  plt.plot(sig_array1, "b:")
  plt.plot(sig_array2, color="black")
  plt.plot(sig_array4, "r:")
#  plt.plot(sig_array5, "g:")

  plt.figure()
  plt.plot(sig_array2-sig_array1, color="b")
  plt.plot(sig_array2-sig_array4, color="r")
#  plt.plot(sig_array2-sig_array5, color="g")

  #plt.ylim(-0.05, 1.05)
  plt.xlabel("Time [ns]")
  plt.ylabel("Charge [arb.]")
  plt.show()