Python API Reference
ftmwpipeline exposes two Python interfaces over one shared implementation:
the
Pipelineclass, bound to a single.ftmwfile for its lifetime, anda stateless functional API (
import ftmwpipeline.api as ftmw) whose every function takes a.ftmwpath 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) |
||
Start detection |
||
Fourier transform (Stage 1) |
||
Noise (Stage 2) |
||
Decay time (Stage 2b) |
||
Timebase calibration |
||
Peaks (Stage 3) |
||
Windows (Stage 4) |
||
Fit (Stage 5) |
||
Review (Stage 6) |
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, raisingFileNotFoundErrorwith guidance if it does not exist. UsePipeline.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()andopen()supply both metadata arguments directly. Passing only a path performs the same load asopen().
- 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:
- Raises:
PipelineExistsError – If file exists with different source and force=False
FileNotFoundError – If source data does not exist
ValueError – If format detection or validation fails
RuntimeError – If data loading or file creation fails
- 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:
- Raises:
FileNotFoundError – If pipeline file doesn’t exist
PipelineCorruptionError – If file appears to be corrupted
ValueError – If file format is invalid
- 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, withreport=True, the report), with live per-stage progress. trim (the active-band FT range, MHz) is required.outputis the destination.ftmw(derived from source if omitted). Remaining keyword arguments are forwarded torun_pipeline_impl()(per-stage*_paramsoverride 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 withPipeline.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:
- Raises:
FileNotFoundError – If pipeline file does not exist
PipelineCorruptionError – If file is corrupted or invalid
RuntimeError – If FID loading fails
- 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 > recommendedand persists the resolved canonical settings to the.ftmwfile. 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:
- Raises:
StageDependencyError – If Stage 0 (FID data) is not available.
RuntimeError – If FT computation fails.
- 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 showcommand. Never persists settings; exploration only. Passsave_params=Trueto write the explicitly provided kwargs to the canonicalft_processingrecord. 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:
StageDependencyError – If required dependencies are not available.
RuntimeError – If visualization fails.
- 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 runcommand. 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
NoiseSettingsbundle as the explicit override layer, a YAML preset’sstage2:block as the preset layer beneath the persisted record). Individual knobs (window_mhz/smoothing_mhz/smoothing_percentile/convolve_mhz/ …) are set on theNoiseSettingsinstance; 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
NoiseSettingsbundle as the explicit override layer, a YAML preset’sstage2:block as the preset layer beneath the persisted record). Individual knobs (window_mhz/smoothing_mhz/smoothing_percentile/convolve_mhz/ …) are set on theNoiseSettingsinstance; 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:
- Raises:
StageDependencyError – If Stage 1 (FT computation) has not been completed
ValueError – If noise estimation parameters are invalid
RuntimeError – If noise estimation computation fails
- 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 showcommand.- 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:
- Raises:
StageDependencyError – If Stage 2 (noise estimation) has not been completed
RuntimeError – If visualization fails
- 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 spreadsigma_tau) from the raw FID by sliding aT_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.shapeselects the decay model and its persistence group:"lorentzian"(pure-exponential,/stage2b_tau_calibration; consumed by ashape='lorentzian'Stage 5 fit) or"gaussian"(pure-Gaussian envelope τ_G,/stage2b_tau_G_calibration; consumed by ashape='gaussian'fit). The result invalidates downstream stages.Settings resolve through the chain (
settings/preset> persisted > hard default); passsettings=to drive the calibration from aTauCalibrationSettingsinstance, orpreset=NAME_OR_PATHto load from packaged YAML. They may be combined: thesettingsbundle is the explicit override that outranks the persisted record, while thepresetseeds 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 sharedprocessing_parameters/stage2b_taublock both shape variants use).
- load_tau_calibration(*, shape: str = 'lorentzian') TauCalibrationResult[source]
Load the persisted Stage 2b
TauCalibrationResultforshape.
- calibrate_timebase(*, clocks: Any | None = None, kappa_sys: float | None = None, snr_min: float | None = None) TimebaseCalibrationResult[source]
Measure the scope-timebase scale error
epsfrom 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
clocksargument, else the persisted Stage 5spur.clocks; raisesValueErrorif neither yields a non-empty declaration with at least one locked source. Persists the measuredepsto/timebase_calibration. Measuresepsonly; 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.
clocksis a sequence ofClockSourceor{freq_mhz, locked, label}mappings. Withreplace=Falsethe 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).
- 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=andpreset=may be combined – thesettingsbundle is the explicit override that outranks the persisted record, while thepresetseeds 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 toprocessing_parameters/stage2b_tauso 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).
shapeselects 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.
shapeselects 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_usfrom 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). Whenstamp=True(default) the recommendedstart_usis written to the Stage 0recommended_processinglayer, so a latercompute_ftwith no explicitstart_usinherits 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 CLIstart runcommand andftmwpipeline.api.detect_start_time.- Parameters:
band (tuple of float, optional) – Explicit
(min_mhz, max_mhz)integration band override (a convenience forsettingsband_min_mhz/band_max_mhz).stamp (bool, default True) – Whether to persist the recommended
start_usto 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
StartDetectionSettingswith the fields to override (sweep_max_us/step_us/guard_margin_us/floor_factor/ …).bandwins over the bundle’s band fields when supplied.
- Returns:
The recommendation plus diagnostics (chirp-end, sweep arrays).
- Return type:
- 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 runcommand andftmwpipeline.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); passsettings=to drive detection from aPeakDetectionSettingsinstance, orpreset=NAME_OR_PATHto load from packaged YAML. They may be combined: asettingsbundle is the explicit override that outranks the persisted record, while apresetseeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs viasettings=PeakDetectionSettings(...)or a YAML preset’sstage3:block.- Parameters:
settings (PeakDetectionSettings, optional) – Bundle of Stage 3 knobs; fields left
Nonefall through the resolution chain. May be combined withpreset.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 withsettings.
- Returns:
ALL detected peaks (promoted and non-promoted), sorted by frequency. Each peak’s
propertiesdict includespromoted(bool),internal_snr,internal_frequency, anddetection_pass.- Return type:
- Raises:
StageDependencyError – If Stage 1 or Stage 2 has not been completed.
RuntimeError – If detection fails.
- 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 showcommand. Interactive matplotlib (log-y) by default; passinteractive=Falsewithoutput_fileto 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 runcommand andftmwpipeline.api.assign_windows.Consumes only the peaks flagged
promotedby Stage 3, on the Stage 1 canonical spectrum with the canonical Stage 2 noise. The result is persisted to/stage4_windowsand the stage marked complete.Settings resolve through the chain (
settings/preset> persisted > hard default); passsettings=to drive window planning from aWindowPlanningSettingsinstance, orpreset=NAME_OR_PATHto load from packaged YAML. They may be combined: asettingsbundle is the explicit override that outranks the persisted record, while apresetseeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs viasettings=WindowPlanningSettings(...)or a YAML preset’sstage4:block.- Parameters:
settings (WindowPlanningSettings, optional) – Bundle of Stage 4 knobs; fields left
Nonefall through the resolution chain. May be combined withpreset.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 withsettings.
- Returns:
The fit plan: disjoint windows, dependency DAG, topological order, parallel batches, parameters and diagnostics.
- Return type:
- Raises:
StageDependencyError – If Stage 3 has not been completed.
RuntimeError – If window assignment fails.
- 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 showcommand. 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
tauand the frozen-contributor model, then the residual edge-coherence handshake (local thaw + structural replan). Equivalent to the CLIfit runcommand andftmwpipeline.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-windowFittingResults, 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); passsettings=to drive the fit from aStageFitSettingsinstance, orpreset=NAME_OR_PATHto load from packaged YAML. They may be combined: asettingsbundle outranks a value persisted in the.ftmwwhile apreset.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"usesexp(-t/τ);"gaussian"usesexp(-(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.Nonefalls 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
Nonefall through the resolution chain. Resolves at the explicit override layer (outranks the persisted record). Build withStageFitSettings. May be combined withpreset.preset (str, optional) – Bare preset name (e.g.
"defaults") or a path to a YAML file carrying astage5:block. Enters at the preset layer (a persisted.ftmwoutranks it). The preset name is captured in the persisted Stage 5 fit’s audit attrs for reproducibility. May be combined withsettings.jobs (int, optional) – Worker-pool size for the cross-window parallel fit.
None(the default) resolves the pool from theFTMW_MAX_WORKERSenvironment variable, falling back tocpu_count() - 2;1forces a sequential fit. The fit result is byte-identical regardless of the worker count.
- Returns:
The persistent fit aggregate.
- Return type:
- Raises:
StageDependencyError – If Stage 4 has not been completed.
RuntimeError – If fitting fails.
- 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_idfrom the persisted Stage 5 fit using the production NLS primitive, applyingadd/removeedits. User- added peaks carryorigin="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_mhzor 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
intopeaks (Stage 6review split).Removes the named peak and adds
intoreplacements spread symmetrically about it by ±½ of one Fourier resolution element (1 / acquisition_usMHz). All products carryorigin="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_fbudget), persists theStage6Reviewto thestage6_reviewHDF5 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_calibrationrecord 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 reportedsigma_fis reproducible from the record alone. Callreview_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;
Noneuntilreview_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
FinalProductstable tocsv,json, or a LaTeXbooktabstable. Renders the persisted record; does not recompute. Requiresreview_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:
- 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. Requiresreview_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.htmlwith 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 theFTMW_MAX_WORKERSenvironment variable, falling back tocpu_count() - 2;1renders sequentially.
- Returns:
{"table": <path|None>, "html": <path|None>}– the path of each artifact written (Nonewhen suppressed).- Return type:
- 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.htmlwith 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.htmlfile.- Return type:
- 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 returnsNone. 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 theRefitWindowResult.- 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,paramsrows) 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. Withdry_runthe 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_runpreviews the removed/ surviving split and the replay plan without writing.- Parameters:
ids – Decision ids (
order_indexvalues fromreview_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:
- 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(seeRANK_METRICSfor 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;
Nonereturns 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)**2with the fractional deficitepsbinned by SNR) / Tier 2 (rescue/merge/thaw gate firing) / Tier 3 (known-line ground truth, whenground_truthis given) report. Equivalent to the CLIfit checkcommand. 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 showcommand. Withwindow_idset, 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 showcommand. With no selector, returns the spectrum-wide overview. The selectors (window_ids/freqs/random_n/top_snr/all_windows) compose as a union; withoutput_direach detail figure is written as<stem>_window_<id>.png. Withrescuean 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:
- validate() Dict[str, Any][source]
Validate pipeline file integrity.
- Returns:
Detailed validation report
- Return type:
- 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 returnedKnobSpectuple is independent of any file, so this is a staticmethod; it is exposed on the class for dual-interface parity.selectorfilters by dotted-path prefix (e.g."stage2b"/"stage2b.gaussian");include_advancedreveals 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 aSweepResultwith the table, CSV path, optional plot, recommendation, and how-to-apply instructions. A progress indicator is printed to stderr unlessquiet=True.zoom_regionspins 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_mhzinstead tune how many regions to auto-select and how wide each is. Thefit_*controls bound a Stage 5 fit sweep to a window subset (thefit_top_snrbrightest + a seededfit_samplesample + the windows nearestfit_freqs);fit_allre-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
selectoron its default grid.Equivalent to
ftmwpipeline.api.scan_all(). A convenience overscan_run()for reviewing a whole stage / sub-block at once:selectorfilters by dotted-path prefix (e.g."stage2b"/"stage2b.gaussian") exactly asscan_list(), andinclude_advancedadds 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 failedBatchItemand the batch continues. Thezoom_*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 oneSettingRowper setting – itspath, the resolvedvalue, thesourcelayer that supplied it (.ftmw/.yml:<name>/recommended/default), thehard_defaultfor reference, and the registrytier/helpenrichment.selectorfilters by dotted-path prefix (e.g."stage2b"/"stage2b.gaussian");include_advancedreveals advanced-tier rows;preset(a bare name or YAML path) populates the.ymlprovenance layer. Because a persisted.ftmwvalue 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
knobinto this file’s persisted layer.Equivalent to
ftmwpipeline.api.settings_set().knobis a dotted settings path (stage2.window_mhz/stage5.tau.max_decay_factor);valueis 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 tocompute_ft(). Returns aSetResultwith 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
.ymlpreset block.Equivalent to
ftmwpipeline.api.settings_export(). Each stage’s persisted settings are serialized into the matchingstageN:block, filtered by the dottedselector; the result loads back through the stages’--presetpath. Stage 1 is excluded (presets do not carry FT settings). Returns anExportResultwith the written path and the exported setting paths.
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:
- Raises:
PipelineExistsError – If file exists with different source and force=False
FileNotFoundError – If source data does not exist
ValueError – If format detection or validation fails
RuntimeError – If data loading or file creation fails
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.
clocksis a sequence ofClockSourceor{freq_mhz, locked, label}mappings. Declare chain fundamentals (e.g. 5760, not the 11520 product). Withreplace=Falsethe 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:
- Raises:
FileNotFoundError – If pipeline file does not exist
PipelineCorruptionError – If file is corrupted or invalid
RuntimeError – If FID loading fails
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:
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_usfrom the data, equivalent toPipeline.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. Whenstamp=True(default) the value is written to the Stage 0recommended_processinglayer so a latercompute_ft()with no explicitstart_usinherits 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
.ftmwfile with the FID imported.band (tuple of float, optional) – Explicit
(min_mhz, max_mhz)integration band override (a convenience for thesettingsband 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
StartDetectionSettingswith the fields to override (sweep_max_us/step_us/guard_margin_us/floor_factor/ …).
- Returns:
The recommendation plus diagnostics.
- Return type:
- 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:
- Raises:
FileNotFoundError – If pipeline file does not exist.
StageDependencyError – If required dependencies (FID data) are not available.
RuntimeError – If FT computation fails.
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:
FileNotFoundError – If pipeline file does not exist
StageDependencyError – If required dependencies are not available
RuntimeError – If visualization fails
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:
- Raises:
FileNotFoundError – If pipeline file does not exist
RuntimeError – If parameter saving fails
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
NoiseSettingsbundle as the explicit override layer, a YAML preset’sstage2:block as the preset layer beneath the persisted record). Individual scatter knobs (window_mhz/smoothing_mhz/smoothing_percentile/convolve_mhz/ …) are set on theNoiseSettingsinstance; 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
NoiseSettingsbundle as the explicit override layer, a YAML preset’sstage2:block as the preset layer beneath the persisted record). Individual scatter knobs (window_mhz/smoothing_mhz/smoothing_percentile/convolve_mhz/ …) are set on theNoiseSettingsinstance; 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:
- Raises:
FileNotFoundError – If pipeline file does not exist
ValueError – If Stage 1 dependencies are not met or parameters are invalid
RuntimeError – If noise estimation fails
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:
- Raises:
FileNotFoundError – If pipeline file does not exist
ValueError – If Stage 2 dependencies are not met
RuntimeError – If visualization fails
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.
shapeselects 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.ftmwfile, consumed by the matching-shape Stage 5 fit. Settings resolve through the chain (settings/preset> persisted > hard default);settings=andpreset=may be combined – thesettingsbundle is the explicit override that outranks the persisted record, while thepresetseeds 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 aTauCalibrationSettingsinstance or a YAML preset’sstage2b:block. The resolved settings are stamped to the sharedprocessing_parameters/stage2b_taublock 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
TauCalibrationResultforshape.
- 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 toPipeline.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 readsf_true * (1 + eps)). The clock declaration comes from the explicitclocksargument, else the persisted Stage 5spur.clocks; a non-empty declaration with at least one locked source is required. Persistsepsto/timebase_calibration; measuringepsis 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_shapeis 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=andpreset=may be combined – thesettingsbundle is the explicit override that outranks the persisted record, while thepresetseeds 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().shapeselects 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().shapeselects 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); passsettings=to drive detection from aPeakDetectionSettingsdataclass, orpreset=NAME_OR_PATHto load from packaged YAML. They may be combined: asettingsbundle is the explicit override that outranks the persisted record, while apresetseeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs viasettings=PeakDetectionSettings(...)or a YAML preset’sstage3:block.- Parameters:
file_path (str or Path) – Path to .ftmw pipeline file.
settings (PeakDetectionSettings, optional) – Bundle of Stage 3 knobs; fields left
Nonefall through the resolution chain. May be combined withpreset.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 withsettings.
- Returns:
ALL detected peaks (promoted and non-promoted), sorted by frequency. Each peak’s
propertiesdict includespromoted(bool),internal_snr,internal_frequency, anddetection_pass.- Return type:
- 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); passsettings=to drive window planning from aWindowPlanningSettingsdataclass, orpreset=NAME_OR_PATHto load from packaged YAML. They may be combined: asettingsbundle is the explicit override that outranks the persisted record, while apresetseeds only the fields neither the explicit layer nor the persisted record has fixed (the persisted record outranks the preset, per D11). Set individual knobs viasettings=WindowPlanningSettings(...)or a YAML preset’sstage4:block.- Parameters:
file_path (str or Path) – Path to .ftmw pipeline file.
settings (WindowPlanningSettings, optional) – Bundle of Stage 4 knobs; fields left
Nonefall through the resolution chain. May be combined withpreset.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 withsettings.
- Returns:
The fit plan: disjoint windows, dependency DAG, topological order, parallel batches, parameters and diagnostics.
- Return type:
- 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
tauand 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 persistentSpectrumFit– per-windowFittingResults, 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); passsettings=to drive the fit from aStageFitSettingsdataclass, orpreset=NAME_OR_PATHto load from packaged YAML. They may be combined: asettingsbundle outranks a value persisted in the.ftmwwhile apreset.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"usesexp(-t/τ);"gaussian"usesexp(-(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.Nonefalls 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
Nonefall through the resolution chain. Resolves at the explicit override layer (outranks the persisted record). May be combined withpreset.preset (str, optional) – Bare preset name (e.g.
"defaults") or a path to a YAML file carrying astage5:block. Seeds the preset layer beneath the persisted record; may be combined withsettings.jobs (int, optional) – Worker-pool size for the cross-window parallel fit.
None(the default) resolves the pool from theFTMW_MAX_WORKERSenvironment variable, falling back tocpu_count() - 2;1forces a sequential fit. The fit result is byte-identical regardless of the worker count.
- Returns:
The persistent fit aggregate.
- Return type:
- Raises:
StageDependencyError – If Stage 4 has not been completed.
RuntimeError – If fitting fails.
- 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
.ftmwpipeline 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_idfrom the persisted Stage 5 fit using the production NLS primitive, applyingadd/removeedits. User-added peaks carryorigin="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 toPipeline.review_edit().- Parameters:
file_path – Path to the
.ftmwpipeline 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
.ftmwpipeline 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
intopeaks (Stage 6review split).Equivalent to
Pipeline.review_split().- Parameters:
file_path – Path to the
.ftmwpipeline 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
.ftmwpipeline 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;
Nonekeeps 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 reportedsigma_fis reproducible from the record alone. Runreview_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 tocsv/json/latex; renders the persisted record (does not recompute). Requiresreview_runto have built the table. Passcatalogto 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). Requiresreview_runto have built the final-products table. Passcatalogto add proximity-match cross-references (label echo only, never an assignment).jobssets the worker-pool size for the per-window figure rendering (Noneresolves it from theFTMW_MAX_WORKERSenvironment variable, falling back tocpu_count() - 2;1renders 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.htmlwith 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, withreport=True, the report) in order, showing live per-stage progress. trim (the active-band FT range, MHz) is required;outputis 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 optionalpresetname;detect_start/calibrate/clocksgate the optional stages (timebase is non-fatal – it warns and skips when no clock declaration is resolvable),report/report_output_diremit the report, andprogress=Falsesilences 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
.ftmwpipeline 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 None –
Nonewhen accepting as-is; the refit result whencandidate_freqis 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). Withdry_runthe resolved plan and frequency-resolution warnings are returned without modifying the file.- Parameters:
file_path – Path to the
.ftmwpipeline 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
.ftmwpipeline 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_runpreviews without writing.- Parameters:
file_path – Path to the
.ftmwpipeline 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 beforereview run.- Parameters:
file_path – Path to the
.ftmwpipeline file.- Returns:
The persisted per-window statuses and decision log.
- Return type:
- 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 byby(min-snr,max-vif,chi2r,candidate-evidence,edge-distance,spur-proximity,merged-chi2r).- Parameters:
file_path – Path to the
.ftmwpipeline file.by – Metric name (
_and-interchangeable).top – Return at most this many windows;
Nonereturns 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_truthis given) report, equivalent toPipeline.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 CLIfit showcommand.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. Withoutput_direach detail figure is written there. Withrescuean 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:
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:
- Raises:
FileNotFoundError – If pipeline file does not exist
RuntimeError – If stage information cannot be retrieved
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:
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:
- 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 aSweepResultwith 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
.ftmwalready 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_regionsis not given, how many regions to auto-select and how wide each is;Nonekeeps the adapter defaults.zoom_width_mhz (optional) – When
zoom_regionsis not given, how many regions to auto-select and how wide each is;Nonekeeps the adapter defaults.fit_top_snr (optional) – Window selection for Stage 5 fit knobs: re-fit only the
fit_top_snrbrightest windows + a seededfit_samplerandom sample + the windows nearest eachfit_freqsvalue, rather than the whole plan.fit_all=Truere-fits every window. Ignored by non-fit knobs.fit_sample (optional) – Window selection for Stage 5 fit knobs: re-fit only the
fit_top_snrbrightest windows + a seededfit_samplerandom sample + the windows nearest eachfit_freqsvalue, rather than the whole plan.fit_all=Truere-fits every window. Ignored by non-fit knobs.fit_freqs (optional) – Window selection for Stage 5 fit knobs: re-fit only the
fit_top_snrbrightest windows + a seededfit_samplerandom sample + the windows nearest eachfit_freqsvalue, rather than the whole plan.fit_all=Truere-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_snrbrightest windows + a seededfit_samplerandom sample + the windows nearest eachfit_freqsvalue, rather than the whole plan.fit_all=Truere-fits every window. Ignored by non-fit knobs.fit_all (optional) – Window selection for Stage 5 fit knobs: re-fit only the
fit_top_snrbrightest windows + a seededfit_samplerandom sample + the windows nearest eachfit_freqsvalue, rather than the whole plan.fit_all=Truere-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
selectoron its default grid, equivalent toPipeline.scan_all().A convenience over
scan_run()for reviewing a whole stage / sub-block at once instead of driving knobs one-by-one.selectorfilters by dotted-path prefix (e.g."stage2b"/"stage2b.gaussian") just likescan_list();include_advancedadds the advanced-tier knobs. Each knob runs on its own working copy offile_path(never mutated); a knob whose scan fails (e.g. its required stage is absent) is recorded as a failedBatchItemand the batch continues.- Returns:
One per matched knob, in registry order;
item.ok/item.result/item.errorreport 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 toscan_list()’s tunable-knob listing.- Parameters:
file_path (str or Path) – The
.ftmwexperiment to inspect.selector (str, optional) – Filter by dotted-path prefix (e.g.
"stage2b"/"stage2b.gaussian");Nonereturns every setting.include_advanced (bool, default False) – Reveal advanced-tier settings hidden from the default view.
preset (str or Path, optional) – Populate the
.ymlprovenance layer from this preset (bare name or path). Because a persisted.ftmwvalue 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 toPipeline.settings_set().Coerces
valuetoknob’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:
- 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
.ymlpreset, equivalent toPipeline.settings_export().Each stage’s persisted settings serialize into the matching
stageN:block, filtered by the dottedselector; the result loads back through the stages’--presetpath. Stage 1 is excluded (presets do not carry FT settings).- Parameters:
file_path (str or Path) – The
.ftmwto read chosen values from.out_path (str or Path) – Destination
.ymlpreset file.selector (str, optional) – Restrict the export to a dotted prefix (e.g.
"stage5"/"stage5.rescue");Noneexports every persisted Stage 2–5 value.name (str, optional) – Preset metadata written alongside the stage blocks (
namedefaults to the output file stem).description (str, optional) – Preset metadata written alongside the stage blocks (
namedefaults 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
- 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:
Extract the active region (
start_ustoend_us); points outside it are zeroed.Remove the DC component of the active region (always).
- 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.
- extract_window(freq_min: float, freq_max: float) SpectralWindow[source]
Extract a frequency window.
- 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
sconnecting the molecular and baseband axes.A line at molecular frequency
fsits at baseband frequencyf_bb = s·(f - f_probe), so the inverse isf = f_probe + s·f_bb.s = -1for the lower sideband (molecular axis descends as baseband rises) ands = +1for 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.
- 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
- 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_idis the Stage 3 promoted-peak index that seeded it,window_idis the originating fit window’s id, andknockoutcarries 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
FittedPeaks may share the samepeak_idin a blend.
- knockout: KnockoutInfo | None = None
Knockout-test outcome from
ftmwpipeline.fitting.window_fit.knockout_test().
- flat_decay: bool = False
Truewhen the line sat in the ambiguous spur-decay band and was kept for review rather than masked.
- __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.
Nonewhen 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
FitWindowand carries the integerFitWindow.window_idhere directly; earlier callers used opaque string ids.peaks (list of Peak, optional) – Detected peaks in this window
- 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_idvalues 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.0is the initial plan frombuild_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).
- 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-windowthaw_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).Nonewhen 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-peakamplitude_error/frequency_error/phase_errorand the sharedtau_us.erroralready 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]
- add_fitted_peak(fitted_peak: FittedPeak) None[source]
Add a fitted peak result.
Set a parameter shared across multiple 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: eachFitWindowproduces oneFittingResult, 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 theFittedPeak.window_idof 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’swindow_idpoints 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
FittingResultfor 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_eventsfor 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_revisionof the plan thewindow_fitsdescribe.0when 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]
- window_fit(window_id: int) FittingResult[source]
Return the
FittingResultforwindow_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
epsilonand 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,epsilonis identically zero / a null op),"self_calibrated"(free-running digitizer with a measuredtimebase_calibrationapplied), or"uncalibrated"(free-running digitizer with no self-calibration; frequencies reported as-is and caveated).epsilon (float) – Fractional timebase scale error applied (
0.0unlessself_calibrated).sigma_epsilon (float) – 1-sigma uncertainty on
epsilonused for the budget term (0.0when 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").
- 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; seedev-docs/planning/stage6-reports.mdfor the budget derivation.- Variables:
frequency_mhz (float) – Calibrated molecular frequency (MHz): the raw fitted frequency with the timebase scale error
epsilonremoved. Equalsfrequency_raw_mhzwhen no calibration was applied (Rb-locked, orepsilon == 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 theepsiloncorrection and thesigma_epsbudget 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.0when 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
Nonewhen unavailable.snr (float or None) – Fitted signal-to-noise ratio, or
Nonewhen 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), orNone.phase_error (float or None) – 1-sigma uncertainty on
phase(radians), orNone.snr_error (float or None) – 1-sigma uncertainty on
snr, propagated from the amplitude error (snr * amplitude_error / amplitude), orNone.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)"), orNonewhen 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.
- __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_fis 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 (seedev-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.
- 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_idtoWindowReviewStatus.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).
Noneuntilreview runbuilds it.
- __init__(window_statuses: Dict[int, ~ftmwpipeline.core.data_structures.WindowReviewStatus]=<factory>, decision_log: List[DecisionLogEntry] = <factory>, final_products: FinalProducts | None = None) None
- 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 throughmolecular_frequencyusing 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_afterproxy), orNonewhen 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 whatbest_evidencemeasures.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_idthis candidate belongs to.
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 inftmwpipeline._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-derivedchirp_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
Falsethe start time could not be inferred andstart_usfalls back toguard_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
Nonewhen no declaration is present.declaration_used (bool) –
Truewhenstart_uswas derived from a chirp-window declaration rather than from the sweep detector.
- 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=Falsewas passed toextract_tau_majority(). Bands with fewer thanmin_contributors_per_bandcontributors fall back to the band- wide(tau_maj_us, sigma_tau_us); seecompute_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).
- bimodality: GMMBimodality
- __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", orNonefor “no clear winner”. Written tostage2b_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 isargmin 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.
- 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 viaf_true = f_measured / (1 + epsilon).0.0when the preconditions fail.sigma_epsilon (float) – Formal 1-sigma uncertainty on
epsilon(1 / sqrt(sum (f / sigma_tot)^2)over kept tones).infwhen 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.0when 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
Tused forsigma_f(microseconds).preconditions_passed (bool) –
Trueonly 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).
- __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.
- 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_scatterkernel signature.
- 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
- 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
- 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
- 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).
- tau: TauSubSettings
- seeder: SeederSubSettings
- conservative: ConservativeSubSettings
- penalties: PenaltySubSettings
- rescue: RescueSubSettings
- thaw: ThawSubSettings
- spur: SpurSubSettings
- baseline: BaselineSubSettings
- doublet_alternative: DoubletAlternativeSubSettings
- peak_survival: PeakSurvivalSubSettings
- __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.
lockedmarks 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. Seedev-docs/planning/instrument-clock-declaration.md.
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.