Source code for deltasigma._impL1

# -*- coding: utf-8 -*-
# _impL1.py
# This module provides the impL1 function.
# Copyright 2013 Giuseppe Venturini
# 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, Richard Schreier.
#
# 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.

"""This module provides the impL1() function, computing the impulse response 
from the comparator output to the comparator input for a given NTF.
"""

import numpy as np
from scipy.signal import convolve, dimpulse

from ._padr import padr
from ._utils import _get_num_den, _is_num_den, _is_zpk


[docs]def impL1(arg1, n=10): """Impulse response evaluation for NTFs. Compute the impulse response from the comparator output to the comparator input for the given NTF. **Parameters:** arg1 : object The NTF, which may be represented as: * ZPK tuple, * num, den tuple, * A, B, C, D tuple, * ABCD matrix, * a scipy LTI object, * a sequence of the tuples of any of the above types (experimental). n : int is the (optional) number of time steps (default: 10), resulting in an impulse response with n+1 (default: 11) samples. This function is useful when verifying the realization of a NTF with a specified topology. **Returns:** y : ndarray The NTF impulse response .. note:: In the original implementation of impL1 in delsig, there is a bug: impL1 calls MATLAB's impulse with tfinal=n, which means that the function will return the impulse response evaluated on the times [0, 1, 2 ... n], ie n+1 points. We keep the same behavior here, but we state clearly that n is the number of time steps. """ if _is_num_den(arg1): num, den = arg1 p = np.roots(den) elif _is_zpk(arg1): z, p, _ = arg1 num = np.poly(z) den = np.poly(p) else: num, den = _get_num_den(arg1) p = np.roots(den) num = np.asarray(num) den = np.asarray(den) p = np.asarray(p) lf_den = padr(num, len(p)+1) lf_num = lf_den - den ts = np.arange(n + 1) # be coherent with the original toolbox all_lf = np.concatenate((lf_num, lf_den), axis=1) lf_num, lf_den = lf_num.squeeze(), lf_den.squeeze() if not np.allclose(np.imag(all_lf), np.zeros(all_lf.shape), atol=1e-9): # Complex loop filter lfr_den = np.real(convolve(lf_den, np.conj(lf_den))).squeeze() lfr_num = convolve(lf_num, np.conj(lf_den)).squeeze() lf_i = (np.real(lfr_num).tolist(), lfr_den.tolist(), 1) lf_q = (np.imag(lfr_num).tolist(), lfr_den.tolist(), 1) y = dimpulse(lf_i, t=ts)[1][0] + 1j*dimpulse(lf_q, t=ts)[1][0] y = y.squeeze() else: _, y = dimpulse((lf_num, lf_den, 1), t=ts) y = y[0].squeeze() return y