Skip to content

feat: implement Lomb-Scargle periodogram - #84

Open
Omiii-215 wants to merge 15 commits into
StingraySoftware:mainfrom
Omiii-215:feat/lomb-scargle
Open

Omiii-215 wants to merge 15 commits into
StingraySoftware:mainfrom
Omiii-215:feat/lomb-scargle

Conversation

@Omiii-215

Copy link
Copy Markdown
Collaborator

Ports the Lomb-Scargle periodogram module from Python Stingray to Julia.

  • Implements lsft_slow and lsft_fast algorithms for unevenly sampled data
  • Adds LombScargleCrossspectrum and LombScarglePowerspectrum structs with all normalizations (frac, leahy, abs, none)
  • Includes spectral analysis methods (time_lag, compute_rms, phase_lag)
  • Comprehensive test coverage

Omiii-215 and others added 15 commits August 3, 2026 13:26
Add direct-summation Lomb-Scargle Fourier Transform that computes
F(ν) = Σ_j y_j · exp(-2πi·ν·t_j). This is the reference O(n²)
implementation matching Python Stingray's fourier.lsft_slow.

- Input validation for matching y/t lengths
- Returns Vector{ComplexF64}
- @inbounds for performance
Add Press & Rybicki fast LSFT using extirpolation (triangle-window
gridding onto an oversampled regular grid) + FFT + interpolation.
Matches Python Stingray's fourier.lsft_fast.

- Internal helper _extirpolate! for gridding
- Configurable oversampling factor (default 5)
- Input validation for y/t length match and oversampling >= 1
Create full (positive + negative) frequency spectrum from one-sided
LSFT by imposing Hermitian symmetry F(-ν) = conj(F(ν)).
Prepends DC component and negative-frequency conjugates.

Matches Python Stingray's fourier.impose_symmetry_lsft.
Add inverse of normalize_periodograms, converting normalized power
back to unnormalized form. Supports all 4 norms (frac, abs, leahy,
none). Needed by compute_rms in the Lomb-Scargle context.

Matches Python Stingray's fourier.unnormalize_periodograms.
Create lombscargle.jl with autofrequency() that builds the frequency
grid for LS periodograms from whatever combination of min_freq,
max_freq, df, dt, length, and nyquist_factor the user provides.

- Validates inputs: errors if both df/length missing, or both max_freq/dt missing
- Warns if min_freq <= 0, resets to df/2
- Returns Vector{Float64}
- Includes ValueError type for Python-style error messages

Matches Python Stingray's lombscargle._autofrequency.
Add the struct definition for unevenly-sampled cross spectra with
all fields matching Python Stingray's LombScargleCrossspectrum:
freq, power, power_err, unnorm_power, df, dt, n, m, k, nphots1/2,
norm, power_type, fullspec, method, oversampling, variance1/2,
err_dist, type.

Includes Base.show for pretty-printing.
Add internal core functions and public constructors:
- _ls_cross: computes F₁ × conj(F₂) via lsft_fast/slow
- _normalize_crossspectrum: normalizes using geometric mean flux
- lscrossspectrum_from_lightcurve: full pipeline orchestrator
- LombScargleCrossspectrum(lc1, lc2; kwargs...): from LightCurves
- LombScargleCrossspectrum(ev1, ev2; dt, kwargs...): from EventLists
- _validate_ls_inputs: input validation matching Python initial_checks

Supports all 4 norms, 3 power_types, fast/slow methods, fullspec.
Add power spectrum type for unevenly sampled data:
- LombScarglePowerspectrum struct with nphots field (== nphots1)
- LightCurve constructor: computes cross-spectrum of signal with itself
- EventList constructor: converts to LC first
- Base.show for pretty-printing
- type field set to 'powerspectrum'
- Default norm is 'frac' (matches Python Stingray)
Add analysis methods for Lomb-Scargle types:
- phase_lag: angle of complex cross-spectral power
- time_lag: phase_lag / (2π·freq), matches Python Stingray
- compute_rms: fractional RMS from unnormalized powers via
  _get_rms_from_unnorm_periodogram, with Poisson noise subtraction
Add include('lombscargle.jl') to Stingray.jl module and export:
- LombScargleCrossspectrum, LombScarglePowerspectrum
- autofrequency, lsft_slow, lsft_fast
- impose_symmetry_lsft, unnormalize_periodograms
- phase_lag, time_lag

Also add test_lombscargle.jl to runtests.jl and export previously
missing rebin_data, rebin_data_log, rebin_log, compute_rms.
… symmetry

Add ~31 tests covering foundational Lomb-Scargle functions:

autofrequency (12 tests):
- All parameter combinations, defaults, Nyquist factor
- Error cases: missing df/length, missing max_freq/dt
- Warning for negative min_freq
- Type, length, monotonicity, spacing checks

lsft_slow (7 tests):
- Constant signal, sinusoid peak detection
- Manual DFT verification, zero signal
- Type, length, input validation

lsft_fast (7 tests):
- Sinusoid peak detection, consistency with lsft_slow
- Higher oversampling accuracy, input validation
- Type, length, zero signal

impose_symmetry_lsft (5 tests):
- Output length, DC component, Hermitian symmetry
- Frequency symmetry, return types
…ases, time_lag

Add ~44 integration tests with helper functions for building test
LightCurves (_make_test_lc, _make_sinusoid_lc, _make_poisson_lc):

LombScargleCrossspectrum (18 tests):
- Construction types, freq properties, power lengths
- All 4 norms, 3 power_types, fullspec, method consistency
- Sinusoid peak detection, metadata fields
- dt/df verification, Base.show

LombScarglePowerspectrum (14 tests):
- nphots == nphots1, type, power real-valuedness
- Known sinusoid, freq/power lengths, all norms
- Methods slow/fast, fullspec, compute_rms, Base.show

Edge cases (7 tests):
- Very short series, all-zero counts
- Invalid norm/power_type/method strings
- min_freq > max_freq, negative min_freq

time_lag (5 tests):
- Return type, length, identical signals → zero lag
- phase_lag consistency, phase_lag type
Adds the internal helper _get_rms_from_unnorm_periodogram to fourier.jl,
which is required by the compute_rms method for LombScarglePowerspectrum.
@codecov-commenter

codecov-commenter commented Aug 4, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.75336% with 34 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.80%. Comparing base (0ce31db) to head (44df042).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
src/fourier.jl 81.52% 17 Missing ⚠️
src/lombscargle.jl 87.02% 17 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #84      +/-   ##
==========================================
- Coverage   89.34%   87.80%   -1.55%     
==========================================
  Files           8        9       +1     
  Lines        1605     1828     +223     
==========================================
+ Hits         1434     1605     +171     
- Misses        171      223      +52     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants