Python API Reference
FLITS is usable as a library as well as through the browser. Everything the interface does goes through the same objects documented here, so an analysis scripted against this API and one performed interactively produce the same numbers.
For reproducing a saved analysis without writing code, see Headless Replay.
A minimal analysis
import json
from flits import BurstSession
session = BurstSession.from_file(
"data/GBT-L/burst.fil",
dm=527.65,
sefd_jy=10.0,
sefd_fractional_uncertainty=0.1,
)
session.set_crop_ms(80.0, 200.0)
session.set_event_ms(120.0, 128.0)
session.add_offpulse_ms(0.0, 80.0)
session.auto_mask_jess("auto")
measurements = session.compute_properties()
print(measurements.fluence_jyms, measurements.snr)
# Persist everything needed to reproduce this later.
with open("burst_flits_session.json", "w") as handle:
json.dump(session.snapshot_dict(), handle, indent=2)
Session
flits.session.BurstSession
dataclass
One burst, loaded and under analysis.
A session owns the dedispersed dynamic spectrum together with every decision made about it: the crop, the event window, the off-pulse regions used as the noise reference, the channel mask, the spectral extent, and the calibration inputs. Analyses are computed against that state and cached on the session, and are discarded automatically when a change invalidates them.
The whole of that state round-trips through to_snapshot and
from_snapshot, which is what makes an analysis reproducible: the snapshot
plus the original file and a compatible software environment permit
supported calculations to be repeated, either in the interface or through
flits replay. Software provenance identifies the environment of each
cached analysis independently of the environment saving the snapshot.
Examples:
>>> session = BurstSession.from_file("burst.fil", dm=527.65, sefd_jy=10.0)
>>> session.set_event_ms(120.0, 128.0)
>>> session.add_offpulse_ms(0.0, 80.0)
>>> measurements = session.compute_properties()
>>> measurements.fluence_jyms is not None
True
Notes
A session is not thread-safe and is not intended to be shared between concurrent requests.
detected_telescope
property
Telescope preset detected from the file header, before any override.
plus_mjd_sec
property
Offset of the read window from the file start, in seconds.
polarization_order
property
Polarization ordering declared by the file header, if any.
software_provenance
Snapshot of software identities; unknown historical origins stay unknown.
from_file
classmethod
from_file(bfile: str, dm: float, telescope: str | None = None, *, sefd_jy: float | None = None, npol_override: int | None = None, read_start_sec: float | None = None, read_end_sec: float | None = None, auto_mask_profile: str | None = 'auto', distance_mpc: float | None = None, redshift: float | None = None, sefd_fractional_uncertainty: float | None = None, distance_fractional_uncertainty: float | None = None, source_ra_deg: float | None = None, source_dec_deg: float | None = None, time_scale: str | None = None, observatory_longitude_deg: float | None = None, observatory_latitude_deg: float | None = None, observatory_height_m: float | None = None, polarization_basis: str | None = None) -> BurstSession
Open a burst file and build a session at the given DM.
The file's format is detected automatically and a matching telescope
preset is applied unless telescope names one explicitly. The data is
dedispersed to dm on load.
from_snapshot
classmethod
from_snapshot(snapshot: AnalysisSessionSnapshot | dict[str, Any], *, loader: Callable[..., BurstSession] | None = None) -> BurstSession
Rebuild a session from a snapshot produced by to_snapshot.
Reopens the burst the snapshot names and restores every recorded
selection. Pass loader to control how the burst file is opened -- the
web layer uses this to enforce data-directory containment.
clear_temporal_structure
Discard the cached temporal-structure analysis.
clear_drift_analysis
Discard the cached sub-burst drift measurement.
Component regions and manual peaks feed the centroid estimator, so editing them invalidates a cached drift result even though they leave the other measurements alone.
clear_polarization
Discard the cached polarization analysis.
The loaded Stokes cube is kept: it is expensive to read and stays valid under every selection change, because the session re-applies its own dispersion shift to it on use.
invalidate_analysis_state
Discard every cached analysis, after a change that invalidates them all.
bin_to_ms
Convert a time-sample index to milliseconds from the start of the window.
ms_to_bin
Convert milliseconds from the start of the window to a time-sample index.
clamp_bin
Clamp a time-sample index into the valid range.
Pass is_end=True for an exclusive end index.
freq_to_channel
Return the channel index nearest to a frequency in MHz.
get_masked_crop
Return the cropped dynamic spectrum with masked channels removed.
get_display_crop
Return the cropped dynamic spectrum at the current display decimation.
get_view
Return the full session state the interface renders, as plain data.
set_time_factor
Set the time decimation factor used for display and analysis.
set_freq_factor
Set the frequency decimation factor used for display and analysis.
set_crop_ms
Set the crop window, in milliseconds from the start of the read window.
set_event_ms
Set the event window that measurements integrate over.
add_region_ms
Add a burst sub-region, used to separate components.
add_offpulse_ms
Add an off-pulse region, used as the noise reference.
add_peak_ms
Mark a component peak at the given time, switching to manual peaks.
remove_peak_ms
Remove the manually marked peak nearest the given time.
mask_channel_freq
Mask the channel nearest the given frequency.
mask_range_freq
Mask every channel in a frequency range.
set_spectral_extent_freq
Set the frequency extent measurements are restricted to.
set_notes
Attach free-text notes, carried through snapshots and exports.
set_timing_metadata
set_timing_metadata(*, source_ra_deg: float | None = None, source_dec_deg: float | None = None, time_scale: str | None = None, observatory_longitude_deg: float | None = None, observatory_latitude_deg: float | None = None, observatory_height_m: float | None = None) -> None
Set the source position and observatory location used for barycentring.
auto_localize
auto_localize(*, detection_snr_threshold: float = 6.0, search_window_bins: tuple[int, int] | None = None, apply: bool = True, **kwargs: Any) -> BurstLocalization
Automatically localize the burst inside the current crop.
Runs the iterative time/frequency search on the masked crop at
native resolution and, when a detection is found and apply is
True, updates the event window, spectral extent, off-pulse
windows, and peak selection. The crop itself is unchanged.
auto_mask_jess
Mask interference automatically using the jess statistical tests.
set_dm
Retune the dispersion measure of the loaded data.
The shift is computed as an absolute solution relative to the DM the data was loaded at, and only the difference from the currently applied shift is moved. Rounding therefore happens once per target DM rather than once per step, so stepping out along a DM sweep and back returns the data to its original alignment exactly.
apply_best_dm
Adopt the best DM found by the last sweep and re-dedisperse to it.
compute_widths
Measure the burst width by every supported method.
accept_width_result
Adopt one width method's result as the reported width.
optimize_dm
optimize_dm(center_dm: float, half_range: float, step: float, metric: str = 'integrated_event_snr') -> DmOptimizationResult
Sweep DM around a centre value and score each trial.
metric selects the criterion: integrated event signal-to-noise, or the
structure-maximizing DM_phase score.
compute_properties
Measure the burst and cache the result.
Produces width, peak flux, fluence and signal-to-noise, together with the provenance and uncertainty classification of each quantity.
fit_model
Fit a burst model to the selected event using fitburst.
run_temporal_structure_analysis
Run temporal-structure and power-spectral analysis on the selection.
run_spectral_analysis
Run averaged spectral analysis on the selection.
run_drift_analysis
run_drift_analysis(*, settings: DriftAnalysisSettings | None = None, dm_uncertainty_pc_cm3: float | None = None) -> DriftAnalysisResult
Measure the sub-burst drift rate of the current selection.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
settings
|
DriftAnalysisSettings | None
|
Fit-region and Monte-Carlo controls. When omitted the session's
stored |
None
|
dm_uncertainty_pc_cm3
|
float | None
|
1-sigma DM uncertainty to fold into the drift uncertainty. It is
stored in |
None
|
polarization_capability
Report whether this burst can support an in-session RM measurement.
Answers the three questions separately -- does the reader have a full-Stokes path, does the file carry four products, and is it known which four -- because they call for different responses: a different file, a different file, and a stated basis.
load_stokes_cube
Return the burst as a (4, channels, time) Stokes I/Q/U/V cube.
The cube is read once, at the DM the file was opened with, and cached.
The session's accumulated dispersion shift is applied on every call, so
the returned cube is aligned with data even after the DM has been
retuned -- and retuning does not force a re-read.
set_polarization_settings
Replace the polarization settings, discarding any stale result.
run_polarization_analysis
run_polarization_analysis(settings: PolarizationSettings | dict[str, Any] | None = None) -> PolarizationAnalysisResult
Measure the rotation measure from this session's own selections.
Integrates Stokes Q and U over the session's event window, takes the noise from its off-pulse regions, drops the channels its mask and spectral extent exclude, and runs RM synthesis on what is left. Nothing is imported and nothing is re-selected: the RM is measured against the same burst definition as every other number in the session.
to_snapshot
Capture the full session state as a snapshot object.
snapshot_dict
Capture the full session state as a JSON-compatible dict.
export_results
export_results(*, session_id: str, include: list[str] | tuple[str, ...] | None = None, plot_formats: list[str] | tuple[str, ...] | None = None, window_formats: list[str] | tuple[str, ...] | None = None, window_resolutions: list[str] | tuple[str, ...] | None = None) -> ExportManifest
Build an export bundle and retain it for download.
preview_export_results
preview_export_results(*, include: list[str] | tuple[str, ...] | None = None, plot_formats: list[str] | tuple[str, ...] | None = None, window_formats: list[str] | tuple[str, ...] | None = None, window_resolutions: list[str] | tuple[str, ...] | None = None) -> ExportPreview
Describe the bundle export_results would build, without building it.
get_export_manifest
Return the manifest of a previously built export bundle.
Input
flits.io
Input layer: format detection and burst loading.
Readers are discovered through flits.readers entry points, so a third party
can add a format without modifying FLITS. See flits.io.reader for the
protocol a reader must satisfy.
load_filterbank_data
load_filterbank_data(path: str | Path, config: ObservationConfig, inspection: FilterbankInspection | None = None) -> tuple[np.ndarray, FilterbankMetadata]
load_stokes_data
load_stokes_data(path: str | Path, config: ObservationConfig, inspection: FilterbankInspection | None = None) -> tuple[np.ndarray, FilterbankMetadata]
Load a full-Stokes I/Q/U/V cube for path.
Raises PolarizationUnavailableError if the matching reader has no full-Stokes path, or if the file itself cannot provide one.
reader_supports_stokes
True if reader implements the optional full-Stokes path.
flits.io.reader.BurstReader
Bases: Protocol
A reader for one or more input formats.
Implementations must be cheap to instantiate (zero-arg constructor) because
they may be created once per process. All I/O happens inside inspect() /
load() — no state is retained between calls.
flits.io.reader.StokesBurstReader
Bases: BurstReader, Protocol
A reader that can additionally return full-Stokes data.
load_stokes returns (cube, metadata) where cube has shape
(4, channels, time) in I/Q/U/V order and shares the time and frequency
axes of the Stokes I array load returns for the same file and config --
same dedispersion, same read window, same channel order. That equivalence is
what lets a session apply its event window, off-pulse regions and channel
mask to the cube without re-deriving any of them.
Implementations raise
:class:~flits.io.errors.PolarizationUnavailableError when the file has
fewer than four polarization products or when the polarization basis is
unknown, rather than guessing.
flits.io.reader.FilterbankInspection
dataclass
flits.stokes
Conversion of raw four-product polarization data into Stokes I/Q/U/V.
Burst files carry four polarization products, but which four is not something FLITS can infer from the numbers alone. A backend may write Stokes directly, or it may write the coherency products of a linear or a circular feed. The three cases differ only by which pair of products carries the linear polarization, so guessing wrong silently swaps Stokes V into Q and produces an RM that is wrong without looking wrong.
This module therefore keeps the basis explicit. Readers resolve it from the file
header where the format records it (PSRFITS POL_TYPE plus FD_POLN), from
the telescope preset where the instrument is known, or from an operator override
-- and refuse to build a Stokes cube when none of those settle the question.
normalize_polarization_basis
Return the canonical basis name for value, or None if unset.
Raises PolarizationBasisError for a non-empty value that names no known basis, so a typo in a preset or an API request fails loudly.
basis_from_psrfits
Map a PSRFITS POL_TYPE (with FD_POLN) onto a FLITS basis.
AABBCRCI names the coherency products without saying which feed produced
them, so the receiver's FD_POLN decides. A file that declares neither is
left unresolved rather than assumed.
stokes_from_products
Convert four polarization products into a Stokes I/Q/U/V cube.
products must have the four products on its first axis; the remaining
axes are carried through untouched. The returned array is float32 and has
the same trailing shape.
The coherency conversions follow the PSRFITS/PSRCHIVE convention:
a linear feed gives I=AA+BB, Q=AA-BB, U=2CR, V=2CI and a circular feed
gives I=AA+BB, V=AA-BB, Q=2CR, U=2CI.
Analysis
flits.analysis.localization.localize_burst
localize_burst(masked: ndarray, *, detection_snr_threshold: float = DETECTION_SNR_THRESHOLD, extent_exit_sn: float = EXTENT_EXIT_SN, spectrum_exit_sn: float = SPECTRUM_EXIT_SN, full_band_fraction: float = FULL_BAND_FRACTION, max_iterations: int = MAX_ITERATIONS, max_width_bins: int | None = None, min_offpulse_bins: int = MIN_OFFPULSE_BINS, search_window_bins: tuple[int, int] | None = None) -> BurstLocalization
Localize a burst in a masked dynamic spectrum (channels x time).
Masked channels must be NaN rows. Returns bins relative to the input
array. search_window_bins optionally restricts the matched-filter
peak location to a known half-open time interval; event boundaries may
extend outside it so burst wings are retained. When nothing crosses
detection_snr_threshold the status is "no_detection".
flits.measurements.compute_burst_measurements
compute_burst_measurements(*, burst_name: str, dm: float, start_mjd: float, read_start_sec: float, crop_start_bin: int, tsamp_ms: float, freqres_mhz: float, freqs_mhz: ndarray, masked: ndarray, event_rel_start: int, event_rel_end: int, spec_lo: int, spec_hi: int, peak_bins_abs: Sequence[int], burst_regions_abs: Sequence[tuple[int, int]], manual_selection: bool, manual_peak_selection: bool, sefd_jy: float | None, npol: int, distance_mpc: float | None, redshift: float | None, sefd_fractional_uncertainty: float | None, distance_fractional_uncertainty: float | None, masked_channels: Sequence[int], offpulse_regions_rel: Sequence[tuple[int, int]] | None = None, noise_settings: NoiseEstimateSettings | None = None, width_results: Sequence[WidthResult] | None = None, accepted_width: AcceptedWidthSelection | None = None, time_axis_ms: ndarray | None = None, timing_context: TimingContext | None = None) -> BurstMeasurements
Measure a burst from a prepared selection.
Integrates the event window against the off-pulse noise reference and returns width, peak flux, fluence, signal-to-noise and, when a distance is supplied, isotropic energy.
Every quantity carries its own uncertainty classification. A value is
reported as formal_1sigma only when the systematic inputs it needs were
supplied -- notably an SEFD fractional uncertainty for flux-like
quantities. Without them the value is statistical_only and is flagged as
not publishable, rather than being presented as a complete uncertainty.
Returns:
| Type | Description |
|---|---|
BurstMeasurements
|
Measured quantities together with their provenance, uncertainty detail and any diagnostic flags raised during measurement. |
flits.analysis.dm_optimization.optimize_dm_trials
optimize_dm_trials(*, data: ndarray, current_dm: float, freqs_mhz: ndarray, tsamp_sec: float, score_data: ndarray | None = None, score_current_dm: float | None = None, score_freqs_mhz: ndarray | None = None, score_tsamp_sec: float | None = None, center_dm: float, half_range: float, step: float, metric_input_builder: Callable[[ndarray], DMMetricInput], residuals: Callable[[ndarray], tuple[ndarray, ndarray, ndarray, str]], provenance: DmOptimizationProvenance, metric: str = 'integrated_event_snr') -> DmOptimizationResult
Run a DM trial sweep and return the optimized DM result.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ndarray
|
Native-resolution dynamic spectrum with shape |
required |
current_dm
|
float
|
DM currently applied to |
required |
freqs_mhz
|
ndarray
|
Native frequency axis in MHz matching |
required |
tsamp_sec
|
float
|
Native sampling interval in seconds. |
required |
score_data
|
ndarray | None
|
Optional waterfall used only for scoring. DMphase passes the current
reduced grid here so the score respects the user's analysis resolution.
Metrics that should score native |
None
|
score_current_dm
|
float | None
|
Applied DM for |
None
|
score_freqs_mhz
|
ndarray | None
|
Frequency axis in MHz matching |
None
|
score_tsamp_sec
|
float | None
|
Sampling interval in seconds for |
None
|
center_dm
|
float
|
Trial grid controls, all in |
required |
half_range
|
float
|
Trial grid controls, all in |
required |
step
|
float
|
Trial grid controls, all in |
required |
metric_input_builder
|
Callable[[ndarray], DMMetricInput]
|
Callback that converts each trial-dedispersed scoring waterfall into a
:class: |
required |
residuals
|
Callable[[ndarray], tuple[ndarray, ndarray, ndarray, str]]
|
Callback that computes subband arrival residuals for a waterfall and
returns |
required |
provenance
|
DmOptimizationProvenance
|
Serialized context describing the selection and effective analysis resolution used for the sweep. |
required |
metric
|
str
|
Registered metric key. Supported values are defined by
|
'integrated_event_snr'
|
Returns:
| Type | Description |
|---|---|
DmOptimizationResult
|
Score curve, sampled and refined DM estimates, residual diagnostics, settings, and provenance. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the metric key is unsupported, the trial grid is invalid, a metric returns an invalid score shape, or no finite score can be computed for the current selection. |
flits.analysis.morphology.compute_width_analysis
compute_width_analysis(*, selected_profile: ndarray, time_axis_ms: ndarray, event_rel_start: int, event_rel_end: int, tsamp_ms: float, noise_summary: NoiseEstimateSummary, offpulse_bins: ndarray, settings: WidthAnalysisSettings | None = None, event_window_ms: list[float], spectral_extent_mhz: list[float], offpulse_windows_ms: list[list[float]], masked_channels: list[int], effective_bandwidth_mhz: float | None, existing_accepted_method: str | None = None, extra_flags: Sequence[str] = ()) -> WidthAnalysisSummary
Compute the full set of morphology-based burst-width measurements.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
selected_profile
|
ndarray
|
Selected-band time profile for the current crop on the same scale used to define the off-pulse baseline. |
required |
time_axis_ms
|
ndarray
|
Time axis in milliseconds matching |
required |
event_rel_start
|
int
|
Half-open event window in profile-bin coordinates. |
required |
event_rel_end
|
int
|
Half-open event window in profile-bin coordinates. |
required |
tsamp_ms
|
float
|
Effective time resolution of the profile in milliseconds. |
required |
noise_summary
|
NoiseEstimateSummary
|
Off-pulse noise estimate and warning flags associated with the current selection. |
required |
offpulse_bins
|
ndarray
|
Off-pulse bins used to bootstrap per-trial baseline/noise estimates. |
required |
settings
|
WidthAnalysisSettings | None
|
Width-analysis settings. If omitted, defaults from
:class: |
None
|
event_window_ms
|
list[float]
|
Event-window bounds in milliseconds for provenance. |
required |
spectral_extent_mhz
|
list[float]
|
Selected spectral extent in MHz for provenance. |
required |
offpulse_windows_ms
|
list[list[float]]
|
Off-pulse windows in milliseconds for provenance. |
required |
masked_channels
|
list[int]
|
Masked channel indices for provenance. |
required |
effective_bandwidth_mhz
|
float | None
|
Effective unmasked bandwidth in MHz, if known. |
required |
existing_accepted_method
|
str | None
|
Previously user-accepted width method. If present and still available, it is preserved as the accepted width. |
None
|
extra_flags
|
Sequence[str]
|
Additional quality flags propagated to every method result. |
()
|
Returns:
| Type | Description |
|---|---|
WidthAnalysisSummary
|
Structured width results for all registered methods plus the accepted width selection and the noise summary used to derive uncertainties. |
Notes
All width values and uncertainties are reported in milliseconds.
flits.analysis.temporal.core.run_temporal_structure_analysis
run_temporal_structure_analysis(*, event_series: ndarray, tsamp_ms: float, segment_length_ms: float, noise_sigma: float, event_window_ms: tuple[float, float], spectral_extent_mhz: tuple[float, float], model_fit_widths_ms: ndarray | None = None, offpulse_series_runs: Sequence[ndarray] | None = None, backend_loader: Callable[[], tuple[type[Any] | None, type[Any] | None, str | None]] = _load_stingray_backend) -> TemporalStructureResult
Run temporal-structure analysis on a selected event series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_series
|
ndarray
|
One-dimensional selected-band event series for the current event window. |
required |
tsamp_ms
|
float
|
Sampling interval in milliseconds. |
required |
segment_length_ms
|
float
|
Requested segment length for the averaged PSD, in milliseconds. |
required |
noise_sigma
|
float
|
Off-pulse noise standard deviation used to normalize matched-filter and wavelet responses. |
required |
event_window_ms
|
tuple[float, float]
|
Event-window bounds in milliseconds for provenance. |
required |
spectral_extent_mhz
|
tuple[float, float]
|
Selected spectral extent in MHz for provenance. |
required |
model_fit_widths_ms
|
ndarray | None
|
Optional model-fit component widths in milliseconds. When provided, the smallest positive width is recorded as a model-based cross-check. |
None
|
offpulse_series_runs
|
Sequence[ndarray] | None
|
Optional contiguous off-pulse time-series runs used to estimate a noise PSD on the same segment grid. |
None
|
backend_loader
|
Callable[[], tuple[type[Any] | None, type[Any] | None, str | None]]
|
Dependency-injection hook for loading Stingray-compatible backend classes. |
_load_stingray_backend
|
Returns:
| Type | Description |
|---|---|
TemporalStructureResult
|
Structured result containing the raw periodogram, averaged PSD,
minimum-timescale scan products, optional power-law fit, crossover
frequency estimate, and optional noise PSD. |
Notes
The primary minimum-structure estimate comes from the first matched-filter scale whose boxcar or Gaussian response exceeds the familywise-corrected threshold. The wavelet estimate is reported separately from the Mexican-hat scan.
flits.analysis.spectral.core.run_averaged_spectral_analysis
run_averaged_spectral_analysis(*, event_series: ndarray, tsamp_ms: float, segment_length_ms: float, event_window_ms: tuple[float, float], spectral_extent_mhz: tuple[float, float], offpulse_series_runs: Sequence[ndarray] | None = None, backend_loader: Callable[[], tuple[type[Any] | None, type[Any] | None, str | None]] = _load_stingray_backend) -> SpectralAnalysisResult
Run averaged spectral analysis on a selected event time series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_series
|
ndarray
|
One-dimensional selected-band event series. The analysis uses the provided samples as a uniformly sampled light curve. |
required |
tsamp_ms
|
float
|
Sampling interval in milliseconds. |
required |
segment_length_ms
|
float
|
Requested segment length for the averaged power spectrum, in milliseconds. |
required |
event_window_ms
|
tuple[float, float]
|
Event-window bounds in milliseconds for provenance. |
required |
spectral_extent_mhz
|
tuple[float, float]
|
Selected spectral extent in MHz for provenance. |
required |
offpulse_series_runs
|
Sequence[ndarray] | None
|
Optional contiguous off-pulse time-series runs. When provided, FLITS computes a noise PSD using the same segment size and backend. |
None
|
backend_loader
|
Callable[[], tuple[type[Any] | None, type[Any] | None, str | None]]
|
Dependency-injection hook for loading Stingray-compatible
|
_load_stingray_backend
|
Returns:
| Type | Description |
|---|---|
SpectralAnalysisResult
|
Structured PSD result. |
Notes
The returned frequency axis is in Hz, the PSD uses Stingray's norm="none"
convention, and any fitted power-law parameters describe the averaged event
PSD rather than the off-pulse noise estimate.
flits.analysis.temporal.multiscale.haar_excess_power
haar_excess_power(event_profile: ndarray | Sequence[float], offpulse_runs: Sequence[ndarray | Sequence[float]], *, tsamp_ms: float, scales_bins: Sequence[int] | ndarray | None = None, min_coefficients: int = MIN_COEFFICIENTS) -> HaarExcessPowerResult
Measure temporal signal power above an empirical off-pulse floor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_profile
|
ndarray | Sequence[float]
|
One-dimensional on-burst time profile. |
required |
offpulse_runs
|
Sequence[ndarray | Sequence[float]]
|
Contiguous off-pulse profile sections. Runs are never joined across a gap, so artificial Haar coefficients are not created at boundaries. |
required |
tsamp_ms
|
float
|
Native or effective sampling interval in milliseconds. |
required |
scales_bins
|
Sequence[int] | ndarray | None
|
Optional positive scales. By default FLITS uses dyadic scales up to a quarter of the event length. |
None
|
min_coefficients
|
int
|
Minimum event and pooled off-pulse coefficient count retained at each scale. |
MIN_COEFFICIENTS
|
Notes
characteristic_scale_ms is the excess-power-weighted geometric mean
scale. It is an aggregate descriptor, not a minimum resolvable timescale.
Its selection dependence should still be assessed with injection/recovery
tests when comparing a burst population.
flits.analysis.temporal.multiscale.excess_power_fraction_below
Fraction of positive excess power at scales no larger than a limit.
flits.analysis.drift.run_drift_analysis
run_drift_analysis(inputs: DriftAnalysisInputs, settings: DriftAnalysisSettings | None = None) -> DriftAnalysisResult
Measure the sub-burst drift rate of the selected event window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
inputs
|
DriftAnalysisInputs
|
Waterfall, axes, selection bounds and DM state; see
:class: |
required |
settings
|
DriftAnalysisSettings | None
|
Fit-region, Monte-Carlo and seeding controls. Defaults are used when omitted. |
None
|
Returns:
| Type | Description |
|---|---|
DriftAnalysisResult
|
|
Notes
The statistical uncertainty comes from a seeded Monte Carlo: each trial adds an independent noise realisation at the measured per-channel off-pulse sigma and repeats the autocorrelation and the fit. That propagates the correlation between neighbouring autocorrelation pixels, which the fit covariance alone does not; the covariance value is kept alongside as a diagnostic. The result is publishable only when a DM uncertainty was supplied, because the DM systematic is usually the larger term.
flits.analysis.drift.DriftAnalysisInputs
dataclass
Everything the drift measurement needs from the session layer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
waterfall
|
ndarray
|
Dedispersed dynamic spectrum on the reduced analysis grid, shaped
|
required |
time_axis_ms
|
ndarray
|
Time axis of |
required |
freqs_mhz
|
ndarray
|
Channel centre frequencies in MHz. Either ordering is accepted; the signed channel spacing is what fixes the sign of the drift rate. |
required |
event_rel_start
|
int
|
Half-open event-window bounds as column indices into |
required |
event_rel_end
|
int
|
Half-open event-window bounds as column indices into |
required |
spec_lo
|
int
|
Inclusive selected-channel bounds as row indices into |
required |
spec_hi
|
int
|
Inclusive selected-channel bounds as row indices into |
required |
offpulse_bins
|
ndarray
|
Column indices used as the off-pulse reference for per-channel baselines and per-channel noise. |
required |
component_windows
|
Sequence[tuple[str, tuple[int, int]]]
|
|
()
|
dm_pc_cm3
|
float
|
DM the waterfall is dedispersed at, in pc cm^-3. |
required |
dm_uncertainty_pc_cm3
|
float | None
|
1-sigma DM uncertainty, when one is known. Supplying it is what turns the drift rate from statistical-only into a publishable measurement. |
None
|
flits.models.DriftAnalysisSettings
dataclass
Inputs that control the sub-burst drift measurement.
normalized
Return settings that are finite and safe to execute or replay.
These values can arrive through the actions API or an imported session snapshot. Normalizing them in the shared model keeps the browser, headless replay, and direct Python entry point on the same bounded behaviour.
flits.models.DriftAnalysisResult
dataclass
Sub-burst drift rate measured from the selected event window.
The drift rate is dnu/dt in MHz per millisecond: negative for the
downward "sad trombone" drift seen in repeaters. drift_rate_mhz_per_ms
comes from a rotated two-dimensional Gaussian fitted to the mask-corrected
2D autocorrelation of the dynamic spectrum. component_* fields hold the
independent component-centroid regression, which is only populated when the
session defines at least two burst components.
flits.analysis.drift.time_frequency_slope
Return the time-on-frequency regression slope dt/dnu in ms/MHz.
This is rho sigma_t / sigma_nu, not the reciprocal of the drift rate.
The two agree only for a perfectly correlated ridge, and it is this one --
not the drift rate -- that a DM error displaces linearly.
flits.analysis.drift.dm_slope_sensitivity
Return d(dt/dnu)/d(DM) in ms/MHz per pc cm^-3.
Differentiating the dispersion delay t(nu) = k DM nu^-2 gives
-2 k nu^-3. This is the one quantity a DM error moves linearly: a
dedispersion error adds g (nu - nu_ref) to every arrival time, which
shifts the time-on-frequency regression slope by exactly g and leaves
the frequency spread untouched.
flits.analysis.drift.drift_dm_sensitivity
drift_dm_sensitivity(sigma_time_ms: float, sigma_freq_mhz: float, correlation: float, reference_frequency_mhz: float) -> float
Return d(drift)/d(DM) in MHz/ms per pc cm^-3.
A DM error shears the burst covariance, Sigma_{t,nu} -> Sigma_{t,nu} + g
Sigma_{nu,nu} and Sigma_{t,t} -> Sigma_{t,t} + 2 g Sigma_{t,nu} + g^2
Sigma_{nu,nu}. Differentiating drift = Sigma_{t,nu} / Sigma_{t,t}
through that shear leaves (sigma_nu / sigma_t)^2 (1 - 2 rho^2) times the
slope sensitivity. The factor (1 - 2 rho^2) is why the naive
d(1/drift)/d(DM) answer is wrong for anything short of a perfectly
correlated ridge: it changes sign at rho^2 = 1/2, where the drift rate is
momentarily insensitive to the DM.
flits.analysis.drift.dm_equivalent_of_slope
Return the DM error that would on its own produce this dt/dnu.
This is the honest statement of the drift/DM degeneracy: if this number is smaller than the DM uncertainty, the measured drift is not distinguishable from a dedispersion error. It is positive when the burst is tilted the way an under-dedispersed burst is, so adding it to the applied DM is what removes the tilt.
Polarization
flits.models.PolarizationSettings
dataclass
Operator-controlled inputs to an in-session polarization analysis.
calibration_confirmed is deliberately not a default-true convenience: an
RM measured from uncalibrated Q/U is a number, not a measurement, and the
workflow refuses to call it calibrated until someone states that the
polarization calibration of this data has been established.
flits.models.PolarizationAnalysisResult
dataclass
A polarization analysis run against a session's own selections.
Holds both halves of the analysis: the channelized Q/U spectrum integrated over the session's event window against its off-pulse regions, and the RM synthesis computed from that spectrum. Keeping them together is what makes the RM reproducible -- the spectrum records which channels survived the mask and the S/N cut, and the provenance records which four products the file held and what established that.
flits.analysis.polarization.extract_normalized_linear_spectrum
extract_normalized_linear_spectrum(*, stokes_iquv: ndarray, freqs_mhz: ndarray, event_bins: tuple[int, int], offpulse_regions: Iterable[tuple[int, int]], channel_mask: ndarray | None = None, spectral_channels: tuple[int, int] | None = None, channel_width_mhz: float | None = None, min_linear_snr: float = 5.0, calibration_status: str = 'unknown') -> IntegratedPolarizationSpectrum
Integrate a burst and prepare weighted Q/L and U/L spectra.
Noise is estimated from non-overlapping, event-length integrations within
the explicit off-pulse regions. This carries native time correlation into
the channel uncertainties more faithfully than dividing a per-sample RMS by
sqrt(N). The normalization supports calibrated linear-polarization
Q/U fitting without assuming a per-sample white-noise correction.
flits.analysis.polarization.run_rm_synthesis
run_rm_synthesis(*, freqs_mhz: ndarray, stokes_q: ndarray, stokes_u: ndarray, sigma_q: ndarray | float | None = None, sigma_u: ndarray | float | None = None, channel_width_mhz: ndarray | float | None = None, phi_min_rad_m2: float | None = None, phi_max_rad_m2: float | None = None, phi_step_rad_m2: float | None = None, clean: bool = False, clean_gain: float = 0.1, clean_threshold_sigma: float = 3.0, clean_max_iterations: int = 1000) -> RMSynthesisResult
Compute a weighted dirty Faraday spectrum and optional RM-CLEAN product.
Q and U must be channelized spectra on the supplied frequency centres. If per-channel uncertainties are available they drive both inverse-variance weighting and the propagated Faraday-spectrum noise. Otherwise FLITS uses equal weights and estimates noise from the residual of the best thin model.
Signal primitives
flits.signal
Signal-processing primitives: dedispersion, normalization and decimation.
dedisperse
dedisperse(data: ndarray, dm: float, freqs_mhz: ndarray, tsamp_sec: float, *, fill_value: float | None = None) -> np.ndarray
Dedisperse a dynamic spectrum to the top of the band.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
ndarray
|
Dynamic spectrum with shape |
required |
dm
|
float
|
Dispersion measure in pc cm^-3, relative to the current dedispersion of
|
required |
freqs_mhz
|
ndarray
|
Channel centre frequencies in MHz. |
required |
tsamp_sec
|
float
|
Sample interval in seconds. |
required |
fill_value
|
float | None
|
What to put in samples vacated by the shift. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
The dedispersed dynamic spectrum, same shape and dtype as |
dedispersion_shift_bins
Return the per-channel sample shift that dedisperses to the top of band.
Shifts are rounded to whole samples, so the achievable DM resolution is
limited by the time resolution of the data. dedispersion_bin_resolution
reports the smallest DM step that moves the band edge by one sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dm
|
float
|
Dispersion measure in pc cm^-3, relative to the current dedispersion of
|
required |
freqs_mhz
|
ndarray
|
Channel centre frequencies in MHz. |
required |
tsamp_sec
|
float
|
Sample interval in seconds. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Integer sample shift for each channel, positive towards later times. |
dedispersion_edge_bins
Return how many samples at each end are affected by the dedispersion shift.
These are the samples whose content came from outside the read window. They
are either wrapped-around data or fill values depending on how dedisperse
was called, and in both cases they are not valid burst samples.
Returns:
| Type | Description |
|---|---|
tuple of int
|
|
dedispersion_bin_resolution
Return the smallest DM step that shifts the lowest channel by one sample.
DM trials finer than this produce bit-identical dedispersed data, so a sweep stepped below it wastes work and reports a spuriously smooth score curve.
shift_channels
shift_channels(data: ndarray, shift_bins: ndarray, *, fill_value: float | None = None) -> np.ndarray
Apply a per-channel integer sample shift to a dynamic spectrum.
Separated from dedisperse so a session can retune its dispersion by the
exact difference between two absolute shift solutions, rather than by
re-rounding an incremental DM step each time.
normalize_stokes
Baseline and scale a Stokes cube without distorting its polarization.
Each Stokes parameter has its own off-pulse median removed, but all four are
divided by the same per-channel scale, taken from the off-pulse standard
deviation of Stokes I. Scaling the four independently would rescale Q/I and
U/I channel by channel and corrupt every polarization fraction and every
Faraday rotation measured from them; using one scale per channel only
flattens the bandpass, exactly as normalize does for Stokes I alone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cube
|
ndarray
|
Stokes data with shape |
required |
offpulse
|
ndarray
|
Off-pulse samples with shape |
required |
Configuration
flits.settings
Observation configuration and telescope presets.
Presets carry the instrument-specific values -- SEFD, polarization count, observatory location -- that calibrated measurements depend on, and are matched against file headers automatically where possible.
Command line
flits.cli
Command line entry point for FLITS.
flits starts the browser interface. flits replay re-runs a saved session
snapshot without a browser, which is what makes the reproducibility claim
checkable: the snapshot records the selected analysis state, and replaying it
recomputes the measurements from the original data file.
Invoking flits with server options and no subcommand still starts the
server, so existing commands and container entrypoints keep working.
main
Dispatch a FLITS subcommand, defaulting to the server.
replay
Run the flits replay command. Returns the process exit code.