Skip to content

Commit 092c614

Browse files
committed
Merge branch 'dev' of github.com:fronzbot/python-adc-eval into add-adcs
2 parents 2f069eb + 9055b27 commit 092c614

File tree

4 files changed

+38
-20
lines changed

4 files changed

+38
-20
lines changed

adc_eval/eval/spectrum.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def sndr_sfdr(spectrum, freq, fs, nfft, leak, full_scale=0):
2727
"""Get SNDR and SFDR."""
2828

2929
# Zero the DC bin
30-
spectrum[0] = 0
30+
for i in range(0, leak + 1):
31+
spectrum[i] = 0
3132
bin_sig = np.argmax(spectrum)
3233
psig = sum(spectrum[i] for i in range(bin_sig - leak, bin_sig + leak + 1))
3334
spectrum_n = spectrum
@@ -80,7 +81,7 @@ def sndr_sfdr(spectrum, freq, fs, nfft, leak, full_scale=0):
8081
return stats
8182

8283

83-
def find_harmonics(spectrum, freq, nfft, bin_sig, psig, harms=5, leak=20):
84+
def find_harmonics(spectrum, freq, nfft, bin_sig, psig, harms=5, leak=20, fscale=1e6):
8485
"""Get the harmonic contents of the data."""
8586
harm_stats = {"harm": {}}
8687
harm_index = 2
@@ -110,7 +111,7 @@ def find_harmonics(spectrum, freq, nfft, bin_sig, psig, harms=5, leak=20):
110111

111112
harm_stats["harm"][harm_index]["bin"] = bin_harm_max
112113
harm_stats["harm"][harm_index]["power"] = pwr_max
113-
harm_stats["harm"][harm_index]["freq"] = round(freq[bin_harm] / 1e6, 1)
114+
harm_stats["harm"][harm_index]["freq"] = round(freq[bin_harm] / fscale, 1)
114115
harm_stats["harm"][harm_index]["dBc"] = dBW(pwr_max / psig)
115116
harm_stats["harm"][harm_index]["dB"] = dBW(pwr_max)
116117

@@ -161,6 +162,7 @@ def plot_spectrum(
161162
no_plot=False,
162163
yaxis="power",
163164
single_sided=True,
165+
fscale="MHz",
164166
):
165167
"""Plot Power Spectrum for input signal."""
166168
wsize = data.size
@@ -169,10 +171,21 @@ def plot_spectrum(
169171
"hanning": np.hanning(wsize),
170172
}
171173

174+
fscalar = {
175+
"Hz": 1,
176+
"kHz": 1e3,
177+
"MHz": 1e6,
178+
"GHz": 1e9,
179+
}
180+
172181
if window not in windows:
173182
print(f"WARNING: {window} not implemented. Defaulting to 'rectangular'.")
174183
window = "rectangular"
175184

185+
if fscale not in fscalar:
186+
print(f"WARNING: {fscale} not implemented. Defaulting to 'MHz'.")
187+
fscale = "MHz"
188+
176189
wscale = {
177190
"rectangular": 1.0,
178191
"hanning": 1.633,
@@ -193,6 +206,7 @@ def plot_spectrum(
193206
lut_key = yaxis.lower()
194207
scalar = yaxis_lut[lut_key][0]
195208
yunits = yaxis_lut[lut_key][1]
209+
xscale = fscalar[fscale]
196210

197211
psd_out = 10 * np.log10(pwr) - scalar
198212
if lut_key in ["magnitude"]:
@@ -207,6 +221,7 @@ def plot_spectrum(
207221
)
208222

209223
sndr_stats = sndr_sfdr(psd_ss, f_ss, fs, nfft, leak=leak, full_scale=full_scale)
224+
210225
harm_stats = find_harmonics(
211226
psd_ss,
212227
f_ss,
@@ -215,20 +230,21 @@ def plot_spectrum(
215230
sndr_stats["sig"]["power"],
216231
harms=harmonics,
217232
leak=leak,
233+
fscale=xscale,
218234
)
219235

220236
stats = {**sndr_stats, **harm_stats}
221237

222238
xmin = 0 if single_sided else -fs / 2e6
223239

224240
if not no_plot:
225-
plt_str = get_plot_string(stats, full_scale, fs, nfft, window)
241+
plt_str = get_plot_string(stats, full_scale, fs, nfft, window, xscale, fscale)
226242
fig, ax = plt.subplots(figsize=(15, 8))
227-
ax.plot(freq / 1e6, psd_out)
243+
ax.plot(freq / xscale, psd_out)
228244
ax.set_ylabel(f"Power Spectrum ({yunits})", fontsize=18)
229-
ax.set_xlabel("Frequency (MHz)", fontsize=16)
245+
ax.set_xlabel(f"Frequency ({fscale})", fontsize=16)
230246
ax.set_title("Output Power Spectrum", fontsize=16)
231-
ax.set_xlim([xmin, fs / 2e6])
247+
ax.set_xlim([xmin, fs / (2 * xscale)])
232248
ax.set_ylim([1.1 * min(psd_out), 1])
233249

234250
ax.annotate(
@@ -291,7 +307,7 @@ def plot_spectrum(
291307
return (freq, psd_out, stats)
292308

293309

294-
def get_plot_string(stats, full_scale, fs, nfft, window):
310+
def get_plot_string(stats, full_scale, fs, nfft, window, xscale=1e6, fscale="MHz"):
295311
"""Generate plot string from stats dict."""
296312

297313
plt_str = "==== FFT ====\n"
@@ -302,22 +318,22 @@ def get_plot_string(stats, full_scale, fs, nfft, window):
302318
plt_str += "==== Signal ====\n"
303319
plt_str += f"FullScale = {full_scale} dB\n"
304320
plt_str += f"Psig = {stats['sig']['dBFS']} dBFS ({stats['sig']['dB']} dB)\n"
305-
plt_str += f"fsig = {round(stats['sig']['freq']/1e6, 2)} MHz\n"
306-
plt_str += f"fsamp = {round(fs/1e6, 2)} MHz\n"
321+
plt_str += f"fsig = {round(stats['sig']['freq']/xscale, 2)} {fscale}\n"
322+
plt_str += f"fsamp = {round(fs/xscale, 2)} {fscale}\n"
307323
plt_str += "\n"
308324
plt_str += "==== SNDR/SFDR ====\n"
309325
plt_str += f"ENOB = {stats['enob']['bits']} bits\n"
310326
plt_str += f"SNDR = {stats['sndr']['dBFS']} dBFS ({stats['sndr']['dBc']} dBc)\n"
311327
plt_str += f"SFDR = {stats['sfdr']['dBFS']} dBFS ({stats['sfdr']['dBc']} dBc)\n"
312328
plt_str += f"Pspur = {stats['spur']['dBFS']} dBFS\n"
313-
plt_str += f"fspur = {round(stats['spur']['freq']/1e6, 2)} MHz\n"
329+
plt_str += f"fspur = {round(stats['spur']['freq']/xscale, 2)} {fscale}\n"
314330
plt_str += f"Noise Floor = {stats['noise']['dBHz']} dBFS\n"
315331
plt_str += f"NSD = {stats['noise']['NSD']} dBFS\n"
316332
plt_str += "\n"
317333
plt_str += "==== Harmonics ====\n"
318334

319335
for hindex, hdata in stats["harm"].items():
320-
plt_str += f"HD{hindex} = {round(hdata['dB'] - full_scale, 1)} dBFS @ {hdata['freq']} MHz\n"
336+
plt_str += f"HD{hindex} = {round(hdata['dB'] - full_scale, 1)} dBFS @ {hdata['freq']} {fscale}\n"
321337

322338
plt_str += "\n"
323339

@@ -335,6 +351,7 @@ def analyze(
335351
no_plot=False,
336352
yaxis="fullscale",
337353
single_sided=True,
354+
fscale="MHz",
338355
):
339356
"""Perform spectral analysis on input waveform."""
340357
(freq, spectrum, stats) = plot_spectrum(
@@ -348,6 +365,7 @@ def analyze(
348365
no_plot=no_plot,
349366
yaxis=yaxis,
350367
single_sided=single_sided,
368+
fscale=fscale,
351369
)
352370

353371
return (freq, spectrum, stats)

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ classifiers = [
2121
]
2222
requires-python = ">=3.9.0"
2323
dependencies = [
24-
"matplotlib==3.9.1",
24+
"matplotlib==3.9.2",
2525
]
2626

2727
[project.urls]

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
matplotlib==3.9.1
1+
matplotlib==3.9.2
22
tqdm==4.67.1
33
scipy==1.15.2

requirements_test.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
black==24.4.2
2-
coverage==7.6.0
3-
pylint==3.2.5
4-
pytest==8.2.2
1+
black==24.8.0
2+
coverage==7.6.1
3+
pylint==3.2.7
4+
pytest==8.3.2
55
pytest-cov==5.0.0
66
pytest-sugar==1.0.0
77
pytest-timeout==2.3.1
8-
ruff==0.5.2
9-
tox==4.16.0
8+
ruff==0.6.3
9+
tox==4.18.0
1010
restructuredtext-lint==1.4.0
1111
pygments==2.18.0

0 commit comments

Comments
 (0)