<reponame>michi7x7/python-deltasigma<filename>deltasigma/_synthesizeChebyshevNTF.py
# -*- coding: utf-8 -*-
# _synthesizeChebyshevNTF.py
# Module providing the synthesizeChebyshevNTF function
# Copyright 2013 <NAME>
# This file is part of python-deltasigma.
#
# python-deltasigma is a 1:1 Python replacement of Richard Schreier's
# MATLAB delta sigma toolbox (aka "delsigma"), upon which it is heavily based.
# The delta sigma toolbox is (c) 2009, <NAME>.
#
# python-deltasigma is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# LICENSE file for the licensing terms.

"""Module providing the synthesizeChebyshevNTF() function
"""

from __future__ import division

from warnings import warn

import numpy as np
from scipy.signal import cheby2

from ._ds_f1f2 import ds_f1f2


def synthesizeChebyshevNTF(order=3, OSR=64, opt=0, H_inf=1.5, f0=0.):
    """Synthesize a noise transfer function for a delta-sigma modulator.

    The NTF is a type-2 highpass Chebyshev function.

    :func:`synthesizeNTF` assumes that magnitude of the denominator of the NTF
    is approximately constant in the passband. When the OSR or ``H_inf`` are
    low, this assumption breaks down and :func:`synthesizeNTF` yields a
    non-optimal NTF. :func:`synthesizeChebyshevNTF` creates non-optimal NTFs, but fares
    better than :func:`synthesizeNTF` in the aforementioned circumstances.

    **Parameters:**

    order : int, optional
        order of the modulator, defaults to 3

    OSR : int, optional
        oversampling ratio, defaults to 64

    opt : int, optional
        ignored value, for consistency with :func:`synthesizeNTF`

    H_inf : float, optional
        maximum NTF gain, defaults to 1.5

    f0 : float, optional
        center frequency (1->fs), defaults to 0.

    **Returns:**

    z, p, k : tuple
        a zpk tuple containing the zeros and poles of the NTF.

    **Warns:**

    * If a non-zero value is passed for ``opt``.

    **Raises:**

    * ValueError: Order must be even for a bandpass modulator.

    **Example:**

    Compare the NTFs created by :func:`synthesizeNTF` and
    :func:`synthesizeChebyshevNTF` when ``OSR`` is low::

        OSR = 4
        order = 8
        H_inf = 3
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)

    .. plot::

        import pylab as plt
        import numpy as np
        from deltasigma import *
        OSR = 4
        order = 8
        H_inf = 3
        plt.figure(figsize=(12,6))
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)
        # 1. Plot the singularities.
        plt.subplot(121)
        # we plot the singularities of the optimized NTF in light
        # green with slightly bigger markers so that we can better
        # distinguish the two NTF's when overlayed.
        plotPZ(H1, markersize=7, color='#90EE90')
        plt.hold(True)
        plotPZ(H0, markersize=5)
        plt.title('NTF Poles and Zeros')
        f = np.concatenate((np.linspace(0, 0.75/OSR, 100), np.linspace(0.75/OSR, 0.5, 100)))
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        # 2. Plot the magnitude responses.
        plt.subplot(222)
        plt.plot(f, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.plot(f, magH1, label='synthesizeChebyshevNTF')
        figureMagic([0, 0.5], 0.05, None, [-80, 20], 10, None)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_s)$')
        plt.ylabel('dB')
        plt.legend(loc=4)
        plt.title('NTF Magnitude Response')
        # 3. Plot the magnitude responses in the signal band.
        plt.subplot(224)
        fstart = 0.01
        f = np.linspace(fstart, 1.2, 200)/(2*OSR)
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        plt.semilogx(f*2*OSR, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.semilogx(f*2*OSR, magH1, label='synthesizeChebyshevNTF')
        plt.axis([fstart, 1, -50, 0])
        plt.grid(True)
        sigma_H0 = dbv(rmsGain(H0, 0, 0.5/OSR))
        sigma_H1 = dbv(rmsGain(H1, 0, 0.5/OSR))
        plt.semilogx([fstart, 1], sigma_H0*np.array([1, 1]), linewidth=3, color='#191970')
        plt.text(0.15, sigma_H0 + 1.5, 'RMS gain = %5.0fdB' % sigma_H0)
        plt.semilogx([fstart, 1], sigma_H1*np.array([1, 1]), linewidth=3, color='#228B22')
        plt.text(0.15, sigma_H1 + 1.5, 'RMS gain = %5.0fdB' % sigma_H1)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_B$)')
        plt.ylabel('dB')
        plt.legend(loc=3)
        plt.tight_layout()

    Repeat for ``H_inf`` low::

        OSR = 32
        order = 5
        H_inf = 1.2
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)

    .. plot::

        import pylab as plt
        import numpy as np
        from deltasigma import *
        OSR = 32
        order = 5
        H_inf = 1.2
        plt.figure(figsize=(12,6))
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)
        # 1. Plot the singularities.
        plt.subplot(121)
        # we plot the singularities of the optimized NTF in light
        # green with slightly bigger markers so that we can better
        # distinguish the two NTF's when overlayed.
        plotPZ(H1, markersize=7, color='#90EE90')
        plt.hold(True)
        plotPZ(H0, markersize=5)
        plt.title('NTF Poles and Zeros')
        f = np.concatenate((np.linspace(0, 0.75/OSR, 100), np.linspace(0.75/OSR, 0.5, 100)))
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        # 2. Plot the magnitude responses.
        plt.subplot(222)
        plt.plot(f, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.plot(f, magH1, label='synthesizeChebyshevNTF')
        figureMagic([0, 0.5], 0.05, None, [-80, 20], 10, None)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_s)$')
        plt.ylabel('dB')
        plt.legend(loc=4)
        plt.title('NTF Magnitude Response')
        # 3. Plot the magnitude responses in the signal band.
        plt.subplot(224)
        fstart = 0.01
        f = np.linspace(fstart, 1.2, 200)/(2*OSR)
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        plt.semilogx(f*2*OSR, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.semilogx(f*2*OSR, magH1, label='synthesizeChebyshevNTF')
        plt.axis([fstart, 1, -60, -20])
        plt.grid(True)
        sigma_H0 = dbv(rmsGain(H0, 0, 0.5/OSR))
        sigma_H1 = dbv(rmsGain(H1, 0, 0.5/OSR))
        plt.semilogx([fstart, 1], sigma_H0*np.array([1, 1]), linewidth=3, color='#191970')
        plt.text(0.15, sigma_H0 + 1.5, 'RMS gain = %5.0fdB' % sigma_H0)
        plt.semilogx([fstart, 1], sigma_H1*np.array([1, 1]), linewidth=3, color='#228B22')
        plt.text(0.15, sigma_H1 + 1.5, 'RMS gain = %5.0fdB' % sigma_H1)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_B$)')
        plt.ylabel('dB')
        plt.legend(loc=3)
        plt.tight_layout()

    """
    if opt:
        warn("Got a non-zero 'opt' value. Not such optimization is " + \
             "available, opt is only meant to ease switching between " + \
             "synthesizeNTF and synthesizeChebyshevNTF.")
    if f0 != 0:
        if order % 2 != 0:
            raise ValueError('Order must be even for a bandpass modulator.')
        else:
            f1, f2 = ds_f1f2(OSR, f0)
            f1f2 = np.array([f1, f2])
    x_min = 0
    x_max = 300
    dx_max = 10
    ftol = 1e-06
    xtol = 1e-06
    x = 60
    f_p = None # will be redefined later
    itn_limit = 10
    converged = False
    for itn in range(itn_limit):
        if f0 == 0:
            z, p, k = cheby2(order, x, 1./OSR, btype='high', output='zpk')
        else:
            z, p, k = cheby2(order/2., x, 2.*f1f2, btype='stop', output='zpk')
        f = 1./k - H_inf
        if f > 0:
            x_max = x
        else:
            x_min = x
        if itn == 0:
            dx = -dx_max*np.sign(f)
        else:
            df = f - f_p
            if abs(df) < ftol:
                converged = True
                break
            dx = -f*dx/df
        x_p = x
        f_p = f
        x = max(x_min, min(x + dx, x_max))
        dx = x - x_p
        if abs(dx) < xtol:
            break
    ntf = (z, p, 1)
    return ntf

# -*- coding: utf-8 -*-
# _synthesizeChebyshevNTF.py
# Module providing the synthesizeChebyshevNTF function
# Copyright 2013 <NAME>
# This file is part of python-deltasigma.
#
# python-deltasigma is a 1:1 Python replacement of Richard Schreier's
# MATLAB delta sigma toolbox (aka "delsigma"), upon which it is heavily based.
# The delta sigma toolbox is (c) 2009, <NAME>.
#
# python-deltasigma is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# LICENSE file for the licensing terms.

"""Module providing the synthesizeChebyshevNTF() function
"""

from __future__ import division

from warnings import warn

import numpy as np
from scipy.signal import cheby2

from ._ds_f1f2 import ds_f1f2


def synthesizeChebyshevNTF(order=3, OSR=64, opt=0, H_inf=1.5, f0=0.):
    """Synthesize a noise transfer function for a delta-sigma modulator.

    The NTF is a type-2 highpass Chebyshev function.

    :func:`synthesizeNTF` assumes that magnitude of the denominator of the NTF
    is approximately constant in the passband. When the OSR or ``H_inf`` are
    low, this assumption breaks down and :func:`synthesizeNTF` yields a
    non-optimal NTF. :func:`synthesizeChebyshevNTF` creates non-optimal NTFs, but fares
    better than :func:`synthesizeNTF` in the aforementioned circumstances.

    **Parameters:**

    order : int, optional
        order of the modulator, defaults to 3

    OSR : int, optional
        oversampling ratio, defaults to 64

    opt : int, optional
        ignored value, for consistency with :func:`synthesizeNTF`

    H_inf : float, optional
        maximum NTF gain, defaults to 1.5

    f0 : float, optional
        center frequency (1->fs), defaults to 0.

    **Returns:**

    z, p, k : tuple
        a zpk tuple containing the zeros and poles of the NTF.

    **Warns:**

    * If a non-zero value is passed for ``opt``.

    **Raises:**

    * ValueError: Order must be even for a bandpass modulator.

    **Example:**

    Compare the NTFs created by :func:`synthesizeNTF` and
    :func:`synthesizeChebyshevNTF` when ``OSR`` is low::

        OSR = 4
        order = 8
        H_inf = 3
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)

    .. plot::

        import pylab as plt
        import numpy as np
        from deltasigma import *
        OSR = 4
        order = 8
        H_inf = 3
        plt.figure(figsize=(12,6))
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)
        # 1. Plot the singularities.
        plt.subplot(121)
        # we plot the singularities of the optimized NTF in light
        # green with slightly bigger markers so that we can better
        # distinguish the two NTF's when overlayed.
        plotPZ(H1, markersize=7, color='#90EE90')
        plt.hold(True)
        plotPZ(H0, markersize=5)
        plt.title('NTF Poles and Zeros')
        f = np.concatenate((np.linspace(0, 0.75/OSR, 100), np.linspace(0.75/OSR, 0.5, 100)))
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        # 2. Plot the magnitude responses.
        plt.subplot(222)
        plt.plot(f, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.plot(f, magH1, label='synthesizeChebyshevNTF')
        figureMagic([0, 0.5], 0.05, None, [-80, 20], 10, None)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_s)$')
        plt.ylabel('dB')
        plt.legend(loc=4)
        plt.title('NTF Magnitude Response')
        # 3. Plot the magnitude responses in the signal band.
        plt.subplot(224)
        fstart = 0.01
        f = np.linspace(fstart, 1.2, 200)/(2*OSR)
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        plt.semilogx(f*2*OSR, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.semilogx(f*2*OSR, magH1, label='synthesizeChebyshevNTF')
        plt.axis([fstart, 1, -50, 0])
        plt.grid(True)
        sigma_H0 = dbv(rmsGain(H0, 0, 0.5/OSR))
        sigma_H1 = dbv(rmsGain(H1, 0, 0.5/OSR))
        plt.semilogx([fstart, 1], sigma_H0*np.array([1, 1]), linewidth=3, color='#191970')
        plt.text(0.15, sigma_H0 + 1.5, 'RMS gain = %5.0fdB' % sigma_H0)
        plt.semilogx([fstart, 1], sigma_H1*np.array([1, 1]), linewidth=3, color='#228B22')
        plt.text(0.15, sigma_H1 + 1.5, 'RMS gain = %5.0fdB' % sigma_H1)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_B$)')
        plt.ylabel('dB')
        plt.legend(loc=3)
        plt.tight_layout()

    Repeat for ``H_inf`` low::

        OSR = 32
        order = 5
        H_inf = 1.2
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)

    .. plot::

        import pylab as plt
        import numpy as np
        from deltasigma import *
        OSR = 32
        order = 5
        H_inf = 1.2
        plt.figure(figsize=(12,6))
        H0 = synthesizeNTF(order, OSR, 1, H_inf)
        H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)
        # 1. Plot the singularities.
        plt.subplot(121)
        # we plot the singularities of the optimized NTF in light
        # green with slightly bigger markers so that we can better
        # distinguish the two NTF's when overlayed.
        plotPZ(H1, markersize=7, color='#90EE90')
        plt.hold(True)
        plotPZ(H0, markersize=5)
        plt.title('NTF Poles and Zeros')
        f = np.concatenate((np.linspace(0, 0.75/OSR, 100), np.linspace(0.75/OSR, 0.5, 100)))
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        # 2. Plot the magnitude responses.
        plt.subplot(222)
        plt.plot(f, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.plot(f, magH1, label='synthesizeChebyshevNTF')
        figureMagic([0, 0.5], 0.05, None, [-80, 20], 10, None)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_s)$')
        plt.ylabel('dB')
        plt.legend(loc=4)
        plt.title('NTF Magnitude Response')
        # 3. Plot the magnitude responses in the signal band.
        plt.subplot(224)
        fstart = 0.01
        f = np.linspace(fstart, 1.2, 200)/(2*OSR)
        z = np.exp(2j*np.pi*f)
        magH0 = dbv(evalTF(H0, z))
        magH1 = dbv(evalTF(H1, z))
        plt.semilogx(f*2*OSR, magH0, label='synthesizeNTF')
        plt.hold(True)
        plt.semilogx(f*2*OSR, magH1, label='synthesizeChebyshevNTF')
        plt.axis([fstart, 1, -60, -20])
        plt.grid(True)
        sigma_H0 = dbv(rmsGain(H0, 0, 0.5/OSR))
        sigma_H1 = dbv(rmsGain(H1, 0, 0.5/OSR))
        plt.semilogx([fstart, 1], sigma_H0*np.array([1, 1]), linewidth=3, color='#191970')
        plt.text(0.15, sigma_H0 + 1.5, 'RMS gain = %5.0fdB' % sigma_H0)
        plt.semilogx([fstart, 1], sigma_H1*np.array([1, 1]), linewidth=3, color='#228B22')
        plt.text(0.15, sigma_H1 + 1.5, 'RMS gain = %5.0fdB' % sigma_H1)
        plt.xlabel('Normalized frequency ($1\\\\rightarrow f_B$)')
        plt.ylabel('dB')
        plt.legend(loc=3)
        plt.tight_layout()

    """
    if opt:
        warn("Got a non-zero 'opt' value. Not such optimization is " + \
             "available, opt is only meant to ease switching between " + \
             "synthesizeNTF and synthesizeChebyshevNTF.")
    if f0 != 0:
        if order % 2 != 0:
            raise ValueError('Order must be even for a bandpass modulator.')
        else:
            f1, f2 = ds_f1f2(OSR, f0)
            f1f2 = np.array([f1, f2])
    x_min = 0
    x_max = 300
    dx_max = 10
    ftol = 1e-06
    xtol = 1e-06
    x = 60
    f_p = None # will be redefined later
    itn_limit = 10
    converged = False
    for itn in range(itn_limit):
        if f0 == 0:
            z, p, k = cheby2(order, x, 1./OSR, btype='high', output='zpk')
        else:
            z, p, k = cheby2(order/2., x, 2.*f1f2, btype='stop', output='zpk')
        f = 1./k - H_inf
        if f > 0:
            x_max = x
        else:
            x_min = x
        if itn == 0:
            dx = -dx_max*np.sign(f)
        else:
            df = f - f_p
            if abs(df) < ftol:
                converged = True
                break
            dx = -f*dx/df
        x_p = x
        f_p = f
        x = max(x_min, min(x + dx, x_max))
        dx = x - x_p
        if abs(dx) < xtol:
            break
    ntf = (z, p, 1)
    return ntf
# -*- coding: utf-8 -*- # _synthesizeChebyshevNTF.py # Module providing the synthesizeChebyshevNTF function # Copyright 2013 <NAME> # This file is part of python-deltasigma. # # python-deltasigma is a 1:1 Python replacement of Richard Schreier's # MATLAB delta sigma toolbox (aka "delsigma"), upon which it is heavily based. # The delta sigma toolbox is (c) 2009, <NAME>. # # python-deltasigma is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the # LICENSE file for the licensing terms. Module providing the synthesizeChebyshevNTF() function Synthesize a noise transfer function for a delta-sigma modulator.      The NTF is a type-2 highpass Chebyshev function.      :func:`synthesizeNTF` assumes that magnitude of the denominator of the NTF     is approximately constant in the passband. When the OSR or ``H_inf`` are     low, this assumption breaks down and :func:`synthesizeNTF` yields a     non-optimal NTF. :func:`synthesizeChebyshevNTF` creates non-optimal NTFs, but fares     better than :func:`synthesizeNTF` in the aforementioned circumstances.      **Parameters:**      order : int, optional         order of the modulator, defaults to 3      OSR : int, optional         oversampling ratio, defaults to 64      opt : int, optional         ignored value, for consistency with :func:`synthesizeNTF`      H_inf : float, optional         maximum NTF gain, defaults to 1.5      f0 : float, optional         center frequency (1->fs), defaults to 0.      **Returns:**      z, p, k : tuple         a zpk tuple containing the zeros and poles of the NTF.      **Warns:**      * If a non-zero value is passed for ``opt``.      **Raises:**      * ValueError: Order must be even for a bandpass modulator.      **Example:**      Compare the NTFs created by :func:`synthesizeNTF` and     :func:`synthesizeChebyshevNTF` when ``OSR`` is low::          OSR = 4         order = 8         H_inf = 3         H0 = synthesizeNTF(order, OSR, 1, H_inf)         H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)      .. plot::          import pylab as plt         import numpy as np         from deltasigma import *         OSR = 4         order = 8         H_inf = 3         plt.figure(figsize=(12,6))         H0 = synthesizeNTF(order, OSR, 1, H_inf)         H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)         # 1. Plot the singularities.         plt.subplot(121)         # we plot the singularities of the optimized NTF in light         # green with slightly bigger markers so that we can better         # distinguish the two NTF's when overlayed.         plotPZ(H1, markersize=7, color='#90EE90')         plt.hold(True)         plotPZ(H0, markersize=5)         plt.title('NTF Poles and Zeros')         f = np.concatenate((np.linspace(0, 0.75/OSR, 100), np.linspace(0.75/OSR, 0.5, 100)))         z = np.exp(2j*np.pi*f)         magH0 = dbv(evalTF(H0, z))         magH1 = dbv(evalTF(H1, z))         # 2. Plot the magnitude responses.         plt.subplot(222)         plt.plot(f, magH0, label='synthesizeNTF')         plt.hold(True)         plt.plot(f, magH1, label='synthesizeChebyshevNTF')         figureMagic([0, 0.5], 0.05, None, [-80, 20], 10, None)         plt.xlabel('Normalized frequency ($1\\\\rightarrow f_s)$')         plt.ylabel('dB')         plt.legend(loc=4)         plt.title('NTF Magnitude Response')         # 3. Plot the magnitude responses in the signal band.         plt.subplot(224)         fstart = 0.01         f = np.linspace(fstart, 1.2, 200)/(2*OSR)         z = np.exp(2j*np.pi*f)         magH0 = dbv(evalTF(H0, z))         magH1 = dbv(evalTF(H1, z))         plt.semilogx(f*2*OSR, magH0, label='synthesizeNTF')         plt.hold(True)         plt.semilogx(f*2*OSR, magH1, label='synthesizeChebyshevNTF')         plt.axis([fstart, 1, -50, 0])         plt.grid(True)         sigma_H0 = dbv(rmsGain(H0, 0, 0.5/OSR))         sigma_H1 = dbv(rmsGain(H1, 0, 0.5/OSR))         plt.semilogx([fstart, 1], sigma_H0*np.array([1, 1]), linewidth=3, color='#191970')         plt.text(0.15, sigma_H0 + 1.5, 'RMS gain = %5.0fdB' % sigma_H0)         plt.semilogx([fstart, 1], sigma_H1*np.array([1, 1]), linewidth=3, color='#228B22')         plt.text(0.15, sigma_H1 + 1.5, 'RMS gain = %5.0fdB' % sigma_H1)         plt.xlabel('Normalized frequency ($1\\\\rightarrow f_B$)')         plt.ylabel('dB')         plt.legend(loc=3)         plt.tight_layout()      Repeat for ``H_inf`` low::          OSR = 32         order = 5         H_inf = 1.2         H0 = synthesizeNTF(order, OSR, 1, H_inf)         H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)      .. plot::          import pylab as plt         import numpy as np         from deltasigma import *         OSR = 32         order = 5         H_inf = 1.2         plt.figure(figsize=(12,6))         H0 = synthesizeNTF(order, OSR, 1, H_inf)         H1 = synthesizeChebyshevNTF(order, OSR, 0, H_inf)         # 1. Plot the singularities.         plt.subplot(121)         # we plot the singularities of the optimized NTF in light         # green with slightly bigger markers so that we can better         # distinguish the two NTF's when overlayed.         plotPZ(H1, markersize=7, color='#90EE90')         plt.hold(True)         plotPZ(H0, markersize=5)         plt.title('NTF Poles and Zeros')         f = np.concatenate((np.linspace(0, 0.75/OSR, 100), np.linspace(0.75/OSR, 0.5, 100)))         z = np.exp(2j*np.pi*f)         magH0 = dbv(evalTF(H0, z))         magH1 = dbv(evalTF(H1, z))         # 2. Plot the magnitude responses.         plt.subplot(222)         plt.plot(f, magH0, label='synthesizeNTF')         plt.hold(True)         plt.plot(f, magH1, label='synthesizeChebyshevNTF')         figureMagic([0, 0.5], 0.05, None, [-80, 20], 10, None)         plt.xlabel('Normalized frequency ($1\\\\rightarrow f_s)$')         plt.ylabel('dB')         plt.legend(loc=4)         plt.title('NTF Magnitude Response')         # 3. Plot the magnitude responses in the signal band.         plt.subplot(224)         fstart = 0.01         f = np.linspace(fstart, 1.2, 200)/(2*OSR)         z = np.exp(2j*np.pi*f)         magH0 = dbv(evalTF(H0, z))         magH1 = dbv(evalTF(H1, z))         plt.semilogx(f*2*OSR, magH0, label='synthesizeNTF')         plt.hold(True)         plt.semilogx(f*2*OSR, magH1, label='synthesizeChebyshevNTF')         plt.axis([fstart, 1, -60, -20])         plt.grid(True)         sigma_H0 = dbv(rmsGain(H0, 0, 0.5/OSR))         sigma_H1 = dbv(rmsGain(H1, 0, 0.5/OSR))         plt.semilogx([fstart, 1], sigma_H0*np.array([1, 1]), linewidth=3, color='#191970')         plt.text(0.15, sigma_H0 + 1.5, 'RMS gain = %5.0fdB' % sigma_H0)         plt.semilogx([fstart, 1], sigma_H1*np.array([1, 1]), linewidth=3, color='#228B22')         plt.text(0.15, sigma_H1 + 1.5, 'RMS gain = %5.0fdB' % sigma_H1)         plt.xlabel('Normalized frequency ($1\\\\rightarrow f_B$)')         plt.ylabel('dB')         plt.legend(loc=3)         plt.tight_layout() # will be redefined later