A professional desktop GUI toolbox for analog/mixed-signal IC engineers, providing comprehensive ADC, DAC, noise, jitter, and spectral analysis capabilities.
- Analog circuit engineers
- ADC / DAC design engineers
- SerDes / mixed-signal engineers
- Test & measurement engineers
# 1. Install dependencies
pip install -r requirements.txt
# 2. Launch the toolbox
python main.pyOn first launch, click Tools > Generate Demo Data (or the button on the Home tab) to load sample datasets and start exploring.
- Python 3.10+
- PySide6 >= 6.5
- NumPy >= 1.24
- SciPy >= 1.10
- Matplotlib >= 3.7
- Pandas >= 2.0
- openpyxl >= 3.1
| Tab | Description |
|---|---|
| Home | Quick-start guide, loaded dataset overview, navigation shortcuts |
| Import | Load CSV/TXT/Excel files, set metadata (fs, bits, full-scale), preview data |
| Time Domain | Waveform plot, histogram, RMS/peak-to-peak/slew rate/zero crossings |
| FFT / Dynamic | FFT spectrum with SNR, THD, SINAD, SFDR, ENOB, harmonic markers |
| ADC Static | Code density, DNL/INL (endpoint & best-fit), missing codes, offset/gain error |
| DAC Analysis | Transfer curve, DNL/INL, monotonicity check, gain/offset error |
| Noise | PSD, RMS noise, integrated noise, 1/f corner, white noise floor |
| Jitter | Period jitter, cycle-to-cycle jitter, TIE, histograms |
| Curve Fit | Linear/polynomial fitting, residual analysis, R-squared |
| Preprocess | Remove mean, detrend, moving average, FIR smooth, resample, crop |
| Report | Export HTML reports, CSV metrics, PNG figures |
ADC_tool_box/
├── main.py # Entry point
├── requirements.txt
├── README.md
├── core/
│ ├── data_model.py # DataSet & AnalysisResult dataclasses
│ └── config.py # Global defaults, colors, styles
├── analysis/
│ ├── fft_analysis.py # FFT spectrum, SNR/THD/SINAD/SFDR/ENOB
│ ├── time_domain.py # Time-domain statistics
│ ├── adc_static.py # ADC DNL/INL/histogram analysis
│ ├── dac_analysis.py # DAC linearity, monotonicity
│ ├── noise_analysis.py # PSD, integrated noise, 1/f
│ ├── jitter_analysis.py # Zero-crossing jitter, TIE
│ ├── curve_fitting.py # Linear/polynomial fitting
│ └── preprocessing.py # Signal conditioning utilities
├── io/
│ ├── data_import.py # CSV/TXT/Excel import
│ └── data_export.py # CSV/PNG export
├── gui/
│ ├── main_window.py # Main application window
│ ├── widgets/
│ │ ├── plot_widget.py # Matplotlib canvas with toolbar
│ │ ├── data_table.py # Data preview table
│ │ └── log_console.py # Message console
│ └── tabs/
│ ├── home_tab.py # Home / welcome
│ ├── import_tab.py # Data import
│ ├── time_domain_tab.py
│ ├── fft_tab.py # FFT / dynamic analysis
│ ├── adc_static_tab.py
│ ├── dac_tab.py
│ ├── noise_tab.py
│ ├── jitter_tab.py
│ ├── curve_fit_tab.py
│ ├── preprocess_tab.py
│ └── report_tab.py
├── demo/
│ └── generators.py # Synthetic data generators
├── reports/
│ └── report_generator.py # HTML/CSV report generation
└── utils/
└── helpers.py # dB conversions, engineering format, etc.
Defines the two central data structures:
DataSet- Holds waveform data with metadata (sampling rate, resolution bits, full-scale range, etc.). Properties auto-compute statistics like RMS, peak-to-peak, duration.AnalysisResult- Container for analysis outputs: metrics dict, plot data, formulas, settings, timestamp.
Each module is a pure-function library that takes a DataSet (or raw arrays) and returns an AnalysisResult. No GUI dependencies.
PySide6-based GUI. The MainWindow holds a shared dataset store and a tab widget. Each tab accesses datasets via self._parent.datasets and calls analysis functions when the user clicks "Analyze".
Synthetic signal generators for testing: sine waves (with noise/harmonics/quantization), ADC ramp codes, DAC transfer data, noise signals, clock signals with jitter.
All metrics are computed from the single-sided power spectrum after windowing.
SNR (Signal-to-Noise Ratio)
SNR = 10 * log10(P_signal / P_noise) [dB]
Where P_signal = power in the fundamental bin cluster, P_noise = total power minus signal and harmonic power.
THD (Total Harmonic Distortion)
THD = 10 * log10(P_harmonics / P_signal) [dB]
SINAD (Signal-to-Noise-and-Distortion)
SINAD = 10 * log10(P_signal / (P_noise + P_harmonics)) [dB]
SFDR (Spurious-Free Dynamic Range)
SFDR = 20 * log10(V_fundamental / V_largest_spur) [dBc]
ENOB (Effective Number of Bits)
ENOB = (SINAD - 1.76) / 6.02 [bits]
dBFS conversion
V_FS_rms = (full_scale / 2) / sqrt(2)
dBFS = 20 * log10(V / V_FS_rms)
DNL (Differential Non-Linearity)
For ramp input: DNL[k] = H[k] / H_ideal - 1 [LSB]
For sine input: DNL[k] = H[k] / H_expected[k] - 1 [LSB]
Where H[k] = histogram count for code k, H_ideal = N / num_codes.
INL (Integral Non-Linearity)
- Endpoint method: INL = cumsum(DNL) with linear trend removed (endpoint-to-endpoint line)
- Best-fit method: INL = deviation from least-squares fit line to transition levels
DNL
DNL[k] = (V[k+1] - V[k]) / ideal_step - 1 [LSB]
Monotonicity: Flagged when any V[k+1] <= V[k].
- RMS noise:
std(data)after DC removal - PSD: Welch method via
scipy.signal.welch - Integrated noise:
sqrt(integral of PSD over bandwidth) - 1/f corner: Frequency where 1/f trend meets white noise floor (log-log fit)
- Period jitter: Standard deviation of periods between same-direction threshold crossings
- Cycle-to-cycle jitter:
std(diff(periods)) - TIE: Deviation of actual crossings from ideal equally-spaced crossings
- Import data - Use the Import tab or "Generate Demo Data"
- Set metadata - Sampling rate, bits, full-scale, tone frequency
- Select analysis tab - Navigate to the desired analysis
- Choose dataset - Select from the dropdown
- Configure & Analyze - Set parameters and click "Analyze"
- Review results - View plots and metrics
- Export - Use the Report tab to generate HTML/CSV/PNG
-
Create
analysis/my_analysis.py:from core.data_model import DataSet, AnalysisResult def analyze_my_thing(dataset: DataSet, **params) -> AnalysisResult: # Your analysis logic here return AnalysisResult( name="My Analysis", metrics={"metric1": value1}, plots_data={"x": x_data, "y": y_data}, formulas={"metric1": "formula explanation"}, )
-
Create
gui/tabs/my_analysis_tab.pyfollowing the pattern of existing tabs (dataset combo, left/center/right panels). -
Register in
gui/main_window.pyby adding to the_tabslist.
Each tab follows this pattern:
User clicks "Analyze"
-> Tab reads GUI parameters
-> Tab gets DataSet from parent.datasets
-> Tab calls analysis function (pure computation)
-> Analysis returns AnalysisResult
-> Tab plots results on PlotWidget
-> Tab displays metrics in right panel
-> Tab logs to parent.log()
The MainWindow acts as a mediator:
datasetsdict is shared across all tabsadd_dataset()adds data and notifies all tabs viarefresh_datasets()log()writes to the bottom log console
- dBFS: Referenced to full-scale RMS of a sine wave occupying the full ADC/DAC range
- DNL/INL: Reported in LSB units
- Endpoint vs Best-fit INL: Both are industry-standard; endpoint is more common in datasheets, best-fit generally gives tighter numbers
- FFT windowing: Hann is the default; flattop is best for amplitude accuracy; rectangular only for coherent sampling
- Harmonic aliasing: Harmonics that exceed Nyquist are correctly folded back into the spectrum
For internal/educational use.