Skip to content

feat(swr): export SWR sweep data to CSV (#2241)#3882

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
M7HNF-Ian:feat/swr-sweep-csv-export
Jun 28, 2026
Merged

feat(swr): export SWR sweep data to CSV (#2241)#3882
ten9876 merged 1 commit into
aethersdr:mainfrom
M7HNF-Ian:feat/swr-sweep-csv-export

Conversation

@M7HNF-Ian

Copy link
Copy Markdown
Contributor

Implements the CSV-export portion of #2241.

Adds a Save CSV button to the SWR sweep controls in the spectrum overlay menu. After a sweep finishes, the samples (frequency + SWR) and band name already persist in m_swrSweep, so the export is available whenever a trace is on the panadapter.

  • Button → new swrSweepSaveCsvRequested() signal → MainWindow::saveSwrSweepCsv().
  • Opens a save dialog pre-filled with swr_sweep_<band>_<YYYYMMDD>_<HHMMSS>.csv (defaults to Documents).
  • Writes a Frequency (Hz),SWR header followed by one row per sample.
  • Guards for an in-progress sweep, an empty dataset, and a failed file open, each with a status-bar message.

Tested live on a FLEX-6600: ran a 20 m sweep, exported, and confirmed the file opens correctly in a spreadsheet (18 points, resonant dip ~14.31 MHz).

Scope is deliberately limited to CSV export. The resonance/bandwidth markers and user-bounded sweep range remain as separate follow-ups.

Add a "Save CSV" button to the SWR sweep controls in the spectrum overlay
menu. After a sweep completes, the collected samples (frequency + SWR) and
the band name already persist in m_swrSweep until an explicit clear or band
change, so the export is available whenever a trace is on the panadapter.

The button emits swrSweepSaveCsvRequested(); MainWindow::saveSwrSweepCsv()
opens a save dialog pre-filled with swr_sweep_<band>_<YYYYMMDD>_<HHMMSS>.csv
(defaulting to the Documents folder) and writes a "Frequency (Hz),SWR"
header followed by one row per sample. Guards cover an in-progress sweep,
an empty dataset, and a failed file open, each with a status-bar message.

This is part 1 of aethersdr#2241 (CSV export); the resonance/bandwidth markers and
user-bounded sweep range remain as separate follow-ups.

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, @M7HNF-Ian — nicely scoped and the error handling is genuinely solid. The three guards (in-progress sweep / empty dataset / failed open), the C-locale QString::number(..., 'f', 3) to avoid comma decimal separators breaking the CSV, and the filename sanitisation are all the right calls. Verified against MainWindow.h: every field referenced (m_swrSweep.running, .samples, .originalBandName, SwrSweepSample::freqMhz/swr) exists with matching types, <cmath> is already in the includes, and the signal→slot wiring is correct. All five files are within the stated CSV-export scope.

A couple of small, optional notes — none blocking:

  • llround unqualified (MainWindow_SwrSweep.cpp): <cmath> only guarantees std::llround; the global-namespace llround is technically provided by <cmath.h>/<math.h>. It compiles fine on libstdc++/libc++, but std::llround would be the strictly-portable form and matches the codebase's usual std:: prefixing.

  • Save button is always enabled: clicking it with no sweep data falls through to the friendly status-bar message, which is fine. If you'd like slightly tighter UX you could grey out m_swrSaveBtn until a trace exists, but the guard handles it gracefully as-is.

  • Last-used directory (future, not for this PR): the dialog always defaults to Documents. Remembering the last export location via AppSettings would be a nice follow-up, consistent with how the rest of the app persists paths.

The live FLEX-6600 test detail (18 points, dip ~14.31 MHz) is appreciated. Looks good to me.


🤖 aethersdr-agent · cost: $1.3793 · model: claude-opus-4-8

@ten9876 ten9876 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Verified the implementation:

  • Three guards (in-progress sweep / empty dataset / failed open), each with a clear status-bar or dialog message. Not a keying path — exports the already-captured m_swrSweep and refuses mid-sweep (Principle VI N/A).
  • Filename sanitization is solid[^A-Za-z0-9_-]_ on the band label (falls back to "band"), and the final path is user-chosen via QFileDialog anyway, so no traversal/injection concern.
  • CSV correctness — C-locale QString::number(swr, 'f', 3) (no comma-decimal break), integer Hz via llround(MHz×1e6), header + one row/sample, WriteOnly|Text|Truncate.
  • Signal→slot wiring correct; all referenced fields exist.

One non-blocking nit: llroundstd::llround for strict portability/convention (compiles fine on all three CI platforms as-is). Nice, well-scoped first contribution — thanks @M7HNF-Ian, and the live FLEX-6600 test detail is appreciated. CI green on all 6.

@ten9876 ten9876 merged commit f875853 into aethersdr:main Jun 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants