def simulateSNR(arg1, osr, amp=None, f0=0, nlev=2, f=None, k=13,
                quadrature=False):
    # Look at arg1 and decide if the system is quadrature
    quadrature_ntf = False
    if callable(arg1):
        raise ValueError('There is no support for NTFs described through ' +
                         'a function.')
    elif not isinstance(arg1, np.ndarray):
        # NTF of LTI type or zpk tuple, or (num,den) etc...
        # in this case, if the modulator is in quadrature, 
        # we will have to call simulateQDSM
        for roots in _get_zpk(arg1)[:2]:
            if np.any(np.abs(np.imag(np.poly(roots))) > 0.0001):
                quadrature = True
                quadrature_ntf = True
    else: # ABCD matrix, no matter what, here we will get through the
        # simulation with simulateDSM()
        arg1 = np.real_if_close(arg1) # tiny imaginary parts due to rounding
        if not np.all(np.imag(arg1) == 0):
            quadrature = True

    if amp is None:
        amp = np.concatenate((np.arange(- 120, -20 + 1, 10),
                              np.array((-15,)),
                              np.arange(-10, 1)))
    elif not isinstance(amp, collections.Iterable):
        amp = np.array((amp, ))
    else:
        amp = np.asarray(amp)
    osr_mult = 2
    if f0 != 0 and not quadrature:
        osr_mult = 2*osr_mult
    if f is None or np.isnan(f):
        f = f0 + 0.5/(osr*osr_mult) # Halfway across the band
    M = nlev - 1
    if quadrature and not quadrature_ntf:
        # Modify arg1 (ABCD) and nlev so that simulateDSM can be used
        nlev = np.array([nlev, nlev])
        arg1 = mapQtoR(arg1)
    if abs(f - f0) > 1./(osr*osr_mult):
        warn('The input tone is out-of-band.')
    N = 2**k
    if N < 8*2*osr:
        warn('Increasing k to accommodate a large oversampling ratio.')
        k = np.array(np.ceil(np.log2(8*2*osr)), dtype=np.int64)
        N = 2**k
    F = np.round(f*N)
    if np.abs(F) <= 1:
        warn('Increasing k to accommodate a low input frequency.')
        # Want f*N >= 1
        k = np.ceil(np.log2(1./f))
        N = 2**k
        F = 2
    Ntransient = 100
    soft_start = 0.5*(1 - np.cos(2*np.pi/Ntransient * \
                                 np.arange(Ntransient/2)))
    if not quadrature:
        tone = M*np.sin(2*np.pi*F/N*np.arange(N + Ntransient))
        tone[:Ntransient/2] = tone[:Ntransient/2] * soft_start
    else:
        tone = M*np.exp(2j*np.pi*F/N * np.arange(N + Ntransient))
        tone[:Ntransient/2] = tone[:Ntransient/2] * soft_start
        if not quadrature_ntf:
            tone = tone.reshape((1, -1))
            tone = np.vstack((np.real(tone), np.imag(tone)))
    # create a Hann window
    window = 0.5*(1 - np.cos(2*np.pi*np.arange(N)/N))
    if f0 == 0:
        # Exclude DC and its adjacent bin
        inBandBins = int(N/2) + np.arange(3,
                                     np.round(N/osr_mult/osr) + 1,
                                     dtype=np.int32)
        F = F - 2
    else:
        f1 = np.round(N*(f0 - 1./osr_mult/osr))
        # Should exclude DC
        inBandBins = int(N/2) + np.arange(f1,
                                     np.round(N*(f0 + 1./osr_mult/osr)) + 1,
                                     dtype=np.int32)
        F = F - f1 + 1
    snr = np.zeros(amp.shape)
    for i, A in enumerate(np.power(10.0, amp/20)):
        if quadrature_ntf:
            v, _, _, _ = simulateQDSM(A*tone, arg1, nlev)
        else:
            v, _, _, _ = simulateDSM(A*tone, arg1, nlev)
            if quadrature:
                v = v[0, :] + 1j*v[1, :]
        hwfft = fftshift(fft(window*v[Ntransient:N + Ntransient]))
        snr[i] = calculateSNR(hwfft[inBandBins - 1], F)
    return snr, amp
Determine the SNR for a delta-sigma modulator by using simulations.
dataset/ETHPy150Open ggventurini/python-deltasigma/deltasigma/_simulateSNR.py/simulateSNR