fs = <NUM_LIT> <EOL>NB = len(GdB)<EOL>if not NB == <NUM_LIT:10>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>Fc = <NUM_LIT>*<NUM_LIT:2>**np.arange(NB)<EOL>B = np.zeros((NB,<NUM_LIT:3>))<EOL>A = np.zeros((NB,<NUM_LIT:3>))<EOL>for k in range(NB):<EOL><INDENT>[b,a] = peaking(GdB[k],Fc[k],Q)<EOL>B[k,:] = b<EOL>A[k,:] = a<EOL><DEDENT>y = np.zeros(len(x))<EOL>for k in range(NB):<EOL><INDENT>if k == <NUM_LIT:0>:<EOL><INDENT>y = signal.lfilter(B[k,:],A[k,:],x)<EOL><DEDENT>else:<EOL><INDENT>y = signal.lfilter(B[k,:],A[k,:],y)<EOL><DEDENT><DEDENT>return y<EOL>

Filter the input signal x with a ten-band equalizer having octave gain values in ndarray GdB.

The signal x is filtered using octave-spaced peaking filters starting at 31.25 Hz and
stopping at 16 kHz. The Q of each filter is 3.5, but can be changed. The sampling rate
is assumed to be 44.1 kHz.

Parameters
----------
x : ndarray of the input signal samples
GdB : ndarray containing ten octave band gain values [G0dB,...,G9dB]
Q : Quality factor vector for each of the NB peaking filters

Returns
-------
y : ndarray of output signal samples

Examples
--------
>>> # Test with white noise
>>> w = randn(100000)
>>> y = ten_band_eq_filt(x,GdB)
>>> psd(y,2**10,44.1)


def biquad2(w_num, r_num, w_den, r_den):

b = np.array([<NUM_LIT:1>, -<NUM_LIT:2>*r_num*np.cos(w_num), r_num**<NUM_LIT:2>])<EOL>a = np.array([<NUM_LIT:1>, -<NUM_LIT:2>*r_den*np.cos(w_den), r_den**<NUM_LIT:2>])<EOL>return b, a<EOL>

A biquadratic filter in terms of conjugate pole and zero pairs.

Parameters
----------
w_num : zero frequency (angle) in rad/sample
r_num : conjugate zeros radius
w_den : pole frequency (angle) in rad/sample
r_den : conjugate poles radius; less than 1 for stability

Returns
-------
b : ndarray of numerator coefficients
a : ndarray of denominator coefficients

Examples
--------
>>> b,a = biquad2(pi/4., 1, pi/4., 0.95)


fs = <NUM_LIT:1>/(t[<NUM_LIT:1>] - t[<NUM_LIT:0>])<EOL>t0 = (t[-<NUM_LIT:1>]+t[<NUM_LIT:0>])/<NUM_LIT:2> <EOL>N0 = len(t)/<NUM_LIT:2> <EOL>f = np.arange(-<NUM_LIT:1.>/<NUM_LIT:2>,<NUM_LIT:1.>/<NUM_LIT:2>,<NUM_LIT:1.>/Nfft)<EOL>w, X = signal.freqz(x,<NUM_LIT:1>,<NUM_LIT:2>*np.pi*f)<EOL>X /= fs <EOL>X *= np.exp(-<NUM_LIT>*<NUM_LIT:2>*np.pi*f*fs*t0)<EOL>X *= np.exp(<NUM_LIT>*<NUM_LIT:2>*np.pi*f*N0)<EOL>F = f*fs<EOL>return F, X<EOL>

Approximate the Fourier transform of a finite duration signal using scipy.signal.freqz()

Parameters
----------
x : input signal array
t : time array used to create x(t)
Nfft : the number of frdquency domain points used to
       approximate X(f) on the interval [fs/2,fs/2], where
       fs = 1/Dt. Dt being the time spacing in array t

Returns
-------
f : frequency axis array in Hz
X : the Fourier transform approximation (complex)

Notes
-----
The output time axis starts at the sum of the starting values in x1 and x2
and ends at the sum of the two ending values in x1 and x2. The default
extents of ('f','f') are used for signals that are active (have support)
on or within n1 and n2 respectively. A right-sided signal such as
:math:`a^n*u[n]` is semi-infinite, so it has extent 'r' and the
convolution output will be truncated to display only the valid results.

Examples
--------
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import sk_dsp_comm.sigsys as ss
>>> fs = 100 # sampling rate in Hz
>>> tau = 1
>>> t = np.arange(-5,5,1/fs)
>>> x0 = ss.rect(t-.5,tau)
>>> plt.figure(figsize=(6,5))
>>> plt.plot(t,x0)
>>> plt.grid()
>>> plt.ylim([-0.1,1.1])
>>> plt.xlim([-2,2])
>>> plt.title(r'Exact Waveform')
>>> plt.xlabel(r'Time (s)')
>>> plt.ylabel(r'$x_0(t)$')
>>> plt.show()

>>> # FT Exact Plot
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import sk_dsp_comm.sigsys as ss
>>> fs = 100 # sampling rate in Hz
>>> tau = 1
>>> t = np.arange(-5,5,1/fs)
>>> x0 = ss.rect(t-.5,tau)
>>> fe = np.arange(-10,10,.01)
>>> X0e = tau*np.sinc(fe*tau)
>>> plt.plot(fe,abs(X0e))
>>> #plot(f,angle(X0))
>>> plt.grid()
>>> plt.xlim([-10,10])
>>> plt.title(r'Exact (Theory) Spectrum Magnitude')
>>> plt.xlabel(r'Frequency (Hz)')
>>> plt.ylabel(r'$|X_0e(f)|$')
>>> plt.show()

>>> # FT Approximation Plot
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import sk_dsp_comm.sigsys as ss
>>> fs = 100 # sampling rate in Hz
>>> tau = 1
>>> t = np.arange(-5,5,1/fs)
>>> x0 = ss.rect(t-.5,tau)
>>> f,X0 = ss.ft_approx(x0,t,4096)
>>> plt.plot(f,abs(X0))
>>> #plt.plot(f,angle(X0))
>>> plt.grid()
>>> plt.xlim([-10,10])
>>> plt.title(r'Approximation Spectrum Magnitude')
>>> plt.xlabel(r'Frequency (Hz)')
>>> plt.ylabel(r'$|X_0(f)|$');
>>> plt.tight_layout()
>>> plt.show()


plt.figure(figsize=fsize)<EOL>idx = np.nonzero(Xk)[<NUM_LIT:0>]<EOL>Xk = Xk[idx]<EOL>fk = fk[idx]<EOL>if mode == '<STR_LIT>':<EOL><INDENT>for k in range(len(fk)):<EOL><INDENT>if fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, np.abs(Xk[k])],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, np.abs(Xk[k])],linetype, linewidth=<NUM_LIT:2>*lwidth)            <EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, np.abs(Xk[k])],linetype, linewidth=lwidth)<EOL>plt.plot([-fk[k], -fk[k]],[<NUM_LIT:0>, np.abs(Xk[k])],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, <NUM_LIT>*np.abs(Xk[k])],linetype, linewidth=lwidth)<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT><DEDENT>plt.grid()<EOL>if sides == <NUM_LIT:2>:<EOL><INDENT>plt.axis([-<NUM_LIT>*max(fk), <NUM_LIT>*max(fk), <NUM_LIT:0>, <NUM_LIT>*max(abs(Xk))])        <EOL><DEDENT>elif sides == <NUM_LIT:1>:<EOL><INDENT>plt.axis([<NUM_LIT:0>, <NUM_LIT>*max(fk), <NUM_LIT:0>, <NUM_LIT>*<NUM_LIT:2>*max(abs(Xk))])<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT>plt.ylabel('<STR_LIT>')<EOL>plt.xlabel('<STR_LIT>')<EOL><DEDENT>elif mode == '<STR_LIT>':<EOL><INDENT>Xk_dB = <NUM_LIT:20>*np.log10(np.abs(Xk))<EOL>for k in range(len(fk)):<EOL><INDENT>if fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=<NUM_LIT:2>*lwidth)            <EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=lwidth)<EOL>plt.plot([-fk[k], -fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]+<NUM_LIT>],linetype, linewidth=lwidth)<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT><DEDENT>plt.grid()<EOL>max_dB = np.ceil(max(Xk_dB/<NUM_LIT>))*<NUM_LIT:10><EOL>min_dB = max(floor_dB,np.floor(min(Xk_dB/<NUM_LIT>))*<NUM_LIT:10>)<EOL>if sides == <NUM_LIT:2>:<EOL><INDENT>plt.axis([-<NUM_LIT>*max(fk), <NUM_LIT>*max(fk), min_dB, max_dB])        <EOL><DEDENT>elif sides == <NUM_LIT:1>:<EOL><INDENT>plt.axis([<NUM_LIT:0>, <NUM_LIT>*max(fk), min_dB, max_dB])<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT>plt.ylabel('<STR_LIT>')<EOL>plt.xlabel('<STR_LIT>')<EOL><DEDENT>elif mode == '<STR_LIT>':<EOL><INDENT>Xk_dB = <NUM_LIT:20>*np.log10(np.abs(Xk)/max(np.abs(Xk)))<EOL>for k in range(len(fk)):<EOL><INDENT>if fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=<NUM_LIT:2>*lwidth)            <EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=lwidth)<EOL>plt.plot([-fk[k], -fk[k]],[floor_dB, Xk_dB[k]],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[floor_dB, Xk_dB[k]+<NUM_LIT>],linetype, linewidth=lwidth)<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT><DEDENT>plt.grid()<EOL>max_dB = np.ceil(max(Xk_dB/<NUM_LIT>))*<NUM_LIT:10><EOL>min_dB = max(floor_dB,np.floor(min(Xk_dB/<NUM_LIT>))*<NUM_LIT:10>)<EOL>if sides == <NUM_LIT:2>:<EOL><INDENT>plt.axis([-<NUM_LIT>*max(fk), <NUM_LIT>*max(fk), min_dB, max_dB])        <EOL><DEDENT>elif sides == <NUM_LIT:1>:<EOL><INDENT>plt.axis([<NUM_LIT:0>, <NUM_LIT>*max(fk), min_dB, max_dB])<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT>plt.ylabel('<STR_LIT>')<EOL>plt.xlabel('<STR_LIT>')    <EOL><DEDENT>elif mode == '<STR_LIT>':<EOL><INDENT>for k in range(len(fk)):<EOL><INDENT>if fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, np.angle(Xk[k])],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] == <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, np.angle(Xk[k])],linetype, linewidth=<NUM_LIT:2>*lwidth)<EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, np.angle(Xk[k])],linetype, linewidth=lwidth)<EOL>plt.plot([-fk[k], -fk[k]],[<NUM_LIT:0>, -np.angle(Xk[k])],linetype, linewidth=lwidth)<EOL><DEDENT>elif fk[k] > <NUM_LIT:0> and sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([fk[k], fk[k]],[<NUM_LIT:0>, np.angle(Xk[k])],linetype, linewidth=lwidth)<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT><DEDENT>plt.grid()<EOL>if sides == <NUM_LIT:2>:<EOL><INDENT>plt.plot([-<NUM_LIT>*max(fk), <NUM_LIT>*max(fk)], [<NUM_LIT:0>, <NUM_LIT:0>],'<STR_LIT:k>')<EOL>plt.axis([-<NUM_LIT>*max(fk), <NUM_LIT>*max(fk), -<NUM_LIT>*max(np.abs(np.angle(Xk))), <NUM_LIT>*max(np.abs(np.angle(Xk)))])<EOL><DEDENT>elif sides == <NUM_LIT:1>:<EOL><INDENT>plt.plot([<NUM_LIT:0>, <NUM_LIT>*max(fk)], [<NUM_LIT:0>, <NUM_LIT:0>],'<STR_LIT:k>')<EOL>plt.axis([<NUM_LIT:0>, <NUM_LIT>*max(fk), -<NUM_LIT>*max(np.abs(np.angle(Xk))), <NUM_LIT>*max(np.abs(np.angle(Xk)))])<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT>plt.ylabel('<STR_LIT>')<EOL>plt.xlabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT>

Plot the Fouier series line spectral given the coefficients.

This function plots two-sided and one-sided line spectra of a periodic
signal given the complex exponential Fourier series coefficients and
the corresponding harmonic frequencies.

Parameters
----------
fk : vector of real sinusoid frequencies
Xk : magnitude and phase at each positive frequency in fk
mode : 'mag' => magnitude plot, 'magdB' => magnitude in dB plot,
mode cont : 'magdBn' => magnitude in dB normalized, 'phase' => a phase plot in radians
sides : 2; 2-sided or 1-sided
linetype : line type per Matplotlib definitions, e.g., 'b';
lwidth : 2; linewidth in points
fsize : optional figure size in inches, default = (6,4) inches

Returns
-------
Nothing : A plot window opens containing the line spectrum plot

Notes
-----
Since real signals are assumed the frequencies of fk are 0 and/or positive
numbers. The supplied Fourier coefficients correspond.

Examples
--------
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> from sk_dsp_comm.sigsys import line_spectra
>>> n = np.arange(0,25)
>>> # a pulse train with 10 Hz fundamental and 20% duty cycle
>>> fk = n*10
>>> Xk = np.sinc(n*10*.02)*np.exp(-1j*2*np.pi*n*10*.01) # 1j = sqrt(-1)

>>> line_spectra(fk,Xk,'mag')
>>> plt.show()

>>> line_spectra(fk,Xk,'phase')


nnx1 = np.arange(<NUM_LIT:0>,len(nx1))<EOL>nnx2 = np.arange(<NUM_LIT:0>,len(nx2))<EOL>n1 = nnx1[<NUM_LIT:0>]<EOL>n2 = nnx1[-<NUM_LIT:1>]<EOL>n3 = nnx2[<NUM_LIT:0>]<EOL>n4 = nnx2[-<NUM_LIT:1>]<EOL>if extent[<NUM_LIT:0>] == '<STR_LIT:f>' and extent[<NUM_LIT:1>] == '<STR_LIT:f>':<EOL><INDENT>nny = np.arange(n1+n3,n2+<NUM_LIT:1>+n4+<NUM_LIT:1>-<NUM_LIT:1>)<EOL>ny = np.arange(<NUM_LIT:0>,len(x1)+len(x2)-<NUM_LIT:1>) + nx1[<NUM_LIT:0>]+nx2[<NUM_LIT:0>]<EOL><DEDENT>elif extent[<NUM_LIT:0>] == '<STR_LIT:f>' and extent[<NUM_LIT:1>] == '<STR_LIT:r>':<EOL><INDENT>nny = np.arange(n1+n3,n1+<NUM_LIT:1>+n4+<NUM_LIT:1>-<NUM_LIT:1>)<EOL>ny = nny + nx1[<NUM_LIT:0>]+nx2[<NUM_LIT:0>]<EOL><DEDENT>elif extent[<NUM_LIT:0>] == '<STR_LIT:r>' and extent[<NUM_LIT:1>] == '<STR_LIT:f>':<EOL><INDENT>nny = np.arange(n1+n3,n2+<NUM_LIT:1>+n3+<NUM_LIT:1>-<NUM_LIT:1>)<EOL>ny = nny + nx1[<NUM_LIT:0>]+nx2[<NUM_LIT:0>]<EOL><DEDENT>elif extent[<NUM_LIT:0>] == '<STR_LIT:f>' and extent[<NUM_LIT:1>] == '<STR_LIT:l>':<EOL><INDENT>nny = np.arange(n2+n3,n2+<NUM_LIT:1>+n4+<NUM_LIT:1>-<NUM_LIT:1>)<EOL>ny = nny + nx1[-<NUM_LIT:1>]+nx2[<NUM_LIT:0>]<EOL><DEDENT>elif extent[<NUM_LIT:0>] == '<STR_LIT:l>' and extent[<NUM_LIT:1>] == '<STR_LIT:f>':<EOL><INDENT>nny = np.arange(n1+n4,n2+<NUM_LIT:1>+n4+<NUM_LIT:1>-<NUM_LIT:1>)<EOL>ny = nny + nx1[<NUM_LIT:0>]+nx2[-<NUM_LIT:1>]<EOL><DEDENT>elif extent[<NUM_LIT:0>] == '<STR_LIT:r>' and extent[<NUM_LIT:1>] == '<STR_LIT:r>':<EOL><INDENT>nny = np.arange(n1+n3,min(n1+<NUM_LIT:1>+n4+<NUM_LIT:1>,n2+<NUM_LIT:1>+n3+<NUM_LIT:1>)-<NUM_LIT:1>)<EOL>ny = nny + nx1[<NUM_LIT:0>]+nx2[<NUM_LIT:0>]<EOL><DEDENT>elif extent[<NUM_LIT:0>] == '<STR_LIT:l>' and extent[<NUM_LIT:1>] == '<STR_LIT:l>':<EOL><INDENT>nny = np.arange(max(n1+n4,n2+n3),n2+<NUM_LIT:1>+n4+<NUM_LIT:1>-<NUM_LIT:1>)<EOL>ny = nny + max(nx1[<NUM_LIT:0>]+nx2[-<NUM_LIT:1>],nx1[-<NUM_LIT:1>]+nx2[<NUM_LIT:0>])<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>y = signal.convolve(x1, x2)<EOL>print('<STR_LIT>' % (ny[<NUM_LIT:0>],ny[-<NUM_LIT:1>]))<EOL>return y[nny], ny<EOL>

Discrete convolution of x1 and x2 with proper tracking of the output time axis.

Convolve two discrete-time signals using the SciPy function :func:`scipy.signal.convolution`.
The time (sequence axis) are managed from input to output. y[n] = x1[n]*x2[n].

Parameters
----------
x1 : ndarray of signal x1 corresponding to nx1
nx1 : ndarray time axis for x1
x2  : ndarray of signal x2 corresponding to nx2
nx2 : ndarray time axis for x2
extent : ('e1','e2') where 'e1', 'e2' may be 'f' finite, 'r' right-sided, or 'l' left-sided

Returns
-------
y : ndarray of output values y
ny : ndarray of the corresponding sequence index n

Notes
-----
The output time axis starts at the sum of the starting values in x1 and x2
and ends at the sum of the two ending values in x1 and x2. The default
extents of ('f','f') are used for signals that are active (have support)
on or within n1 and n2 respectively. A right-sided signal such as
a^n*u[n] is semi-infinite, so it has extent 'r' and the
convolution output will be truncated to display only the valid results.

Examples
--------
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import sk_dsp_comm.sigsys as ss
>>> nx = np.arange(-5,10)
>>> x = ss.drect(nx,4)
>>> y,ny = ss.conv_sum(x,nx,x,nx)
>>> plt.stem(ny,y)
>>> plt.show()

Consider a pulse convolved with an exponential. ('r' type extent)

>>> h = 0.5**nx*ss.dstep(nx)
>>> y,ny = ss.conv_sum(x,nx,h,nx,('f','r')) # note extents set
>>> plt.stem(ny,y) # expect a pulse charge and discharge sequence


if not isinstance(M, int):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>x = x[<NUM_LIT:0>:int(np.floor(len(x)/M))*M]<EOL>x = x.reshape((int(np.floor(len(x)/M)),M))<EOL>y = x[:,p]<EOL>return y<EOL>

Downsample by factor M

Keep every Mth sample of the input. The phase of the input samples
kept can be selected.

Parameters
----------
x : ndarray of input signal values
M : downsample factor
p : phase of decimated value, 0 (default), 1, ..., M-1

Returns
-------
y : ndarray of the output signal values

Examples
--------
>>> y = downsample(x,3)
>>> y = downsample(x,3,1)


def peaking(GdB, fc, Q=<NUM_LIT>, fs=<NUM_LIT>):

mu = <NUM_LIT:10>**(GdB/<NUM_LIT>)<EOL>kq = <NUM_LIT:4>/(<NUM_LIT:1> + mu)*np.tan(<NUM_LIT:2>*np.pi*fc/fs/(<NUM_LIT:2>*Q))<EOL>Cpk = (<NUM_LIT:1> + kq *mu)/(<NUM_LIT:1> + kq)<EOL>b1 = -<NUM_LIT:2>*np.cos(<NUM_LIT:2>*np.pi*fc/fs)/(<NUM_LIT:1> + kq*mu)<EOL>b2 = (<NUM_LIT:1> - kq*mu)/(<NUM_LIT:1> + kq*mu)<EOL>a1 = -<NUM_LIT:2>*np.cos(<NUM_LIT:2>*np.pi*fc/fs)/(<NUM_LIT:1> + kq)<EOL>a2 = (<NUM_LIT:1> - kq)/(<NUM_LIT:1> + kq)<EOL>b = Cpk*np.array([<NUM_LIT:1>, b1, b2])<EOL>a = np.array([<NUM_LIT:1>, a1, a2])<EOL>return b,a<EOL>

A second-order peaking filter having GdB gain at fc and approximately
and 0 dB otherwise.

The filter coefficients returns correspond to a biquadratic system function
containing five parameters.

Parameters
----------
GdB : Lowpass gain in dB
fc : Center frequency in Hz
Q : Filter Q which is inversely proportional to bandwidth
fs : Sampling frquency in Hz

Returns
-------
b : ndarray containing the numerator filter coefficients
a : ndarray containing the denominator filter coefficients

Examples
--------
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> from sk_dsp_comm.sigsys import peaking
>>> from scipy import signal
>>> b,a = peaking(2.0,500)
>>> f = np.logspace(1,5,400)
>>> w,H = signal.freqz(b,a,2*np.pi*f/44100)
>>> plt.semilogx(f,20*np.log10(abs(H)))
>>> plt.ylabel("Power Spectral Density (dB)")
>>> plt.xlabel("Frequency (Hz)")
>>> plt.show()

>>> b,a = peaking(-5.0,500,4)
>>> w,H = signal.freqz(b,a,2*np.pi*f/44100)
>>> plt.semilogx(f,20*np.log10(abs(H)))
>>> plt.ylabel("Power Spectral Density (dB)")
>>> plt.xlabel("Frequency (Hz)")


x = np.zeros(len(t))<EOL>for k,tk in enumerate(t):<EOL><INDENT>if np.abs(tk) > tau/<NUM_LIT>:<EOL><INDENT>x[k] = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>x[k] = <NUM_LIT:1><EOL><DEDENT><DEDENT>return x<EOL>

Approximation to the rectangle pulse Pi(t/tau).

In this numerical version of Pi(t/tau) the pulse is active
over -tau/2 <= t <= tau/2.

Parameters
----------
t : ndarray of the time axis
tau : the pulse width

Returns
-------
x : ndarray of the signal Pi(t/tau)

Examples
--------
>>> import matplotlib.pyplot as plt
>>> from numpy import arange
>>> from sk_dsp_comm.sigsys import rect
>>> t = arange(-1,5,.01)
>>> x = rect(t,1.0)
>>> plt.plot(t,x)
>>> plt.ylim([0, 1.01])
>>> plt.show()

To turn on the pulse at t = 1 shift t.

>>> x = rect(t - 1.0,1.0)
>>> plt.plot(t,x)
>>> plt.ylim([0, 1.01])


if m == <NUM_LIT:2>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:3>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:4>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:5>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:6>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:7>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:8>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:9>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:10>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:11>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:12>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:1>])<EOL><DEDENT>elif m == <NUM_LIT:16>:<EOL><INDENT>taps = np.array([<NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:0>, <NUM_LIT:1>, <NUM_LIT:1>])<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>sr = np.ones(m)<EOL>Q = <NUM_LIT:2>**m - <NUM_LIT:1><EOL>c = np.zeros(Q)<EOL>for n in range(Q):<EOL><INDENT>tap_xor = <NUM_LIT:0><EOL>c[n] = sr[-<NUM_LIT:1>]<EOL>for k in range(<NUM_LIT:1>,m):<EOL><INDENT>if taps[k] == <NUM_LIT:1>:<EOL><INDENT>tap_xor = np.bitwise_xor(tap_xor,np.bitwise_xor(int(sr[-<NUM_LIT:1>]),int(sr[m-<NUM_LIT:1>-k])))<EOL><DEDENT><DEDENT>sr[<NUM_LIT:1>:] = sr[:-<NUM_LIT:1>]<EOL>sr[<NUM_LIT:0>] = tap_xor<EOL><DEDENT>return c<EOL>

Generate an m-sequence ndarray using an all-ones initialization.

Available m-sequence (PN generators) include m = 2,3,...,12, & 16.

Parameters
----------
m : the number of shift registers. 2,3, .., 12, & 16

Returns
-------
c : ndarray of one period of the m-sequence

Notes
-----
The sequence period is 2**m - 1 (2^m - 1).

Examples
--------
>>> c = m_seq(5)


N = len(r)-<NUM_LIT:1>;<EOL>y = signal.lfilter(np.hstack((np.zeros(delta), np.array([<NUM_LIT:1>]))),<NUM_LIT:1>,r)<EOL>r_hat = np.zeros(N+<NUM_LIT:1>)<EOL>e = np.zeros(N+<NUM_LIT:1>)<EOL>ao = np.zeros(M+<NUM_LIT:1>)<EOL>z = np.zeros(M)<EOL>ym = np.zeros(M+<NUM_LIT:1>)<EOL>for k in range(N+<NUM_LIT:1>):<EOL><INDENT>r_hat[k],z = signal.lfilter(ao,np.array([<NUM_LIT:1>]),np.array([y[k]]),zi=z)<EOL>e[k] = r[k] - r_hat[k]<EOL>ao = ao + <NUM_LIT:2>*mu*e[k]*ym<EOL>ym = np.hstack((np.array([y[k]]), ym[:-<NUM_LIT:1>]))<EOL><DEDENT>F, Ao = signal.freqz(ao,<NUM_LIT:1>,<NUM_LIT>)<EOL>F/= (<NUM_LIT:2>*np.pi)<EOL>Ao = <NUM_LIT:20>*np.log10(abs(Ao))<EOL>return np.arange(<NUM_LIT:0>,N+<NUM_LIT:1>), r, r_hat, e, ao, F, Ao<EOL>

Least mean square (LMS) interference canceller adaptive filter.

A complete LMS adaptive filter simulation function for the case of
interference cancellation. Used in the digital filtering case study.

Parameters
----------
M : FIR Filter length (order M-1)
delta : Delay used to generate the reference signal
mu : LMS step-size
delta : decorrelation delay between input and FIR filter input

Returns
-------
n : ndarray Index vector
r : ndarray noisy (with interference) input signal
r_hat : ndarray filtered output (NB_hat[n])
e : ndarray error sequence (WB_hat[n])
ao : ndarray final value of weight vector
F : ndarray frequency response axis vector
Ao : ndarray frequency response of filter

Examples
----------
>>> # import a speech signal
>>> fs,s = from_wav('OSR_us_000_0030_8k.wav')
>>> # add interference at 1kHz and 1.5 kHz and
>>> # truncate to 5 seconds
>>> r = soi_snoi_gen(s,10,5*8000,[1000, 1500])
>>> # simulate with a 64 tap FIR and mu = 0.005
>>> n,r,r_hat,e,ao,F,Ao = lms_ic(r,64,0.005)


def BPSK_tx(N_bits,Ns,ach_fc=<NUM_LIT>,ach_lvl_dB=-<NUM_LIT:100>,pulse='<STR_LIT>',alpha = <NUM_LIT>,M=<NUM_LIT:6>):

pulse_types = ['<STR_LIT>', '<STR_LIT:src>']<EOL>if pulse not in pulse_types:<EOL><INDENT>raise ValueError('<STR_LIT>''<STR_LIT>')<EOL><DEDENT>x0,b,data0 = NRZ_bits(N_bits,Ns,pulse,alpha,M)<EOL>x1p,b,data1p = NRZ_bits(N_bits,Ns,pulse,alpha,M)<EOL>x1m,b,data1m = NRZ_bits(N_bits,Ns,pulse,alpha,M)<EOL>n = np.arange(len(x0))<EOL>x1p = x1p*np.exp(<NUM_LIT>*<NUM_LIT:2>*np.pi*ach_fc/float(Ns)*n)<EOL>x1m = x1m*np.exp(-<NUM_LIT>*<NUM_LIT:2>*np.pi*ach_fc/float(Ns)*n)<EOL>ach_lvl = <NUM_LIT:10>**(ach_lvl_dB/<NUM_LIT>)<EOL>return x0 + ach_lvl*(x1p + x1m), b, data0<EOL>

Generates biphase shift keyed (BPSK) transmitter with adjacent channel interference.

Generates three BPSK signals with rectangular or square root raised cosine (SRC)
pulse shaping of duration N_bits and Ns samples per bit. The desired signal is
centered on f = 0, which the adjacent channel signals to the left and right
are also generated at dB level relative to the desired signal. Used in the
digital communications Case Study supplement.

Parameters
----------
N_bits : the number of bits to simulate
Ns : the number of samples per bit
ach_fc : the frequency offset of the adjacent channel signals (default 2.0)
ach_lvl_dB : the level of the adjacent channel signals in dB (default -100)
pulse :the pulse shape 'rect' or 'src'
alpha : square root raised cosine pulse shape factor (default = 0.25)
M : square root raised cosine pulse truncation factor (default = 6)

Returns
-------
x : ndarray of the composite signal x0 + ach_lvl*(x1p + x1m)
b : the transmit pulse shape
data0 : the data bits used to form the desired signal; used for error checking

Notes
-----

Examples
--------
>>> x,b,data0 = BPSK_tx(1000,10,pulse='src')


x = np.zeros(len(n))<EOL>for k,nn in enumerate(n):<EOL><INDENT>if nn >= <NUM_LIT:0> and nn < N:<EOL><INDENT>x[k] = <NUM_LIT:1.0><EOL><DEDENT><DEDENT>return x<EOL>

Discrete rectangle function of duration N samples.

The signal is active on the interval 0 <= n <= N-1. Also known
as the rectangular window function, which is available in
scipy.signal.

Parameters
----------
n : ndarray of the time axis
N : the pulse duration

Returns
-------
x : ndarray of the signal

Notes
-----
The discrete rectangle turns on at n = 0, off at n = N-1 and
has duration of exactly N samples.

Examples
--------
>>> import matplotlib.pyplot as plt
>>> from numpy import arange
>>> from sk_dsp_comm.sigsys import drect
>>> n = arange(-5,5)
>>> x = drect(n, N=3)
>>> plt.stem(n,x)
>>> plt.show()

Shift the delta left by 2.

>>> x = drect(n+2, N=3)
>>> plt.stem(n,x)


def unique_cpx_roots(rlist,tol = <NUM_LIT>):

uniq = [rlist[<NUM_LIT:0>]]<EOL>mult = [<NUM_LIT:1>]<EOL>for k in range(<NUM_LIT:1>,len(rlist)):<EOL><INDENT>N_uniq = len(uniq)<EOL>for m in range(N_uniq):<EOL><INDENT>if abs(rlist[k]-uniq[m]) <= tol:<EOL><INDENT>mult[m] += <NUM_LIT:1><EOL>uniq[m] = (uniq[m]*(mult[m]-<NUM_LIT:1>) + rlist[k])/float(mult[m])<EOL>break<EOL><DEDENT><DEDENT>uniq = np.hstack((uniq,rlist[k]))<EOL>mult = np.hstack((mult,[<NUM_LIT:1>]))<EOL><DEDENT>return np.array(uniq), np.array(mult)<EOL>

The average of the root values is used when multiplicity
is greater than one.

Mark Wickert October 2016


x_edet192 = env_det(x192)<EOL>m_rx8 = deci24(x_edet192)<EOL>m_rx8 -= np.mean(m_rx8)<EOL>t8 = np.arange(len(m_rx8))/<NUM_LIT><EOL>"""<STR_LIT>"""<EOL>b192,a192 = signal.butter(<NUM_LIT:5>,<NUM_LIT:2>*<NUM_LIT>/<NUM_LIT>)<EOL>m_rx192 = signal.lfilter(b192,a192,x_edet192)<EOL>m_rx192 = signal.lfilter(b192,a192,m_rx192)<EOL>m_rx192 -= np.mean(m_rx192)<EOL>return m_rx8,t8,m_rx192,x_edet192<EOL>

AM envelope detector receiver for the Chapter 17 Case Study

The receiver bandpass filter is not included in this function.

Parameters
----------
x192 : ndarray of the AM signal at sampling rate 192 ksps

Returns
-------
m_rx8 : ndarray of the demodulated message at 8 ksps
t8 : ndarray of the time axis at 8 ksps
m_rx192 : ndarray of the demodulated output at 192 ksps
x_edet192 : ndarray of the envelope detector output at 192 ksps

Notes
-----
The bandpass filter needed at the receiver front-end can be designed
using b_bpf,a_bpf = :func:`am_rx_BPF`.

Examples
--------
>>> import numpy as np
>>> n = np.arange(0,1000)
>>> # 1 kHz message signal
>>> m = np.cos(2*np.pi*1000/8000.*n)
>>> m_rx8,t8,m_rx192,x_edet192 = am_rx(x192)


x = np.zeros(len(f))<EOL>for k in range(len(f)):<EOL><INDENT>if abs(f[k]) <= fb:<EOL><INDENT>x[k] = <NUM_LIT:1> - abs(f[k])/float(fb)<EOL><DEDENT><DEDENT>return x<EOL>

Triangle spectral shape function used by :func:`lp_samp`.

Parameters
----------
f : ndarray containing frequency samples
fb : the bandwidth as a float constant

Returns
-------
x : ndarray of spectrum samples for a single triangle shape

Notes
-----
This is a support function for the lowpass spectrum plotting function
:func:`lp_samp`.

Examples
--------
>>> x = lp_tri(f, fb)


Nx = len(x)<EOL>K = int(Nx/NS)<EOL>print('<STR_LIT>', K)<EOL>if NAVG > K:<EOL><INDENT>print('<STR_LIT>')<EOL>return <NUM_LIT:0>,<NUM_LIT:0><EOL><DEDENT>if window.lower() == '<STR_LIT>' or window.lower() == '<STR_LIT>':<EOL><INDENT>w = signal.boxcar(NS)<EOL><DEDENT>elif window.lower() == '<STR_LIT>':<EOL><INDENT>w = signal.hanning(NS)<EOL><DEDENT>xsw = np.zeros((K,NS)) + <NUM_LIT>*np.zeros((K,NS))<EOL>for k in range(NAVG):<EOL><INDENT>xsw[k,] = w*x[k*NS:(k+<NUM_LIT:1>)*NS]<EOL><DEDENT>Sx = np.zeros(NFFT)<EOL>for k in range(NAVG):<EOL><INDENT>X = fft.fft(xsw[k,],NFFT)<EOL>Sx += abs(X)**<NUM_LIT:2><EOL><DEDENT>Sx /= float(NAVG)<EOL>Sx /= float(NFFT**<NUM_LIT:2>)<EOL>NFFTby2 = int(NFFT/<NUM_LIT:2>)<EOL>if x.dtype != '<STR_LIT>':<EOL><INDENT>n = np.arange(NFFTby2)<EOL>f = fs*n/float(NFFT)<EOL>Sx = Sx[<NUM_LIT:0>:NFFTby2]<EOL><DEDENT>else:<EOL><INDENT>n = np.arange(NFFTby2)<EOL>f = fs*np.hstack((np.arange(-NFFTby2,<NUM_LIT:0>),np.arange(NFFTby2)))/float(NFFT)<EOL>Sx = np.hstack((Sx[NFFTby2:],Sx[<NUM_LIT:0>:NFFTby2]))<EOL><DEDENT>return f, Sx<EOL>

Spectral estimation using windowing and averaging.

This function implements averaged periodogram spectral estimation
estimation similar to the NumPy's psd() function, but more
specialized for the the windowing case study of Chapter 16.

Parameters
----------
x : ndarray containing the input signal
NS : The subrecord length less zero padding, e.g. NS < NFFT
NFFT : FFT length, e.g., 1024 = 2**10
fs : sampling rate in Hz
NAVG : the number of averages, e.g., 1 for deterministic signals
window : hardcoded window 'boxcar' (default) or 'hanning'

Returns
-------
f : ndarray frequency axis in Hz on [0, fs/2]
Sx : ndarray the power spectrum estimate

Notes
-----
The function also prints the maximum number of averages K possible
for the input data record.

Examples
--------
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> from sk_dsp_comm import sigsys as ss
>>> n = np.arange(0,2048)
>>> x = np.cos(2*np.pi*1000/10000*n) + 0.01*np.cos(2*np.pi*3000/10000*n)
>>> f, Sx = ss.simple_SA(x,128,512,10000)
>>> plt.plot(f, 10*np.log10(Sx))
>>> plt.ylim([-80, 0])
>>> plt.xlabel("Frequency (Hz)")
>>> plt.ylabel("Power Spectral Density (dB)")
>>> plt.show()

With a hanning window.

>>> f, Sx = ss.simple_SA(x,256,1024,10000,window='hanning')
>>> plt.plot(f, 10*np.log10(Sx))
>>> plt.xlabel("Frequency (Hz)")
>>> plt.ylabel("Power Spectral Density (dB)")
>>> plt.ylim([-80, 0])


def am_rx_BPF(N_order = <NUM_LIT:7>, ripple_dB = <NUM_LIT:1>, B = <NUM_LIT>, fs = <NUM_LIT>):

b_bpf,a_bpf = signal.cheby1(N_order,ripple_dB,<NUM_LIT:2>*np.array([<NUM_LIT>-B/<NUM_LIT>,<NUM_LIT>+B/<NUM_LIT>])/fs,'<STR_LIT>')<EOL>return b_bpf,a_bpf<EOL>

Bandpass filter design for the AM receiver Case Study of Chapter 17.

Design a 7th-order Chebyshev type 1 bandpass filter to remove/reduce
adjacent channel intereference at the envelope detector input.

Parameters
----------
N_order : the filter order (default = 7)
ripple_dB : the passband ripple in dB (default = 1)
B : the RF bandwidth (default = 10e3)
fs : the sampling frequency

Returns
-------
b_bpf : ndarray of the numerator filter coefficients
a_bpf : ndarray of the denominator filter coefficients

Examples
--------
>>> from scipy import signal
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> import sk_dsp_comm.sigsys as ss
>>> # Use the default values
>>> b_bpf,a_bpf = ss.am_rx_BPF()

Pole-zero plot of the filter.

>>> ss.zplane(b_bpf,a_bpf)
>>> plt.show()

Plot of the frequency response.

>>> f = np.arange(0,192/2.,.1)
>>> w, Hbpf = signal.freqz(b_bpf,a_bpf,2*np.pi*f/192)
>>> plt.plot(f*10,20*np.log10(abs(Hbpf)))
>>> plt.axis([0,1920/2.,-80,10])
>>> plt.ylabel("Power Spectral Density (dB)")
>>> plt.xlabel("Frequency (kHz)")
>>> plt.show()


fs = <NUM_LIT> <EOL>NB = len(GdB)<EOL>if not NB == <NUM_LIT:10>:<EOL><INDENT>raise ValueError("<STR_LIT>")<EOL><DEDENT>Fc = <NUM_LIT>*<NUM_LIT:2>**np.arange(NB)<EOL>B = np.zeros((NB,<NUM_LIT:3>));<EOL>A = np.zeros((NB,<NUM_LIT:3>));<EOL>for k in range(NB):<EOL><INDENT>b,a = peaking(GdB[k],Fc[k],Q,fs)<EOL>B[k,:] = b<EOL>A[k,:] = a<EOL><DEDENT>F = np.logspace(<NUM_LIT:1>,np.log10(<NUM_LIT>),<NUM_LIT:1000>)<EOL>H = np.ones(len(F))*np.complex(<NUM_LIT:1.0>,<NUM_LIT:0.0>)<EOL>for k in range(NB):<EOL><INDENT>w,Htemp = signal.freqz(B[k,:],A[k,:],<NUM_LIT:2>*np.pi*F/fs)<EOL>H *= Htemp<EOL><DEDENT>plt.figure(figsize=(<NUM_LIT:6>,<NUM_LIT:4>))<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.semilogx(F,<NUM_LIT:20>*np.log10(abs(H)))<EOL>plt.axis([<NUM_LIT:10>, fs/<NUM_LIT:2>, -<NUM_LIT:12>, <NUM_LIT:12>])<EOL>plt.grid()<EOL>plt.title('<STR_LIT>')<EOL>plt.xlabel('<STR_LIT>')<EOL>plt.ylabel('<STR_LIT>')<EOL>plt.subplot(<NUM_LIT>)<EOL>plt.stem(np.arange(NB),GdB,'<STR_LIT:b>','<STR_LIT>')<EOL>plt.axis([<NUM_LIT:0>, NB-<NUM_LIT:1>, -<NUM_LIT:12>, <NUM_LIT:12>])<EOL>plt.xlabel('<STR_LIT>')<EOL>plt.ylabel('<STR_LIT>')<EOL>plt.grid()<EOL>

Create a frequency response magnitude plot in dB of a ten band equalizer
using a semilogplot (semilogx()) type plot

Parameters
----------
GdB : Gain vector for 10 peaking filters [G0,...,G9]
Q : Quality factor for each peaking filter (default 3.5)

Returns
-------
Nothing : two plots are created

Examples
--------
>>> import matplotlib.pyplot as plt
>>> from sk_dsp_comm import sigsys as ss
>>> ss.ten_band_eq_resp([0,10.0,0,0,-1,0,5,0,-4,0])
>>> plt.show()


<EOL>b2,a2 = signal.butter(<NUM_LIT:10>,<NUM_LIT:1>/<NUM_LIT>)<EOL>y1 = signal.lfilter(b2,a2,x)<EOL>y1 = downsample(y1,<NUM_LIT:2>)<EOL>b3,a3 = signal.butter(<NUM_LIT:10>,<NUM_LIT:1>/<NUM_LIT>)<EOL>y2 = signal.lfilter(b3,a3,y1)<EOL>y2 = downsample(y2,<NUM_LIT:3>)<EOL>b4,a4 = signal.butter(<NUM_LIT:10>,<NUM_LIT:1>/<NUM_LIT>)<EOL>y3 = signal.lfilter(b4,a4,y2)<EOL>y3 = downsample(y3,<NUM_LIT:4>)<EOL>return y3<EOL>

Decimate by L = 24 using Butterworth filters.

The decimation is done using two three stages. Downsample sample by
L = 2 and lowpass filter, downsample by 3 and lowpass filter, then
downsample by L = 4 and lowpass filter. In all cases the lowpass
filter is a 10th-order Butterworth lowpass.

Parameters
----------
x : ndarray of the input signal

Returns
-------
y : ndarray of the output signal

Notes
-----
The cutoff frequency of the lowpass filters is 1/2, 1/3, and 1/4 to
track the upsampling by 2, 3, and 4 respectively.

Examples
--------
>>> y = deci24(x)


def NRZ_bits2(data,Ns,pulse='<STR_LIT>',alpha = <NUM_LIT>,M=<NUM_LIT:6>):

N_bits = len(data)<EOL>n_zeros = np.zeros((N_bits,int(Ns)-<NUM_LIT:1>))<EOL>x = np.hstack((<NUM_LIT:2>*data.reshape(N_bits,<NUM_LIT:1>)-<NUM_LIT:1>,n_zeros))<EOL>x = x.flatten()<EOL>if pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = np.ones(int(Ns))<EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = rc_imp(Ns,alpha,M)<EOL><DEDENT>elif pulse.lower() == '<STR_LIT:src>':<EOL><INDENT>b = sqrt_rc_imp(Ns,alpha,M)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>x = signal.lfilter(b,<NUM_LIT:1>,x)<EOL>return x,b/float(Ns)<EOL>

Generate non-return-to-zero (NRZ) data bits with pulse shaping with user data

A baseband digital data signal using +/-1 amplitude signal values
and including pulse shaping. The data sequence is user supplied.

Parameters
----------
data : ndarray of the data bits as 0/1 values
Ns : the number of samples per bit,
pulse_type : 'rect' , 'rc', 'src' (default 'rect')
alpha : excess bandwidth factor(default 0.25)
M : single sided pulse duration (default = 6)

Returns
-------
x : ndarray of the NRZ signal values
b : ndarray of the pulse shape

Notes
-----
Pulse shapes include 'rect' (rectangular), 'rc' (raised cosine),
'src' (root raised cosine). The actual pulse length is 2*M+1 samples.

Examples
--------
>>> import matplotlib.pyplot as plt
>>> from sk_dsp_comm.sigsys import NRZ_bits2
>>> from sk_dsp_comm.sigsys import m_seq
>>> from numpy import arange
>>> x,b = NRZ_bits2(m_seq(5),10)
>>> t = arange(len(x))
>>> plt.ylim([-1.01, 1.01])
>>> plt.plot(t,x)


d = np.zeros(len(t))<EOL>for k,tt in enumerate(t):<EOL><INDENT>if abs(tt) <= eps/<NUM_LIT>:<EOL><INDENT>d[k] = <NUM_LIT:1>/float(eps)<EOL><DEDENT><DEDENT>return d<EOL>

Rectangular pulse approximation to impulse function.

Parameters
----------
t : ndarray of time axis
eps : pulse width

Returns
-------
d : ndarray containing the impulse approximation

Examples
--------
>>> import matplotlib.pyplot as plt
>>> from numpy import arange
>>> from sk_dsp_comm.sigsys import delta_eps
>>> t = np.arange(-2,2,.001)
>>> d = delta_eps(t,.1)
>>> plt.plot(t,d)
>>> plt.show()


x_approx = np.zeros(len(t))<EOL>for k,Xkk in enumerate(Xk):<EOL><INDENT>if fk[k] == <NUM_LIT:0>:<EOL><INDENT>x_approx += Xkk.real*np.ones(len(t))<EOL><DEDENT>else:<EOL><INDENT>x_approx += <NUM_LIT:2>*np.abs(Xkk)*np.cos(<NUM_LIT:2>*np.pi*fk[k]*t+np.angle(Xkk))<EOL><DEDENT><DEDENT>return x_approx<EOL>

Synthesize periodic signal x(t) using Fourier series coefficients at harmonic frequencies

Assume the signal is real so coefficients Xk are supplied for nonnegative
indicies. The negative index coefficients are assumed to be complex
conjugates.

Parameters
----------
Xk : ndarray of complex Fourier series coefficients
fk : ndarray of harmonic frequencies in Hz
t : ndarray time axis corresponding to output signal array x_approx

Returns
-------
x_approx : ndarray of periodic waveform approximation over time span t

Examples
--------
>>> t = arange(0,2,.002)
>>> # a 20% duty cycle pulse train
>>> n = arange(0,20,1) # 0 to 19th harmonic
>>> fk = 1*n % period = 1s
>>> t, x_approx = fs_approx(Xk,fk,t)
>>> plot(t,x_approx)


def freq_resp(self, mode= '<STR_LIT>', fs = <NUM_LIT>, ylim = [-<NUM_LIT:100>,<NUM_LIT:2>]):

iir_d.freqz_resp_cas_list([self.sos],mode,fs=fs)<EOL>pylab.grid()<EOL>pylab.ylim(ylim)<EOL>


y = signal.lfilter(self.b,[<NUM_LIT:1>],x)<EOL>y = ssd.downsample(y,M_change)<EOL>return y<EOL>


y = signal.lfilter(self.b,self.a,x)<EOL>y = ssd.downsample(y,self.M)<EOL>return y<EOL>


def __init__(self,M_change = <NUM_LIT:12>,fcutoff=<NUM_LIT>,N_filt_order=<NUM_LIT:8>,ftype='<STR_LIT>'):

self.M = M_change <EOL>self.fc = fcutoff*<NUM_LIT> <EOL>self.N_forder = N_filt_order<EOL>if ftype.lower() == '<STR_LIT>':<EOL><INDENT>self.b, self.a = signal.butter(self.N_forder,<NUM_LIT:2>/self.M*self.fc)<EOL><DEDENT>elif ftype.lower() == '<STR_LIT>':<EOL><INDENT>self.b, self.a = signal.cheby1(self.N_forder,<NUM_LIT>,<NUM_LIT:2>/self.M*self.fc)<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT>


y = L_change*ssd.upsample(x,L_change)<EOL>y = signal.lfilter(self.b,[<NUM_LIT:1>],y)<EOL>return y<EOL>


iir_d.sos_zplane(self.sos,auto_scale,size,tol)<EOL>

Plot the poles and zeros of the FIR filter in the z-plane


def freqz_resp(b,a=[<NUM_LIT:1>],mode = '<STR_LIT>',fs=<NUM_LIT:1.0>,Npts = <NUM_LIT>,fsize=(<NUM_LIT:6>,<NUM_LIT:4>)):

f = np.arange(<NUM_LIT:0>,Npts)/(<NUM_LIT>*Npts)<EOL>w,H = signal.freqz(b,a,<NUM_LIT:2>*np.pi*f)<EOL>plt.figure(figsize=fsize)<EOL>if mode.lower() == '<STR_LIT>':<EOL><INDENT>plt.plot(f*fs,<NUM_LIT:20>*np.log10(np.abs(H)))<EOL>plt.xlabel('<STR_LIT>')<EOL>plt.ylabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL><DEDENT>elif mode.lower() == '<STR_LIT>':<EOL><INDENT>plt.plot(f*fs,np.angle(H))<EOL>plt.xlabel('<STR_LIT>')<EOL>plt.ylabel('<STR_LIT>')<EOL>plt.title('<STR_LIT>')<EOL><DEDENT>elif (mode.lower() == '<STR_LIT>') or (mode.lower() == '<STR_LIT>'):<EOL><INDENT>"""<STR_LIT>"""<EOL>theta = np.unwrap(np.angle(H))<EOL>theta2 = np.unwrap(<NUM_LIT:2>*theta)/<NUM_LIT><EOL>theta_dif = np.diff(theta2)<EOL>f_diff = np.diff(f)<EOL>Tg = -np.diff(theta2)/np.diff(w)<EOL>idx = pylab.find(<NUM_LIT:20>*np.log10(H[:-<NUM_LIT:1>]) < -<NUM_LIT>)<EOL>Tg[idx] = np.zeros(len(idx))<EOL>max_Tg = np.max(Tg)<EOL>if mode.lower() == '<STR_LIT>':<EOL><INDENT>max_Tg /= fs<EOL>plt.plot(f[:-<NUM_LIT:1>]*fs,Tg/fs)<EOL>plt.ylim([<NUM_LIT:0>,<NUM_LIT>*max_Tg])<EOL><DEDENT>else:<EOL><INDENT>plt.plot(f[:-<NUM_LIT:1>]*fs,Tg)<EOL>plt.ylim([<NUM_LIT:0>,<NUM_LIT>*max_Tg])<EOL><DEDENT>plt.xlabel('<STR_LIT>')<EOL>if mode.lower() == '<STR_LIT>':<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>plt.ylabel('<STR_LIT>')<EOL><DEDENT>plt.title('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>s1 = '<STR_LIT>'<EOL>s2 = '<STR_LIT>'<EOL>print(s1 + s2)<EOL><DEDENT>

A method for displaying digital filter frequency response magnitude,
phase, and group delay. A plot is produced using matplotlib

freq_resp(self,mode = 'dB',Npts = 1024)

A method for displaying the filter frequency response magnitude,
phase, and group delay. A plot is produced using matplotlib

freqz_resp(b,a=[1],mode = 'dB',Npts = 1024,fsize=(6,4))

    b = ndarray of numerator coefficients
    a = ndarray of denominator coefficents
 mode = display mode: 'dB' magnitude, 'phase' in radians, or
        'groupdelay_s' in samples and 'groupdelay_t' in sec,
        all versus frequency in Hz
 Npts = number of points to plot; defult is 1024
fsize = figure size; defult is (6,4) inches

Mark Wickert, January 2015


ssd.zplane(self.b,[<NUM_LIT:1>],auto_scale,size,tol)<EOL>


plt.figure(figsize=fig_size)<EOL>N = len(x)<EOL>Mx = int(np.ceil(N/float(Nx)))<EOL>x_max = np.max(np.abs(x))<EOL>for kk in range(Mx):<EOL><INDENT>plt.plot(np.array([<NUM_LIT:0>,Nx]),-kk*Nx*np.array([<NUM_LIT:1>,<NUM_LIT:1>]),'<STR_LIT>')<EOL>plt.plot(x[kk*Nx:(kk+<NUM_LIT:1>)*Nx]/x_max*<NUM_LIT>*Nx-kk*Nx,'<STR_LIT:b>')<EOL><DEDENT>plt.axis([<NUM_LIT:0>,Nx,-Nx*(Mx-<NUM_LIT:0.5>),Nx*<NUM_LIT:0.5>])<EOL>plt.yticks(np.arange(<NUM_LIT:0>,-Nx*Mx,-Nx),np.arange(<NUM_LIT:0>,Nx*Mx,Nx))<EOL>plt.xlabel('<STR_LIT>')<EOL>plt.ylabel('<STR_LIT>')<EOL>return <NUM_LIT:0><EOL>

Plots the contents of real ndarray x as a vertical stacking of
strips, each of length Nx. The default figure size is (6,4) inches.
The yaxis tick labels are the starting index of each strip. The red
dashed lines correspond to zero amplitude in each strip.

strips(x,Nx,my_figsize=(6,4))

Mark Wickert April 2014


xq = np.int16(np.rint(x*<NUM_LIT:2>**(N_bits-<NUM_LIT:1>)))<EOL>x_bits = np.zeros((N_bits,len(xq)))<EOL>for k, xk in enumerate(xq):<EOL><INDENT>x_bits[:,k] = to_bin(xk,N_bits)<EOL><DEDENT>x_bits = np.reshape(x_bits,(<NUM_LIT:1>,len(x)*N_bits),'<STR_LIT:F>')<EOL>return np.int16(x_bits.flatten())<EOL>

Parameters
----------
x : signal samples to be PCM encoded
N_bits ; bit precision of PCM samples

Returns
-------
x_bits = encoded serial bit stream of 0/1 values. MSB first.

Mark Wickert, Mark 2015


Ns = int(np.round(fs/Rs))<EOL>print('<STR_LIT>', Ns)<EOL>print('<STR_LIT>', fs/float(Ns))<EOL>print('<STR_LIT>', EsN0, '<STR_LIT>')<EOL>print('<STR_LIT>', phase, '<STR_LIT>')<EOL>print('<STR_LIT>', pulse)<EOL>x, b, data = QPSK_bb(N_symb,Ns,lfsr_len,pulse)<EOL>x = cpx_AWGN(x,EsN0,Ns)<EOL>n = np.arange(len(x))<EOL>xc = x*np.exp(<NUM_LIT>*<NUM_LIT:2>*np.pi*fc/float(fs)*n) * np.exp(<NUM_LIT>*phase)<EOL>return xc, b, data<EOL>


def bit_errors(tx_data,rx_data,Ncorr = <NUM_LIT>,Ntransient = <NUM_LIT:0>):

<EOL>tx_data = <NUM_LIT:2>*tx_data[Ntransient:]-<NUM_LIT:1><EOL>rx_data = <NUM_LIT:2>*rx_data[Ntransient:]-<NUM_LIT:1><EOL>R0 = np.fft.ifft(np.fft.fft(rx_data,Ncorr)*<EOL>np.conj(np.fft.fft(tx_data,Ncorr)))<EOL>R1 = np.fft.ifft(np.fft.fft(-<NUM_LIT:1>*rx_data,Ncorr)*<EOL>np.conj(np.fft.fft(tx_data,Ncorr)))<EOL>R0 = np.fft.fftshift(R0)<EOL>R1 = np.fft.fftshift(R1)<EOL>R0max = np.max(R0.real)<EOL>R1max = np.max(R1.real)<EOL>R = np.array([R0max,R1max])<EOL>Rmax = np.max(R)<EOL>kphase_max = np.where(R == Rmax)[<NUM_LIT:0>]<EOL>kmax = kphase_max[<NUM_LIT:0>]<EOL>if kmax == <NUM_LIT:0>:<EOL><INDENT>lagmax = np.where(R0.real == Rmax)[<NUM_LIT:0>] - Ncorr/<NUM_LIT:2><EOL><DEDENT>elif kmax == <NUM_LIT:1>:<EOL><INDENT>lagmax = np.where(R1.real == Rmax)[<NUM_LIT:0>] - Ncorr/<NUM_LIT:2><EOL><DEDENT>taumax = lagmax[<NUM_LIT:0>]<EOL>print('<STR_LIT>' % (kmax, taumax))<EOL>if taumax < <NUM_LIT:0>:<EOL><INDENT>tx_data = tx_data[int(-taumax):]<EOL>tx_data = tx_data[:min(len(tx_data),len(rx_data))]<EOL>rx_data = (-<NUM_LIT:1>)**kmax*rx_data[:len(tx_data)]<EOL><DEDENT>else:<EOL><INDENT>rx_data = (-<NUM_LIT:1>)**kmax * rx_data[int(taumax):]<EOL>rx_data = rx_data[:min(len(tx_data),len(rx_data))]<EOL>tx_data = tx_data[:len(rx_data)]<EOL><DEDENT>Bit_count = len(tx_data)<EOL>tx_I = np.int16((tx_data.real + <NUM_LIT:1>)/<NUM_LIT:2>)<EOL>rx_I = np.int16((rx_data.real + <NUM_LIT:1>)/<NUM_LIT:2>)<EOL>Bit_errors = tx_I ^ rx_I<EOL>return Bit_count,np.sum(Bit_errors)<EOL>

Count bit errors between a transmitted and received BPSK signal.
Time delay between streams is detected as well as ambiquity resolution
due to carrier phase lock offsets of :math:`k*\\pi`, k=0,1.
The ndarray tx_data is Tx 0/1 bits as real numbers I.
The ndarray rx_data is Rx 0/1 bits as real numbers I.
Note: Ncorr needs to be even


return <NUM_LIT:1.>/<NUM_LIT:2>*erfc(x/np.sqrt(<NUM_LIT>))<EOL>


<EOL>n = np.arange(-M*Ns,M*Ns+<NUM_LIT:1>)<EOL>b = np.zeros(len(n))<EOL>a = alpha<EOL>Ns *= <NUM_LIT:1.0><EOL>for i in range(len(n)):<EOL><INDENT>if (<NUM_LIT:1> - <NUM_LIT:4>*(a*n[i]/Ns)**<NUM_LIT:2>) == <NUM_LIT:0>:<EOL><INDENT>b[i] = np.pi/<NUM_LIT:4>*np.sinc(<NUM_LIT:1>/(<NUM_LIT>*a))<EOL><DEDENT>else:<EOL><INDENT>b[i] = np.sinc(n[i]/Ns)*np.cos(np.pi*a*n[i]/Ns)/(<NUM_LIT:1> - <NUM_LIT:4>*(a*n[i]/Ns)**<NUM_LIT:2>)<EOL><DEDENT><DEDENT>return b<EOL>

A truncated raised cosine pulse used in digital communications.

The pulse shaping factor :math:`0 < \\alpha < 1` is required as well as the
truncation factor M which sets the pulse duration to be :math:`2*M*T_{symbol}`.

Parameters
----------
Ns : number of samples per symbol
alpha : excess bandwidth factor on (0, 1), e.g., 0.35
M : equals RC one-sided symbol truncation factor

Returns
-------
b : ndarray containing the pulse shape

See Also
--------
sqrt_rc_imp

Notes
-----
The pulse shape b is typically used as the FIR filter coefficients
when forming a pulse shaped digital communications waveform.

Examples
--------
Ten samples per symbol and :math:`\\alpha = 0.35`.

>>> import matplotlib.pyplot as plt
>>> from sk_dsp_comm.digitalcom import rc_imp
>>> from numpy import arange
>>> b = rc_imp(10,0.35)
>>> n = arange(-10*6,10*6+1)
>>> plt.stem(n,b)
>>> plt.show()


bits_in = to_bin(d_word,b_width)<EOL>bits_out = np.zeros(b_width,dtype=np.int)<EOL>for k, bit_k in enumerate(bits_in):<EOL><INDENT>if k > <NUM_LIT:0>:<EOL><INDENT>bits_out[k] = bit_k^bits_out[k-<NUM_LIT:1>]<EOL><DEDENT>else:<EOL><INDENT>bits_out[k] = bit_k<EOL><DEDENT><DEDENT>return from_bin(bits_out)<EOL>

Convert gray encoded binary words to integer bit words via
Gray decoding starting from the MSB to the LSB

Mark Wickert November 2018


N_samples = len(x_bits)//N_bits<EOL>xrs_bits = x_bits.copy()<EOL>xrs_bits = np.reshape(xrs_bits,(N_bits,N_samples),'<STR_LIT:F>')<EOL>xq = np.zeros(N_samples)<EOL>w = <NUM_LIT:2>**np.arange(N_bits-<NUM_LIT:1>,-<NUM_LIT:1>,-<NUM_LIT:1>) <EOL>for k in range(N_samples):<EOL><INDENT>xq[k] = np.dot(xrs_bits[:,k],w) - xrs_bits[<NUM_LIT:0>,k]*<NUM_LIT:2>**N_bits<EOL><DEDENT>return xq/<NUM_LIT:2>**(N_bits-<NUM_LIT:1>)<EOL>

Parameters
----------
x_bits : serial bit stream of 0/1 values. The length of
         x_bits must be a multiple of N_bits
N_bits : bit precision of PCM samples

Returns
-------
  xhat : decoded PCM signal samples

Mark Wickert, March 2015


data_str = bin(data & (<NUM_LIT:2>**width-<NUM_LIT:1>))[<NUM_LIT:2>:].zfill(width)<EOL>return [int(x) for x in tuple(data_str)]<EOL>

Convert an unsigned integer to a numpy binary array with the first
element the MSB and the last element the LSB.


<EOL>n = np.arange(-M*Ns,M*Ns+<NUM_LIT:1>)<EOL>b = np.zeros(len(n))<EOL>Ns *= <NUM_LIT:1.0><EOL>a = alpha<EOL>for i in range(len(n)):<EOL><INDENT>if abs(<NUM_LIT:1> - <NUM_LIT:16>*a**<NUM_LIT:2>*(n[i]/Ns)**<NUM_LIT:2>) <= np.finfo(np.float).eps/<NUM_LIT:2>:<EOL><INDENT>b[i] = <NUM_LIT:1>/<NUM_LIT>*((<NUM_LIT:1>+a)*np.sin((<NUM_LIT:1>+a)*np.pi/(<NUM_LIT>*a))-(<NUM_LIT:1>-a)*np.cos((<NUM_LIT:1>-a)*np.pi/(<NUM_LIT>*a))+(<NUM_LIT:4>*a)/np.pi*np.sin((<NUM_LIT:1>-a)*np.pi/(<NUM_LIT>*a)))<EOL><DEDENT>else:<EOL><INDENT>b[i] = <NUM_LIT:4>*a/(np.pi*(<NUM_LIT:1> - <NUM_LIT:16>*a**<NUM_LIT:2>*(n[i]/Ns)**<NUM_LIT:2>))<EOL>b[i] = b[i]*(np.cos((<NUM_LIT:1>+a)*np.pi*n[i]/Ns) + np.sinc((<NUM_LIT:1>-a)*n[i]/Ns)*(<NUM_LIT:1>-a)*np.pi/(<NUM_LIT>*a))<EOL><DEDENT><DEDENT>return b<EOL>

A truncated square root raised cosine pulse used in digital communications.

The pulse shaping factor :math:`0 < \\alpha < 1` is required as well as the
truncation factor M which sets the pulse duration to be :math:`2*M*T_{symbol}`.

Parameters
----------
Ns : number of samples per symbol
alpha : excess bandwidth factor on (0, 1), e.g., 0.35
M : equals RC one-sided symbol truncation factor

Returns
-------
b : ndarray containing the pulse shape

Notes
-----
The pulse shape b is typically used as the FIR filter coefficients
when forming a pulse shaped digital communications waveform. When
square root raised cosine (SRC) pulse is used to generate Tx signals and
at the receiver used as a matched filter (receiver FIR filter), the
received signal is now raised cosine shaped, thus having zero
intersymbol interference and the optimum removal of additive white
noise if present at the receiver input.

Examples
--------
Ten samples per symbol and :math:`\\alpha = 0.35`.

>>> import matplotlib.pyplot as plt
>>> from numpy import arange
>>> from sk_dsp_comm.digitalcom import sqrt_rc_imp
>>> b = sqrt_rc_imp(10,0.35)
>>> n = arange(-10*6,10*6+1)
>>> plt.stem(n,b)
>>> plt.show()


bits_in = to_bin(d_word,b_width)<EOL>bits_out = np.zeros(b_width,dtype=np.int)<EOL>for k, bit_k in enumerate(bits_in):<EOL><INDENT>if k > <NUM_LIT:0>:<EOL><INDENT>bits_out[k] = bit_k^bits_in[k-<NUM_LIT:1>]<EOL><DEDENT>else:<EOL><INDENT>bits_out[k] = bit_k<EOL><DEDENT><DEDENT>return from_bin(bits_out)<EOL>

Convert integer bit words to gray encoded binary words via
Gray coding starting from the MSB to the LSB

Mark Wickert November 2018


<EOL>bin2gray1 = [<NUM_LIT:0>,<NUM_LIT:1>]<EOL>bin2gray2 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>]<EOL>bin2gray3 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:7>,<NUM_LIT:6>,<NUM_LIT:4>,<NUM_LIT:5>] <EOL>bin2gray4 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:7>,<NUM_LIT:6>,<NUM_LIT:4>,<NUM_LIT:5>,<NUM_LIT:15>,<NUM_LIT>,<NUM_LIT:12>,<NUM_LIT>,<NUM_LIT:8>,<NUM_LIT:9>,<NUM_LIT:11>,<NUM_LIT:10>]<EOL>bin2gray5 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:7>,<NUM_LIT:6>,<NUM_LIT:4>,<NUM_LIT:5>,<NUM_LIT:15>,<NUM_LIT>,<NUM_LIT:12>,<NUM_LIT>,<NUM_LIT:8>,<NUM_LIT:9>,<NUM_LIT:11>,<NUM_LIT:10>,<NUM_LIT>,<NUM_LIT:30>,<EOL><NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT:16>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT>,<NUM_LIT:20>,<NUM_LIT>]<EOL>N_word = int(np.log2(M))<EOL>if N_symb == None:<EOL><INDENT>N_symb = int(np.floor(len(ext_data)/N_word))<EOL>data = ext_data[:N_symb*N_word]<EOL><DEDENT>else:<EOL><INDENT>data = np.random.randint(<NUM_LIT:0>,<NUM_LIT:2>,size=int(np.log2(M))*N_symb)<EOL><DEDENT>x_IQ = np.zeros(N_symb,dtype=np.complex128)<EOL>bin_wgts = <NUM_LIT:2>**np.arange(N_word-<NUM_LIT:1>,-<NUM_LIT:1>,-<NUM_LIT:1>)<EOL>if M == <NUM_LIT:2>: <EOL><INDENT>x_IQ = <NUM_LIT:2>*data - <NUM_LIT:1><EOL><DEDENT>elif M == <NUM_LIT:4>: <EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray2[np.dot(word_phase,bin_wgts)]/M + np.pi/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>elif M == <NUM_LIT:8>:<EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray3[np.dot(word_phase,bin_wgts)]/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>elif M == <NUM_LIT:16>:<EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray4[np.dot(word_phase,bin_wgts)]/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>elif M == <NUM_LIT:32>:<EOL><INDENT>for k in range(N_symb):<EOL><INDENT>word_phase = data[k*N_word:(k+<NUM_LIT:1>)*N_word]<EOL>x_phase = <NUM_LIT:2>*np.pi*bin2gray5[np.dot(word_phase,bin_wgts)]/M<EOL>x_IQ[k] = np.exp(<NUM_LIT>*x_phase)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')        <EOL><DEDENT>if Ns > <NUM_LIT:1>:<EOL><INDENT>if pulse.lower() == '<STR_LIT:src>':<EOL><INDENT>b = sqrt_rc_imp(Ns,alpha,<NUM_LIT:6>)<EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = rc_imp(Ns,alpha,<NUM_LIT:6>)    <EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = np.ones(int(Ns)) <EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>x = signal.lfilter(b,<NUM_LIT:1>,upsample(x_IQ,Ns))<EOL>b = b/sum(b)<EOL>return x, b, data<EOL><DEDENT>else:<EOL><INDENT>return x_IQ, <NUM_LIT:1>, data<EOL><DEDENT>

MPSK_gray_bb: A gray code mapped MPSK complex baseband transmitter
x,b,tx_data = MPSK_gray_bb(K,Ns,M)

//////////// Inputs //////////////////////////////////////////////////
  N_symb = the number of symbols to process
      Ns = number of samples per symbol
       M = modulation order: 2, 4, 8, 16 MPSK
   alpha = squareroot raised cosine excess bandwidth factor.
           Can range over 0 < alpha < 1.
   pulse = 'rect', 'src', or 'rc'
//////////// Outputs /////////////////////////////////////////////////
       x = complex baseband digital modulation
       b = transmitter shaping filter, rectangle or SRC
 tx_data = xI+1j*xQ = inphase symbol sequence +
           1j*quadrature symbol sequence

Mark Wickert November 2018


def RZ_bits(N_bits,Ns,pulse='<STR_LIT>',alpha = <NUM_LIT>,M=<NUM_LIT:6>):

data = np.random.randint(<NUM_LIT:0>,<NUM_LIT:2>,N_bits) <EOL>x = np.hstack((data.reshape(N_bits,<NUM_LIT:1>),np.zeros((N_bits,int(Ns)-<NUM_LIT:1>))))<EOL>x =x.flatten()<EOL>if pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = np.ones(int(Ns))<EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = rc_imp(Ns,alpha,M)<EOL><DEDENT>elif pulse.lower() == '<STR_LIT:src>':<EOL><INDENT>b = sqrt_rc_imp(Ns,alpha,M)<EOL><DEDENT>else:<EOL><INDENT>print('<STR_LIT>')<EOL><DEDENT>x = signal.lfilter(b,<NUM_LIT:1>,x)<EOL>return x,b/float(Ns),data<EOL>

Generate return-to-zero (RZ) data bits with pulse shaping.

A baseband digital data signal using +/-1 amplitude signal values
and including pulse shaping.

Parameters
----------
N_bits : number of RZ {0,1} data bits to produce
Ns : the number of samples per bit,
pulse_type : 'rect' , 'rc', 'src' (default 'rect')
alpha : excess bandwidth factor(default 0.25)
M : single sided pulse duration (default = 6)

Returns
-------
x : ndarray of the RZ signal values
b : ndarray of the pulse shape
data : ndarray of the underlying data bits

Notes
-----
Pulse shapes include 'rect' (rectangular), 'rc' (raised cosine),
'src' (root raised cosine). The actual pulse length is 2*M+1 samples.
This function is used by BPSK_tx in the Case Study article.

Examples
--------
>>> import matplotlib.pyplot as plt
>>> from numpy import arange
>>> from sk_dsp_comm.digitalcom import RZ_bits
>>> x,b,data = RZ_bits(100,10)
>>> t = arange(len(x))
>>> plt.plot(t,x)
>>> plt.ylim([-0.01, 1.01])
>>> plt.show()


width = len(bin_array)<EOL>bin_wgts = <NUM_LIT:2>**np.arange(width-<NUM_LIT:1>,-<NUM_LIT:1>,-<NUM_LIT:1>)<EOL>return int(np.dot(bin_array,bin_wgts))<EOL>

Convert binary array back a nonnegative integer. The array length is
the bit width. The first input index holds the MSB and the last holds the LSB.


def QAM_gray_decode(x_hat,M = <NUM_LIT:4>):

<EOL>gray2bin1 = [<NUM_LIT:0>,<NUM_LIT:1>]<EOL>gray2bin2 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>]<EOL>gray2bin3 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:6>,<NUM_LIT:7>,<NUM_LIT:5>,<NUM_LIT:4>] <EOL>gray2bin4 = [<NUM_LIT:0>,<NUM_LIT:1>,<NUM_LIT:3>,<NUM_LIT:2>,<NUM_LIT:6>,<NUM_LIT:7>,<NUM_LIT:5>,<NUM_LIT:4>,<NUM_LIT:12>,<NUM_LIT>,<NUM_LIT:15>,<NUM_LIT>,<NUM_LIT:10>,<NUM_LIT:11>,<NUM_LIT:9>,<NUM_LIT:8>]<EOL>x_m = np.sqrt(M)-<NUM_LIT:1><EOL>if M == <NUM_LIT:2>: x_m = <NUM_LIT:1><EOL>N_symb = len(x_hat)<EOL>N_word = int(np.log2(M)/<NUM_LIT:2>)<EOL>x_hat = x_hat/(np.std(x_hat) * np.sqrt(<NUM_LIT:3>/(<NUM_LIT:2>*(M-<NUM_LIT:1>))))<EOL>k_hat_gray = (x_hat + x_m*(<NUM_LIT:1>+<NUM_LIT>))/<NUM_LIT:2><EOL>k_hat_grayI = np.int16(np.clip(np.rint(k_hat_gray.real),<NUM_LIT:0>,x_m))<EOL>k_hat_grayQ = np.int16(np.clip(np.rint(k_hat_gray.imag),<NUM_LIT:0>,x_m))<EOL>data_hat = np.zeros(<NUM_LIT:2>*N_word*N_symb,dtype=int)<EOL>for k in range(N_symb):<EOL><INDENT>if M == <NUM_LIT:2>: <EOL><INDENT>data_hat = k_hat_grayI<EOL><DEDENT>elif M == <NUM_LIT:4>: <EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin1[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin1[k_hat_grayQ[k]],N_word)))<EOL><DEDENT>elif M == <NUM_LIT:16>:<EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin2[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin2[k_hat_grayQ[k]],N_word)))            <EOL><DEDENT>elif M == <NUM_LIT:64>:<EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin3[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin3[k_hat_grayQ[k]],N_word)))            <EOL><DEDENT>elif M == <NUM_LIT>:<EOL><INDENT>data_hat[<NUM_LIT:2>*k*N_word:<NUM_LIT:2>*(k+<NUM_LIT:1>)*N_word]= np.hstack((to_bin(gray2bin4[k_hat_grayI[k]],N_word),<EOL>to_bin(gray2bin4[k_hat_grayQ[k]],N_word)))<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')  <EOL><DEDENT><DEDENT>return data_hat<EOL>

Decode MQAM IQ symbols to a serial bit stream using
gray2bin decoding

x_hat = symbol spaced samples of the QAM waveform taken at the maximum
        eye opening. Normally this is following the matched filter

Mark Wickert April 2018


K = <NUM_LIT:2>*(int(np.floor(len(x1)/<NUM_LIT:2>)))<EOL>X1 = fft.fft(x1[:K])<EOL>X2 = fft.fft(x2[:K])<EOL>E1 = sum(abs(x1[:K])**<NUM_LIT:2>)<EOL>E2 = sum(abs(x2[:K])**<NUM_LIT:2>)<EOL>r12 = np.fft.ifft(X1*np.conj(X2))/np.sqrt(E1*E2)<EOL>k = np.arange(K) - int(np.floor(K/<NUM_LIT:2>))<EOL>r12 = np.fft.fftshift(r12)<EOL>idx = np.nonzero(np.ravel(abs(k) <= Nlags))<EOL>return r12[idx], k[idx]<EOL>

r12, k = xcorr(x1,x2,Nlags), r12 and k are ndarray's
Compute the energy normalized cross correlation between the sequences
x1 and x2. If x1 = x2 the cross correlation is the autocorrelation.
The number of lags sets how many lags to return centered about zero


def OFDM_rx(x, Nf, N, Np=<NUM_LIT:0>, cp=False, Ncp=<NUM_LIT:0>, alpha=<NUM_LIT>, ht=None):

N_symb = len(x) // (N + Ncp)<EOL>y_out = np.zeros(N_symb * N, dtype=np.complex128)<EOL>for k in range(N_symb):<EOL><INDENT>if cp:<EOL><INDENT>buff = x[k * (N + Ncp) + Ncp:(k + <NUM_LIT:1>) * (N + Ncp)]<EOL><DEDENT>else:<EOL><INDENT>buff = x[k * N:(k + <NUM_LIT:1>) * N]<EOL><DEDENT>y_out[k * N:(k + <NUM_LIT:1>) * N] = fft.fft(buff)<EOL><DEDENT>z_out = np.reshape(y_out, (N_symb, N))<EOL>z_out = np.hstack((z_out[:, <NUM_LIT:1>:Nf // <NUM_LIT:2> + <NUM_LIT:1>], z_out[:, N - Nf // <NUM_LIT:2>:N]))<EOL>if Np > <NUM_LIT:0>:<EOL><INDENT>if isinstance(type(None), type(ht)):<EOL><INDENT>z_out, H = chan_est_equalize(z_out, Np, alpha)<EOL><DEDENT>else:<EOL><INDENT>Ht = fft.fft(ht, N)<EOL>Hht = np.hstack((Ht[<NUM_LIT:1>:Nf // <NUM_LIT:2> + <NUM_LIT:1>], Ht[N - Nf // <NUM_LIT:2>:]))<EOL>z_out, H = chan_est_equalize(z_out, Np, alpha, Hht)<EOL><DEDENT><DEDENT>elif Np == -<NUM_LIT:1>:  <EOL><INDENT>Ht = fft.fft(ht, N)<EOL>H = np.hstack((Ht[<NUM_LIT:1>:Nf // <NUM_LIT:2> + <NUM_LIT:1>], Ht[N - Nf // <NUM_LIT:2>:]))<EOL>for k in range(N_symb):<EOL><INDENT>z_out[k, :] /= H<EOL><DEDENT><DEDENT>else:<EOL><INDENT>H = np.ones(Nf)<EOL><DEDENT>return z_out.flatten(), H<EOL>

Parameters
----------
x : Received complex baseband OFDM signal
Nf : Number of filled carriers, must be even and Nf < N
N : Total number of carriers; generally a power 2, e.g., 64, 1024, etc
Np : Period of pilot code blocks; 0 <=> no pilots; -1 <=> use the ht impulse response input to equalize the OFDM symbols; note equalization still requires Ncp > 0 to work on a delay spread channel.
cp : False/True <=> if False assume no CP is present
Ncp : The length of the cyclic prefix
alpha : The filter forgetting factor in the channel estimator. Typically alpha is 0.9 to 0.99.
nt : Input the known theoretical channel impulse response

Returns
-------
z_out : Recovered complex baseband QAM symbols as a serial stream; as appropriate channel estimation has been applied.
H : channel estimate (in the frequency domain at each subcarrier)

See Also
--------
OFDM_tx

Examples
--------

>>> import matplotlib.pyplot as plt
>>> from sk_dsp_comm import digitalcom as dc
>>> from scipy import signal
>>> from numpy import array
>>> hc = array([1.0, 0.1, -0.05, 0.15, 0.2, 0.05]) # impulse response spanning five symbols
>>> # Quick example using the above channel with no cyclic prefix
>>> x1,b1,IQ_data1 = dc.QAM_bb(50000,1,'16qam')
>>> x_out = dc.OFDM_tx(IQ_data1,32,64,0,True,0)
>>> c_out = signal.lfilter(hc,1,x_out) # Apply channel distortion
>>> r_out = dc.cpx_AWGN(c_out,100,64/32) # Es/N0 = 100 dB
>>> z_out,H = dc.OFDM_rx(r_out,32,64,-1,True,0,alpha=0.95,ht=hc)
>>> plt.plot(z_out[200:].real,z_out[200:].imag,'.')
>>> plt.xlabel('In-Phase')
>>> plt.ylabel('Quadrature')
>>> plt.axis('equal')
>>> plt.grid()
>>> plt.show()

Another example with noise using a 10 symbol cyclic prefix and channel estimation:

>>> x_out = dc.OFDM_tx(IQ_data1,32,64,100,True,10)
>>> c_out = signal.lfilter(hc,1,x_out) # Apply channel distortion
>>> r_out = dc.cpx_AWGN(c_out,25,64/32) # Es/N0 = 25 dB
>>> z_out,H = dc.OFDM_rx(r_out,32,64,100,True,10,alpha=0.95,ht=hc);
>>> plt.figure() # if channel estimation is turned on need this
>>> plt.plot(z_out[-2000:].real,z_out[-2000:].imag,'.') # allow settling time
>>> plt.xlabel('In-Phase')
>>> plt.ylabel('Quadrature')
>>> plt.axis('equal')
>>> plt.grid()
>>> plt.show()


def QAM_SEP(tx_data,rx_data,mod_type,Ncorr = <NUM_LIT>,Ntransient = <NUM_LIT:0>,SEP_disp=True):

<EOL>tx_data = tx_data[Ntransient:]<EOL>rx_data = rx_data[Ntransient:]<EOL>Nmin = min([len(tx_data),len(rx_data)])<EOL>tx_data = tx_data[:Nmin]<EOL>rx_data = rx_data[:Nmin]<EOL>if mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:2> <EOL><DEDENT>elif mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:4><EOL><DEDENT>elif mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:8><EOL><DEDENT>elif mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:16><EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>rx_data = np.rint((M-<NUM_LIT:1>)*(rx_data + (<NUM_LIT:1>+<NUM_LIT>))/<NUM_LIT>)<EOL>s1r = np.nonzero(np.ravel(rx_data.real > M - <NUM_LIT:1>))[<NUM_LIT:0>]<EOL>s2r = np.nonzero(np.ravel(rx_data.real < <NUM_LIT:0>))[<NUM_LIT:0>]<EOL>rx_data.real[s1r] = (M - <NUM_LIT:1>)*np.ones(len(s1r))<EOL>rx_data.real[s2r] = np.zeros(len(s2r))<EOL>s1i = np.nonzero(np.ravel(rx_data.imag > M - <NUM_LIT:1>))[<NUM_LIT:0>]<EOL>s2i = np.nonzero(np.ravel(rx_data.imag < <NUM_LIT:0>))[<NUM_LIT:0>]<EOL>rx_data.imag[s1i] = (M - <NUM_LIT:1>)*np.ones(len(s1i))<EOL>rx_data.imag[s2i] = np.zeros(len(s2i))<EOL>rx_data = <NUM_LIT:2>*rx_data - (M - <NUM_LIT:1>)*(<NUM_LIT:1> + <NUM_LIT>)<EOL>R0,lags = xcorr(rx_data,tx_data,Ncorr)<EOL>R1,lags = xcorr(rx_data*(<NUM_LIT>)**<NUM_LIT:1>,tx_data,Ncorr) <EOL>R2,lags = xcorr(rx_data*(<NUM_LIT>)**<NUM_LIT:2>,tx_data,Ncorr) <EOL>R3,lags = xcorr(rx_data*(<NUM_LIT>)**<NUM_LIT:3>,tx_data,Ncorr) <EOL>R0max = np.max(R0.real)<EOL>R1max = np.max(R1.real)<EOL>R2max = np.max(R2.real)<EOL>R3max = np.max(R3.real)<EOL>R = np.array([R0max,R1max,R2max,R3max])<EOL>Rmax = np.max(R)<EOL>kphase_max = np.where(R == Rmax)[<NUM_LIT:0>]<EOL>kmax = kphase_max[<NUM_LIT:0>]<EOL>if kmax == <NUM_LIT:0>:<EOL><INDENT>lagmax = lags[np.where(R0.real == Rmax)[<NUM_LIT:0>]]<EOL><DEDENT>elif kmax == <NUM_LIT:1>:<EOL><INDENT>lagmax = lags[np.where(R1.real == Rmax)[<NUM_LIT:0>]]<EOL><DEDENT>elif kmax == <NUM_LIT:2>:<EOL><INDENT>lagmax = lags[np.where(R2.real == Rmax)[<NUM_LIT:0>]]<EOL><DEDENT>elif kmax == <NUM_LIT:3>:<EOL><INDENT>lagmax = lags[np.where(R3.real == Rmax)[<NUM_LIT:0>]]<EOL><DEDENT>taumax = lagmax[<NUM_LIT:0>]<EOL>if SEP_disp:<EOL><INDENT>print('<STR_LIT>' % (kmax, taumax))<EOL><DEDENT>if taumax < <NUM_LIT:0>:<EOL><INDENT>tx_data = tx_data[-taumax:]<EOL>tx_data = tx_data[:min(len(tx_data),len(rx_data))]<EOL>rx_data = (<NUM_LIT>)**kmax*rx_data[:len(tx_data)]<EOL><DEDENT>else:<EOL><INDENT>rx_data = (<NUM_LIT>)**kmax*rx_data[taumax:]<EOL>rx_data = rx_data[:min(len(tx_data),len(rx_data))]<EOL>tx_data = tx_data[:len(rx_data)]<EOL><DEDENT>errors = np.int16(abs(rx_data-tx_data))<EOL>idx = np.nonzero(np.ravel(errors != <NUM_LIT:0>))[<NUM_LIT:0>]<EOL>if SEP_disp:<EOL><INDENT>print('<STR_LIT>'% (len(errors), len(idx), len(idx)/float(len(errors))))<EOL><DEDENT>return  len(errors), len(idx), len(idx)/float(len(errors))<EOL>

Nsymb, Nerr, SEP_hat =
QAM_symb_errors(tx_data,rx_data,mod_type,Ncorr = 1024,Ntransient = 0)

Count symbol errors between a transmitted and received QAM signal.
The received symbols are assumed to be soft values on a unit square.
Time delay between streams is detected.
The ndarray tx_data is Tx complex symbols.
The ndarray rx_data is Rx complex symbols.
Note: Ncorr needs to be even


<EOL>if pulse.lower() == '<STR_LIT:src>':<EOL><INDENT>b = sqrt_rc_imp(Ns,alpha,<NUM_LIT:6>)<EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = rc_imp(Ns,alpha,<NUM_LIT:6>)    <EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = np.ones(int(Ns)) <EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>if mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:2> <EOL><DEDENT>elif mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:4><EOL><DEDENT>elif mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:8><EOL><DEDENT>elif mod_type.lower() == '<STR_LIT>':<EOL><INDENT>M = <NUM_LIT:16><EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>xI = np.random.randint(<NUM_LIT:0>,M,N_symb)<EOL>xI = <NUM_LIT:2>*xI - (M-<NUM_LIT:1>)<EOL>xQ = np.random.randint(<NUM_LIT:0>,M,N_symb)<EOL>xQ = <NUM_LIT:2>*xQ - (M-<NUM_LIT:1>)<EOL>symbI = np.hstack((xI.reshape(N_symb,<NUM_LIT:1>),np.zeros((N_symb,int(Ns)-<NUM_LIT:1>))))<EOL>symbI = symbI.flatten()<EOL>symbQ = np.hstack((xQ.reshape(N_symb,<NUM_LIT:1>),np.zeros((N_symb,int(Ns)-<NUM_LIT:1>))))<EOL>symbQ = symbQ.flatten()<EOL>symb = symbI + <NUM_LIT>*symbQ<EOL>if M > <NUM_LIT:2>:<EOL><INDENT>symb /= (M-<NUM_LIT:1>)<EOL><DEDENT>x = signal.lfilter(b,<NUM_LIT:1>,symb)<EOL>x = x.flatten() <EOL>b = b/sum(b)<EOL>return x, b, xI+<NUM_LIT>*xQ<EOL>

QAM_BB_TX: A complex baseband transmitter
x,b,tx_data = QAM_bb(K,Ns,M)

//////////// Inputs //////////////////////////////////////////////////
  N_symb = the number of symbols to process
      Ns = number of samples per symbol
mod_type = modulation type: qpsk, 16qam, 64qam, or 256qam
   alpha = squareroot raised codine pulse shape bandwidth factor.
           For DOCSIS alpha = 0.12 to 0.18. In general alpha can
           range over 0 < alpha < 1.
     SRC = pulse shape: 0-> rect, 1-> SRC
//////////// Outputs /////////////////////////////////////////////////
       x = complex baseband digital modulation
       b = transmitter shaping filter, rectangle or SRC
 tx_data = xI+1j*xQ = inphase symbol sequence +
           1j*quadrature symbol sequence

Mark Wickert November 2014


def MPSK_bb(N_symb,Ns,M,pulse='<STR_LIT>',alpha = <NUM_LIT>,MM=<NUM_LIT:6>):

data = np.random.randint(<NUM_LIT:0>,M,N_symb) <EOL>xs = np.exp(<NUM_LIT>*<NUM_LIT:2>*np.pi/M*data)<EOL>x = np.hstack((xs.reshape(N_symb,<NUM_LIT:1>),np.zeros((N_symb,int(Ns)-<NUM_LIT:1>))))<EOL>x =x.flatten()<EOL>if pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = np.ones(int(Ns))<EOL><DEDENT>elif pulse.lower() == '<STR_LIT>':<EOL><INDENT>b = rc_imp(Ns,alpha,MM)<EOL><DEDENT>elif pulse.lower() == '<STR_LIT:src>':<EOL><INDENT>b = sqrt_rc_imp(Ns,alpha,MM)<EOL><DEDENT>else:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>x = signal.lfilter(b,<NUM_LIT:1>,x)<EOL>if M == <NUM_LIT:4>:<EOL><INDENT>x = x*np.exp(<NUM_LIT>*np.pi/<NUM_LIT:4>); <EOL><DEDENT>return x,b/float(Ns),data<EOL>

Generate a complex baseband MPSK signal with pulse shaping.

Parameters
----------
N_symb : number of MPSK symbols to produce
Ns : the number of samples per bit,
M : MPSK modulation order, e.g., 4, 8, 16, ...
pulse_type : 'rect' , 'rc', 'src' (default 'rect')
alpha : excess bandwidth factor(default 0.25)
MM : single sided pulse duration (default = 6)

Returns
-------
x : ndarray of the MPSK signal values
b : ndarray of the pulse shape
data : ndarray of the underlying data bits

Notes
-----
Pulse shapes include 'rect' (rectangular), 'rc' (raised cosine),
'src' (root raised cosine). The actual pulse length is 2*M+1 samples.
This function is used by BPSK_tx in the Case Study article.

Examples
--------
>>> from sk_dsp_comm import digitalcom as dc
>>> import scipy.signal as signal
>>> import matplotlib.pyplot as plt
>>> x,b,data = dc.MPSK_bb(500,10,8,'src',0.35)
>>> # Matched filter received signal x
>>> y = signal.lfilter(b,1,x)
>>> plt.plot(y.real[12*10:],y.imag[12*10:])
>>> plt.xlabel('In-Phase')
>>> plt.ylabel('Quadrature')
>>> plt.axis('equal')
>>> # Sample once per symbol
>>> plt.plot(y.real[12*10::10],y.imag[12*10::10],'r.')
>>> plt.show()


w = Gdk.get_default_root_window()<EOL>if bbox is not None:<EOL><INDENT>g = [bbox[<NUM_LIT:0>], bbox[<NUM_LIT:1>], bbox[<NUM_LIT:2>] - bbox[<NUM_LIT:0>], bbox[<NUM_LIT:3>] - bbox[<NUM_LIT:1>]]<EOL><DEDENT>else:<EOL><INDENT>g = w.get_geometry()<EOL><DEDENT>pb = Gdk.pixbuf_get_from_window(w, *g)<EOL>if pb.get_bits_per_sample() != <NUM_LIT:8>:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>elif pb.get_n_channels() != <NUM_LIT:3>:<EOL><INDENT>raise ValueError('<STR_LIT>')<EOL><DEDENT>pixel_bytes = pb.read_pixel_bytes().get_data()  <EOL>width, height = g[<NUM_LIT:2>], g[<NUM_LIT:3>]<EOL>return Image.frombytes(<EOL>'<STR_LIT>', (width, height), pixel_bytes, '<STR_LIT>', '<STR_LIT>', pb.get_rowstride(), <NUM_LIT:1>)<EOL>

Grabs an image directly to a buffer.

        :param bbox: Optional tuple or list containing (x1, y1, x2, y2) coordinates
            of sub-region to capture.
        :return: PIL RGB image
        :raises: ValueError, if image data does not have 3 channels (RGB), each with 8
            bits.
        :rtype: Image


def grab(bbox=None, childprocess=None, backend=None):

if childprocess is None:<EOL><INDENT>childprocess = childprocess_default_value()<EOL><DEDENT>return _grab(<EOL>to_file=False, childprocess=childprocess, backend=backend, bbox=bbox)<EOL>

Copy the contents of the screen to PIL image memory.

    :param bbox: optional bounding box (x1,y1,x2,y2)
    :param childprocess: pyscreenshot can cause an error,
            if it is used on more different virtual displays
            and back-end is not in different process.
            Some back-ends are always different processes: scrot, imagemagick
            The default is False if the program was started inside IDLE,
            otherwise it is True.
    :param backend: back-end can be forced if set (examples:scrot, wx,..),
                    otherwise back-end is automatic


def grab_to_file(filename, childprocess=None, backend=None):

if childprocess is None:<EOL><INDENT>childprocess = childprocess_default_value()<EOL><DEDENT>return _grab(to_file=True, childprocess=childprocess,<EOL>backend=backend, filename=filename)<EOL>

Copy the contents of the screen to a file. Internal function! Use
    PIL.Image.save() for saving image to file.

    :param filename: file for saving
    :param childprocess: see :py:func:`grab`
    :param backend: see :py:func:`grab`


if childprocess is None:<EOL><INDENT>childprocess = childprocess_default_value()<EOL><DEDENT>if not childprocess:<EOL><INDENT>return _backend_version(backend)<EOL><DEDENT>else:<EOL><INDENT>return run_in_childprocess(_backend_version, None, backend)<EOL><DEDENT>

Back-end version.

    :param backend: back-end (examples:scrot, wx,..)
    :param childprocess: see :py:func:`grab`
    :return: version as string


return Loader().all_names<EOL>

Back-end names as a list.

    :return: back-ends as string list


if not isinstance(values, Iterable) or isinstance(values, (str, bytes)):<EOL><INDENT>raise TypeError("<STR_LIT>")<EOL><DEDENT>if isinstance(nb_class, float) and int(nb_class) == nb_class:<EOL><INDENT>nb_class = int(nb_class)<EOL><DEDENT>if not isinstance(nb_class, int):<EOL><INDENT>raise TypeError(<EOL>"<STR_LIT>"<EOL>"<STR_LIT>"<EOL>.format(type(nb_class)))<EOL><DEDENT>nb_values = len(values)<EOL>if np and isinstance(values, np.ndarray):<EOL><INDENT>values = values[np.argwhere(np.isfinite(values)).reshape(-<NUM_LIT:1>)]<EOL><DEDENT>else:<EOL><INDENT>values = [i for i in values if isfinite(i)]<EOL><DEDENT>if len(values) != nb_values:<EOL><INDENT>warnings.warn('<STR_LIT>')<EOL>nb_values = len(values)<EOL><DEDENT>if nb_class >= nb_values or nb_class < <NUM_LIT:2>:<EOL><INDENT>raise ValueError("<STR_LIT>"<EOL>"<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>return jenks._jenks_breaks(values, nb_class)<EOL>

Compute jenks natural breaks on a sequence of `values`, given `nb_class`,
the number of desired class.

Parameters
----------
values : array-like
    The Iterable sequence of numbers (integer/float) to be used.
nb_class : int
    The desired number of class (as some other functions requests
    a `k` value, `nb_class` is like `k` + 1). Have to be lesser than
    the length of `values` and greater than 2.

Returns
-------
breaks : tuple of floats
    The computed break values, including minimum and maximum, in order
    to have all the bounds for building `nb_class` class,
    so the returned tuple has a length of `nb_class` + 1.

Examples
--------
Using nb_class = 3, expecting 4 break values , including min and max :

>>> jenks_breaks(
        [1.3, 7.1, 7.3, 2.3, 3.9, 4.1, 7.8, 1.2, 4.3, 7.3, 5.0, 4.3],
        nb_class = 3)  # Should output (1.2, 2.3, 5.0, 7.8)


marker = self.markers.pop()<EOL>if reset:<EOL><INDENT>marker.extend(self.look_ahead)<EOL>self.look_ahead = marker<EOL><DEDENT>elif self.markers:<EOL><INDENT>self.markers[-<NUM_LIT:1>].extend(marker)<EOL><DEDENT>else:<EOL><INDENT>pass<EOL><DEDENT>

Pop a marker off of the marker stack. If reset is True then the
        iterator will be returned to the state it was in before the
        corresponding call to push_marker().


self.saved_markers.append(self.marker)<EOL>


self.markers.append(list())<EOL>


try:<EOL><INDENT>self.value = self.list[self.marker + i]<EOL><DEDENT>except IndexError:<EOL><INDENT>return self.default<EOL><DEDENT>return self.value<EOL>

Look ahead of the iterable by some number of values with advancing
        past them.

        If the requested look ahead is past the end of the iterable then None is
        returned.


saved = self.saved_markers.pop()<EOL>if reset:<EOL><INDENT>self.marker = saved<EOL><DEDENT>elif self.saved_markers:<EOL><INDENT>self.saved_markers[-<NUM_LIT:1>] = saved<EOL><DEDENT>


return (isinstance(self.tokens.look(i), Annotation)<EOL>and not self.tokens.look(i + <NUM_LIT:1>).value == '<STR_LIT>')<EOL>

Returns true if the position is the start of an annotation application
        (as opposed to an annotation declaration)


return (isinstance(self.tokens.look(i), Annotation)<EOL>and self.tokens.look(i + <NUM_LIT:1>).value == '<STR_LIT>')<EOL>


try:<EOL><INDENT>BLOCKSIZE = <NUM_LIT><EOL>hasher = hashlib.sha1()<EOL>with io.open(a_file, "<STR_LIT:rb>") as fh:<EOL><INDENT>buf = fh.read(BLOCKSIZE)<EOL>while len(buf) > <NUM_LIT:0>:<EOL><INDENT>hasher.update(buf)<EOL>buf = fh.read(BLOCKSIZE)<EOL><DEDENT><DEDENT>the_hash = hasher.hexdigest()<EOL><DEDENT>except IOError:<EOL><INDENT>errmes = "<STR_LIT>".format(a_file)<EOL>sys.stdout.write(errmes)<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>except:<EOL><INDENT>errmes = "<STR_LIT>"<EOL>sys.stdout.write(errmes)<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>return the_hash<EOL>

Returns sha1 hash of the file supplied as an argument


if sys.version_info[<NUM_LIT:0>] < <NUM_LIT:3>:<EOL><INDENT>fn_open = open<EOL><DEDENT>else:<EOL><INDENT>fn_open = io.open<EOL><DEDENT>with fn_open("<STR_LIT>", "<STR_LIT:w>") as fh:<EOL><INDENT>fh.write("<STR_LIT>")<EOL>fh.write('<STR_LIT>'.format(constants.VERSION))<EOL>if sha_dict:<EOL><INDENT>fh.write(yaml.dump(sha_dict))<EOL><DEDENT>fh.write("<STR_LIT>")<EOL><DEDENT>

Writes a sha1 dictionary stored in memory to
the .shastore file


def parallel_run_these(G, list_of_targets, in_mem_shas, from_store,<EOL>settings, dont_update_shas_of):

verbose = settings["<STR_LIT>"]<EOL>quiet = settings["<STR_LIT>"]<EOL>error = settings["<STR_LIT:error>"]<EOL>sprint = settings["<STR_LIT>"]<EOL>if len(list_of_targets) == <NUM_LIT:1>:<EOL><INDENT>target = list_of_targets[<NUM_LIT:0>]<EOL>sprint("<STR_LIT>".format(target),<EOL>level="<STR_LIT>")<EOL>run_the_target(G, target, settings)<EOL>node_dict = get_the_node_dict(G, target)<EOL>if "<STR_LIT>" in node_dict:<EOL><INDENT>for output in acts.get_all_outputs(node_dict):<EOL><INDENT>if output not in dont_update_shas_of:<EOL><INDENT>in_mem_shas['<STR_LIT>'][output] = {"<STR_LIT>": get_sha(output,<EOL>settings)}<EOL>in_mem_shas[output] = get_sha(output, settings)<EOL>write_shas_to_shastore(in_mem_shas)<EOL><DEDENT><DEDENT><DEDENT>if "<STR_LIT>" in node_dict:<EOL><INDENT>for dep in acts.get_all_dependencies(node_dict):<EOL><INDENT>if dep not in dont_update_shas_of:<EOL><INDENT>in_mem_shas['<STR_LIT>'][dep] = {"<STR_LIT>": get_sha(dep, settings)}<EOL>write_shas_to_shastore(in_mem_shas)<EOL><DEDENT><DEDENT><DEDENT>return True<EOL><DEDENT>a_failure_occurred = False<EOL>out = "<STR_LIT>"<EOL>sprint(out.format("<STR_LIT:U+002CU+0020>".join(list_of_targets)))<EOL>info = [(target, get_the_node_dict(G, target))<EOL>for target in list_of_targets]<EOL>commands = [item[<NUM_LIT:1>]['<STR_LIT>'].rstrip() for item in info]<EOL>if not quiet:<EOL><INDENT>procs = [Popen(command, shell=True) for command in commands]<EOL><DEDENT>else:<EOL><INDENT>procs = [Popen(command, shell=True, stdout=PIPE, stderr=PIPE)<EOL>for command in commands]<EOL><DEDENT>for index, process in enumerate(procs):<EOL><INDENT>if process.wait():<EOL><INDENT>error("<STR_LIT>".format(info[index][<NUM_LIT:0>]))<EOL>a_failure_occurred = True<EOL><DEDENT>else:<EOL><INDENT>if "<STR_LIT>" in info[index][<NUM_LIT:1>]:<EOL><INDENT>for output in acts.get_all_outputs(info[index][<NUM_LIT:1>]):<EOL><INDENT>if output not in dont_update_shas_of:<EOL><INDENT>in_mem_shas['<STR_LIT>'][output] = {"<STR_LIT>": get_sha(output,<EOL>settings)}<EOL>write_shas_to_shastore(in_mem_shas)<EOL><DEDENT><DEDENT><DEDENT>if "<STR_LIT>" in info[index][<NUM_LIT:1>]:<EOL><INDENT>for dep in acts.get_all_dependencies(info[index][<NUM_LIT:1>]):<EOL><INDENT>if dep not in dont_update_shas_of:<EOL><INDENT>in_mem_shas['<STR_LIT>'][dep] = {"<STR_LIT>": get_sha(dep, settings)}<EOL>write_shas_to_shastore(in_mem_shas)<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>if a_failure_occurred:<EOL><INDENT>error("<STR_LIT>")<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>return True<EOL>

The parallel equivalent of "run_this_target()"
It receives a list of targets to execute in parallel.
Unlike "run_this_target()" it has to update the shas
(in memory and in the store) within the function.
This is because one of the targets may fail but many can
succeed, and those outputs need to be updated

Args:
    G
    A graph
    A list of targets that we need to build in parallel
    The dictionary containing the in-memory sha store
    The dictionary containing the contents of the .shastore file
    The settings dictionary
    A list of outputs to not update shas of


sprint = settings["<STR_LIT>"]<EOL>quiet = settings["<STR_LIT>"]<EOL>error = settings["<STR_LIT:error>"]<EOL>enhanced_errors = True<EOL>the_shell = None<EOL>if settings["<STR_LIT>"]:<EOL><INDENT>enhanced_errors = False<EOL><DEDENT>if "<STR_LIT>" in settings:<EOL><INDENT>the_shell = settings["<STR_LIT>"]<EOL><DEDENT>windows_p = sys.platform == "<STR_LIT:win32>"<EOL>STDOUT = None<EOL>STDERR = None<EOL>if quiet:<EOL><INDENT>STDOUT = PIPE<EOL>STDERR = PIPE<EOL><DEDENT>commands = commands.rstrip()<EOL>sprint("<STR_LIT>".format(commands), level="<STR_LIT>")<EOL>if not quiet:<EOL><INDENT>sprint(commands)<EOL><DEDENT>if the_shell:<EOL><INDENT>tmp = shlex.split(the_shell)<EOL>the_shell = tmp[<NUM_LIT:0>]<EOL>tmp = tmp[<NUM_LIT:1>:]<EOL>if enhanced_errors and not windows_p:<EOL><INDENT>tmp.append("<STR_LIT>")<EOL><DEDENT>tmp.append(commands)<EOL>commands = tmp<EOL><DEDENT>else:<EOL><INDENT>if enhanced_errors and not windows_p:<EOL><INDENT>commands = ["<STR_LIT>", commands]<EOL><DEDENT><DEDENT>p = Popen(commands, shell=True, stdout=STDOUT, stderr=STDERR,<EOL>executable=the_shell)<EOL>out, err = p.communicate()<EOL>if p.returncode:<EOL><INDENT>if quiet:<EOL><INDENT>error(err.decode(locale.getpreferredencoding()))<EOL><DEDENT>error("<STR_LIT>")<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>

Runs the commands supplied as an argument
It will exit the program if the commands return a
non-zero code

Args:
    the commands to run
    The settings dictionary


parents = []<EOL>for item in list_of_nodes:<EOL><INDENT>anc = G.predecessors(item)<EOL>for one in anc:<EOL><INDENT>parents.append(one)<EOL><DEDENT><DEDENT>return parents<EOL>

Returns a list of nodes that are the parents
from all of the nodes given as an argument.
This is for use in the parallel topo sort


if settings:<EOL><INDENT>error = settings["<STR_LIT:error>"]<EOL><DEDENT>else:<EOL><INDENT>error = ERROR_FN<EOL><DEDENT>try:<EOL><INDENT>BLOCKSIZE = <NUM_LIT><EOL>hasher = hashlib.sha1()<EOL>with io.open(a_file, "<STR_LIT:rb>") as fh:<EOL><INDENT>buf = fh.read(BLOCKSIZE)<EOL>while len(buf) > <NUM_LIT:0>:<EOL><INDENT>hasher.update(buf)<EOL>buf = fh.read(BLOCKSIZE)<EOL><DEDENT><DEDENT>the_hash = hasher.hexdigest()<EOL><DEDENT>except IOError:<EOL><INDENT>errmes = "<STR_LIT>".format(a_file)<EOL>error(errmes)<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>except:<EOL><INDENT>errmes = "<STR_LIT>"<EOL>error(errmes)<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>return the_hash<EOL>


for node in G.nodes(data=True):<EOL><INDENT>if node[<NUM_LIT:0>] == name:<EOL><INDENT>return node[<NUM_LIT:1>]<EOL><DEDENT><DEDENT>

Helper function that returns the node data
of the node with the name supplied


sprint = settings["<STR_LIT>"]<EOL>error = settings["<STR_LIT:error>"]<EOL>sprint("<STR_LIT>", level="<STR_LIT>")<EOL>if not sakefile:<EOL><INDENT>error("<STR_LIT>")<EOL>return False<EOL><DEDENT>if len(sakefile.keys()) != len(set(sakefile.keys())):<EOL><INDENT>error("<STR_LIT>")<EOL>return False<EOL><DEDENT>for target in sakefile:<EOL><INDENT>if target == "<STR_LIT:all>":<EOL><INDENT>if not check_target_integrity(target, sakefile["<STR_LIT:all>"], all=True):<EOL><INDENT>error("<STR_LIT>")<EOL>return False<EOL><DEDENT>continue<EOL><DEDENT>if "<STR_LIT>" not in sakefile[target]:<EOL><INDENT>if not check_target_integrity(target, sakefile[target],<EOL>meta=True):<EOL><INDENT>errmes = "<STR_LIT>".format(target)<EOL>error(errmes)<EOL>return False<EOL><DEDENT>for atom_target in sakefile[target]:<EOL><INDENT>if atom_target == "<STR_LIT>":<EOL><INDENT>continue<EOL><DEDENT>if not check_target_integrity(atom_target,<EOL>sakefile[target][atom_target],<EOL>parent=target):<EOL><INDENT>errmes = "<STR_LIT>".format(<EOL>atom_target)<EOL>error(errmes)<EOL>return False<EOL><DEDENT><DEDENT>continue<EOL><DEDENT>if not check_target_integrity(target, sakefile[target]):<EOL><INDENT>errmes = "<STR_LIT>".format(target)<EOL>error(errmes)<EOL>return False<EOL><DEDENT><DEDENT>return True<EOL>

Checks the format of the sakefile dictionary
to ensure it conforms to specification

Args:
    A dictionary that is the parsed Sakefile (from sake.py)
    The setting dictionary (for print functions)
Returns:
    True if the Sakefile is conformant
    False if not


verbose = settings["<STR_LIT>"]<EOL>def sprint(message, level=None, color=False):<EOL><INDENT>if level=="<STR_LIT>" and not verbose:<EOL><INDENT>return<EOL><DEDENT>prepend = "<STR_LIT>"<EOL>postfix = "<STR_LIT>"<EOL>if settings["<STR_LIT>"] and color:<EOL><INDENT>prepend = "<STR_LIT>"<EOL>postfix = "<STR_LIT>"<EOL><DEDENT>print("<STR_LIT>".format(prepend, message, postfix))<EOL>sys.stdout.flush()<EOL><DEDENT>def warn(message, level=None, color=True):<EOL><INDENT>if level=="<STR_LIT>" and not verbose:<EOL><INDENT>return<EOL><DEDENT>prepend = "<STR_LIT>"<EOL>postfix = "<STR_LIT>"<EOL>if settings["<STR_LIT>"] and color:<EOL><INDENT>prepend = "<STR_LIT>"<EOL>postfix = "<STR_LIT>"<EOL><DEDENT>print("<STR_LIT>".format(prepend, message, postfix))<EOL>sys.stdout.flush()<EOL><DEDENT>def error(message, level=None, color=True):<EOL><INDENT>if level=="<STR_LIT>" and not verbose:<EOL><INDENT>return<EOL><DEDENT>prepend = "<STR_LIT>"<EOL>postfix = "<STR_LIT>"<EOL>if settings["<STR_LIT>"] and color:<EOL><INDENT>prepend = "<STR_LIT>"<EOL>postfix = "<STR_LIT>"<EOL><DEDENT>print("<STR_LIT>".format(prepend, message, postfix), file=sys.stderr)<EOL>sys.stderr.flush()<EOL><DEDENT>return sprint, warn, error<EOL>

This returns the appropriate print functions
in a tuple
The print function are:
    - sprint - for standard printing
    - warn - for warnings
    - error - for errors
This will all be the same if color is False.

The returned print functions will contain an optional parameter
that specifies the output level (verbose or not). If not verbose,
the print function will ignore the message.


<EOL>ties = []<EOL>dep_dict = {}<EOL>for node in G.nodes(data=True):<EOL><INDENT>if '<STR_LIT>' in node[<NUM_LIT:1>]:<EOL><INDENT>for item in node[<NUM_LIT:1>]['<STR_LIT>']:<EOL><INDENT>if item not in dep_dict:<EOL><INDENT>dep_dict[item] = []<EOL><DEDENT>dep_dict[item].append(node[<NUM_LIT:0>])<EOL><DEDENT><DEDENT><DEDENT>for item in dep_dict:<EOL><INDENT>if len(list(set(dep_dict[item]))) > <NUM_LIT:1>:<EOL><INDENT>ties.append(list(set(dep_dict[item])))<EOL><DEDENT><DEDENT>return ties<EOL>

If you specify a target that shares a dependency with another target,
both targets need to be updated. This is because running one will resolve
the sha mismatch and sake will think that the other one doesn't have to
run. This is called a "tie". This function will find such ties.


def check_for_dep_in_outputs(dep, verbose, G):

if verbose:<EOL><INDENT>print("<STR_LIT>".format(dep))<EOL><DEDENT>ret_list = []<EOL>for node in G.nodes(data=True):<EOL><INDENT>if "<STR_LIT>" not in node[<NUM_LIT:1>]:<EOL><INDENT>continue<EOL><DEDENT>for out in node[<NUM_LIT:1>]['<STR_LIT>']:<EOL><INDENT>if fnmatch.fnmatch(out, dep):<EOL><INDENT>ret_list.append(node[<NUM_LIT:0>])<EOL>break<EOL><DEDENT><DEDENT><DEDENT>return ret_list<EOL>

Function to help construct_graph() identify dependencies

Args:
    A dependency
    A flag indication verbosity
    A (populated) NetworkX DiGraph

Returns:
    A list of targets that build given dependency


outlist = []<EOL>for item in node_dict['<STR_LIT>']:<EOL><INDENT>glist = glob.glob(item)<EOL>if glist:<EOL><INDENT>for oneglob in glist:<EOL><INDENT>outlist.append(oneglob)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>outlist.append(item)<EOL><DEDENT><DEDENT>return outlist<EOL>

This function takes a node dictionary and returns a list of
the node's output files. Some of the entries in the 'output'
attribute may be globs, and without this function, sake won't
know how to handle that. This will unglob all globs and return
the true list of *all* outputs.


def visualize(G, settings, filename="<STR_LIT>", no_graphviz=False):

error = settings["<STR_LIT:error>"]<EOL>if no_graphviz:<EOL><INDENT>write_dot_file(G, filename)<EOL>return <NUM_LIT:0><EOL><DEDENT>write_dot_file(G, "<STR_LIT>")<EOL>renderer = "<STR_LIT>"<EOL>if re.search("<STR_LIT>", filename, re.IGNORECASE):<EOL><INDENT>renderer = "<STR_LIT>"<EOL><DEDENT>elif re.search("<STR_LIT>", filename, re.IGNORECASE):<EOL><INDENT>renderer = "<STR_LIT>"<EOL><DEDENT>elif re.search("<STR_LIT>", filename, re.IGNORECASE):<EOL><INDENT>renderer = "<STR_LIT>"<EOL><DEDENT>elif re.search("<STR_LIT>", filename, re.IGNORECASE):<EOL><INDENT>renderer = "<STR_LIT>"<EOL><DEDENT>elif re.search("<STR_LIT>", filename, re.IGNORECASE):<EOL><INDENT>renderer = "<STR_LIT>"<EOL><DEDENT>elif re.search("<STR_LIT>", filename, re.IGNORECASE):<EOL><INDENT>renderer = "<STR_LIT>"<EOL><DEDENT>elif re.search("<STR_LIT>", filename, re.IGNORECASE):<EOL><INDENT>renderer = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>renderer = "<STR_LIT>"<EOL>filename += "<STR_LIT>"<EOL><DEDENT>command = "<STR_LIT>".format(renderer, filename)<EOL>p = Popen(command, shell=True)<EOL>p.communicate()<EOL>if p.returncode:<EOL><INDENT>errmes = "<STR_LIT>"<EOL>os.remove("<STR_LIT>")<EOL>error(errmes)<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>os.remove("<STR_LIT>")<EOL>return <NUM_LIT:0><EOL>

Uses networkX to draw a graphviz dot file either (a) calls the
graphviz command "dot" to turn it into a SVG and remove the
dotfile (default), or (b) if no_graphviz is True, just output
the graphviz dot file

Args:
    a NetworkX DiGraph
    the settings dictionary
    a filename (a default is provided
    a flag indicating whether graphviz should *not* be called

Returns:
    0 if everything worked
    will cause fatal error on failure


quiet = settings["<STR_LIT>"]<EOL>recon = settings["<STR_LIT>"]<EOL>sprint = settings["<STR_LIT>"]<EOL>error = settings["<STR_LIT:error>"]<EOL>all_outputs = []<EOL>for node in G.nodes(data=True):<EOL><INDENT>if "<STR_LIT>" in node[<NUM_LIT:1>]:<EOL><INDENT>for item in get_all_outputs(node[<NUM_LIT:1>]):<EOL><INDENT>all_outputs.append(item)<EOL><DEDENT><DEDENT><DEDENT>all_outputs.append("<STR_LIT>")<EOL>retcode = <NUM_LIT:0><EOL>for item in sorted(all_outputs):<EOL><INDENT>if os.path.isfile(item):<EOL><INDENT>if recon:<EOL><INDENT>sprint("<STR_LIT>".format(item))<EOL>continue<EOL><DEDENT>sprint("<STR_LIT>", level="<STR_LIT>")<EOL>try:<EOL><INDENT>os.remove(item)<EOL>sprint("<STR_LIT>", level="<STR_LIT>")<EOL><DEDENT>except:<EOL><INDENT>errmes = "<STR_LIT>"<EOL>error(errmes.format(item))<EOL>retcode = <NUM_LIT:1><EOL><DEDENT><DEDENT><DEDENT>if not retcode and not recon:<EOL><INDENT>sprint("<STR_LIT>", color=True)<EOL><DEDENT>return retcode<EOL>

Removes all the output files from all targets. Takes
the graph as the only argument

Args:
    The networkx graph object
    The settings dictionary

Returns:
    0 if successful
    1 if removing even one file failed


macros = {}<EOL>for arg in args:<EOL><INDENT>try:<EOL><INDENT>var, val = arg.split('<STR_LIT:=>', <NUM_LIT:1>)<EOL><DEDENT>except ValueError:<EOL><INDENT>var = arg<EOL>val = '<STR_LIT:1>'<EOL><DEDENT>macros[var] = val<EOL><DEDENT>return macros<EOL>

This parses a list of define argument in the form of -DNAME=VALUE or -DNAME (
which is treated as -DNAME=1).


with io.open(filename, "<STR_LIT:w>") as fh:<EOL><INDENT>fh.write("<STR_LIT>")<EOL>edge_list = G.edges()<EOL>node_list = set(G.nodes())<EOL>if edge_list:<EOL><INDENT>for edge in sorted(edge_list):<EOL><INDENT>source, targ = edge<EOL>node_list = node_list - set(source)<EOL>node_list = node_list - set(targ)<EOL>line = '<STR_LIT>'<EOL>fh.write(line.format(source, targ))<EOL><DEDENT><DEDENT>if node_list:<EOL><INDENT>for node in sorted(node_list):<EOL><INDENT>line = '<STR_LIT>'.format(node)<EOL>fh.write(line)<EOL><DEDENT><DEDENT>fh.write("<STR_LIT:}>")<EOL><DEDENT>

Writes the graph G in dot file format for graphviz visualization.

Args:
    a Networkx graph
    A filename to name the dot files


def clean_path(a_path, force_os=None, force_start=None):

if not force_start:<EOL><INDENT>force_start = os.curdir<EOL><DEDENT>if force_os == "<STR_LIT>":<EOL><INDENT>import ntpath<EOL>return ntpath.relpath(ntpath.normpath(a_path),<EOL>start=force_start)<EOL><DEDENT>if force_os == "<STR_LIT>":<EOL><INDENT>import posixpath<EOL>return posixpath.relpath(posixpath.normpath(a_path),<EOL>start=force_start)<EOL><DEDENT>return os.path.relpath(os.path.normpath(a_path),<EOL>start=force_start)<EOL>

This function is used to normalize the path (of an output or
dependency) and also provide the path in relative form. It is
relative to the current working directory


full_string = "<STR_LIT>"<EOL>errmes = "<STR_LIT>"<EOL>outerlines = []<EOL>for target in sakefile:<EOL><INDENT>if target == "<STR_LIT:all>":<EOL><INDENT>continue<EOL><DEDENT>middle_lines = []<EOL>if "<STR_LIT>" not in sakefile[target]:<EOL><INDENT>innerstr = "<STR_LIT>".format(escp(target),<EOL>sakefile[target]["<STR_LIT>"])<EOL>inner = []<EOL>for atom_target in sakefile[target]:<EOL><INDENT>if atom_target == "<STR_LIT>":<EOL><INDENT>continue<EOL><DEDENT>inner.append("<STR_LIT>".format(escp(atom_target),<EOL>sakefile[target][atom_target]["<STR_LIT>"]))<EOL><DEDENT>if inner:<EOL><INDENT>innerstr += '<STR_LIT:\n>'.join(sorted(inner))<EOL><DEDENT>middle_lines.append(innerstr)<EOL><DEDENT>else:<EOL><INDENT>middle_lines.append("<STR_LIT>".format(escp(target),<EOL>sakefile[target]["<STR_LIT>"]))<EOL><DEDENT>if middle_lines:<EOL><INDENT>outerlines.append('<STR_LIT:\n>'.join(sorted(middle_lines)))<EOL><DEDENT><DEDENT>if outerlines:<EOL><INDENT>full_string += '<STR_LIT:\n>'.join(sorted(outerlines))<EOL><DEDENT>what_clean_does = "<STR_LIT>"<EOL>full_string += "<STR_LIT>".format(what_clean_does)<EOL>what_visual_does = "<STR_LIT>"<EOL>full_string += "<STR_LIT>".format(what_visual_does)<EOL>full_string = re.sub("<STR_LIT>", "<STR_LIT>", full_string)<EOL>return full_string<EOL>

Returns the prettily formatted help strings (for printing)

Args:
    A dictionary that is the parsed Sakefile (from sake.py)

NOTE:
    the list sorting in this function is required for this
    function to be deterministic


includes = {}<EOL>result = []<EOL>pattern = re.compile("<STR_LIT>", re.UNICODE)<EOL>ipattern = re.compile("<STR_LIT>", re.UNICODE)<EOL>for line in raw_text.split("<STR_LIT:\n>"):<EOL><INDENT>line = string.Template(line).safe_substitute(macros)<EOL>result.append(line)<EOL>if line.startswith("<STR_LIT>"):<EOL><INDENT>match = pattern.match(line)<EOL>try:<EOL><INDENT>var, opt, val, or_ = match.group(<NUM_LIT:1>, <NUM_LIT:2>, <NUM_LIT:3>, <NUM_LIT:4>)<EOL><DEDENT>except:<EOL><INDENT>raise InvalidMacroError("<STR_LIT>".format(line))<EOL><DEDENT>if or_:<EOL><INDENT>if var not in macros:<EOL><INDENT>raise InvalidMacroError("<STR_LIT>".format(var, or_))<EOL><DEDENT><DEDENT>elif not (opt and var in macros):<EOL><INDENT>macros[var] = val<EOL><DEDENT><DEDENT>elif line.startswith("<STR_LIT>"):<EOL><INDENT>match = ipattern.match(line)<EOL>try:<EOL><INDENT>filename = match.group(<NUM_LIT:1>)<EOL><DEDENT>except:<EOL><INDENT>error("<STR_LIT>".format(line))<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT>try:<EOL><INDENT>with io.open(filename, '<STR_LIT:r>') as f:<EOL><INDENT>includes[filename] = expand_macros(f.read(), macros)<EOL><DEDENT><DEDENT>except IOError:<EOL><INDENT>if match.group(<NUM_LIT:2>):<EOL><INDENT>if match.group(<NUM_LIT:2>).startswith('<STR_LIT>'):<EOL><INDENT>sprint(match.group(<NUM_LIT:3>))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>error("<STR_LIT>".format(filename))<EOL>sys.exit(<NUM_LIT:1>)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>return "<STR_LIT:\n>".join(result), includes<EOL>

this gets called before the sakefile is parsed. it looks for
macros defined anywhere in the sakefile (the start of the line
is '#!') and then replaces all occurences of '$variable' with the
value defined in the macro. it then returns the contents of the
file with the macros expanded.


return self['<STR_LIT>']<EOL>

Returns the name of the data associated with the mapper.


return self['<STR_LIT>']<EOL>

Returns a list with all keys which are supported by the mapper.


return self._name<EOL>


def io_mode(ID_s):<EOL><INDENT>'''<STR_LIT>'''<EOL>unlist_return = False<EOL>list_of_lists = False<EOL>if isinstance(ID_s, str):<EOL><INDENT>ID_s = [ID_s]<EOL>unlist_return = True<EOL><DEDENT>elif isinstance(ID_s, list):<EOL><INDENT>if len(ID_s) > <NUM_LIT:0> and isinstance(ID_s[<NUM_LIT:0>], list):<EOL><INDENT>list_of_lists = True<EOL><DEDENT><DEDENT>return ID_s, unlist_return, list_of_lists<EOL><DEDENT>if FROM == TO:<EOL><INDENT>return ID_s<EOL><DEDENT>ID_s, unlist_return, list_of_lists = io_mode(ID_s)<EOL>if list_of_lists:<EOL><INDENT>mapped_ids = [self.map(ID, FROM, TO, target_as_set, no_match_sub) for ID in ID_s]<EOL><DEDENT>else:<EOL><INDENT>mapped_ids = self._map(ID_s, FROM, TO, target_as_set, no_match_sub)<EOL><DEDENT>if unlist_return:<EOL><INDENT>return mapped_ids[<NUM_LIT:0>]<EOL><DEDENT>return Mapping(ID_s, mapped_ids)<EOL>

The main method of this class and the essence of the package.
It allows to "map" stuff.

Args:

    ID_s: Nested lists with strings as leafs (plain strings also possible)
    FROM (str): Origin key for the mapping (default: main key)
    TO (str): Destination key for the mapping (default: main key)
    target_as_set (bool): Whether to summarize the output as a set (removes duplicates)
    no_match_sub: Object representing the status of an ID not being able to be matched
                  (default: None)

Returns:

    Mapping: a mapping object capturing the result of the mapping request


return self.get('<STR_LIT>', [])<EOL>

Returns a list of supported keys whose values are
list of strings.


return self.get('<STR_LIT>', [])<EOL>

Returns all list-values keys for which it is assured
that for any two values of that key the set of the
entries of that value are disjoint (do not have an
element in common).


return self['<STR_LIT:name>']<EOL>


pass<EOL>

Backend-specific implementation of Mapper.get_all.


return self._definition<EOL>