Source code for adctoolbox.oversampling.ntf_analyzer

"""NTF performance analysis helpers."""

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal


def _frequency_grid(n_grid, grid_policy):
    n_grid = int(n_grid)
    if n_grid <= 0:
        raise ValueError("n_grid must be a positive integer")

    if grid_policy == "python":
        return np.linspace(0, 0.5, n_grid)

    if grid_policy == "matlab":
        return np.arange(1, n_grid + 1, dtype=float) / n_grid / 2

    raise ValueError("grid_policy must be 'python' or 'matlab'")


[docs] def ntf_analyzer(ntf, flow, fhigh, is_plot=None, *, n_grid=2**16, grid_policy="python"): """ Analyze the performance of NTF (Noise Transfer Function) Args: ntf: The noise transfer function (in z domain) - scipy.signal.TransferFunction or tuple (num, den) flow: Low bound frequency of signal band (relative to Fs) fhigh: High bound frequency of signal band (relative to Fs) is_plot: Optional plotting flag (1 to plot, None or 0 to skip) n_grid: Number of frequency grid points used for integration. grid_policy: "python" keeps the historical linspace grid; "matlab" uses the same grid as MATLAB ntfperf.m. Returns: noiSup: Integrated noise suppression of NTF in signal band in dB (compared to NTF=1) """ w = _frequency_grid(n_grid, grid_policy) # Convert NTF to transfer function if needed if isinstance(ntf, tuple): # ntf is (numerator, denominator) tuple num, den = ntf tf = signal.TransferFunction(num, den, dt=1) # dt=1 for discrete time else: tf = ntf # Calculate frequency response for discrete-time system w_rad = w * 2 * np.pi _, mag = signal.dfreqresp(tf, w_rad) mag = np.abs(mag) # Calculate noise suppression in signal band band_mask = (w > flow) & (w < fhigh) np_val = np.sum(mag[band_mask]**2) / len(w) noiSup = -10 * np.log10(np_val) # Plot if requested if is_plot == 1: plt.semilogx(w, 20 * np.log10(mag)) if flow > 0: plt.semilogx([flow, flow], 20 * np.log10([np.min(mag), np.max(mag)]), 'k--') plt.semilogx([fhigh, fhigh], 20 * np.log10([np.min(mag), np.max(mag)]), 'k--') plt.xlabel('Normalized Frequency') plt.ylabel('Magnitude (dB)') plt.title('NTF Frequency Response') plt.grid(True) plt.show() return noiSup