Skip to content

Spectroscopy physics review: qPlus setpoint gate, time-axis sanitisation, derivative units#27

Merged
jacobson30-bot merged 1 commit into
mainfrom
spectroscopy-physics-review
Jun 11, 2026
Merged

Spectroscopy physics review: qPlus setpoint gate, time-axis sanitisation, derivative units#27
jacobson30-bot merged 1 commit into
mainfrom
spectroscopy-physics-review

Conversation

@jacobson30-bot

Copy link
Copy Markdown
Contributor

Summary

Physics/maths correctness review of probeflow/spectroscopy + io/spectroscopy.py (first dedicated pass over this package).

Findings (physics-check format)

[CRITICAL] io/spectroscopy.py:341 — fixed
What: _createc_setpoint_a read SetPoint unconditionally as amps.
Why: on constant-Δf qPlus VERT files SetPoint is a frequency shift in Hz; the value feeds setpoint normalization, silently dividing displayed spectra by a frequency pretending to be a current (~10 orders of magnitude wrong, no error). Same bug class fixed for scan metadata in an earlier round — the spec path never got the gate.
Fix: share _createc_feedback_is_current with the scan path; qPlus files report no current setpoint and setpoint normalization now blocks with a clear error.

[WARN] io/spectroscopy.py time axis — fixed
What: x = idx / spec_freq with SpecFreq=0/negative/non-finite → inf or negative seconds.
Fix: sanitise to the documented 1000 Hz missing-value default with a log warning.

[INFO] spectroscopy/transforms.py:67 — fixed
What: derivative unit built via f"{y}/{x}".rstrip("/") collapsed empty-unit cases.
Fix: mirror SpectrumDeltaMeasurement.slope_unit (A/V, 1/V, or bare y-unit).

Verified clean: pipeline order (smoothing→derivative→normalization→outliers→offset, now pinned numerically), monotonicity-guarded np.gradient(y, x), forward+backward sweep refusal, all normalization denominator guards, channel-norm-with-derivative rejection, unit propagation to "relative", export round-trips.

Noted, unchanged: per-trace span normalization in nearest_point_across_traces mildly biases cross-trace click snapping; jump-mode outlier masking drops finite neighbours of NaN samples (defensible — their derivative is unknown).

Test plan

  • New tests/test_spectroscopy_physics.py (22 tests) covering the header→setpoint seam end-to-end, time-axis sanitisation, unit propagation, and pipeline-order invariants.
  • Full suite green locally: 2356 passed, 3 skipped.

🤖 Generated with Claude Code

…ative units

Physics review of the spectroscopy package (probeflow/spectroscopy +
io/spectroscopy.py), pinned by tests/test_spectroscopy_physics.py:

- _createc_setpoint_a read Current[A]/SetPoint unconditionally as amps: for
  a constant-delta-f qPlus .VERT (PLL on / FBChannel != 0) SetPoint is a
  frequency shift in hertz, so metadata carried e.g. setpoint_a = 3.2 "A"
  and setpoint normalization silently divided spectra by a frequency
  pretending to be a current (~10 orders of magnitude off, no error). The
  same bug was fixed for scan metadata earlier; the spectroscopy path now
  shares that gate (_createc_feedback_is_current), so a qPlus file reports
  no current setpoint and setpoint normalization blocks honestly.

- SpecFreq=0/negative/non-finite turned the whole time-trace x axis into
  inf or negative seconds (x = idx / spec_freq). Sanitised to the
  documented 1000 Hz missing-value default, with a log warning.

- Derivative unit propagation now mirrors SpectrumDeltaMeasurement.slope_unit:
  A/V for the usual case, 1/V when y is unitless ("A/" .rstrip slicing
  previously collapsed mixed cases), bare y unit when x is unitless.

Verified clean: pipeline order (smoothing -> derivative -> normalization ->
outliers -> offset, now pinned numerically), monotonicity-guarded
np.gradient(y, x), all four normalization modes raise on bad denominators,
channel-normalization-with-derivative rejected, forward+backward sweeps
refused. Noted unchanged: per-trace span normalization in
nearest_point_across_traces mildly biases cross-trace snapping; jump-mode
outlier masking excludes finite neighbours of NaN samples (defensible).

Co-Authored-By: Claude Fable 5 <[email protected]>
@jacobson30-bot jacobson30-bot merged commit 58f0ce2 into main Jun 11, 2026
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.

1 participant