See it move

These pages run this in your browser, with the parameters in your hands: Reading the bits, Binary vs redundant SAR, How much training a calibration needs.

Digital Output Analysis (dout)#

The dout module provides tools for analyzing digital ADC outputs and bit-weighted architectures.

Weight Calibration#

See Calibration (calibration) for sine-weight fitting, output scaling, identification diagnostics and supervised polynomial/MLP correction APIs.

Bit And Weight Analysis#

analyze_weight_radix returns radix, wgtsca, and effres. effres is computed from the significant absolute weights as log2(sum(abs_w_sig) / min(abs_w_sig) + 1). It is a theoretical weight-list span, not a missing-code, DNL, INL, or SAR reachability proof.

adctoolbox.analyze_bit_activity(bits: ndarray, create_plot: bool = True, ax=None, title: str | None = None) → ndarray[源代码]#

Analyze and plot the percentage of 1's in each bit.

Ideal SAR ADC should have 50% activity for all bits. Deviations indicate input signal DC offset or amplitude clipping.

参数:
  • bits (np.ndarray) -- Binary matrix (N x B), N=samples, B=bits (MSB to LSB)

  • create_plot (bool, default=True) -- If True, create bar chart visualization

  • ax (plt.Axes, optional) -- Axes to plot on. If None, uses current axes (plt.gca())

  • title (str, optional) -- Title for the plot. If None, uses default title

返回:

Percentage of 1's for each bit (1D array of length B)

返回类型:

np.ndarray

adctoolbox.analyze_overflow(raw_code: ndarray, weight: ndarray, ofb: int | None = None, create_plot: bool = True, ax=None, title: str | None = None) → tuple[ndarray, ndarray, ndarray, ndarray][源代码]#

Analyze residue distribution at each bit position for overflow detection.

Calculates normalized residue (remaining bits weighted sum) and detects overflow conditions where residue exceeds [0, 1] range.

参数:
  • raw_code (np.ndarray) -- Digital codes array, shape (N, M) where N=samples, M=bits (MSB first)

  • weight (np.ndarray) -- Weight array for each bit, shape (M,)

  • ofb (int, optional) -- Overflow bit position for overflow detection. Default is M (check at MSB, MATLAB convention: 1=LSB, M=MSB)

  • create_plot (bool, default=True) -- If True, generate residue distribution visualization

  • ax (plt.Axes, optional) -- Axes to plot on. If None, uses current axes (plt.gca())

  • title (str, optional) -- Title for the plot. If None, no title is set

返回:

  • range_min: Minimum normalized residue per bit (shape M,)

  • range_max: Maximum normalized residue per bit (shape M,)

  • ovf_percent_zero: Underflow percentage per bit (shape M,)

  • ovf_percent_one: Overflow percentage per bit (shape M,)

返回类型:

tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]

备注

  • A bit segment is the sub-code formed from one bit to the LSB

  • Residue is normalized by dividing by the sum of weights in the segment

  • Matches MATLAB ovfchk.m behavior exactly

adctoolbox.analyze_weight_radix(weights: ndarray, create_plot: bool = True, ax=None, title: str | None = None) → dict[源代码]#

Analyze absolute bit weights, radix ratios, and weight-list resolution.

Pure binary: radix = 2.00. Sub-radix/redundancy: radix < 2.00. effres is a theoretical resolution estimate from the supplied weight dynamic range, not a missing-code/DNL proof.

参数:
  • weights (np.ndarray) -- Bit weights (1D array), nominally from MSB to LSB for radix plotting. Effective-resolution analysis uses sorted absolute magnitudes, so negative trim weights count by magnitude.

  • create_plot (bool, default=True) -- If True, create line plot with radix annotations

  • ax (plt.Axes, optional) -- Axes to plot on. If None, uses current axes (plt.gca())

  • title (str, optional) -- Title for the plot. If None, uses default title

返回:

radix:

Radix between consecutive input-order weights, abs(weight[i-1]) / abs(weight[i]). The first entry is NaN.

wgtsca:

Scale factor that maps the significant absolute weights closest to integer LSB units.

effres:

Effective resolution in bits, log2(sum(abs_w_sig) / min(abs_w_sig) + 1).

返回类型:

dict

备注

The significant set abs_w_sig is formed by sorting abs(weights) in descending order, then dropping the tail after the first adjacent ratio >= 3. This excludes very small trim/noise weights from effres.

effres is useful for questions like "how many bits does this SAR weight list span?" It does not verify SAR decision reachability, code monotonicity, missing codes, DNL/INL, comparator noise, or sampling noise.

What to look for in radix values: - Radix = 2.00: Binary scaling (SAR, pure binary) - Radix < 2.00: Redundancy or sub-radix (e.g., 1.5-bit/stage → ~1.90) - Radix > 2.00: Unusual, may indicate calibration error - Consistent pattern: Expected architecture behavior - Random jumps: Calibration errors or bit mismatch

ENOB Analysis#

adctoolbox.analyze_enob_sweep(bits: ndarray, freq: float | None = None, harmonic_order: int = 1, osr: int = 1, win_type: str = 'hamming', calibration_mode: str = 'prefix_of_full_calibration', frequency_policy: str = 'python', create_plot: bool = True, ax=None, title: str | None = None, verbose: bool = False) → tuple[ndarray, ndarray][源代码]#

Sweep ENOB vs number of bits used for calibration.

Incrementally adds bits (MSB to LSB) and measures ENOB after calibration to understand diminishing returns and optimal bit count.

参数:
  • bits (np.ndarray) -- Binary matrix (N samples x M bits, MSB to LSB order)

  • freq (float, optional) -- Normalized frequency (0-0.5). If None, auto-detect from data

  • harmonic_order (int, default=1) -- Harmonic order for calibrate_weight_sine

  • osr (int, default=1) -- Oversampling ratio for spectrum analysis

  • win_type (str, default='hamming') -- Window function: 'boxcar', 'hann', 'hamming'

  • calibration_mode ({'prefix_of_full_calibration',) -- 'recalibrate_each_subset'}, default='prefix_of_full_calibration' ENOB sweep calibration policy. 'prefix_of_full_calibration' calibrates all bits once and sweeps prefixes of the full-weight solution. 'recalibrate_each_subset' estimates the frequency once when needed, then recalibrates each bit-prefix subset independently.

  • frequency_policy ({'python', 'matlab'}, default='python') -- Coarse frequency estimator passed to calibrate_weight_sine when automatic frequency search is requested.

  • create_plot (bool, default=True) -- If True, plot ENOB sweep curve

  • ax (plt.Axes, optional) -- Axes to plot on. If None, uses current axes (plt.gca())

  • title (str, optional) -- Title for the plot. If None, uses default title

  • verbose (bool, default=False) -- If True, print progress messages

返回:

  • enob_sweep: ENOB for each bit count (length M)

  • n_bits_vec: Bit counts from 1 to M

返回类型:

tuple[np.ndarray, np.ndarray]

备注

The default 'prefix_of_full_calibration' mode answers the calibration ablation question: "after a full-bit calibration, how much performance remains if lower-bit terms are removed?" Use 'recalibrate_each_subset' only when intentionally asking: "if only the first n bits are available, how well can that n-bit subsystem be calibrated?"

What to look for in the plot: - Increasing trend: More bits improve resolution - Plateau: Additional bits don't help (noise/distortion limited) - Decrease: Extra bits add noise/calibration errors

Visualization#

adctoolbox.plot_residual_scatter(signal: ndarray, bits: ndarray, weights: ndarray | None = None, pairs: list[tuple[int, int]] | None = None, alpha: float | str = 'auto', create_plot: bool = True) → dict[源代码]#

Plot partial-sum residuals of an ADC bit matrix.

For each pair (x_bit, y_bit), computes the residual after subtracting the first x_bit (or y_bit) weighted bits from the input signal, then plots y-residual vs x-residual as a scatter plot.

参数:
  • signal (np.ndarray) -- Ideal input signal to the ADC (1D, length N).

  • bits (np.ndarray) -- Raw ADC output bit matrix (N x M), MSB-first columns.

  • weights (np.ndarray, optional) -- Bit weights (length M). Default: binary [2^(M-1), ..., 1].

  • pairs (list of (int, int), optional) -- Pairs of bit indices whose residuals are plotted. Range: 0 (raw signal) to M (residual after all bits). Default: [(0, M), (1, M), ..., (M-1, M)].

  • alpha (float or 'auto', default='auto') -- Marker transparency. 'auto' scales as clamp(1000/N, 0.1, 1.0).

  • create_plot (bool, default=True) -- If True, create scatter subplots.

返回:

'pairs': list of (x_bit, y_bit) tuples used 'residuals_x': list of 1D arrays, one per pair 'residuals_y': list of 1D arrays, one per pair

返回类型:

dict