Python API Reference

ftmwpipeline exposes two Python interfaces over one shared implementation:

  • the Pipeline class, bound to a single .ftmw file for its lifetime, and

  • a stateless functional API (import ftmwpipeline.api as ftmw) whose every function takes a .ftmw path as its first argument.

The two are thin wrappers around the same internal stage code, so they produce identical results for identical inputs; the functional API delegates to the Pipeline class internally. Use the class when you hold one experiment open and step it through the stages interactively; use the functional API for batch and scripting work where each call stands alone. Both surfaces persist their results into the file, so the choice of interface never changes what is stored. The command-line interface (Command-Line Reference) is the third wrapper over the same core.

Stage parameters resolve through the layered chain described in Settings and presets (explicit argument > value persisted in the file > preset > recommended default). Passing an explicit override to a stage method persists it as the file’s new canonical state and invalidates the downstream stages that depended on the old value.

Operations by stage

Each pipeline stage offers a matching pair of operations on both surfaces — a Pipeline method and a module-level function of the same name. The compute operation runs the stage and persists its result; the load_* operation reads a previously persisted result back; the visualize_* operation renders a diagnostic figure.

Stage

Compute (persist)

Read back / visualize

Import (Stage 0)

import_data()

load_fid()

Start detection

detect_start_time()

visualize_start_detection()

Fourier transform (Stage 1)

compute_ft()

visualize_ft()

Noise (Stage 2)

estimate_noise()

visualize_noise()

Decay time (Stage 2b)

calibrate_tau()

load_tau_calibration(), recommend_shape()

Timebase calibration

calibrate_timebase()

load_timebase_calibration()

Peaks (Stage 3)

detect_peaks()

load_peaks(), visualize_peaks()

Windows (Stage 4)

assign_windows()

load_windows(), visualize_windows()

Fit (Stage 5)

fit_peaks()

load_fit(), visualize_fit(), show_fit()

Review (Stage 6)

review_run()

get_review_status(), report_run(), report_diff()

To drive a raw source through every stage in one call, use run_pipeline() (functional) or Pipeline.build (class).

Pipeline class

class ftmwpipeline.pipeline.Pipeline(filepath: str | Path, source_metadata: SourceMetadata | None = None, stage_tracker: PipelineStageTracker | None = None)[source]

Object-oriented pipeline interface for FTMW spectroscopy data processing.

Each Pipeline instance is bound to a specific .ftmw pipeline file and provides high-level methods for data processing and analysis. This implements the object-oriented interface of the dual-interface architecture.

Key Features: - File-bound design: each instance manages one .ftmw pipeline file - Safe re-execution: methods can be called multiple times - Consistent with CLI: methods behave identically to CLI commands - Error handling: clear error messages using custom exceptions

Example Usage:

# Create new pipeline from raw data
pipe = Pipeline.create("exp_2638.ftmw", source='examples/blackchirp_data/2638/')

# Open existing pipeline for analysis
pipe = Pipeline.open("exp_2638.ftmw")

# Stage 1: FT Processing (canonical FT is unapodized, native-length)
pipe.compute_ft(trim=(26500, 40000))
pipe.visualize_ft(save_params=True)

# File info and validation
pipe.info()       # Show pipeline status and metadata
pipe.validate()   # Check file integrity
__init__(filepath: str | Path, source_metadata: SourceMetadata | None = None, stage_tracker: PipelineStageTracker | None = None)[source]

Bind a Pipeline instance to a specific .ftmw file.

Smart constructor: Pipeline(path) opens an existing pipeline file, raising FileNotFoundError with guidance if it does not exist. Use Pipeline.create() to make a new analysis from raw data.

Parameters:
  • filepath (str or Path) – Path to the pipeline file.

  • source_metadata (SourceMetadata, optional) – Source provenance. When omitted (the smart-constructor path) it is loaded from the file.

  • stage_tracker (PipelineStageTracker, optional) – Stage completion tracker. When omitted it is loaded from the file.

Notes

create() and open() supply both metadata arguments directly. Passing only a path performs the same load as open().

classmethod create(filepath: str | Path, source: str | Path, format_name: str | None = None, fid_index: int | None = None, force: bool = False, **loader_params: Any) Pipeline[source]

Create new pipeline from raw experimental data.

Parameters:
  • filepath (str or Path) – Path for new pipeline file (should have .ftmw extension)

  • source (str or Path) – Path to source data (file or directory)

  • format_name (str, optional) – Data format name. If None, auto-detect format.

  • fid_index (int, optional) – FID index for multi-FID formats (e.g., Blackchirp)

  • force (bool, default False) – If True, overwrite existing file even with different source

  • **loader_params – Additional parameters for data loader

Returns:

New Pipeline instance bound to the created file

Return type:

Pipeline

Raises:
classmethod open(filepath: str | Path) Pipeline[source]

Open existing pipeline file.

Parameters:

filepath (str or Path) – Path to existing pipeline file

Returns:

Pipeline instance bound to the opened file

Return type:

Pipeline

Raises:
classmethod build(source: str | Path, *, trim: Tuple[float, float] | None = None, output: str | Path | None = None, **kwargs: Any) Dict[str, Any][source]

Drive source through every stage end-to-end and return the result.

Convenience classmethod over run_pipeline_impl(): imports the raw source, then runs FT -> noise -> tau -> peaks -> windows -> fit -> timebase -> review (and, with report=True, the report), with live per-stage progress. trim (the active-band FT range, MHz) is required. output is the destination .ftmw (derived from source if omitted). Remaining keyword arguments are forwarded to run_pipeline_impl() (per-stage *_params override dicts, detect_start / calibrate / clocks, report / report_output_dir, sigma_floor_khz, force, progress, …).

Returns the structured run result (pipeline_file, status, completed_stages, failed_stage, error, timebase, report, elapsed_s). Open the finished file with Pipeline.open() (result["pipeline_file"]).

load_data() FID[source]

Load FID data from the pipeline file.

This method implements Stage 0 data loading, providing access to the raw FID data stored in the pipeline file.

Returns:

The loaded FID object with all metadata

Return type:

FID

Raises:
compute_ft(trim: Tuple[float, float] | None = None, start_us: float | None = None, end_us: float | None = None, units_power: int | None = None, from_saved_params: bool = False) ComplexFT[source]

Compute Fourier Transform (Stage 1, user-driven).

Resolves settings through explicit > persisted > recommended and persists the resolved canonical settings to the .ftmw file. Can be called multiple times safely. The canonical FT is unconditionally unapodized, un-windowed, and native-length.

Parameters:
  • trim (tuple of float, optional) – (min_mhz, max_mhz) frequency analysis range to keep.

  • start_us (float, optional) – FID window start time in microseconds.

  • end_us (float, optional) – FID window end time in microseconds.

  • units_power (int, optional) – Spectrum scaling as power of 10.

  • from_saved_params (bool, default False) – If True, ignore the explicit kwargs above and use only the persisted / recommended settings (no explicit overrides).

Returns:

Computed frequency-domain data.

Return type:

ComplexFT

Raises:
visualize_ft(trim: Tuple[float, float] | None = None, start_us: float | None = None, end_us: float | None = None, units_power: int | None = None, save_params: bool = False, interactive: bool = True, output_file: str | Path | None = None, show_fid_panels: bool = True) Any[source]

Create enhanced FT visualization with processing workflow display.

Equivalent to the CLI ft show command. Never persists settings; exploration only. Pass save_params=True to write the explicitly provided kwargs to the canonical ft_processing record. The canonical FT is unconditionally unapodized, un-windowed, and native-length.

Parameters:
  • trim (tuple of float, optional) – (min_mhz, max_mhz) frequency analysis range.

  • start_us (float, optional) – FID window start time in microseconds.

  • end_us (float, optional) – FID window end time in microseconds.

  • units_power (int, optional) – Spectrum scaling as power of 10.

  • save_params (bool, default False) – If True, persist the explicitly provided settings.

  • interactive (bool, default True) – Whether to show an interactive plot.

  • output_file (str or Path, optional) – Path to save the plot image (non-interactive mode).

  • show_fid_panels (bool, default True) – Whether to include FID processing panels.

Returns:

Matplotlib figure object.

Return type:

figure

Raises:
estimate_noise(*, settings: NoiseSettings | None = None, preset: str | None = None) NoiseResult[source]

Estimate frequency-dependent noise with the scatter estimator.

This method implements Stage 2 noise estimation, equivalent to the CLI noise run command. Requires Stage 1 (FT computation) to be completed.

The scatter estimator is high-pass and region-aware: it is immune to the leakage pedestal on high-SNR, line-dense spectra.

Parameters:
  • settings – Composable ways to drive the settings chain (a NoiseSettings bundle as the explicit override layer, a YAML preset’s stage2: block as the preset layer beneath the persisted record). Individual knobs (window_mhz / smoothing_mhz / smoothing_percentile / convolve_mhz / …) are set on the NoiseSettings instance; the explicit layer outranks the persisted record, which outranks the preset (per D11), so a no-arg call reproduces the persisted recipe.

  • preset – Composable ways to drive the settings chain (a NoiseSettings bundle as the explicit override layer, a YAML preset’s stage2: block as the preset layer beneath the persisted record). Individual knobs (window_mhz / smoothing_mhz / smoothing_percentile / convolve_mhz / …) are set on the NoiseSettings instance; the explicit layer outranks the persisted record, which outranks the preset (per D11), so a no-arg call reproduces the persisted recipe.

Returns:

Container with RMS noise estimate, noise mask, and diagnostics

Return type:

NoiseResult

Raises:
visualize_noise(y_max_factor: float | None = None, figsize: tuple | None = None, title: str | None = None, show_noise_points: bool | None = None, interactive: bool = True, output_file: str | Path | None = None, **plot_kwargs: Any) Any[source]

Create noise estimation diagnostic visualization.

This method creates diagnostic plots showing the spectrum, the noise points, and the per-bin σ estimate (with 3×/5×σ reference levels). Equivalent to the CLI noise show command.

Parameters:
  • y_max_factor (float, optional) – Y-axis maximum as multiple of median RMS noise (default: 20.0)

  • figsize (tuple, optional) – Figure size (width, height) in inches (default: (16, 6))

  • title (str, optional) – Custom title for the plot

  • show_noise_points (bool, optional) – Whether to highlight noise points (default: True)

  • interactive (bool, default True) – Whether to create interactive plots

  • output_file (str or Path, optional) – If provided, save plot to this file

  • **plot_kwargs – Additional plotting parameters

Returns:

The created figure object

Return type:

matplotlib.figure.Figure

Raises:
calibrate_tau(*, shape: str = 'lorentzian', settings: TauCalibrationSettings | None = None, preset: str | None = None) TauCalibrationResult[source]

Run the Stage 2b data-driven tau calibration.

Requires Stages 0-2 completed. Extracts a global majority-vote molecular decay constant tau_maj (with robust spread sigma_tau) from the raw FID by sliding a T_w = T_full / n_seg-long active sub-window across the zero-padded record and fitting a per-bin decay to the magnitude vs frame-start time.

shape selects the decay model and its persistence group: "lorentzian" (pure-exponential, /stage2b_tau_calibration; consumed by a shape='lorentzian' Stage 5 fit) or "gaussian" (pure-Gaussian envelope τ_G, /stage2b_tau_G_calibration; consumed by a shape='gaussian' fit). The result invalidates downstream stages.

Settings resolve through the chain (settings / preset > persisted > hard default); pass settings= to drive the calibration from a TauCalibrationSettings instance, or preset=NAME_OR_PATH to load from packaged YAML. They may be combined: the settings bundle is the explicit override that outranks the persisted record, while the preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11), so a no-arg follow-up call reproduces the previously resolved settings (stamped to the shared processing_parameters/stage2b_tau block both shape variants use).

load_tau_calibration(*, shape: str = 'lorentzian') TauCalibrationResult[source]

Load the persisted Stage 2b TauCalibrationResult for shape.

calibrate_timebase(*, clocks: Any | None = None, kappa_sys: float | None = None, snr_min: float | None = None) TimebaseCalibrationResult[source]

Measure the scope-timebase scale error eps from Rb-locked tones.

Requires Stage 0 (the raw FID); the canonical Stage 1 active-region bounds are read opportunistically. Resolves the instrument clock declaration from the explicit clocks argument, else the persisted Stage 5 spur.clocks; raises ValueError if neither yields a non-empty declaration with at least one locked source. Persists the measured eps to /timebase_calibration. Measures eps only; applying it to the frequency axis is out of scope.

load_timebase_calibration() TimebaseCalibrationResult[source]

Load the persisted TimebaseCalibrationResult.

get_clock_sources() Tuple[ClockSource, ...] | None[source]

Return the declared (recommended) instrument clock sources, or None.

These are the clock fundamentals the Stage 5 spur gate builds its lattice prior from. The declaration is the recommended resolver layer; an explicit clocks= at fit time and persisted Stage 5 settings still outrank it.

set_clock_sources(clocks: Any, *, replace: bool = True) Tuple[ClockSource, ...][source]

Declare instrument clock sources on this experiment.

clocks is a sequence of ClockSource or {freq_mhz, locked, label} mappings. With replace=False the sources are appended to the current declaration. Declare chain fundamentals (e.g. 5760, not the 11520 product). Returns the resulting declaration. Writes the recommended layer, so the D11 reproducibility guarantee holds.

remove_clock_sources(freqs_mhz: Sequence[float]) Tuple[ClockSource, ...][source]

Remove declared clock sources matching the given frequencies (MHz).

clear_clock_sources() None[source]

Clear the clock-source declaration on this experiment.

recommend_shape(*, settings: TauCalibrationSettings | None = None, preset: str | None = None) ShapeRecommendation[source]

Run the 3-way L/G/V per-bin AICc shape-recommendation hook.

Mirrors the τ calibrations’ STFT classifier and per-bin fit machinery, then fits exp / gauss / voigt on every contributor bin, computes AICc per bin, and aggregates an SNR-weighted majority vote. The verdict’s recommended_shape ("lorentzian" / "gaussian" / None) is stamped onto every Stage 2b group present on the file so the Stage 5 resolver’s recommended layer picks it up automatically. The Voigt vote mass is reported as a diagnostic but does not enter the recommendation (the production Stage 5 line-shape selector supports L and G only).

Requires Stage 1 (active region + frequency trim) to have completed. The Stage 2b calibrations are not required for the verdict itself, but the persisted contract only fires when at least one of them has run; without a Stage 2b group the verdict is returned but no attr is stamped.

Settings resolve through the chain (settings / preset > persisted > hard default); settings= and preset= may be combined – the settings bundle is the explicit override that outranks the persisted record, while the preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). The resolved settings are stamped to processing_parameters/stage2b_tau so a follow-up no-arg call inherits the same recipe.

visualize_tau_heatmap(output_file: str | Path | None = None, interactive: bool = True, figsize: tuple | None = None, shape: str = 'lorentzian') Any[source]

Render the 2D STFT-magnitude heatmap (frame x molecular frequency).

shape selects the pure-exp ("lorentzian") or Gaussian ("gaussian") Stage 2b calibration group.

visualize_tau_distribution(output_file: str | Path | None = None, interactive: bool = True, figsize: tuple | None = None, shape: str = 'lorentzian') Any[source]

Render the tau-distribution analysis panel.

shape selects the pure-exp ("lorentzian") or Gaussian ("gaussian") Stage 2b calibration group.

detect_start_time(*, band: Tuple[float, float] | None = None, stamp: bool = True, settings: StartDetectionSettings | None = None) StartDetectionResult[source]

Infer a good FID start_us from the data and stamp it.

Sweeps the FID window start time, integrates the FT magnitude over the active band, and locates the chirp-end collapse; the recommended start is chirp_end + guard_margin_us (the switch-bounce settling time). When stamp=True (default) the recommended start_us is written to the Stage 0 recommended_processing layer, so a later compute_ft with no explicit start_us inherits it. Requires Stage 0 (FID) only; the integration band is resolved from the canonical Stage 1 trim when present, else the full positive spectrum. Equivalent to the CLI start run command and ftmwpipeline.api.detect_start_time.

Parameters:
  • band (tuple of float, optional) – Explicit (min_mhz, max_mhz) integration band override (a convenience for settings band_min_mhz / band_max_mhz).

  • stamp (bool, default True) – Whether to persist the recommended start_us to the recommended layer.

  • settings (StartDetectionSettings, optional) – The detection knobs. Unlike the resolver-backed stages, Stage 0 is a flat bundle with concrete defaults: construct a StartDetectionSettings with the fields to override (sweep_max_us / step_us / guard_margin_us / floor_factor / …). band wins over the bundle’s band fields when supplied.

Returns:

The recommendation plus diagnostics (chirp-end, sweep arrays).

Return type:

StartDetectionResult

visualize_start_detection(output_file: str | Path | None = None, interactive: bool = True, figsize: tuple | None = None, *, settings: StartDetectionSettings | None = None) Any[source]

Render the start-detection sweep diagnostic (no stamping).

detect_peaks(*, settings: PeakDetectionSettings | None = None, preset: str | None = None) List[Peak][source]

Detect and classify peaks (Stage 3, two-pass).

Requires Stage 1 (FT) and Stage 2 (noise) completed. Runs an apodized (Blackman-Harris) primary pass for the robust strong-line list plus a shape-aware matched-filter gap pass that recovers weak lines the apodization smears; both raise their detection floor continuously by the local coherent-leakage amplitude rather than a hard mask. Every peak is then scored (amplitude + SNR) on the canonical unapodized active FT, classified by SNR, and ALL detected peaks are persisted to the .ftmw file. Equivalent to the CLI peaks run command and ftmwpipeline.api.detect_peaks.

Detection operates on the Stage 1 persisted canonical spectrum, including its frequency trim range. Peaks are reported on that user grid with amplitude and SNR measured against the canonical Stage 2 noise. There is no per-Stage-3 trim or zpf.

Settings resolve through the chain (settings / preset > persisted > hard default); pass settings= to drive detection from a PeakDetectionSettings instance, or preset=NAME_OR_PATH to load from packaged YAML. They may be combined: a settings bundle is the explicit override that outranks the persisted record, while a preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs via settings=PeakDetectionSettings(...) or a YAML preset’s stage3: block.

Parameters:
  • settings (PeakDetectionSettings, optional) – Bundle of Stage 3 knobs; fields left None fall through the resolution chain. May be combined with preset.

  • preset (str, optional) – Bare preset name or path to a YAML file carrying a stage3: block. Seeds the preset layer beneath the persisted record; may be combined with settings.

Returns:

ALL detected peaks (promoted and non-promoted), sorted by frequency. Each peak’s properties dict includes promoted (bool), internal_snr, internal_frequency, and detection_pass.

Return type:

list of Peak

Raises:
load_peaks() List[Peak][source]

Load the persisted Stage 3 peak list (validates structure loudly).

visualize_peaks(figsize: tuple | None = None, title: str | None = None, y_max_factor: float | None = None, interactive: bool = True, output_file: str | Path | None = None, show_snr_histogram: bool = False) Any[source]

Overlay classified detected peaks on the unapodized spectrum (Stage 3).

Equivalent to the CLI peaks show command. Interactive matplotlib (log-y) by default; pass interactive=False with output_file to save instead.

Parameters:
  • figsize (tuple, optional) – Figure size (width, height) in inches.

  • title (str, optional) – Custom plot title.

  • y_max_factor (float, optional) – Y-axis max as multiple of median RMS noise (default 25.0).

  • interactive (bool, default True) – Whether to open an interactive window.

  • output_file (str or Path, optional) – Save plot to this path (non-interactive mode).

  • show_snr_histogram (bool, default False) – If True, add a second panel showing the user-grid SNR distribution with the promotion cutoff marked (curation view).

Returns:

Matplotlib figure (single-panel or two-panel when show_snr_histogram=True).

Return type:

figure

Raises:

RuntimeError – If Stage 3 has not been completed or visualization fails.

assign_windows(*, settings: WindowPlanningSettings | None = None, preset: str | None = None) WindowPlan[source]

Assign analysis windows (Stage 4), turning promoted peaks into a fit plan.

Requires Stage 3 (peak detection) completed. Builds a set of disjoint fit windows over the persisted user spectrum, each annotated with the peaks to fit freely, the strong out-of-band lines whose leakage is carried frozen, and a fit dependency order. Stage 4 is purely structural – it makes no fits. Equivalent to the CLI windows run command and ftmwpipeline.api.assign_windows.

Consumes only the peaks flagged promoted by Stage 3, on the Stage 1 canonical spectrum with the canonical Stage 2 noise. The result is persisted to /stage4_windows and the stage marked complete.

Settings resolve through the chain (settings / preset > persisted > hard default); pass settings= to drive window planning from a WindowPlanningSettings instance, or preset=NAME_OR_PATH to load from packaged YAML. They may be combined: a settings bundle is the explicit override that outranks the persisted record, while a preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs via settings=WindowPlanningSettings(...) or a YAML preset’s stage4: block.

Parameters:
  • settings (WindowPlanningSettings, optional) – Bundle of Stage 4 knobs; fields left None fall through the resolution chain. May be combined with preset.

  • preset (str, optional) – Bare preset name or path to a YAML file carrying a stage4: block. Seeds the preset layer beneath the persisted record; may be combined with settings.

Returns:

The fit plan: disjoint windows, dependency DAG, topological order, parallel batches, parameters and diagnostics.

Return type:

WindowPlan

Raises:
load_windows() WindowPlan[source]

Load the persisted Stage 4 window plan (validates structure loudly).

visualize_windows(figsize: tuple | None = None, title: str | None = None, y_max_factor: float | None = None, interactive: bool = True, output_file: str | Path | None = None) Any[source]

Overlay the Stage 4 window plan on the spectrum.

Equivalent to the CLI windows show command. Shows each fit window’s span, free peaks, fixed contributors, and the rolling complex-edge coherence statistic. Requires Stage 4 completed.

Parameters:
  • figsize (tuple, optional) – Figure size (width, height) in inches.

  • title (str, optional) – Custom plot title.

  • y_max_factor (float, optional) – Spectrum-panel y-axis headroom (default 25.0).

  • interactive (bool, default True) – Whether to open an interactive window.

  • output_file (str or Path, optional) – Save plot to this path (non-interactive mode).

Returns:

Matplotlib figure.

Return type:

figure

Raises:

RuntimeError – If Stage 4 has not been completed or visualization fails.

fit_peaks(*, shape: str | None = None, tau_maj_override_us: float | None = None, sigma_tau_override_us: float | None = None, settings: StageFitSettings | None = None, preset: str | None = None, jobs: int | None = None) SpectrumFit[source]

Fit each Stage 4 window’s lines (Stage 5).

Requires Stage 4 (window assignment) completed. Drives the conservative add-one-peak loop over each window with the shared per-window decay tau and the frozen-contributor model, then the residual edge-coherence handshake (local thaw + structural replan). Equivalent to the CLI fit run command and ftmwpipeline.api.fit_peaks.

The fit runs on the active-portion FT (computed on demand from the FID + canonical Stage 1 settings), so per-bin statistics are independent and reduced chi-squared / F-test / AIC are calibrated as written. The persistent SpectrumFit – per-window FittingResult s, the merged global fitted-peak list, the thaw / replan histories, and the parameters used – is written to /stage5_fitting.

Settings resolve through the chain (settings / preset > persisted > recommended > hard default); pass settings= to drive the fit from a StageFitSettings instance, or preset=NAME_OR_PATH to load from packaged YAML. They may be combined: a settings bundle outranks a value persisted in the .ftmw while a preset .yml seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11).

Parameters:
  • shape ({"lorentzian", "gaussian"}, optional) – Time-domain envelope of the per-line model, kept as a first-class convenience argument. "lorentzian" uses exp(-t/τ); "gaussian" uses exp(-(t/τ_G)²) and consumes the Stage 2b τ_G calibration (calibrate_tau(shape="gaussian")) in place of the pure-exp variant for the bidirectional τ anchoring penalty. None falls through to the resolved settings (preset / persisted / default).

  • tau_maj_override_us (float, optional) – Atomic-pair manual override for the Stage 2b tau calibration, kept as explicit arguments (an A/B escape hatch crossing a stage boundary, not a fit knob). When both are supplied (positive), they replace any persisted Stage 2b result for this fit. Supplying only one of the pair raises ValueError.

  • sigma_tau_override_us (float, optional) – Atomic-pair manual override for the Stage 2b tau calibration, kept as explicit arguments (an A/B escape hatch crossing a stage boundary, not a fit knob). When both are supplied (positive), they replace any persisted Stage 2b result for this fit. Supplying only one of the pair raises ValueError.

  • settings (StageFitSettings, optional) – Bundle of Stage 5 knobs; fields left None fall through the resolution chain. Resolves at the explicit override layer (outranks the persisted record). Build with StageFitSettings. May be combined with preset.

  • preset (str, optional) – Bare preset name (e.g. "defaults") or a path to a YAML file carrying a stage5: block. Enters at the preset layer (a persisted .ftmw outranks it). The preset name is captured in the persisted Stage 5 fit’s audit attrs for reproducibility. May be combined with settings.

  • jobs (int, optional) – Worker-pool size for the cross-window parallel fit. None (the default) resolves the pool from the FTMW_MAX_WORKERS environment variable, falling back to cpu_count() - 2; 1 forces a sequential fit. The fit result is byte-identical regardless of the worker count.

Returns:

The persistent fit aggregate.

Return type:

SpectrumFit

Raises:
load_fit() SpectrumFit[source]

Load the persisted Stage 5 fit (validates structure loudly).

candidate_ledger(window_id: int | None = None, *, bar: float = 4.0) List[LedgerCandidate][source]

Derive the Stage 6 candidate ledger from the persisted Stage 5 fit.

Returns revivable candidates from the conservative add-loop and rescue records – candidates that were considered but not accepted by the automatic fit. The ledger is derived on demand from the already-persisted audit trail; it does not re-fit anything.

Parameters:
  • window_id – When given, return candidates for that window only.

  • bar – Display SNR / evidence bar; candidates below it are dropped.

Returns:

  • list of LedgerCandidate – Sorted by molecular frequency.

  • Requires Stage 5 completed.

review_edit(window_id: int, *, add: Sequence[float] = (), remove: Sequence[float] = (), snap_tol_mhz: float = 0.05) RefitWindowResult[source]

User-directed single-window refit (Stage 6 review edit).

Re-fits window_id from the persisted Stage 5 fit using the production NLS primitive, applying add/remove edits. User- added peaks carry origin="user" and survive the HDF5 round-trip; removed peaks are excluded from the refit and will not be re-added by the rescue pass.

Parameters:
  • window_id – The window to refit.

  • add – Molecular frequencies (MHz) of peaks to add. Snapped to the nearest ledger candidate within snap_tol_mhz or seeded fresh at F.

  • remove – Molecular frequencies (MHz) of fitted peaks to remove. Snapped to the nearest fitted peak within snap_tol_mhz.

  • snap_tol_mhz – Snap tolerance for add/remove (MHz; default 0.05 = 50 kHz).

Returns:

  • RefitWindowResult – Old vs new peak count, χ²ᵣ before/after, and the new fitted peaks.

  • Requires Stage 5 completed.

review_merge(window_id: int, peaks: Sequence[float], *, snap_tol_mhz: float = 0.05) RefitWindowResult[source]

Collapse ≥2 fitted peaks in a window into one (Stage 6 review merge).

Removes the named peaks and adds one replacement seeded at their SNR-weighted centroid (or amplitude-weighted centroid when SNR is unavailable). When the pair matches a persisted doublet-alternative record with a successful merged refit, the recorded merged seed is used instead of the centroid. All products carry origin="user".

Parameters:
  • window_id – The window containing the peaks to merge.

  • peaks – Molecular frequencies (MHz) of the peaks to collapse (≥2).

  • snap_tol_mhz – Maximum distance (MHz) for frequency snapping to fitted peaks.

Returns:

  • RefitWindowResult – Old vs new peak count, χ²ᵣ before/after, and the new fitted peaks.

  • Requires Stage 5 completed.

review_split(window_id: int, peak: float, *, into: int = 2, snap_tol_mhz: float = 0.05) RefitWindowResult[source]

Replace one fitted peak with into peaks (Stage 6 review split).

Removes the named peak and adds into replacements spread symmetrically about it by ±½ of one Fourier resolution element (1 / acquisition_us MHz). All products carry origin="user".

Parameters:
  • window_id – The window containing the peak to split.

  • peak – Molecular frequency (MHz) of the peak to split.

  • into – Number of replacement peaks (≥2, default 2).

  • snap_tol_mhz – Maximum distance (MHz) for frequency snapping to fitted peaks.

Returns:

  • RefitWindowResult – Old vs new peak count, χ²ᵣ before/after, and the new fitted peaks.

  • Requires Stage 5 completed.

review_run(*, bar: float = 4.0, attention_candidate_evidence: float = 10.0, sigma_floor_khz: float | None = None) ReviewRunResult[source]

Build or refresh the Stage 6 curation layer and final-products table.

Computes advisory attention reasons for each fitted window, consolidates the calibrated final-products table (timebase-corrected frequencies + the three-term sigma_f budget), persists the Stage6Review to the stage6_review HDF5 group, and marks the stage complete.

Existing per-window provenance ("reviewed"/"user-edited") and the decision log are preserved; only attention reasons are refreshed.

Parameters:
  • bar – Display bar for the candidate-bearing attention reason.

  • attention_candidate_evidence – Evidence threshold above which a candidate-bearing window flags (stiffer than bar; keeps the attention surface actionable).

  • sigma_floor_khz – When given, persist this user-declared accuracy floor (kHz) into the file-level /frequency_calibration record and fold it into the budget. None (default) keeps the persisted floor unchanged.

Returns:

  • ReviewRunResult – Total window count, attention count, and per-kind breakdown.

  • Requires Stage 5 completed.

set_sigma_floor(sigma_floor_khz: float) None[source]

Declare the systematic frequency-accuracy floor (kHz), persisted in-file.

Stores the floor as file-level provenance (/frequency_calibration) so any reported sigma_f is reproducible from the record alone. Call review_run() afterwards to fold the new floor into the budget.

final_products() FinalProducts | None[source]

Return the persisted Stage 6 calibrated final-products table.

Read-only; None until review_run() has built it.

report_table(*, fmt: str = 'csv', output: str | Path | None = None, catalog: str | Path | None = None, catalog_n_sigma: float = 3.0) str[source]

Render the calibrated final-products table (report Level 1).

Serializes the persisted FinalProducts table to csv, json, or a LaTeX booktabs table. Renders the persisted record; does not recompute. Requires review_run() to have built the table.

Parameters:
  • fmt"csv" (default), "json", or "latex".

  • output – When given, also write the rendered text to this path.

  • catalog – Optional frequency-catalog path; when given, each line is proximity-flagged against the nearest catalog entry (label echo only, never an assignment) and the match is added to the output.

  • catalog_n_sigma – Catalog match tolerance in combined sigmas (default 3).

Returns:

The rendered table.

Return type:

str

report_run(*, output_dir: str | Path | None = None, windows: str = 'all', emit_table: bool = True, emit_html: bool = True, table_format: str = 'csv', scope: str = 'full', catalog: str | Path | None = None, catalog_n_sigma: float = 3.0, jobs: int | None = None) Dict[str, str | None][source]

Write the default Stage 6 deliverables: the L1 table + the L3 report.

Writes the Level-1 final-products table (<stem>_lines.csv) and the self-contained Level-3 HTML report with every window folded in (<stem>_report.html) into output_dir, reusing the existing renderers. Renders the persisted record; does not recompute. Requires review_run() to have built the final-products table.

Parameters:
  • output_dir – Directory to write the artifacts into (created if absent). Defaults to the current working directory when omitted.

  • windows"all" (a detail page per window) or "attention" (pages only for review-flagged windows). The index always lists every window.

  • emit_table – Write the Level-1 table artifact (default True).

  • emit_html – Write the Level-3 HTML report (default True).

  • table_format – Format for the table artifact: "csv" (default), "json", or "latex".

  • scope"full" (default) writes one self-contained <stem>_report.html with every per-window detail folded in; "summary" writes <stem>_report_summary.html (index + methods only). Either way the output is a single self-contained file.

  • catalog – Optional frequency-catalog path; adds proximity-match cross-references to the table and HTML (label echo only, never an assignment).

  • catalog_n_sigma – Catalog match tolerance in combined sigmas (default 3).

  • jobs – Worker-pool size for the per-window figure rendering. None (the default) resolves the pool from the FTMW_MAX_WORKERS environment variable, falling back to cpu_count() - 2; 1 renders sequentially.

Returns:

{"table": <path|None>, "html": <path|None>} – the path of each artifact written (None when suppressed).

Return type:

dict

report_diff(*, output_dir: str | Path | None = None, dpi: int = 110) str[source]

Render the post-curation before/after diff report; return its path.

Compares the automatic-fit baseline snapshot with the current curated fit and writes a self-contained <stem>_diff.html with a side-by-side panel for every window that differs materially – both the windows edited directly and the dependents the contributor-edit cascade changed – so the changes can be evaluated before they are committed. When no curation edit has been made (no baseline snapshot exists), a report stating that is written instead. Read-only; never recomputes the fit.

Parameters:
  • output_dir – Directory to write the report into (created if absent). Defaults to the current working directory.

  • dpi – Resolution for the per-window panels.

Returns:

Path to the generated <stem>_diff.html file.

Return type:

str

review_accept(window_id: int, *, candidate_freq: float | None = None) RefitWindowResult | None[source]

Accept a window as-is or accept a specific revived candidate.

With no candidate_freq: records a "accept" log entry, sets the window’s provenance to "reviewed", and returns None. The fit is left unchanged; the acceptance is a “looked, no change needed” decision.

With candidate_freq: adds the candidate peak via a single-window refit, records an "add" log entry, sets provenance to "user-edited", and returns the RefitWindowResult.

Parameters:
  • window_id – The window to accept.

  • candidate_freq – When given, accept by adding this molecular frequency (MHz) as a new peak. Snapped to the nearest ledger candidate within 50 kHz.

Return type:

RefitWindowResult or None

review_apply(curation_path: str | Path, *, dry_run: bool = False) CurationApplyResult[source]

Apply a curation file of batched review edits.

Replays a curation CSV (action,window,freqs,params rows) through the same edit impls the interactive verbs use: a run of add/remove rows on one window coalesces into a single refit, while merge/split/accept stand alone. With dry_run the resolved plan and any frequency-resolution warnings are returned without modifying the file.

Parameters:
  • curation_path – Path to the curation CSV to apply.

  • dry_run – Preview the resolved plan without writing (default False).

Returns:

The resolved action plan, warnings, and the number applied.

Return type:

CurationApplyResult

review_log() List[DecisionLogEntry][source]

Return the persisted Stage 6 decision log (read-only, in order).

Returns:

Every recorded user decision, keyed by order_index.

Return type:

list of DecisionLogEntry

review_undo(ids: Sequence[int], *, dry_run: bool = False) UndoResult[source]

Undo recorded decisions by id, replaying the rest from baseline.

Restores the automatic Stage 5 fit (snapshotted before the first edit), rebuilds the review from it, and re-applies every surviving decision, so decision ids are renumbered afterward. dry_run previews the removed/ surviving split and the replay plan without writing.

Parameters:
  • ids – Decision ids (order_index values from review_log()) to undo.

  • dry_run – Preview without mutating (default False).

Return type:

UndoResult

Raises:

ValueError – If an id is unknown, there are no decisions, or the automatic-fit baseline is unavailable while fit-mutating decisions exist.

review_status() Stage6Review[source]

Load the persisted Stage 6 review state, or return an empty one.

Read-only: safe to call before review run.

Returns:

The persisted per-window statuses and decision log.

Return type:

Stage6Review

rank_windows(by: str, *, top: int | None = None) List[RankedWindow][source]

Rank fit windows by a persisted per-window statistic (read-only).

On-demand exploration decoupled from the attention flags: ranks all windows worst-first by by (see RANK_METRICS for the choices – min-snr, max-vif, chi2r, candidate-evidence, edge-distance, spur-proximity, merged-chi2r).

Parameters:
  • by – Metric name (_ and - interchangeable).

  • top – Return at most this many windows; None returns all.

  • completed. (Requires Stage 5)

validate_stage5_shape_error(kappa: float | None = None, noise_floor: float | None = None, ground_truth: str | Path | None = None, match_tol_fwhm: float = 0.5) Dict[str, Any][source]

Assess the persisted Stage 5 fit against the SNR-aware framework.

Read-only. Returns a Tier 1 (SNR-aware per-window acceptance chi2r <= F + (kappa*SNR_max)**2 with the fractional deficit eps binned by SNR) / Tier 2 (rescue/merge/thaw gate firing) / Tier 3 (known-line ground truth, when ground_truth is given) report. Equivalent to the CLI fit check command. Requires Stage 5 completed.

visualize_fit(figsize: tuple | None = None, title: str | None = None, window_id: int | None = None, interactive: bool = True, output_file: str | Path | None = None) Any[source]

Overlay the Stage 5 fit on the spectrum.

Equivalent to the CLI fit show command. With window_id set, draws a per-window detail figure (re/im, magnitude+residual, time envelope, audit-trail); otherwise an overview overlay of the fitted model on the persisted spectrum. Requires Stage 5 completed.

show_fit(*, window_ids: list | None = None, freqs: list | None = None, random_n: int | None = None, random_seed: int | None = None, top_snr: int | None = None, all_windows: bool = False, output_dir: str | Path | None = None, show_audit: bool = False, apodize: str | None = None, apodize_us: float | None = None, rescue: bool = False, figsize: tuple | None = None, title: str | None = None, interactive: bool = False) Dict[str, Any][source]

Show the Stage 5 fit – overview, or a consolidated per-window detail figure for each selected window.

Equivalent to the CLI fit show command. With no selector, returns the spectrum-wide overview. The selectors (window_ids / freqs / random_n / top_snr / all_windows) compose as a union; with output_dir each detail figure is written as <stem>_window_<id>.png. With rescue an extra residual-rescue summary figure is produced per window (no re-fit): data/model, the final residual with each round’s nominations, the chi-squared trajectory, and the peak budget. Returns {"mode", "window_ids", "figures", "paths", "log"}. Requires Stage 5.

info() Dict[str, Any][source]

Get pipeline file information and status.

Returns:

Pipeline status and metadata information

Return type:

dict

validate() Dict[str, Any][source]

Validate pipeline file integrity.

Returns:

Detailed validation report

Return type:

dict

Raises:

PipelineCorruptionError – If file is corrupted and cannot be validated

static scan_list(selector: str | None = None, *, include_advanced: bool = False) Tuple[KnobSpec, ...][source]

List the registered tunable knobs.

Equivalent to ftmwpipeline.api.scan_list(). The returned KnobSpec tuple is independent of any file, so this is a staticmethod; it is exposed on the class for dual-interface parity. selector filters by dotted-path prefix (e.g. "stage2b" / "stage2b.gaussian"); include_advanced reveals advanced-tier knobs hidden from the default listing.

scan_run(knob: str, grid: Sequence[Any] | None = None, output_dir: str | Path | None = None, reuse: bool = False, make_plot: bool = True, quiet: bool = False, zoom_regions: Sequence[Tuple[float, float]] | None = None, n_zoom: int | None = None, zoom_width_mhz: float | None = None, fit_top_snr: int = 3, fit_sample: int = 20, fit_freqs: Sequence[float] | None = None, fit_sample_seed: int = 0, fit_all: bool = False) SweepResult[source]

Sweep a single knob across a grid on a copy of this file.

Equivalent to ftmwpipeline.api.scan_run(). Re-runs the knob’s stage for each grid value on a working copy (this file is never mutated), returning a SweepResult with the table, CSV path, optional plot, recommendation, and how-to-apply instructions. A progress indicator is printed to stderr unless quiet=True.

zoom_regions pins explicit (lo_mhz, hi_mhz) windows for the region-based plot adapters (Stage 3 / Stage 4), overriding their divergence auto-selection; n_zoom / zoom_width_mhz instead tune how many regions to auto-select and how wide each is. The fit_* controls bound a Stage 5 fit sweep to a window subset (the fit_top_snr brightest + a seeded fit_sample sample + the windows nearest fit_freqs); fit_all re-fits every window.

scan_all(selector: str | None = None, *, include_advanced: bool = False, output_dir: str | Path | None = None, reuse: bool = False, make_plot: bool = True, quiet: bool = False, zoom_regions: Sequence[Tuple[float, float]] | None = None, n_zoom: int | None = None, zoom_width_mhz: float | None = None, fit_top_snr: int = 3, fit_sample: int = 20, fit_freqs: Sequence[float] | None = None, fit_sample_seed: int = 0, fit_all: bool = False) List[BatchItem][source]

Sweep every knob matched by selector on its default grid.

Equivalent to ftmwpipeline.api.scan_all(). A convenience over scan_run() for reviewing a whole stage / sub-block at once: selector filters by dotted-path prefix (e.g. "stage2b" / "stage2b.gaussian") exactly as scan_list(), and include_advanced adds the advanced-tier knobs. Each knob runs on its own working copy (this file is never mutated); a knob whose scan fails (e.g. its required stage is absent) is recorded as a failed BatchItem and the batch continues. The zoom_* controls apply the same explicit-regions / count-width steering to every knob’s plot.

settings_show(selector: str | None = None, *, include_advanced: bool = False, preset: str | Path | None = None) Tuple[SettingRow, ...][source]

Resolved value + provenance for each covered setting of this file.

Equivalent to ftmwpipeline.api.settings_show(). Returns one SettingRow per setting – its path, the resolved value, the source layer that supplied it (.ftmw / .yml:<name> / recommended / default), the hard_default for reference, and the registry tier / help enrichment. selector filters by dotted-path prefix (e.g. "stage2b" / "stage2b.gaussian"); include_advanced reveals advanced-tier rows; preset (a bare name or YAML path) populates the .yml provenance layer. Because a persisted .ftmw value outranks a preset, a named preset changes the resolved view only for fields the file has not persisted.

settings_set(knob: str, value: str) SetResult[source]

Persist a chosen value for knob into this file’s persisted layer.

Equivalent to ftmwpipeline.api.settings_set(). knob is a dotted settings path (stage2.window_mhz / stage5.tau.max_decay_factor); value is the string form, coerced to the field’s type. Because the stored stage results were computed against the old value, the affected stage and all downstream stages are invalidated (their results dropped and completion cleared) so the file never carries results inconsistent with its settings. Stage 1 data-selection knobs (stage1.start_us / stage1.end_us / stage1.trim_min_mhz / stage1.trim_max_mhz / stage1.units_power) may also be set here, equivalently to passing them to compute_ft(). Returns a SetResult with the invalidated stage names.

settings_export(out_path: str | Path, selector: str | None = None, *, name: str | None = None, description: str | None = None) ExportResult[source]

Write this file’s chosen Stage 2–5 values to a .yml preset block.

Equivalent to ftmwpipeline.api.settings_export(). Each stage’s persisted settings are serialized into the matching stageN: block, filtered by the dotted selector; the result loads back through the stages’ --preset path. Stage 1 is excluded (presets do not carry FT settings). Returns an ExportResult with the written path and the exported setting paths.

__repr__() str[source]

String representation of Pipeline instance.

Functional API

Functional API for FTMW Pipeline - Stateless file-based operations.

This module provides a functional, stateless API for FTMW spectroscopy data processing as an alternative to the object-oriented Pipeline class. All functions operate on .ftmw file paths and delegate to the Pipeline class internally to ensure identical behavior and avoid code duplication.

Key Features: - File-centric design: All functions take .ftmw file paths as first argument - Stateless: Each function call is independent, no shared state - Consistent: Same behavior as Pipeline class methods - Efficient: Leverages existing tested implementations

Example Usage:

import ftmwpipeline.api as ftmw

# Create pipeline from data
ftmw.import_data("experiment.ftmw", source="examples/blackchirp_data/2638/")

# Load and process data
fid = ftmw.load_fid("experiment.ftmw")
complex_ft = ftmw.compute_ft("experiment.ftmw", trim=(26500, 40000))

# Visualization and parameter management
ftmw.visualize_ft("experiment.ftmw", save_params=True)
ftmw.save_ft_parameters("experiment.ftmw", {'trim': (26500, 40000)})

# File management
info = ftmw.get_pipeline_info("experiment.ftmw")
stages = ftmw.list_available_stages("experiment.ftmw")
ftmwpipeline.api.import_data(file_path: str | Path, source: str | Path, format_name: str | None = None, fid_index: int | None = None, force: bool = False, **loader_params: Any) Dict[str, Any][source]

Create new pipeline from raw experimental data.

This function creates a new .ftmw pipeline file from experimental data, equivalent to Pipeline.create(). It handles format detection, data loading, and source metadata tracking.

Parameters:
  • file_path (str or Path) – Path for new pipeline file (should have .ftmw extension)

  • source (str or Path) – Path to source data (file or directory)

  • format_name (str, optional) – Data format name. If None, auto-detect format.

  • fid_index (int, optional) – FID index for multi-FID formats (e.g., Blackchirp)

  • force (bool, default False) – If True, overwrite existing file even with different source

  • **loader_params – Additional parameters for data loader

Returns:

Import result with pipeline file path, source info, and FID metadata

Return type:

dict

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> result = ftmw.import_data("exp_2638.ftmw",
...                           source="examples/blackchirp_data/2638/")
>>> print(f"Created: {result['pipeline_file']}")
ftmwpipeline.api.get_clock_sources(file_path: str | Path) Tuple[ClockSource, ...] | None[source]

Return the declared (recommended) instrument clock sources, or None.

These clock fundamentals seed the Stage 5 spur-gate lattice. The declaration is the recommended resolver layer; an explicit clocks= at fit time and persisted Stage 5 settings outrank it.

Parameters:

file_path (str or Path) – Path to an existing .ftmw pipeline file.

Examples

>>> import ftmwpipeline.api as ftmw
>>> ftmw.get_clock_sources("exp_2638.ftmw")
ftmwpipeline.api.set_clock_sources(file_path: str | Path, clocks: Any, *, replace: bool = True) Tuple[ClockSource, ...][source]

Declare instrument clock sources on an existing experiment.

clocks is a sequence of ClockSource or {freq_mhz, locked, label} mappings. Declare chain fundamentals (e.g. 5760, not the 11520 product). With replace=False the sources are appended to the current declaration. Returns the resulting declaration.

The declaration is written to the recommended layer, so it never overrides a persisted Stage 5 setting (the D11 reproducibility guarantee).

Examples

>>> import ftmwpipeline.api as ftmw
>>> ftmw.set_clock_sources(
...     "exp.ftmw",
...     [{"freq_mhz": 5760.0, "locked": True, "label": "synth"}],
... )
ftmwpipeline.api.remove_clock_sources(file_path: str | Path, freqs_mhz: Sequence[float]) Tuple[ClockSource, ...][source]

Remove declared clock sources matching the given frequencies (MHz).

ftmwpipeline.api.clear_clock_sources(file_path: str | Path) None[source]

Clear the clock-source declaration on an existing experiment.

ftmwpipeline.api.load_fid(file_path: str | Path) FID[source]

Load FID data from pipeline file.

This function loads the raw FID data stored in a .ftmw pipeline file, equivalent to Pipeline.load_data().

Parameters:

file_path (str or Path) – Path to existing .ftmw pipeline file

Returns:

The loaded FID object with all metadata

Return type:

FID

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> fid = ftmw.load_fid("experiment.ftmw")
>>> print(f"FID: {fid.n_points:,} points, {fid.duration_us:.1f} μs")
ftmwpipeline.api.validate_pipeline(file_path: str | Path) Dict[str, Any][source]

Validate pipeline file integrity.

This function performs comprehensive validation of a .ftmw pipeline file, equivalent to Pipeline.validate().

Parameters:

file_path (str or Path) – Path to .ftmw pipeline file to validate

Returns:

Validation report with status and any issues found

Return type:

dict

Examples

>>> import ftmwpipeline.api as ftmw
>>> report = ftmw.validate_pipeline("experiment.ftmw")
>>> if report['valid']:
...     print("Pipeline file is valid")
>>> else:
...     print(f"Issues found: {report['errors']}")
ftmwpipeline.api.detect_start_time(file_path: str | Path, *, band: Tuple[float, float] | None = None, stamp: bool = True, settings: StartDetectionSettings | None = None) StartDetectionResult[source]

Infer a good FID start_us from the data, equivalent to Pipeline.detect_start_time().

Sweeps the FID window start time and integrates the FT magnitude over the active band; the chirp-end collapse plus an instrument-specific guard margin gives the recommended start_us. When stamp=True (default) the value is written to the Stage 0 recommended_processing layer so a later compute_ft() with no explicit start_us inherits it. Requires only Stage 0 (FID); the band is resolved from the canonical Stage 1 trim when present, else the full positive spectrum.

Parameters:
  • file_path (str or Path) – Path to a .ftmw file with the FID imported.

  • band (tuple of float, optional) – Explicit (min_mhz, max_mhz) integration band override (a convenience for the settings band fields).

  • stamp (bool, default True) – Whether to persist the recommended start_us.

  • settings (StartDetectionSettings, optional) – The detection knobs. Stage 0 is a flat bundle with concrete defaults: construct a StartDetectionSettings with the fields to override (sweep_max_us / step_us / guard_margin_us / floor_factor / …).

Returns:

The recommendation plus diagnostics.

Return type:

StartDetectionResult

ftmwpipeline.api.visualize_start_detection(file_path: str | Path, output_file: str | Path | None = None, interactive: bool = True, figsize: tuple | None = None, *, settings: StartDetectionSettings | None = None) Any[source]

Render the start-detection sweep diagnostic, equivalent to Pipeline.visualize_start_detection() (runs detection without stamping).

ftmwpipeline.api.compute_ft(file_path: str | Path, trim: Tuple[float, float] | None = None, start_us: float | None = None, end_us: float | None = None, units_power: int | None = None, from_saved_params: bool = False) ComplexFT[source]

Compute Fourier Transform with specified processing parameters.

This function performs FT computation on FID data stored in a .ftmw pipeline file, equivalent to Pipeline.compute_ft(). Can be called multiple times safely. The canonical FT is unconditionally unapodized, un-windowed, and native-length.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file containing FID data

  • trim (tuple of float, optional) – (min_freq, max_freq) in MHz to trim spectrum

  • start_us (float, optional) – FID window start time in microseconds

  • end_us (float, optional) – FID window end time in microseconds

  • units_power (int, optional) – Scaling factor as power of 10. If None, uses cached default or 6.

  • from_saved_params (bool, default False) – If True, ignore the explicit kwargs and use only the persisted / recommended settings (no explicit overrides).

Returns:

Computed frequency domain data.

Return type:

ComplexFT

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> # Compute with specific parameters (persisted as canonical)
>>> complex_ft = ftmw.compute_ft("experiment.ftmw", trim=(26500, 40000))
>>>
>>> # Use saved/recommended settings only
>>> complex_ft = ftmw.compute_ft("experiment.ftmw", from_saved_params=True)
ftmwpipeline.api.visualize_ft(file_path: str | Path, trim: Tuple[float, float] | None = None, start_us: float | None = None, end_us: float | None = None, units_power: int | None = None, save_params: bool = False, interactive: bool = True, output_file: str | Path | None = None, show_fid_panels: bool = True) Any[source]

Create enhanced FT visualization with processing workflow display.

This function creates comprehensive FT visualization showing the complete FID-to-spectrum processing workflow, equivalent to Pipeline.visualize_ft(). The canonical FT is unconditionally unapodized, un-windowed, and native-length.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file

  • trim (tuple of float, optional) – (min_freq, max_freq) in MHz to trim spectrum

  • start_us (float, optional) – FID window start time in microseconds

  • end_us (float, optional) – FID window end time in microseconds

  • units_power (int, optional) – Scaling factor as power of 10. If None, uses cached default or 6.

  • save_params (bool, default False) – Whether to save parameters as defaults for this experiment

  • interactive (bool, default True) – Whether to show interactive plot

  • output_file (str or Path, optional) – Path to save plot image (for non-interactive mode)

  • show_fid_panels (bool, default True) – Whether to show FID processing panels

Returns:

Matplotlib figure object

Return type:

figure

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> # Create interactive visualization
>>> fig = ftmw.visualize_ft("experiment.ftmw", save_params=True)
>>>
>>> # Save plot to file
>>> fig = ftmw.visualize_ft("experiment.ftmw", interactive=False,
...                         output_file="spectrum.png")
ftmwpipeline.api.save_ft_parameters(file_path: str | Path, parameters: Dict[str, Any]) None[source]

Save FT processing parameters as defaults for pipeline file.

This function saves processing parameters to the .ftmw pipeline file for use in subsequent computations with from_saved_params=True.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file

  • parameters (dict) – Processing parameters to save. Valid keys include: - ‘start_us’, ‘end_us’: FID time window - ‘units_power’: Scaling factor - ‘trim_min_mhz’, ‘trim_max_mhz’: Frequency trimming range

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> params = {
...     'trim_min_mhz': 26500,
...     'trim_max_mhz': 40000
... }
>>> ftmw.save_ft_parameters("experiment.ftmw", params)
ftmwpipeline.api.estimate_noise(file_path: str | Path, *, settings: NoiseSettings | None = None, preset: str | None = None) NoiseResult[source]

Estimate frequency-dependent noise with the scatter (high-pass) estimator.

This function performs noise estimation on ComplexFT data stored in a .ftmw pipeline file, equivalent to Pipeline.estimate_noise(). Requires Stage 1 (FT computation) to be completed first.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file containing ComplexFT data

  • settings – Composable ways to drive the settings chain (a NoiseSettings bundle as the explicit override layer, a YAML preset’s stage2: block as the preset layer beneath the persisted record). Individual scatter knobs (window_mhz / smoothing_mhz / smoothing_percentile / convolve_mhz / …) are set on the NoiseSettings instance; the explicit layer outranks the persisted record, which outranks the preset (per D11), so a no-arg call reproduces the persisted recipe.

  • preset – Composable ways to drive the settings chain (a NoiseSettings bundle as the explicit override layer, a YAML preset’s stage2: block as the preset layer beneath the persisted record). Individual scatter knobs (window_mhz / smoothing_mhz / smoothing_percentile / convolve_mhz / …) are set on the NoiseSettings instance; the explicit layer outranks the persisted record, which outranks the preset (per D11), so a no-arg call reproduces the persisted recipe.

Returns:

Container with RMS noise estimate, noise mask, and diagnostics

Return type:

NoiseResult

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> from ftmwpipeline.core.noise_settings import NoiseSettings
>>> # First compute FT if not already done
>>> ftmw.compute_ft("experiment.ftmw", trim=(26500, 40000))
>>> # Estimate noise with default parameters
>>> noise_result = ftmw.estimate_noise("experiment.ftmw")
>>> # Override a scatter knob
>>> noise_result = ftmw.estimate_noise(
...     "experiment.ftmw", settings=NoiseSettings(window_mhz=120.0)
... )
ftmwpipeline.api.visualize_noise(file_path: str | Path, y_max_factor: float | None = None, figsize: tuple | None = None, title: str | None = None, show_noise_points: bool | None = None, interactive: bool = True, output_file: str | Path | None = None, **plot_kwargs: Any) Any[source]

Create noise estimation diagnostic visualization.

This function creates diagnostic plots showing the spectrum, the noise points, and the per-bin σ estimate (with 3×/5×σ reference levels), equivalent to Pipeline.visualize_noise(). Requires Stage 2 (noise estimation) completion.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file containing noise estimation results

  • y_max_factor (float, optional) – Y-axis maximum as multiple of median RMS noise (default: 20.0)

  • figsize (tuple, optional) – Figure size (width, height) in inches (default: (16, 6))

  • title (str, optional) – Custom title for the plot

  • show_noise_points (bool, optional) – Whether to highlight noise points (default: True)

  • interactive (bool, default True) – Whether to create interactive plots

  • output_file (str or Path, optional) – If provided, save plot to this file

  • **plot_kwargs – Additional plotting parameters

Returns:

The created figure object

Return type:

matplotlib.figure.Figure

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> # Create basic noise visualization
>>> fig = ftmw.visualize_noise("experiment.ftmw")
>>> # Save to file
>>> fig = ftmw.visualize_noise("experiment.ftmw",
...                           output_file="noise_diagnostics.png")
ftmwpipeline.api.calibrate_tau(file_path: str | Path, *, shape: str = 'lorentzian', settings: TauCalibrationSettings | None = None, preset: str | None = None) TauCalibrationResult[source]

Run the Stage 2b data-driven tau calibration, equivalent to Pipeline.calibrate_tau().

Requires Stages 0-2 completed. shape selects the decay model and its persistence group: "lorentzian" (pure-exponential, /stage2b_tau_calibration) or "gaussian" (pure-Gaussian envelope τ_G, /stage2b_tau_G_calibration); the two are independent and can coexist on one .ftmw file, consumed by the matching-shape Stage 5 fit. Settings resolve through the chain (settings / preset > persisted > hard default); settings= and preset= may be combined – the settings bundle is the explicit override that outranks the persisted record, while the preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Individual knobs are set on a TauCalibrationSettings instance or a YAML preset’s stage2b: block. The resolved settings are stamped to the shared processing_parameters/stage2b_tau block so a no-arg follow-up call reproduces the same recipe.

ftmwpipeline.api.load_tau_calibration(file_path: str | Path, *, shape: str = 'lorentzian') TauCalibrationResult[source]

Load the persisted Stage 2b TauCalibrationResult for shape.

ftmwpipeline.api.calibrate_timebase(file_path: str | Path, *, clocks: Any | None = None, kappa_sys: float | None = None, snr_min: float | None = None) TimebaseCalibrationResult[source]

Measure the scope-timebase scale error eps, equivalent to Pipeline.calibrate_timebase().

Requires Stage 0 (the raw FID). Demodulates the active FID at the Rb-locked clock spur lattice and fits the shared fractional scale error eps (every measured frequency reads f_true * (1 + eps)). The clock declaration comes from the explicit clocks argument, else the persisted Stage 5 spur.clocks; a non-empty declaration with at least one locked source is required. Persists eps to /timebase_calibration; measuring eps is the whole job – applying it is out of scope.

ftmwpipeline.api.load_timebase_calibration(file_path: str | Path) TimebaseCalibrationResult[source]

Load the persisted TimebaseCalibrationResult.

ftmwpipeline.api.recommend_shape(file_path: str | Path, *, settings: TauCalibrationSettings | None = None, preset: str | None = None) ShapeRecommendation[source]

Run the 3-way L/G/V shape-recommendation hook, equivalent to Pipeline.recommend_shape().

Per-bin AICc vote (exp / gauss / voigt) over the same STFT contributor pool the τ calibrations use; SNR-weighted majority decides between the two pure shapes (Voigt is reported as a diagnostic but does not enter the recommendation). The verdict’s recommended_shape is stamped onto every Stage 2b group present on the file so the Stage 5 resolver’s recommended layer picks it up automatically. Requires Stage 1 (active region + frequency trim) to have completed; the Stage 2b calibrations are optional but the persisted contract only fires when at least one of them has run.

Settings resolve through the chain (settings / preset > persisted > hard default); settings= and preset= may be combined – the settings bundle is the explicit override that outranks the persisted record, while the preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11).

ftmwpipeline.api.visualize_tau_heatmap(file_path: str | Path, output_file: str | Path | None = None, interactive: bool = True, figsize: tuple | None = None, shape: str = 'lorentzian') Any[source]

2D STFT magnitude heatmap, equivalent to Pipeline.visualize_tau_heatmap(). shape selects the pure-exp or Gaussian calibration group.

ftmwpipeline.api.visualize_tau_distribution(file_path: str | Path, output_file: str | Path | None = None, interactive: bool = True, figsize: tuple | None = None, shape: str = 'lorentzian') Any[source]

tau-distribution analysis panel, equivalent to Pipeline.visualize_tau_distribution(). shape selects the pure-exp or Gaussian calibration group.

ftmwpipeline.api.detect_peaks(file_path: str | Path, *, settings: PeakDetectionSettings | None = None, preset: str | None = None) List[Peak][source]

Detect and classify peaks (Stage 3), equivalent to Pipeline.detect_peaks().

Requires Stage 1 (FT) and Stage 2 (noise). Two-pass detection operates on the Stage 1 persisted canonical spectrum (including its frequency trim range); peaks are reported on that user grid with SNR measured against the canonical Stage 2 noise. There is no per-Stage-3 trim or zpf.

Settings resolve through the chain (settings / preset > persisted > hard default); pass settings= to drive detection from a PeakDetectionSettings dataclass, or preset=NAME_OR_PATH to load from packaged YAML. They may be combined: a settings bundle is the explicit override that outranks the persisted record, while a preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs via settings=PeakDetectionSettings(...) or a YAML preset’s stage3: block.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file.

  • settings (PeakDetectionSettings, optional) – Bundle of Stage 3 knobs; fields left None fall through the resolution chain. May be combined with preset.

  • preset (str, optional) – Bare preset name or path to a YAML file carrying a stage3: block. Seeds the preset layer beneath the persisted record; may be combined with settings.

Returns:

ALL detected peaks (promoted and non-promoted), sorted by frequency. Each peak’s properties dict includes promoted (bool), internal_snr, internal_frequency, and detection_pass.

Return type:

list of Peak

ftmwpipeline.api.load_peaks(file_path: str | Path) List[Peak][source]

Load the persisted Stage 3 peak list, equivalent to Pipeline.load_peaks(). Validates the on-disk structure loudly.

ftmwpipeline.api.visualize_peaks(file_path: str | Path, figsize: tuple | None = None, title: str | None = None, y_max_factor: float | None = None, interactive: bool = True, output_file: str | Path | None = None, show_snr_histogram: bool = False) Any[source]

Overlay classified detected peaks on the spectrum (Stage 3), equivalent to Pipeline.visualize_peaks(). Requires Stage 3 completion.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file with Stage 3 results.

  • figsize (tuple, optional) – Figure size (width, height) in inches.

  • title (str, optional) – Custom plot title.

  • y_max_factor (float, optional) – Y-axis max as multiple of median RMS noise (default 25.0).

  • interactive (bool, default True) – Whether to open an interactive window.

  • output_file (str or Path, optional) – Save plot to this path (non-interactive mode).

  • show_snr_histogram (bool, default False) – If True, add a second panel showing the user-grid SNR distribution with the promotion cutoff marked (curation view).

Returns:

Matplotlib figure (single-panel or two-panel when show_snr_histogram=True).

Return type:

figure

ftmwpipeline.api.save_peak_parameters(file_path: str | Path, parameters: Dict[str, Any]) None[source]

Save Stage 3 detection parameters for reuse.

ftmwpipeline.api.assign_windows(file_path: str | Path, *, settings: WindowPlanningSettings | None = None, preset: str | None = None) WindowPlan[source]

Assign analysis windows (Stage 4), equivalent to Pipeline.assign_windows().

Requires Stage 3 (peak detection). Turns the promoted Stage 3 peaks into a fit plan – a set of disjoint analysis windows, each annotated with the peaks to fit freely, the strong out-of-band lines whose leakage is carried frozen, and a fit dependency order. Stage 4 is purely structural; the plan is persisted to the .ftmw file.

Settings resolve through the chain (settings / preset > persisted > hard default); pass settings= to drive window planning from a WindowPlanningSettings dataclass, or preset=NAME_OR_PATH to load from packaged YAML. They may be combined: a settings bundle is the explicit override that outranks the persisted record, while a preset seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs via settings=WindowPlanningSettings(...) or a YAML preset’s stage4: block.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file.

  • settings (WindowPlanningSettings, optional) – Bundle of Stage 4 knobs; fields left None fall through the resolution chain. May be combined with preset.

  • preset (str, optional) – Bare preset name or path to a YAML file carrying a stage4: block. Seeds the preset layer beneath the persisted record; may be combined with settings.

Returns:

The fit plan: disjoint windows, dependency DAG, topological order, parallel batches, parameters and diagnostics.

Return type:

WindowPlan

ftmwpipeline.api.load_windows(file_path: str | Path) WindowPlan[source]

Load the persisted Stage 4 window plan, equivalent to Pipeline.load_windows(). Validates the on-disk structure loudly.

ftmwpipeline.api.visualize_windows(file_path: str | Path, figsize: tuple | None = None, title: str | None = None, y_max_factor: float | None = None, interactive: bool = True, output_file: str | Path | None = None) Any[source]

Overlay the Stage 4 window plan on the spectrum, equivalent to Pipeline.visualize_windows(). Requires Stage 4 completion.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file with Stage 4 results.

  • figsize (tuple, optional) – Figure size (width, height) in inches.

  • title (str, optional) – Custom plot title.

  • y_max_factor (float, optional) – Spectrum-panel y-axis headroom (default 25.0).

  • interactive (bool, default True) – Whether to open an interactive window.

  • output_file (str or Path, optional) – Save plot to this path (non-interactive mode).

Returns:

Matplotlib figure.

Return type:

figure

ftmwpipeline.api.save_window_parameters(file_path: str | Path, parameters: Dict[str, Any]) None[source]

Save Stage 4 window-assignment parameters for reuse.

ftmwpipeline.api.fit_peaks(file_path: str | Path, *, shape: str | None = None, tau_maj_override_us: float | None = None, sigma_tau_override_us: float | None = None, settings: StageFitSettings | None = None, preset: str | None = None, jobs: int | None = None) SpectrumFit[source]

Fit each Stage 4 window’s lines (Stage 5), equivalent to Pipeline.fit_peaks().

Requires Stage 4 (window assignment). Drives the conservative add-one-peak loop over each window with the shared per-window decay tau and the frozen-contributor model, then the residual edge-coherence handshake (local thaw + structural replan). The fit runs on the active-portion FT (computed on demand from the FID + canonical Stage 1 settings), so per-bin statistics are independent and reduced chi-squared / F-test / AIC are calibrated as written. The persistent SpectrumFit – per-window FittingResult s, the merged global fitted-peak list, the thaw / replan histories, and the parameters used – is written to /stage5_fitting.

Settings resolve through the chain (settings / preset > persisted > recommended > hard default); pass settings= to drive the fit from a StageFitSettings dataclass, or preset=NAME_OR_PATH to load from packaged YAML. They may be combined: a settings bundle outranks a value persisted in the .ftmw while a preset .yml seeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11).

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file.

  • shape ({"lorentzian", "gaussian"}, optional) – Time-domain envelope of the per-line model, kept as a first-class convenience argument. "lorentzian" uses exp(-t/τ); "gaussian" uses exp(-(t/τ_G)²) and consumes the Stage 2b τ_G calibration (calibrate_tau(shape="gaussian")) in place of the pure-exp variant for the bidirectional τ anchoring penalty. None falls through to the resolved settings (preset / persisted / default).

  • tau_maj_override_us (float, optional) – Atomic-pair manual override for the Stage 2b tau calibration, kept as explicit arguments (an A/B escape hatch crossing a stage boundary, not a fit knob). When both are supplied (positive), they replace any persisted Stage 2b result for this fit. Supplying only one of the pair raises ValueError.

  • sigma_tau_override_us (float, optional) – Atomic-pair manual override for the Stage 2b tau calibration, kept as explicit arguments (an A/B escape hatch crossing a stage boundary, not a fit knob). When both are supplied (positive), they replace any persisted Stage 2b result for this fit. Supplying only one of the pair raises ValueError.

  • settings (StageFitSettings, optional) – Bundle of Stage 5 knobs; fields left None fall through the resolution chain. Resolves at the explicit override layer (outranks the persisted record). May be combined with preset.

  • preset (str, optional) – Bare preset name (e.g. "defaults") or a path to a YAML file carrying a stage5: block. Seeds the preset layer beneath the persisted record; may be combined with settings.

  • jobs (int, optional) – Worker-pool size for the cross-window parallel fit. None (the default) resolves the pool from the FTMW_MAX_WORKERS environment variable, falling back to cpu_count() - 2; 1 forces a sequential fit. The fit result is byte-identical regardless of the worker count.

Returns:

The persistent fit aggregate.

Return type:

SpectrumFit

Raises:
ftmwpipeline.api.load_fit(file_path: str | Path) SpectrumFit[source]

Load the persisted Stage 5 fit, equivalent to Pipeline.load_fit(). Validates the on-disk structure loudly.

ftmwpipeline.api.get_candidate_ledger(file_path: str | Path, window_id: int | None = None, *, bar: float = 4.0) List[LedgerCandidate][source]

Derive the Stage 6 candidate ledger from the persisted Stage 5 fit.

Returns revivable candidates from the conservative add-loop and rescue records. Equivalent to Pipeline.candidate_ledger().

Parameters:
  • file_path – Path to the .ftmw pipeline file.

  • window_id – When given, return candidates for that window only.

  • bar – Display SNR / evidence bar; candidates below it are dropped.

Returns:

  • list of LedgerCandidate – Sorted by molecular frequency.

  • Requires Stage 5 completed.

ftmwpipeline.api.review_edit(file_path: str | Path, window_id: int, *, add: Sequence[float] = (), remove: Sequence[float] = (), snap_tol_mhz: float = 0.05) RefitWindowResult[source]

User-directed single-window refit (Stage 6 review edit).

Re-fits window_id from the persisted Stage 5 fit using the production NLS primitive, applying add/remove edits. User-added peaks carry origin="user" and survive the HDF5 round-trip; removed peaks are excluded from the refit and will not be re-added by the rescue pass. Equivalent to Pipeline.review_edit().

Parameters:
  • file_path – Path to the .ftmw pipeline file (read-write).

  • window_id – The window to refit.

  • add – Molecular frequencies (MHz) of peaks to add.

  • remove – Molecular frequencies (MHz) of fitted peaks to remove.

  • snap_tol_mhz – Snap tolerance for add/remove (MHz; default 0.05 = 50 kHz).

Returns:

  • RefitWindowResult – Old vs new peak count, χ²ᵣ before/after, and the new fitted peaks.

  • Requires Stage 5 completed.

ftmwpipeline.api.review_merge(file_path: str | Path, window_id: int, peaks: Sequence[float], *, snap_tol_mhz: float = 0.05) RefitWindowResult[source]

Collapse ≥2 fitted peaks in a window into one (Stage 6 review merge).

Equivalent to Pipeline.review_merge().

Parameters:
  • file_path – Path to the .ftmw pipeline file (read-write).

  • window_id – The window containing the peaks to merge.

  • peaks – Molecular frequencies (MHz) of the peaks to collapse (≥2).

  • snap_tol_mhz – Maximum distance (MHz) for frequency snapping.

Returns:

  • RefitWindowResult – Old vs new peak count, χ²ᵣ before/after, and the new fitted peaks.

  • Requires Stage 5 completed.

ftmwpipeline.api.review_split(file_path: str | Path, window_id: int, peak: float, *, into: int = 2, snap_tol_mhz: float = 0.05) RefitWindowResult[source]

Replace one fitted peak with into peaks (Stage 6 review split).

Equivalent to Pipeline.review_split().

Parameters:
  • file_path – Path to the .ftmw pipeline file (read-write).

  • window_id – The window containing the peak to split.

  • peak – Molecular frequency (MHz) of the peak to split.

  • into – Number of replacement peaks (≥2, default 2).

  • snap_tol_mhz – Maximum distance (MHz) for frequency snapping.

Returns:

  • RefitWindowResult – Old vs new peak count, χ²ᵣ before/after, and the new fitted peaks.

  • Requires Stage 5 completed.

ftmwpipeline.api.review_run(file_path: str | Path, *, bar: float = 4.0, attention_candidate_evidence: float = 10.0, sigma_floor_khz: float | None = None) ReviewRunResult[source]

Build or refresh the Stage 6 curation layer and final-products table.

Equivalent to Pipeline.review_run().

Parameters:
  • file_path – Path to the .ftmw pipeline file.

  • bar – Display bar for the candidate-bearing attention reason.

  • attention_candidate_evidence – Evidence threshold above which a candidate-bearing window flags (stiffer than bar; keeps the attention surface actionable).

  • sigma_floor_khz – When given, persist this user-declared accuracy floor (kHz) and fold it into the budget; None keeps the persisted floor unchanged.

Returns:

  • ReviewRunResult – Total window count, attention count, and per-kind breakdown.

  • Requires Stage 5 completed.

ftmwpipeline.api.set_sigma_floor(file_path: str | Path, sigma_floor_khz: float) None[source]

Declare the systematic frequency-accuracy floor (kHz), persisted in-file.

Equivalent to Pipeline.set_sigma_floor(). Stores the floor as file-level provenance so any reported sigma_f is reproducible from the record alone. Run review_run() afterwards to fold it into the budget.

ftmwpipeline.api.get_final_products(file_path: str | Path) FinalProducts | None[source]

Return the persisted Stage 6 calibrated final-products table, or None.

Equivalent to Pipeline.final_products(). Read-only.

ftmwpipeline.api.report_table(file_path: str | Path, *, fmt: str = 'csv', output: str | Path | None = None, catalog: str | Path | None = None, catalog_n_sigma: float = 3.0) str[source]

Render the calibrated final-products table (report Level 1).

Equivalent to Pipeline.report_table(). Serializes the persisted final-products table to csv / json / latex; renders the persisted record (does not recompute). Requires review_run to have built the table. Pass catalog to proximity-flag each line against a frequency catalog (label echo only, never an assignment).

ftmwpipeline.api.report_run(file_path: str | Path, *, output_dir: str | Path | None = None, windows: str = 'all', emit_table: bool = True, emit_html: bool = True, table_format: str = 'csv', scope: str = 'full', catalog: str | Path | None = None, catalog_n_sigma: float = 3.0, jobs: int | None = None) Dict[str, str | None][source]

Write the default Stage 6 deliverables: the L1 table + the L3 report.

Equivalent to Pipeline.report_run(). Writes the Level-1 final-products table (<stem>_lines.csv) and the self-contained Level-3 HTML report with every window folded in (<stem>_report.html) into output_dir (the current working directory when omitted). Either artifact can be suppressed (emit_table / emit_html); the HTML content follows scope ("full" folds in every window, "summary" keeps the index + methods only). Renders the persisted record (does not recompute). Requires review_run to have built the final-products table. Pass catalog to add proximity-match cross-references (label echo only, never an assignment). jobs sets the worker-pool size for the per-window figure rendering (None resolves it from the FTMW_MAX_WORKERS environment variable, falling back to cpu_count() - 2; 1 renders sequentially). Returns {"table": <path|None>, "html": <path|None>}.

ftmwpipeline.api.report_diff(file_path: str | Path, *, output_dir: str | Path | None = None, dpi: int = 110) str[source]

Render the post-curation before/after diff report; return its path.

Equivalent to Pipeline.report_diff(). Compares the automatic-fit baseline snapshot with the current curated fit and writes a self-contained <stem>_diff.html with a side-by-side panel for every window that differs materially – both the windows edited directly and the dependents the contributor-edit cascade changed – so the changes can be evaluated before they are committed. When no curation edit has been made, a report stating that is written instead. Read-only; never recomputes the fit.

ftmwpipeline.api.run_pipeline(source: str | Path, output: str | Path | None = None, *, trim: Tuple[float, float] | None = None, **kwargs: Any) Dict[str, Any][source]

Drive a raw source through every pipeline stage end-to-end.

Equivalent to Pipeline.build(). Imports source, then runs FT -> noise -> tau -> peaks -> windows -> fit -> timebase -> review (and, with report=True, the report) in order, showing live per-stage progress. trim (the active-band FT range, MHz) is required; output is the destination .ftmw (derived from source if omitted).

Per-stage behavior is tuned with override dicts forwarded to each stage (ft_params, noise_params, tau_params, peak_params, window_params, fit_params, timebase_params, review_params, report_params) plus an optional preset name; detect_start / calibrate / clocks gate the optional stages (timebase is non-fatal – it warns and skips when no clock declaration is resolvable), report / report_output_dir emit the report, and progress=False silences the display. Returns the structured run result (pipeline_file, status, completed_stages, failed_stage, error, timebase, report, elapsed_s); stops at the first failing stage.

ftmwpipeline.api.review_accept(file_path: str | Path, window_id: int, *, candidate_freq: float | None = None) RefitWindowResult | None[source]

Accept a window as-is or accept a specific revived candidate.

Equivalent to Pipeline.review_accept().

Parameters:
  • file_path – Path to the .ftmw pipeline file.

  • window_id – The window to accept.

  • candidate_freq – When given, accept by adding this molecular frequency (MHz) as a new peak.

Returns:

  • RefitWindowResult or NoneNone when accepting as-is; the refit result when candidate_freq is given.

  • Requires Stage 5 completed.

ftmwpipeline.api.review_apply(file_path: str | Path, curation_path: str | Path, *, dry_run: bool = False) CurationApplyResult[source]

Apply a curation file of batched review edits.

Equivalent to Pipeline.review_apply(). Replays a curation CSV through the same edit impls the interactive verbs use (add/remove on one window coalesce into a single refit; merge/split/accept stand alone). With dry_run the resolved plan and frequency-resolution warnings are returned without modifying the file.

Parameters:
  • file_path – Path to the .ftmw pipeline file.

  • curation_path – Path to the curation CSV to apply.

  • dry_run – Preview the resolved plan without writing (default False).

Returns:

  • CurationApplyResult

  • Requires Stage 5 completed.

ftmwpipeline.api.review_log(file_path: str | Path) List[DecisionLogEntry][source]

Return the persisted Stage 6 decision log (read-only, execution order).

Equivalent to Pipeline.review_log().

Parameters:

file_path – Path to the .ftmw pipeline file.

Return type:

list of DecisionLogEntry

ftmwpipeline.api.review_undo(file_path: str | Path, ids: Sequence[int], *, dry_run: bool = False) UndoResult[source]

Undo recorded decisions by id, replaying the rest from baseline.

Equivalent to Pipeline.review_undo(). Restores the automatic Stage 5 fit and re-applies every surviving decision (ids are renumbered afterward); dry_run previews without writing.

Parameters:
  • file_path – Path to the .ftmw pipeline file.

  • ids – Decision ids (from review_log()) to undo.

  • dry_run – Preview without mutating (default False).

Return type:

UndoResult

ftmwpipeline.api.get_review_status(file_path: str | Path) Stage6Review[source]

Load the Stage 6 review state from file_path, or return an empty one.

Equivalent to Pipeline.review_status(). Read-only; safe to call before review run.

Parameters:

file_path – Path to the .ftmw pipeline file.

Returns:

The persisted per-window statuses and decision log.

Return type:

Stage6Review

ftmwpipeline.api.rank_windows(file_path: str | Path, by: str, *, top: int | None = None) List[RankedWindow][source]

Rank fit windows by a persisted per-window statistic (read-only).

Equivalent to Pipeline.rank_windows(). On-demand exploration decoupled from the attention flags: ranks all windows worst-first by by (min-snr, max-vif, chi2r, candidate-evidence, edge-distance, spur-proximity, merged-chi2r).

Parameters:
  • file_path – Path to the .ftmw pipeline file.

  • by – Metric name (_ and - interchangeable).

  • top – Return at most this many windows; None returns all.

ftmwpipeline.api.validate_stage5_shape_error(file_path: str | Path, kappa: float | None = None, noise_floor: float | None = None, ground_truth: str | Path | None = None, match_tol_fwhm: float = 0.5) Dict[str, Any][source]

Assess a persisted Stage 5 fit against the SNR-aware acceptance framework.

Read-only. Returns the Tier 1 (SNR-aware health) / Tier 2 (gate firing) / Tier 3 (known-line ground truth, when ground_truth is given) report, equivalent to Pipeline.validate_stage5_shape_error().

ftmwpipeline.api.visualize_fit(file_path: str | Path, figsize: tuple | None = None, title: str | None = None, window_id: int | None = None, interactive: bool = True, output_file: str | Path | None = None) Any[source]

Overlay the Stage 5 fit on the spectrum, equivalent to Pipeline.visualize_fit(). Requires Stage 5 completion.

Parameters:
  • file_path (str or Path) – Path to .ftmw pipeline file with Stage 5 results.

  • figsize (tuple, optional) – Figure size (width, height) in inches.

  • title (str, optional) – Custom plot title.

  • window_id (int, optional) – When set, draw a per-window detail figure (re/im, magnitude+residual, time envelope, audit-trail); otherwise an overview overlay of the fitted model on the persisted spectrum.

  • interactive (bool, default True) – Whether to open an interactive window.

  • output_file (str or Path, optional) – Save plot to this path (non-interactive mode).

ftmwpipeline.api.show_fit(file_path: str | Path, *, window_ids: list | None = None, freqs: list | None = None, random_n: int | None = None, random_seed: int | None = None, top_snr: int | None = None, all_windows: bool = False, output_dir: str | Path | None = None, show_audit: bool = False, apodize: str | None = None, apodize_us: float | None = None, rescue: bool = False, figsize: tuple | None = None, title: str | None = None, interactive: bool = False) Dict[str, Any][source]

Show the Stage 5 fit, equivalent to Pipeline.show_fit() and the CLI fit show command.

With no selector, returns the spectrum-wide overview. Selectors (window_ids / freqs / random_n / top_snr / all_windows) compose as a union and produce one consolidated per-window detail figure each. With output_dir each detail figure is written there. With rescue an extra residual-rescue summary figure is produced per window (no re-fit): data/model, the final residual with each round’s nominations, the chi-squared trajectory, and the peak budget. Returns {"mode", "window_ids", "figures", "paths", "log"}. Requires Stage 5.

ftmwpipeline.api.get_pipeline_info(file_path: str | Path) Dict[str, Any][source]

Get pipeline file information and status.

This function retrieves comprehensive information about a .ftmw pipeline file including source metadata, completed stages, and validation status, equivalent to Pipeline.info().

Parameters:

file_path (str or Path) – Path to .ftmw pipeline file

Returns:

Pipeline information including: - ‘filepath’: Full path to pipeline file - ‘valid’: Whether file is valid - ‘source_path’: Original data source - ‘format’: Data format name - ‘import_time’: When data was imported - ‘completed_stages’: List of completed processing stages - ‘next_available_stages’: Stages ready to run - ‘errors’: List of issues if invalid - ‘warnings’: List of warnings if any

Return type:

dict

Examples

>>> import ftmwpipeline.api as ftmw
>>> info = ftmw.get_pipeline_info("experiment.ftmw")
>>> print(f"Source: {info['source_path']}")
>>> print(f"Completed stages: {info['completed_stages']}")
>>> print(f"Next available: {info['next_available_stages']}")
ftmwpipeline.api.list_available_stages(file_path: str | Path) List[str][source]

Get list of processing stages ready to run.

This function returns the names of processing stages that can be executed based on the current completion status of the pipeline file.

Parameters:

file_path (str or Path) – Path to .ftmw pipeline file

Returns:

Names of stages that can be executed next

Return type:

list of str

Raises:

Examples

>>> import ftmwpipeline.api as ftmw
>>> stages = ftmw.list_available_stages("experiment.ftmw")
>>> print(f"Available stages: {stages}")
>>> if 'stage1_complex_ft' in stages:
...     print("Ready for FT computation")
ftmwpipeline.api.workflow_summary(file_path: str | Path) str[source]

Generate a human-readable summary of pipeline status and workflow.

This convenience function provides a formatted summary of the pipeline file status, completed stages, and suggested next steps.

Parameters:

file_path (str or Path) – Path to .ftmw pipeline file

Returns:

Formatted summary string

Return type:

str

Examples

>>> import ftmwpipeline.api as ftmw
>>> print(ftmw.workflow_summary("experiment.ftmw"))
Pipeline: experiment.ftmw
Source: examples/blackchirp_data/2638/ (blackchirp format)
Status: Valid
Completed: ['stage0_data_import']
Next available: ['stage1_complex_ft']

Suggested workflow: 1. ftmw.compute_ft(“experiment.ftmw”, trim=(26500, 40000)) 2. ftmw.visualize_ft(“experiment.ftmw”, save_params=True)

ftmwpipeline.api.scan_list(selector: str | None = None, *, include_advanced: bool = False) Tuple[Any, ...][source]

List the registered tunable knobs, equivalent to Pipeline.scan_list().

Parameters:
  • selector (str, optional) – Filter by dotted-path prefix (e.g. "stage2b" / "stage2b.gaussian"); the legacy stage-label match ("stage2_noise" / "start_detection") is kept as a fallback.

  • include_advanced (bool, default False) – Reveal advanced-tier knobs hidden from the default listing.

Returns:

Path-sorted knob specifications.

Return type:

tuple of KnobSpec

ftmwpipeline.api.scan_run(file_path: str | Path, knob: str, grid: Sequence[Any] | None = None, output_dir: str | Path | None = None, reuse: bool = False, make_plot: bool = True, quiet: bool = False, zoom_regions: Sequence[Tuple[float, float]] | None = None, n_zoom: int | None = None, zoom_width_mhz: float | None = None, fit_top_snr: int = 3, fit_sample: int = 20, fit_freqs: Sequence[float] | None = None, fit_sample_seed: int = 0, fit_all: bool = False) Any[source]

Sweep a single pipeline knob across a grid, equivalent to Pipeline.scan_run().

Re-runs the knob’s stage for each grid value on a working copy of file_path (the input is never mutated) and returns a SweepResult with the table rows, a CSV path, an optional plot, a best-effort recommendation, and instructions for applying the chosen value.

Parameters:
  • file_path (str or Path) – A .ftmw already built through the knob’s upstream stage.

  • knob (str) – Dotted knob path (see scan_list()), e.g. "stage2.window_mhz".

  • grid (sequence, optional) – Values to sweep; defaults to the knob’s registered grid.

  • output_dir (str or Path, optional) – Where the CSV/plot/working-copy land (default: current directory).

  • reuse (bool, default False) – Reuse an existing working copy instead of re-copying the input.

  • make_plot (bool, default True) – Render the knob’s plot adapter if it has one.

  • quiet (bool, default False) – Suppress the progress indicator (printed to stderr by default).

  • zoom_regions (sequence of (lo_mhz, hi_mhz), optional) – Explicit zoom windows for the region-based plot adapters (Stage 3 / Stage 4), overriding their divergence auto-selection.

  • n_zoom (optional) – When zoom_regions is not given, how many regions to auto-select and how wide each is; None keeps the adapter defaults.

  • zoom_width_mhz (optional) – When zoom_regions is not given, how many regions to auto-select and how wide each is; None keeps the adapter defaults.

  • fit_top_snr (optional) – Window selection for Stage 5 fit knobs: re-fit only the fit_top_snr brightest windows + a seeded fit_sample random sample + the windows nearest each fit_freqs value, rather than the whole plan. fit_all=True re-fits every window. Ignored by non-fit knobs.

  • fit_sample (optional) – Window selection for Stage 5 fit knobs: re-fit only the fit_top_snr brightest windows + a seeded fit_sample random sample + the windows nearest each fit_freqs value, rather than the whole plan. fit_all=True re-fits every window. Ignored by non-fit knobs.

  • fit_freqs (optional) – Window selection for Stage 5 fit knobs: re-fit only the fit_top_snr brightest windows + a seeded fit_sample random sample + the windows nearest each fit_freqs value, rather than the whole plan. fit_all=True re-fits every window. Ignored by non-fit knobs.

  • fit_sample_seed (optional) – Window selection for Stage 5 fit knobs: re-fit only the fit_top_snr brightest windows + a seeded fit_sample random sample + the windows nearest each fit_freqs value, rather than the whole plan. fit_all=True re-fits every window. Ignored by non-fit knobs.

  • fit_all (optional) – Window selection for Stage 5 fit knobs: re-fit only the fit_top_snr brightest windows + a seeded fit_sample random sample + the windows nearest each fit_freqs value, rather than the whole plan. fit_all=True re-fits every window. Ignored by non-fit knobs.

ftmwpipeline.api.scan_all(file_path: str | Path, selector: str | None = None, *, include_advanced: bool = False, output_dir: str | Path | None = None, reuse: bool = False, make_plot: bool = True, quiet: bool = False, zoom_regions: Sequence[Tuple[float, float]] | None = None, n_zoom: int | None = None, zoom_width_mhz: float | None = None, fit_top_snr: int = 3, fit_sample: int = 20, fit_freqs: Sequence[float] | None = None, fit_sample_seed: int = 0, fit_all: bool = False) Any[source]

Sweep every knob matched by selector on its default grid, equivalent to Pipeline.scan_all().

A convenience over scan_run() for reviewing a whole stage / sub-block at once instead of driving knobs one-by-one. selector filters by dotted-path prefix (e.g. "stage2b" / "stage2b.gaussian") just like scan_list(); include_advanced adds the advanced-tier knobs. Each knob runs on its own working copy of file_path (never mutated); a knob whose scan fails (e.g. its required stage is absent) is recorded as a failed BatchItem and the batch continues.

Returns:

One per matched knob, in registry order; item.ok / item.result / item.error report each knob’s outcome.

Return type:

list of BatchItem

ftmwpipeline.api.settings_show(file_path: str | Path, selector: str | None = None, *, include_advanced: bool = False, preset: str | Path | None = None) Tuple[Any, ...][source]

Resolved value + provenance per setting, equivalent to Pipeline.settings_show().

Reports, for each covered setting of file_path, the value actually in effect and the layer that supplied it – the resolved-view counterpart to scan_list()’s tunable-knob listing.

Parameters:
  • file_path (str or Path) – The .ftmw experiment to inspect.

  • selector (str, optional) – Filter by dotted-path prefix (e.g. "stage2b" / "stage2b.gaussian"); None returns every setting.

  • include_advanced (bool, default False) – Reveal advanced-tier settings hidden from the default view.

  • preset (str or Path, optional) – Populate the .yml provenance layer from this preset (bare name or path). Because a persisted .ftmw value outranks a preset, a named preset changes the resolved view only for fields the file has not fixed.

Returns:

One row per setting, carrying path / value / source / hard_default / tier / help.

Return type:

tuple of SettingRow

ftmwpipeline.api.settings_set(file_path: str | Path, knob: str, value: str) Any[source]

Persist a chosen value into the .ftmw, equivalent to Pipeline.settings_set().

Coerces value to knob’s field type, writes it to the persisted layer, and invalidates the affected stage plus every downstream stage so the file never carries results inconsistent with its settings. The retired apodization knobs (zpf / expf_us / window_function) no longer exist – the canonical FT is unconditionally unapodized and native-length.

Parameters:
  • file_path (str or Path) – The .ftmw to modify.

  • knob (str) – Dotted settings path (stage2.window_mhz / stage5.tau.max_decay_factor / stage5.shape).

  • value (str) – The value in string form; coerced to the field’s declared type.

Returns:

Carries the knob path, the coerced value, and the invalidated stages.

Return type:

SetResult

ftmwpipeline.api.settings_export(file_path: str | Path, out_path: str | Path, selector: str | None = None, *, name: str | None = None, description: str | None = None) Any[source]

Write the file’s chosen Stage 2–5 values to a .yml preset, equivalent to Pipeline.settings_export().

Each stage’s persisted settings serialize into the matching stageN: block, filtered by the dotted selector; the result loads back through the stages’ --preset path. Stage 1 is excluded (presets do not carry FT settings).

Parameters:
  • file_path (str or Path) – The .ftmw to read chosen values from.

  • out_path (str or Path) – Destination .yml preset file.

  • selector (str, optional) – Restrict the export to a dotted prefix (e.g. "stage5" / "stage5.rescue"); None exports every persisted Stage 2–5 value.

  • name (str, optional) – Preset metadata written alongside the stage blocks (name defaults to the output file stem).

  • description (str, optional) – Preset metadata written alongside the stage blocks (name defaults to the output file stem).

Returns:

Carries the written path and the exported setting paths.

Return type:

ExportResult

Data structures

The domain types returned and consumed by the stage operations. They are defined in ftmwpipeline.core.data_structures unless noted.

class ftmwpipeline.core.data_structures.FID(data: ndarray, spacing: float, probe_freq_mhz: float, sideband: str | Sideband = Sideband.UPPER, shots: int = 1, processing: FIDProcessingParameters | None = None, metadata: Dict[str, Any] | None = None)[source]

Free Induction Decay time-domain data container.

Contains real-valued time-domain voltage data and all parameters needed for FT processing. Designed to work with a single averaged FID.

__init__(data: ndarray, spacing: float, probe_freq_mhz: float, sideband: str | Sideband = Sideband.UPPER, shots: int = 1, processing: FIDProcessingParameters | None = None, metadata: Dict[str, Any] | None = None)[source]

Initialize FID object.

Parameters:
  • data (np.ndarray) – Real-valued FID voltage data (1D array)

  • spacing (float) – Time spacing between points in seconds

  • probe_freq_mhz (float) – Probe/LO frequency in MHz

  • sideband (str or Sideband) – Sideband configuration (‘upper’ or ‘lower’)

  • shots (int) – Number of shots averaged

  • processing (FIDProcessingParameters, optional) – FT processing parameters

  • metadata (dict, optional) – Additional experimental metadata

property n_points: int

Number of time points.

property duration: float

FID duration in seconds.

property duration_us: float

FID duration in microseconds.

time_array() ndarray[source]

Generate time array in seconds.

time_array_us() ndarray[source]

Generate time array in microseconds.

apply_molecular_frequency(scope_freq_mhz: ndarray) ndarray[source]

Convert scope frequency to molecular frequency.

For upper sideband: molecular = probe + scope For lower sideband: molecular = probe - scope

preprocess(start_us: float | None = None, end_us: float | None = None, units_power: int = 6) PreprocessedFID[source]

Apply preprocessing to FID data, return new PreprocessedFID object.

Stage 1 of FT processing: preprocessing only, no FFT computation. The canonical FT is unconditionally unapodized, un-windowed, and native-length, so preprocessing is just active-region selection plus DC removal:

  1. Extract the active region (start_us to end_us); points outside it are zeroed.

  2. Remove the DC component of the active region (always).

Parameters:
  • start_us (float, optional) – Start time in μs for windowing

  • end_us (float, optional) – End time in μs for windowing

  • units_power (int, default=6) – Scaling factor (10^units_power, 6 for μV)

Returns:

PreprocessedFID object ready for FFT calculation

Return type:

PreprocessedFID

class ftmwpipeline.core.data_structures.ComplexFT(freq_array: ndarray, complex_spectrum: ndarray, metadata: Dict[str, Any] | None = None)[source]

Complex Fourier Transform frequency-domain data container.

Contains the frequency-domain representation of FTMW data with associated experimental parameters. Computed from FID data.

__init__(freq_array: ndarray, complex_spectrum: ndarray, metadata: Dict[str, Any] | None = None)[source]

Initialize ComplexFT object.

Parameters:
  • freq_array (np.ndarray) – Frequency array in MHz

  • complex_spectrum (np.ndarray) – Complex spectrum data

  • metadata (dict, optional) – Additional metadata

classmethod from_spectrum(complex_spectrum: ndarray, freq_array: ndarray, metadata: Dict[str, Any] | None = None) ComplexFT[source]

Create ComplexFT from spectrum data.

Used for Stage 3 post-processing after FFT computation.

Parameters:
  • complex_spectrum (np.ndarray) – Complex spectrum data

  • freq_array (np.ndarray) – Frequency array in MHz

  • metadata (dict, optional) – Additional metadata

Returns:

ComplexFT object

Return type:

ComplexFT

property magnitude_spectrum: ndarray

Magnitude spectrum (cached).

property real_spectrum: ndarray

Real component of spectrum.

property imag_spectrum: ndarray

Imaginary component of spectrum.

property freq_step: float

Frequency step in MHz (cached).

property freq_range: Tuple[float, float]

Frequency range (min, max) in MHz.

property n_points: int

Number of frequency points.

extract_window(freq_min: float, freq_max: float) SpectralWindow[source]

Extract a frequency window.

trim_to_range(freq_min: float, freq_max: float) ComplexFT[source]

Create a new ComplexFT object trimmed to the specified frequency range.

This method is useful for removing noise regions and focusing analysis on the spectral activity region.

Parameters:
  • freq_min (float) – Minimum frequency in MHz

  • freq_max (float) – Maximum frequency in MHz

Returns:

New ComplexFT object containing only the specified frequency range

Return type:

ComplexFT

class ftmwpipeline.core.data_structures.Sideband(value)[source]

Sideband configuration for frequency conversion.

UPPER = 'upper'
LOWER = 'lower'
LSB = 'lower'
USB = 'upper'
classmethod coerce(value: str | Sideband) Sideband[source]

Coerce an enum or string (including lsb/usb) to a Sideband.

property sign: float

Sign s connecting the molecular and baseband axes.

A line at molecular frequency f sits at baseband frequency f_bb = s·(f - f_probe), so the inverse is f = f_probe + s·f_bb. s = -1 for the lower sideband (molecular axis descends as baseband rises) and s = +1 for the upper. This is the single source of truth for the convention; ftmwpipeline.fitting.peak_model.sideband_sign() delegates here.

class ftmwpipeline.preprocessing.noise_estimation.NoiseResult(rms_noise: ndarray, noise_mask: ndarray, bin_info: Dict[str, ndarray | int | float | str])[source]

Result container for noise estimation.

Variables:
  • rms_noise (numpy.ndarray) – σ_x estimate across the full frequency grid (= σ_c·√2).

  • noise_mask (numpy.ndarray) – Boolean mask of points classified as noise by the estimator’s self-mask. Used by downstream consumers that need to discriminate noise vs signal samples; not used in the σ computation itself.

  • bin_info (Dict[str, numpy.ndarray | int | float | str]) – Dictionary of estimator diagnostics.

rms_noise: ndarray
noise_mask: ndarray
bin_info: Dict[str, ndarray | int | float | str]
__init__(rms_noise: ndarray, noise_mask: ndarray, bin_info: Dict[str, ndarray | int | float | str]) None
class ftmwpipeline.core.data_structures.Peak(frequency: float, intensity: float, index: int | None = None, snr: float | None = None, noise_std_local: float | None = None, classification: str | PeakClassification | None = None, **properties: Any)[source]

Pre-fitting detected peak representation.

Represents peaks detected in the spectrum before fitting, used for initial parameter guesses.

__init__(frequency: float, intensity: float, index: int | None = None, snr: float | None = None, noise_std_local: float | None = None, classification: str | PeakClassification | None = None, **properties: Any)[source]

Initialize Peak object.

Parameters:
  • frequency (float) – Peak frequency in MHz

  • intensity (float) – Peak intensity (height above baseline)

  • index (int, optional) – Index in original frequency array

  • snr (float, optional) – Signal-to-noise ratio

  • noise_std_local (float, optional) – Local noise standard deviation

  • classification (str or PeakClassification, optional) – Peak strength classification

  • **properties – Additional peak properties

classification: PeakClassification | None
property is_classified: bool

Check if peak has been classified.

property is_strong: bool

Check if peak is classified as strong.

property is_medium: bool

Check if peak is classified as medium.

property is_weak: bool

Check if peak is classified as weak.

__lt__(other: Peak) bool[source]

Sort peaks by intensity (strongest first).

class ftmwpipeline.core.data_structures.FittedPeak(peak_id: str | int, frequency_mhz: float, amplitude: float, decay_rate: float | None = None, phase: float | None = None, frequency_error: float | None = None, amplitude_error: float | None = None, decay_rate_error: float | None = None, phase_error: float | None = None, snr: float | None = None, chi_squared: float | None = None, window_id: int | None = None, knockout: KnockoutInfo | None = None, clock_lattice: str | None = None, origin: str = 'auto', flat_decay: bool = False, extra_parameters: Dict[str, float]=<factory>, extra_errors: Dict[str, float]=<factory>)[source]

Post-fitting peak results with fitted parameters.

Represents the results of fitting a single peak, including fitted parameters, uncertainties, and quality metrics. The peak originates in one Stage 4 fit window; its peak_id is the Stage 3 promoted-peak index that seeded it, window_id is the originating fit window’s id, and knockout carries the per-peak validation result from the Stage 5 knockout test.

peak_id: str | int

Stage 3 promoted-peak index of the line (the entry in the persisted peak list that seeded this fit). For lines added by the blend-aware seeder without their own Stage 3 detection, this is the seeded peak’s index – multiple FittedPeak s may share the same peak_id in a blend.

frequency_mhz: float
amplitude: float
decay_rate: float | None = None
phase: float | None = None
frequency_error: float | None = None
amplitude_error: float | None = None
decay_rate_error: float | None = None
phase_error: float | None = None
snr: float | None = None
chi_squared: float | None = None
window_id: int | None = None

FitWindow.window_id the line was fit in.

knockout: KnockoutInfo | None = None

Knockout-test outcome from ftmwpipeline.fitting.window_fit.knockout_test().

clock_lattice: str | None = None

Clock-lattice identity string (e.g. "320x6 (bb)"), or None.

origin: str = 'auto'

Per-peak provenance for Stage 6 curation ("auto" or "user").

flat_decay: bool = False

True when the line sat in the ambiguous spur-decay band and was kept for review rather than masked.

extra_parameters: Dict[str, float]
extra_errors: Dict[str, float]
__init__(peak_id: str | int, frequency_mhz: float, amplitude: float, decay_rate: float | None = None, phase: float | None = None, frequency_error: float | None = None, amplitude_error: float | None = None, decay_rate_error: float | None = None, phase_error: float | None = None, snr: float | None = None, chi_squared: float | None = None, window_id: int | None = None, knockout: KnockoutInfo | None = None, clock_lattice: str | None = None, origin: str = 'auto', flat_decay: bool = False, extra_parameters: Dict[str, float]=<factory>, extra_errors: Dict[str, float]=<factory>) None
class ftmwpipeline.core.data_structures.SpectralWindow(parent_ft: ComplexFT | None, freq_array: ndarray, complex_spectrum: ndarray, freq_range: Tuple[float, float], window_id: str | int | None = None, peaks: List[Peak] | None = None)[source]

Analysis window - a subset of ComplexFT data for focused analysis.

Represents a frequency range extracted from a ComplexFT for targeted peak detection and fitting operations.

__init__(parent_ft: ComplexFT | None, freq_array: ndarray, complex_spectrum: ndarray, freq_range: Tuple[float, float], window_id: str | int | None = None, peaks: List[Peak] | None = None)[source]

Initialize SpectralWindow.

Parameters:
  • parent_ft (ComplexFT, optional) – Parent ComplexFT this window was extracted from. None when the window was materialized from a non-persisted spectrum (e.g. Stage 5’s active-portion FT, which is regenerated on demand and not stored on the experiment).

  • freq_array (np.ndarray) – Frequency array for this window

  • complex_spectrum (np.ndarray) – Complex spectrum data for this window

  • freq_range (tuple) – (min_freq, max_freq) in MHz

  • window_id (str or int, optional) – Identifier for this window. Stage 5 materializes one window per FitWindow and carries the integer FitWindow.window_id here directly; earlier callers used opaque string ids.

  • peaks (list of Peak, optional) – Detected peaks in this window

property magnitude_spectrum: ndarray

Magnitude spectrum.

property real_spectrum: ndarray

Real component.

property imag_spectrum: ndarray

Imaginary component.

property n_points: int

Number of frequency points.

property n_peaks: int

Number of detected peaks.

property center_frequency: float

Center frequency in MHz.

property bandwidth: float

Bandwidth in MHz.

add_peak(peak: Peak) None[source]

Add a detected peak to this window.

get_peaks_by_classification(classification: str | PeakClassification) List[Peak][source]

Get peaks with specified classification.

class ftmwpipeline.core.data_structures.WindowPlan(windows: List[FitWindow] = <factory>, dependency_edges: Tuple[int, int]]=<factory>, topological_order: List[int] = <factory>, parameters: Dict[str, ~typing.Any]=<factory>, diagnostics: Dict[str, ~typing.Any]=<factory>, plan_revision: int = 0)[source]

The complete Stage 4 fit plan: ordered windows + a fit dependency DAG.

Variables:
  • windows (list of FitWindow) – The disjoint fit windows, ordered by ascending frequency.

  • dependency_edges (list of tuple of int) – (window_id, depends_on_window_id) pairs — a window depends on the windows that fit its fixed contributors. The graph is acyclic.

  • topological_order (list of int) – window_id values in a valid fit order (every window appears after all windows it depends on).

  • parameters (dict) – The Stage 4 parameters used (edge M/threshold, width cap, …).

  • diagnostics (dict) – Plan-level diagnostics (e.g. coherent regions with no identifiable strong-line source — a hint that peak detection missed a line).

  • plan_revision (int) – Monotonic counter bumped each time replan() applies a structural change. 0 is the initial plan from build_window_plan(). It tracks the live plan during Stage 5’s structural-replan handshake; it is not persisted (a freshly built plan is always revision 0).

windows: List[FitWindow]
dependency_edges: List[Tuple[int, int]]
topological_order: List[int]
parameters: Dict[str, Any]
diagnostics: Dict[str, Any]
plan_revision: int = 0
property n_windows: int

Number of fit windows in the plan.

property n_batches: int

Number of parallel-execution batches.

window(window_id: int) FitWindow[source]

Return the window with the given window_id (raises if absent).

__init__(windows: List[FitWindow] = <factory>, dependency_edges: Tuple[int, int]]=<factory>, topological_order: List[int] = <factory>, parameters: Dict[str, ~typing.Any]=<factory>, diagnostics: Dict[str, ~typing.Any]=<factory>, plan_revision: int = 0) None
class ftmwpipeline.core.data_structures.FittingResult(success: bool = False, fitted_spectrum: ndarray | None = None, cost: float = inf, iterations: int = 0, aic: float = inf, reduced_chi2: float = inf, window: SpectralWindow | None = None, window_id: int | None = None, shape: str = 'lorentzian')[source]

Container for fitting results from analysis of SpectralWindow(s).

Stores fitted parameters, quality metrics, and diagnostic information. Stage 5 also wires the per-iteration audit_trail (the conservative add-one-peak loop’s decision log) and the per-window thaw_events (the residual-edge-coherence renegotiation outcomes that touched this window).

Per-window parameter covariance (covariance / covariance_param_labels): the full fitted-parameter covariance matrix — the inverse of the weighted JᵀJ at the NLS solution — in physical units (amplitude, MHz offset, rad phase, µs tau). None when the covariance was not computed or when JᵀJ was singular at the solution.

Parameter ordering documented in covariance_param_labels (one label per matrix row/column, peak-major):

  • amplitude_{i}, offset_{i}, phase_{i} for each peak i (0-based)

  • tau (only when the window’s tau was a free LSQ parameter)

  • baseline_re_{k} for each baseline polynomial order k (re block first)

  • baseline_im_{k} for each baseline polynomial order k (im block after re)

The molecular-frequency variance equals the offset variance (f = center ± offset; the sign flip from the sideband does not change the variance). sqrt(diag) of the amplitude/offset/phase/tau diagonal entries matches the per-peak amplitude_error / frequency_error / phase_error and the shared tau_us.error already persisted in this object.

__init__(success: bool = False, fitted_spectrum: ndarray | None = None, cost: float = inf, iterations: int = 0, aic: float = inf, reduced_chi2: float = inf, window: SpectralWindow | None = None, window_id: int | None = None, shape: str = 'lorentzian')[source]

Initialize FittingResult.

fitted_peaks: List[FittedPeak]
shared_parameters: Dict[str, Dict[str, Any]]
fixed_parameters: Dict[str, Dict[str, Any]]
residuals: ndarray | None
quality_metrics: Dict[str, float]
audit_trail: List[AuditStep]
thaw_events: List[ThawInfo]
rescue_events: List[RescueRoundInfo]
doublet_alternatives: List[DoubletAlternativeInfo]
covariance: ndarray | None
covariance_param_labels: List[str] | None
add_fitted_peak(fitted_peak: FittedPeak) None[source]

Add a fitted peak result.

set_shared_parameter(name: str, value: float, error: float | None = None, peak_ids: List | None = None) None[source]

Set a parameter shared across multiple peaks.

set_fixed_parameter(name: str, value: float, peak_ids: List | None = None) None[source]

Set a parameter held fixed during fitting.

property n_peaks_fitted: int

Number of fitted peaks.

property frequencies_mhz: List[float]

Fitted frequencies for all peaks.

property amplitudes: List[float]

Fitted amplitudes for all peaks.

class ftmwpipeline.core.data_structures.SpectrumFit(window_fits: List[FittingResult] = <factory>, fitted_peaks: List[FittedPeak] = <factory>, thaw_history: List[ThawInfo] = <factory>, replan_history: List[ReplanInfo] = <factory>, rescue_history: List[RescueRoundInfo] = <factory>, final_plan_revision: int = 0, parameters: Dict[str, ~typing.Any]=<factory>, diagnostics: Dict[str, ~typing.Any]=<factory>)[source]

The complete Stage 5 fit of a WindowPlan.

Parallels WindowPlan: each FitWindow produces one FittingResult, and the plan-level audit and renegotiation histories live alongside the per-window results. The merged global line list (fitted_peaks) is the curated user-facing output, sorted by molecular frequency, with each peak tagged with the FittedPeak.window_id of its originating fit window.

Variables:
  • window_fits (list of FittingResult) – Per-window fit results, ordered by ascending window_id.

  • fitted_peaks (list of FittedPeak) – Merged global line list, sorted by frequency_mhz. Each peak’s window_id points back to its originating window.

  • thaw_history (list of ThawInfo) – Every thaw attempt across all windows, in execution order. The per-window slice is mirrored on each FittingResult for convenience; this list is the canonical plan-level history.

  • replan_history (list of ReplanInfo) – Every structural-replan attempt, in execution order. Empty when no merges were proposed.

  • rescue_history (list of RescueRoundInfo) – Every residual-rescue round across all windows, in execution order. The per-window slice is mirrored on FittingResult.rescue_events for convenience; this list is the canonical plan-level history. Empty when the rescue was disabled or no window produced any candidates.

  • final_plan_revision (int) – WindowPlan.plan_revision of the plan the window_fits describe. 0 when no structural change happened.

  • parameters (dict) – The Stage 5 parameters used to produce this fit (tau0_us, residual_edge_threshold, max_thaw_rounds, etc.). Recorded so the persisted fit is self-describing.

  • diagnostics (dict) – Plan-level diagnostics (e.g. windows whose fit did not converge, bookkeeping summaries).

window_fits: List[FittingResult]
fitted_peaks: List[FittedPeak]
thaw_history: List[ThawInfo]
replan_history: List[ReplanInfo]
rescue_history: List[RescueRoundInfo]
final_plan_revision: int = 0
parameters: Dict[str, Any]
diagnostics: Dict[str, Any]
property n_windows: int

Number of fitted windows.

property n_fitted_peaks: int

Total number of fitted peaks across all windows.

window_fit(window_id: int) FittingResult[source]

Return the FittingResult for window_id (raises if absent).

__init__(window_fits: List[FittingResult] = <factory>, fitted_peaks: List[FittedPeak] = <factory>, thaw_history: List[ThawInfo] = <factory>, replan_history: List[ReplanInfo] = <factory>, rescue_history: List[RescueRoundInfo] = <factory>, final_plan_revision: int = 0, parameters: Dict[str, ~typing.Any]=<factory>, diagnostics: Dict[str, ~typing.Any]=<factory>) None

Final products and review state

The consolidated, calibrated outputs of the review stage.

class ftmwpipeline.core.data_structures.FinalProducts(peaks: List[FinalPeak] = <factory>, calibration_state: str = 'rb_locked', epsilon: float = 0.0, sigma_epsilon: float = 0.0, sigma_floor_khz: float = 0.0, probe_freq_mhz: float = 0.0, sideband: str = 'upper')[source]

The Stage 6 consolidated, calibrated final-products table.

The single canonical “finalized record” reports render: the calibrated line list plus the frequency-calibration state it was produced under. It is self-describing (carries the calibration state, the applied epsilon and its uncertainty, the probe/sideband, and the user accuracy floor) so the report renders it without recomputing the calibration.

Variables:
  • peaks (list of FinalPeak) – One row per accepted peak, ordered as the Stage 5 line list.

  • calibration_state (str) – "rb_locked" (axis absolutely calibrated, epsilon is identically zero / a null op), "self_calibrated" (free-running digitizer with a measured timebase_calibration applied), or "uncalibrated" (free-running digitizer with no self-calibration; frequencies reported as-is and caveated).

  • epsilon (float) – Fractional timebase scale error applied (0.0 unless self_calibrated).

  • sigma_epsilon (float) – 1-sigma uncertainty on epsilon used for the budget term (0.0 when no calibration uncertainty applies).

  • sigma_floor_khz (float) – The user-declared accuracy floor folded into every peak’s budget (kHz).

  • probe_freq_mhz (float) – Probe/LO frequency (MHz) the calibration frame is defined against.

  • sideband (str) – Sideband configuration ("upper" / "lower").

peaks: List[FinalPeak]
calibration_state: str = 'rb_locked'
epsilon: float = 0.0
sigma_epsilon: float = 0.0
sigma_floor_khz: float = 0.0
probe_freq_mhz: float = 0.0
sideband: str = 'upper'
__init__(peaks: List[FinalPeak] = <factory>, calibration_state: str = 'rb_locked', epsilon: float = 0.0, sigma_epsilon: float = 0.0, sigma_floor_khz: float = 0.0, probe_freq_mhz: float = 0.0, sideband: str = 'upper') None
class ftmwpipeline.core.data_structures.FinalPeak(frequency_mhz: float, frequency_raw_mhz: float, f_baseband_mhz: float, sigma_f_khz: float, sigma_stat_khz: float, sigma_eps_khz: float, sigma_floor_khz: float, amplitude: float, phase: float | None = None, snr: float | None = None, origin: str = 'auto', window_id: int | None = None, amplitude_error: float | None = None, phase_error: float | None = None, snr_error: float | None = None, clock_lattice: str | None = None)[source]

One row of the Stage 6 consolidated final-products table.

The calibrated, report-ready view of one accepted Stage 5 peak: the frequency corrected for the digitizer timebase scale error and the three-term frequency-uncertainty budget broken out into its components. Computed by Stage 6 (review run) from the raw fitted peak, the persisted timebase calibration, and the user-declared accuracy floor; see dev-docs/planning/stage6-reports.md for the budget derivation.

Variables:
  • frequency_mhz (float) – Calibrated molecular frequency (MHz): the raw fitted frequency with the timebase scale error epsilon removed. Equals frequency_raw_mhz when no calibration was applied (Rb-locked, or epsilon == 0).

  • frequency_raw_mhz (float) – Uncalibrated fitted molecular frequency (MHz), preserved as a drill-down so the correction is auditable.

  • f_baseband_mhz (float) – Digitized baseband frequency |f_mol - probe| (MHz); the lever the epsilon correction and the sigma_eps budget term scale with.

  • sigma_f_khz (float) – Total reported 1-sigma frequency uncertainty (kHz): sqrt(sigma_stat^2 + sigma_eps^2 + sigma_floor^2).

  • sigma_stat_khz (float) – Statistical (NLS / Cramer-Rao) precision term, from the fitted frequency_error (kHz).

  • sigma_eps_khz (float) – Timebase term sigma_epsilon * f_baseband (kHz); 0.0 when no calibration uncertainty applies.

  • sigma_floor_khz (float) – The user-declared systematic accuracy floor folded into the budget (kHz); the shipped default is 0.0.

  • amplitude (float) – Fitted amplitude (carried through from the Stage 5 peak, base SI units).

  • phase (float or None) – Fitted phase (radians), or None when unavailable.

  • snr (float or None) – Fitted signal-to-noise ratio, or None when unavailable.

  • origin (str) – Per-peak provenance, "auto" or "user" (Stage 6 curation).

  • window_id (int or None) – Originating Stage 4 fit window id.

  • amplitude_error (float or None) – 1-sigma uncertainty on amplitude (same units), or None.

  • phase_error (float or None) – 1-sigma uncertainty on phase (radians), or None.

  • snr_error (float or None) – 1-sigma uncertainty on snr, propagated from the amplitude error (snr * amplitude_error / amplitude), or None.

  • clock_lattice (str or None) – Carried through from the Stage 5 peak: the identity of the declared clock-lattice point the line lands on (e.g. "320x6 (bb)"), or None when off-lattice or no clock declaration was supplied. An on-lattice line is a candidate instrumental artifact that survived the spur gate; the report flags it for review but never removes it.

frequency_mhz: float
frequency_raw_mhz: float
f_baseband_mhz: float
sigma_f_khz: float
sigma_stat_khz: float
sigma_eps_khz: float
sigma_floor_khz: float
amplitude: float
phase: float | None = None
snr: float | None = None
origin: str = 'auto'
window_id: int | None = None
amplitude_error: float | None = None
phase_error: float | None = None
snr_error: float | None = None
clock_lattice: str | None = None
__init__(frequency_mhz: float, frequency_raw_mhz: float, f_baseband_mhz: float, sigma_f_khz: float, sigma_stat_khz: float, sigma_eps_khz: float, sigma_floor_khz: float, amplitude: float, phase: float | None = None, snr: float | None = None, origin: str = 'auto', window_id: int | None = None, amplitude_error: float | None = None, phase_error: float | None = None, snr_error: float | None = None, clock_lattice: str | None = None) None
class ftmwpipeline.core.data_structures.FrequencyCalibration(sigma_floor_khz: float = 0.0)[source]

File-level frequency-calibration provenance (the user’s accuracy floor).

Homes the single user-declared systematic frequency-accuracy floor for the experiment. Persisted as file-level provenance (a sibling of the source metadata, not a tracked pipeline stage) so any reported sigma_f is reproducible from the record alone and never depends on a transient CLI flag. The calibration state is not stored here – it is derived at consolidation time from the clock declaration and whether the timebase was self-calibrated (see dev-docs/planning/stage6-reports.md).

Variables:

sigma_floor_khz (float) – User-declared systematic accuracy floor (kHz), added in quadrature with the measured budget terms. Shipped default 0.0: the pipeline reports precision and declines to assert an accuracy floor it cannot determine.

sigma_floor_khz: float = 0.0
__init__(sigma_floor_khz: float = 0.0) None
class ftmwpipeline.core.data_structures.Stage6Review(window_statuses: Dict[int, ~ftmwpipeline.core.data_structures.WindowReviewStatus]=<factory>, decision_log: List[DecisionLogEntry] = <factory>, final_products: FinalProducts | None = None)[source]

Stage 6 curation state for the full spectrum.

Variables:
  • window_statuses (dict) – Maps window_id to WindowReviewStatus.

  • decision_log (list of DecisionLogEntry) – Ordered list of anchored user decisions (empty until Pass 2 verbs run).

  • final_products (FinalProducts or None) – The consolidated, calibrated final-products table (the finalized record reports render). None until review run builds it.

__init__(window_statuses: Dict[int, ~ftmwpipeline.core.data_structures.WindowReviewStatus]=<factory>, decision_log: List[DecisionLogEntry] = <factory>, final_products: FinalProducts | None = None) None
window_statuses: Dict[int, WindowReviewStatus]
decision_log: List[DecisionLogEntry]
final_products: FinalProducts | None = None
class ftmwpipeline.core.data_structures.LedgerCandidate(frequency_mhz: float, seed_offset_mhz: float, seed_amplitude: float | None, best_evidence: float, evidence_kind: str, reasons: List[str], decision_sites: List[str], window_id: int)[source]

One normalized revivable candidate from the automatic fit ledger.

Derived on demand from the already-persisted Stage 5 audit trail (FittingResult.audit_trail) and rescue events (FittingResult.rescue_events). All frequencies are in molecular MHz (audit-trail baseband offsets have been mapped through molecular_frequency using the window center and sideband sign).

Variables:
  • frequency_mhz (float) – Molecular frequency (MHz) of this candidate.

  • seed_offset_mhz (float) – Baseband offset in the window’s fit frame; the revival seed for a Stage 6 user add.

  • seed_amplitude (float or None) – Recorded magnitude at the candidate bin (from the rescue detector or the audit-trail chi2_before / chi2_after proxy), or None when not available.

  • best_evidence (float) – Strongest evidence value seen across all decision sites (the quantity named by evidence_kind).

  • evidence_kind (str) – "delta_chi2", "f_p", or "residual_snr" – identifies what best_evidence measures.

  • reasons (list of str) – Deduped rejection / non-accept reasons across all decision sites.

  • decision_sites (list of str) – Ordered sites where this candidate was evaluated, e.g. "add-loop:reject", "rescue-round:2".

  • window_id (int) – FitWindow.window_id this candidate belongs to.

frequency_mhz: float
seed_offset_mhz: float
seed_amplitude: float | None
best_evidence: float
evidence_kind: str
reasons: List[str]
decision_sites: List[str]
window_id: int
__init__(frequency_mhz: float, seed_offset_mhz: float, seed_amplitude: float | None, best_evidence: float, evidence_kind: str, reasons: List[str], decision_sites: List[str], window_id: int) None

Calibration results

Result objects returned by the start-detection, decay-time, and timebase calibrations.

class ftmwpipeline.preprocessing.start_detection.StartDetectionResult(start_us: float, chirp_end_us: float, chirp_detected: bool, floor: float, plateau: float, band_mhz: Tuple[float, float] | None, starts_us: ndarray, sum_magnitude: ndarray, chirp_end_declared_us: float | None = None, declaration_used: bool = False)[source]

Outcome of detect_start_time() (sweep-only) or the file-bound orchestration in ftmwpipeline._internal.start_detection_impl.

Variables:
  • start_us (float) – Effective recommended FID window start. When a chirp-window declaration is present this is the declaration-derived value (declared chirp_end + margin); otherwise it is the detector-derived chirp_end_us + guard_margin_us.

  • chirp_end_us (float) – Start time at which Σ|FT| collapses to the post-chirp floor (sweep-detector result; may differ from chirp_end_declared_us).

  • chirp_detected (bool) – Whether a chirp collapse (plateau/floor ratio above the configured minimum) was present. When False the start time could not be inferred and start_us falls back to guard_margin_us.

  • floor (float) – Robust deep-tail Σ|FT| floor.

  • plateau (float) – Σ|FT| on the pre-chirp plateau.

  • band_mhz (Tuple[float, float] | None) – Integration band actually used (None = full positive spectrum).

  • sum_magnitude (starts_us,) – The full sweep, retained for visualization.

  • chirp_end_declared_us (float | None) – Declared chirp end (µs) from the import-time chirp-window record, or None when no declaration is present.

  • declaration_used (bool) – True when start_us was derived from a chirp-window declaration rather than from the sweep detector.

start_us: float
chirp_end_us: float
chirp_detected: bool
floor: float
plateau: float
band_mhz: Tuple[float, float] | None
starts_us: ndarray
sum_magnitude: ndarray
chirp_end_declared_us: float | None = None
declaration_used: bool = False
__init__(start_us: float, chirp_end_us: float, chirp_detected: bool, floor: float, plateau: float, band_mhz: Tuple[float, float] | None, starts_us: ndarray, sum_magnitude: ndarray, chirp_end_declared_us: float | None = None, declaration_used: bool = False) None
class ftmwpipeline.fitting.tau_calibration.TauCalibrationResult(tau_maj_us: float, sigma_tau_us: float, n_contributors: int, n_spur_bins: int, spur_clusters: ~typing.Tuple[~ftmwpipeline.fitting.tau_calibration.SpurCluster, ...], bimodality: ~ftmwpipeline.fitting.tau_calibration.GMMBimodality, pearson_r_log_snr_vs_tau: float, pearson_r_freq_vs_tau: float, frequency_thirds: ~typing.Tuple[~ftmwpipeline.fitting.tau_calibration.FrequencyThird, ...], contributor_bin_indices: ~numpy.ndarray, contributor_taus_us: ~numpy.ndarray, contributor_snrs: ~numpy.ndarray, contributor_freqs_mhz: ~numpy.ndarray, n_seg: int, t_sigma: float, tau_max_us: float, rss_gate_factor: float, sample_dt_us: float, start_us: float, end_us: float, probe_freq_mhz: float, sideband: str, trim_lo_mhz: float, trim_hi_mhz: float, sigma_x_full: float, sigma_frame: float, snr_weighted: bool, preconditions_passed: bool, preconditions_notes: ~typing.Tuple[str, ...], band_majorities: ~typing.Tuple[~ftmwpipeline.fitting.tau_calibration.BandMajority, ...] = <factory>)[source]

Outcome of one STFT tau-calibration pass.

Variables:
  • tau_maj_us (float) – SNR-weighted-majority molecular decay constant (microseconds).

  • sigma_tau_us (float) – Robust spread (weighted IQR / 1.349) of the contributor tau histogram.

  • n_contributors (int) – Number of “contributor” (= above-threshold, not-spur, not-bad-fit) bins inside the analysis frequency range.

  • n_spur_bins (int) – Total number of spur-classified bins (pre-clustering).

  • spur_clusters (tuple of SpurCluster) – Grouped CW spur catalog (adjacent spur-bins collapsed).

  • bimodality (GMMBimodality) – 1- vs 2-component GMM diagnostic on the contributor histogram.

  • pearson_r_log_snr_vs_tau (float) – Pearson correlation of log10(SNR) and tau on the contributor set (NaN if fewer than 5 contributors).

  • pearson_r_freq_vs_tau (float) – Pearson correlation of molecular frequency and tau on the contributor set (NaN if fewer than 5 contributors).

  • frequency_thirds (tuple of FrequencyThird) – Per-band-third median tau (low / mid / high). Diagnostic only — carries the median per band, not the SNR-weighted majority.

  • band_majorities (tuple of BandMajority) – Per-band SNR-weighted majority tau + spread. Empty tuple when compute_band_majorities=False was passed to extract_tau_majority(). Bands with fewer than min_contributors_per_band contributors fall back to the band- wide (tau_maj_us, sigma_tau_us); see compute_band_majorities() for the policy.

  • contributor_bin_indices (np.ndarray) – Indices of contributor bins in the per-bin arrays (sorted by frequency).

  • contributor_taus_us (np.ndarray) – Recovered tau per contributor bin.

  • contributor_snrs (np.ndarray) – On-line SNR (= max-frame magnitude / per-frame sigma) per contributor bin.

  • contributor_freqs_mhz (np.ndarray) – Molecular frequency per contributor bin.

  • n_seg (int) – Number of non-overlapping STFT frames used.

  • t_sigma (float) – Above-threshold gate factor on per-frame noise (max |S_n| >= t_sigma * sigma_frame).

  • tau_max_us (float) – Upper clip on recovered tau (saturation -> spur candidate).

  • rss_gate_factor (float) – Bad-fit gate strength (relative-or-absolute hybrid).

  • sample_dt_us (float) – FID sample spacing the calibration used (microseconds).

  • start_us (float) – FID active-region start time (microseconds).

  • end_us (float) – FID active-region end time (microseconds).

  • probe_freq_mhz (float) – Probe frequency the calibration used to convert baseband bins to molecular frequencies (MHz).

  • sideband (str) – "lower" or "upper".

  • trim_hi_mhz (trim_lo_mhz,) – Analysis frequency range (molecular, MHz). Bins outside are not considered for tau extraction.

  • sigma_x_full (float) – |X|-RMS noise floor on the full-record FT (per-bin, scalar).

  • sigma_frame (float) – Per-frame noise floor (= sigma_x_full / sqrt(n_seg)).

  • snr_weighted (bool) – Whether the majority tau is SNR-weighted (always True in the production extractor; kept for forensic clarity).

  • preconditions_passed (bool) – Whether the calibration satisfies the acceptance pre-conditions (>= 200 contributors AND (not strongly bimodal OR dominant >= 0.70) AND sigma_tau / tau_maj < 0.20). When False, downstream consumers should fall back to a conservative default.

  • preconditions_notes (tuple of str) – Per-precondition diagnostic message (“ok” or the failing reason).

tau_maj_us: float
sigma_tau_us: float
n_contributors: int
n_spur_bins: int
spur_clusters: Tuple[SpurCluster, ...]
bimodality: GMMBimodality
pearson_r_log_snr_vs_tau: float
pearson_r_freq_vs_tau: float
frequency_thirds: Tuple[FrequencyThird, ...]
contributor_bin_indices: ndarray
contributor_taus_us: ndarray
contributor_snrs: ndarray
contributor_freqs_mhz: ndarray
n_seg: int
t_sigma: float
tau_max_us: float
rss_gate_factor: float
sample_dt_us: float
start_us: float
end_us: float
probe_freq_mhz: float
sideband: str
trim_lo_mhz: float
trim_hi_mhz: float
sigma_x_full: float
sigma_frame: float
snr_weighted: bool
preconditions_passed: bool
preconditions_notes: Tuple[str, ...]
band_majorities: Tuple[BandMajority, ...]
__init__(tau_maj_us: float, sigma_tau_us: float, n_contributors: int, n_spur_bins: int, spur_clusters: ~typing.Tuple[~ftmwpipeline.fitting.tau_calibration.SpurCluster, ...], bimodality: ~ftmwpipeline.fitting.tau_calibration.GMMBimodality, pearson_r_log_snr_vs_tau: float, pearson_r_freq_vs_tau: float, frequency_thirds: ~typing.Tuple[~ftmwpipeline.fitting.tau_calibration.FrequencyThird, ...], contributor_bin_indices: ~numpy.ndarray, contributor_taus_us: ~numpy.ndarray, contributor_snrs: ~numpy.ndarray, contributor_freqs_mhz: ~numpy.ndarray, n_seg: int, t_sigma: float, tau_max_us: float, rss_gate_factor: float, sample_dt_us: float, start_us: float, end_us: float, probe_freq_mhz: float, sideband: str, trim_lo_mhz: float, trim_hi_mhz: float, sigma_x_full: float, sigma_frame: float, snr_weighted: bool, preconditions_passed: bool, preconditions_notes: ~typing.Tuple[str, ...], band_majorities: ~typing.Tuple[~ftmwpipeline.fitting.tau_calibration.BandMajority, ...] = <factory>) None
class ftmwpipeline.fitting.tau_calibration.ShapeRecommendation(recommended_shape: str | None, vote_rates: Dict[str, float], median_d_aicc: Dict[str, float], n_contributors: int, notes: Tuple[str, ...])[source]

3-way per-bin model preference verdict for the Stage 5 shape selector.

Variables:
  • recommended_shape (str or None) – "lorentzian", "gaussian", or None for “no clear winner”. Written to stage2b_tau_calibration/.attrs/ recommended_shape (and the Gaussian-twin’s equivalent) so the Stage 5 resolver’s recommended layer picks it up automatically.

  • vote_rates (dict[str, float]) – SNR-weighted vote rate per model. Keys: "exp", "gauss", "voigt". Values sum to 1.0 over eligible contributors. The per-bin verdict is argmin AICc(exp, gauss, voigt); the SNR weighting collapses many low-SNR ambiguous bins onto the few strong on-line bins that actually constrain the shape.

  • median_d_aicc (dict[str, float]) –

    Per-row-pooled median ΔAICc. Keys:

    • "gauss_vs_exp": AICc(gauss) AICc(exp); negative ⇒ Gaussian beats exp.

    • "voigt_vs_exp": AICc(voigt) AICc(exp); negative ⇒ Voigt beats exp.

    • "voigt_vs_gauss": AICc(voigt) AICc(gauss); negative ⇒ Voigt beats Gaussian.

    Negative AICc differences below about −2 are conventionally called “strong preference” for the model on the left of the difference.

  • n_contributors (int) – Number of bins that entered the verdict (cls=3 ∧ SNR > snr_min, with all three fits converged and finite τ inside the bound).

  • notes (tuple of str) – Diagnostic strings, one per acceptance / tiebreaker step.

recommended_shape: str | None
vote_rates: Dict[str, float]
median_d_aicc: Dict[str, float]
n_contributors: int
notes: Tuple[str, ...]
__init__(recommended_shape: str | None, vote_rates: Dict[str, float], median_d_aicc: Dict[str, float], n_contributors: int, notes: Tuple[str, ...]) None
class ftmwpipeline.fitting.timebase_calibration.TimebaseCalibrationResult(epsilon: float, sigma_epsilon: float, n_used: int, n_detected: int, lattice_g_mhz: float, tone_reads: ~typing.Tuple[~ftmwpipeline.fitting.timebase_calibration.TimebaseToneRead, ...], kappa_sys: float, snr_min: float, sample_dt_us: float, start_us: float, end_us: float, span_us: float, preconditions_passed: bool, preconditions_notes: ~typing.Tuple[str, ...] = <factory>)[source]

Outcome of one scope-timebase self-calibration pass.

Variables:
  • epsilon (float) – Fractional scope-timebase scale error (dimensionless). Every measured frequency reads f_true * (1 + epsilon); correct via f_true = f_measured / (1 + epsilon). 0.0 when the preconditions fail.

  • sigma_epsilon (float) – Formal 1-sigma uncertainty on epsilon (1 / sqrt(sum (f / sigma_tot)^2) over kept tones). inf when no tones were kept.

  • n_used (int) – Number of locked lattice tones in the final eps fit.

  • n_detected (int) – Number of locked lattice tones detected above snr_min (before consistency rejection).

  • lattice_g_mhz (float) – GCD of the locked clock fundamentals (baseband MHz); the lattice spacing. 0.0 when no locked clocks were declared.

  • tone_reads (tuple of TimebaseToneRead) – Per-tone diagnostic table (locked detections plus drift controls).

  • kappa_sys (float) – Systematic per-tone fractional floor used in sigma_tot.

  • snr_min (float) – Peak/noise gate applied for tone detection.

  • sample_dt_us (float) – FID sample spacing the calibration used (microseconds).

  • end_us (start_us,) – Active-region bounds the calibration sliced (microseconds).

  • span_us (float) – Active-region duration T used for sigma_f (microseconds).

  • preconditions_passed (bool) – True only when locked clocks were declared, the lattice is valid, and at least three tones survived to the fit.

  • preconditions_notes (tuple of str) – Per-precondition diagnostics (“ok” or the failing reason).

epsilon: float
sigma_epsilon: float
n_used: int
n_detected: int
lattice_g_mhz: float
tone_reads: Tuple[TimebaseToneRead, ...]
kappa_sys: float
snr_min: float
sample_dt_us: float
start_us: float
end_us: float
span_us: float
preconditions_passed: bool
preconditions_notes: Tuple[str, ...]
__init__(epsilon: float, sigma_epsilon: float, n_used: int, n_detected: int, lattice_g_mhz: float, tone_reads: ~typing.Tuple[~ftmwpipeline.fitting.timebase_calibration.TimebaseToneRead, ...], kappa_sys: float, snr_min: float, sample_dt_us: float, start_us: float, end_us: float, span_us: float, preconditions_passed: bool, preconditions_notes: ~typing.Tuple[str, ...] = <factory>) None

Settings objects

Each stage takes an optional settings dataclass bundling its knobs; fields left None fall through the resolution chain. See Settings and presets for how these compose with presets and the persisted layer.

class ftmwpipeline.core.start_detection_settings.StartDetectionSettings(sweep_max_us: float = 7.5, step_us: float = 0.02, floor_factor: float = 3.0, floor_tail_us: float = 1.0, guard_margin_us: float = 0.67, min_chirp_drop_ratio: float = 10.0, band_min_mhz: float | None = None, band_max_mhz: float | None = None)[source]

Knobs for the Σ|FT|-vs-start_us start-time detector.

Parameters:
  • sweep_max_us (float) – Upper bound of the start-time sweep (capped to the FID duration). Must clear the chirp end plus the post-chirp molecular tail used to estimate the floor.

  • step_us (float) – Sweep step. Finer resolves the chirp-end corner more precisely at linear cost.

  • floor_factor (float) – Chirp-end is the first start where Σ|FT| falls below floor_factor * floor (the deep-tail floor). The chirp collapse is ~2-3 decades, so any factor in a few-x of the floor lands on the same corner.

  • floor_tail_us (float) – Width of the deep-tail window (at the end of the sweep) used for the robust floor estimate.

  • guard_margin_us (float) – Added to the detected chirp-end to clear the switch-bounce ringdown. The primary recommendation is chirp_end + guard_margin_us. Instrument-specific.

  • min_chirp_drop_ratio (float) – Minimum plateau/floor ratio for the chirp collapse to be considered present. Below this the start time cannot be inferred from the data (no excitation transient in the recorded FID).

  • band_min_mhz – Optional explicit integration band override. When unset, the impl resolves the band from the canonical Stage 1 frequency trim, falling back to the full positive spectrum.

  • band_max_mhz – Optional explicit integration band override. When unset, the impl resolves the band from the canonical Stage 1 frequency trim, falling back to the full positive spectrum.

sweep_max_us: float = 7.5
step_us: float = 0.02
floor_factor: float = 3.0
floor_tail_us: float = 1.0
guard_margin_us: float = 0.67
min_chirp_drop_ratio: float = 10.0
band_min_mhz: float | None = None
band_max_mhz: float | None = None
__init__(sweep_max_us: float = 7.5, step_us: float = 0.02, floor_factor: float = 3.0, floor_tail_us: float = 1.0, guard_margin_us: float = 0.67, min_chirp_drop_ratio: float = 10.0, band_min_mhz: float | None = None, band_max_mhz: float | None = None) None
class ftmwpipeline.core.noise_settings.NoiseSettings(window_mhz: float | None = None, pedestal_mhz: float | None = None, line_k: float | None = None, n_iter: int | None = None, region_aware: bool | None = None, smoothing_mhz: float | None = None, smoothing_percentile: float | None = None, convolve_mhz: float | None = None)[source]

Stage 2 scatter-estimator settings (see module docstring).

The fields mirror the estimate_noise_scatter kernel signature.

window_mhz: float | None = None
pedestal_mhz: float | None = None
line_k: float | None = None
n_iter: int | None = None
region_aware: bool | None = None
smoothing_mhz: float | None = None
smoothing_percentile: float | None = None
convolve_mhz: float | None = None
is_empty() bool[source]

True if no field is set.

__init__(window_mhz: float | None = None, pedestal_mhz: float | None = None, line_k: float | None = None, n_iter: int | None = None, region_aware: bool | None = None, smoothing_mhz: float | None = None, smoothing_percentile: float | None = None, convolve_mhz: float | None = None) None
class ftmwpipeline.core.tau_calibration_settings.TauCalibrationSettings(stft: StftSubSettings = <factory>, polish: PolishSubSettings = <factory>, aggregation: AggregationSubSettings = <factory>, band: BandSubSettings = <factory>, gaussian: GaussianSubSettings = <factory>, recommendation: RecommendationSubSettings = <factory>)[source]

Stage 2b τ calibration settings (see module docstring).

stft: StftSubSettings
polish: PolishSubSettings
aggregation: AggregationSubSettings
band: BandSubSettings
gaussian: GaussianSubSettings
recommendation: RecommendationSubSettings
is_empty() bool[source]

True if no field is set across any sub-dataclass.

__init__(stft: StftSubSettings = <factory>, polish: PolishSubSettings = <factory>, aggregation: AggregationSubSettings = <factory>, band: BandSubSettings = <factory>, gaussian: GaussianSubSettings = <factory>, recommendation: RecommendationSubSettings = <factory>) None
class ftmwpipeline.core.peak_detection_settings.PeakDetectionSettings(promotion: PromotionSubSettings = <factory>, savgol: SavgolSubSettings = <factory>, primary_pass: PrimaryPassSubSettings = <factory>, gap_pass: GapPassSubSettings = <factory>)[source]

Stage 3 peak-detection settings (see module docstring).

promotion: PromotionSubSettings
savgol: SavgolSubSettings
primary_pass: PrimaryPassSubSettings
gap_pass: GapPassSubSettings
is_empty() bool[source]

True if no field is set across any sub-dataclass.

__init__(promotion: PromotionSubSettings = <factory>, savgol: SavgolSubSettings = <factory>, primary_pass: PrimaryPassSubSettings = <factory>, gap_pass: GapPassSubSettings = <factory>) None
class ftmwpipeline.core.window_planning_settings.WindowPlanningSettings(coherence: CoherenceSubSettings = <factory>, clustering: ClusteringSubSettings = <factory>, contributor: ContributorSubSettings = <factory>, leakage: LeakageSubSettings = <factory>)[source]

Stage 4 window-planning settings (see module docstring).

coherence: CoherenceSubSettings
clustering: ClusteringSubSettings
contributor: ContributorSubSettings
leakage: LeakageSubSettings
is_empty() bool[source]

True if no field is set across any sub-dataclass.

__init__(coherence: CoherenceSubSettings = <factory>, clustering: ClusteringSubSettings = <factory>, contributor: ContributorSubSettings = <factory>, leakage: LeakageSubSettings = <factory>) None
class ftmwpipeline.core.stage_fit_settings.StageFitSettings(shape: ShapeSpec | None = None, tau: TauSubSettings = <factory>, seeder: SeederSubSettings = <factory>, conservative: ConservativeSubSettings = <factory>, penalties: PenaltySubSettings = <factory>, rescue: RescueSubSettings = <factory>, thaw: ThawSubSettings = <factory>, spur: SpurSubSettings = <factory>, baseline: BaselineSubSettings = <factory>, doublet_alternative: DoubletAlternativeSubSettings = <factory>, peak_survival: PeakSurvivalSubSettings = <factory>)[source]

Stage 5 fit settings (see module docstring).

shape: ShapeSpec | None = None
tau: TauSubSettings
seeder: SeederSubSettings
conservative: ConservativeSubSettings
penalties: PenaltySubSettings
rescue: RescueSubSettings
thaw: ThawSubSettings
spur: SpurSubSettings
baseline: BaselineSubSettings
doublet_alternative: DoubletAlternativeSubSettings
peak_survival: PeakSurvivalSubSettings
is_empty() bool[source]

True if no field is set across any sub-dataclass.

__init__(shape: ShapeSpec | None = None, tau: TauSubSettings = <factory>, seeder: SeederSubSettings = <factory>, conservative: ConservativeSubSettings = <factory>, penalties: PenaltySubSettings = <factory>, rescue: RescueSubSettings = <factory>, thaw: ThawSubSettings = <factory>, spur: SpurSubSettings = <factory>, baseline: BaselineSubSettings = <factory>, doublet_alternative: DoubletAlternativeSubSettings = <factory>, peak_survival: PeakSurvivalSubSettings = <factory>) None
class ftmwpipeline.core.stage_fit_settings.ClockSource(freq_mhz: float, locked: bool = True, label: str = '')[source]

One declared instrument clock source.

Declare chain fundamentals (e.g. the 5760 / 5120 MHz synthesizer outputs), not derived products (11520, 40960) – harmonics are generated, so the products come for free. locked marks a source referenced to the instrument’s frequency standard (Rb): the locked fundamentals span the exact intermod lattice (multiples of their GCD), while unlocked sources (a free-running digitizer clock) predict a drifting tone family. See dev-docs/planning/instrument-clock-declaration.md.

freq_mhz: float
locked: bool = True
label: str = ''
to_dict() Dict[str, Any][source]
__init__(freq_mhz: float, locked: bool = True, label: str = '') None

Exceptions

The file-management error family, all subclasses of PipelineFileError.

exception ftmwpipeline.file_manager.PipelineFileError[source]

Base exception for pipeline file operations.

exception ftmwpipeline.file_manager.PipelineExistsError(filepath: Path, existing_source: str, requested_source: str)[source]

Raised when attempting to create a pipeline file that already exists with different source.

__init__(filepath: Path, existing_source: str, requested_source: str)[source]
exception ftmwpipeline.file_manager.PipelineCorruptionError(filepath: Path, corruption_details: str)[source]

Raised when pipeline file is corrupted or invalid.

__init__(filepath: Path, corruption_details: str)[source]
exception ftmwpipeline.file_manager.StageDependencyError(stage_name: str, missing_dependencies: list, filepath: Path)[source]

Raised when attempting to execute a stage without required dependencies.

__init__(stage_name: str, missing_dependencies: list, filepath: Path)[source]