A friendly package for Kepler & TESS time series analysis in Python.
—
Comprehensive periodogram analysis for detecting periodic signals in time series data, with specialized algorithms for different types of astrophysical variability.
class Periodogram:
"""
Power spectrum representation with peak detection and analysis tools.
Attributes:
- frequency: astropy.units.Quantity - Frequency array
- power: astropy.units.Quantity - Power spectrum values
"""
def __init__(self, frequency, power, **kwargs):
"""
Initialize periodogram.
Parameters:
- frequency: array-like - Frequency values
- power: array-like - Power spectrum values
"""
# Analysis methods
def show_properties(self):
"""Display statistical properties of the periodogram"""
def smooth(self, filter_width=0.1):
"""Smooth the periodogram using a moving average"""
def flatten(self):
"""Flatten the periodogram by removing red noise trend"""
# Peak detection properties
@property
def max_power(self):
"""Maximum power value in the periodogram"""
@property
def frequency_at_max_power(self):
"""Frequency corresponding to maximum power"""
@property
def period_at_max_power(self):
"""Period corresponding to maximum power"""
# Visualization
def plot(self, **kwargs):
"""Plot the periodogram"""
def interact(self, **kwargs):
"""Create interactive periodogram widget"""class LombScarglePeriodogram(Periodogram):
"""
Lomb-Scargle periodogram for detecting periodic signals in unevenly sampled data.
Optimal for general stellar variability and rotation periods.
"""
@classmethod
def from_lightcurve(cls, lc, minimum_frequency=None, maximum_frequency=None,
samples_per_peak=5, **kwargs):
"""
Create Lomb-Scargle periodogram from light curve.
Parameters:
- lc: LightCurve - Input light curve
- minimum_frequency: float - Minimum frequency to analyze
- maximum_frequency: float - Maximum frequency to analyze
- samples_per_peak: int - Frequency sampling density
- normalization: str - Power normalization ('standard', 'model', 'log', 'psd')
Returns:
LombScarglePeriodogram object
"""
# Note: Statistical significance methods available in specialized packages
# Use astropy.stats or related libraries for false alarm probability estimationclass BoxLeastSquaresPeriodogram(Periodogram):
"""
Box Least Squares periodogram optimized for detecting transiting exoplanets.
Searches for box-shaped transit signals.
"""
@classmethod
def from_lightcurve(cls, lc, minimum_period=None, maximum_period=None,
minimum_n_transit=3, **kwargs):
"""
Create BLS periodogram from light curve.
Parameters:
- lc: LightCurve - Input light curve
- minimum_period: float - Minimum period to search
- maximum_period: float - Maximum period to search
- minimum_n_transit: int - Minimum number of transits required
- duration: float or array - Transit duration(s) to test
Returns:
BoxLeastSquaresPeriodogram object
"""
def get_transit_model(self, period=None, **kwargs):
"""
Get best-fit transit model.
Parameters:
- period: float - Period for model (uses highest peak if None)
Returns:
LightCurve object with transit model
"""
def compute_stats(self, period=None, **kwargs):
"""Compute detailed transit statistics for a given period"""class FoldedLightCurve(LightCurve):
"""Light curve folded at a specific period for phase analysis"""
def plot_river(self, **kwargs):
"""
Create river plot showing phase evolution over time.
Useful for detecting period variations.
"""
def bin(self, bins=None, **kwargs):
"""
Bin the folded light curve in phase.
Parameters:
- bins: int or array - Number of phase bins or bin edges
Returns:
Binned FoldedLightCurve
"""import lightkurve as lk
# Download and process light curve
lc = lk.search_lightcurve('KIC 11904151')[0].download()
lc = lc.normalize().remove_outliers()
# Create Lomb-Scargle periodogram
pg = lc.to_periodogram(method='lombscargle')
# Plot and find peaks
pg.plot()
max_period = pg.period_at_max_power
print(f"Strongest peak at {max_period.value:.2f} days")# Search for transiting planets
bls = lc.to_periodogram(method='bls',
minimum_period=0.5,
maximum_period=20)
# Plot BLS periodogram
bls.plot()
# Get transit model for highest peak
period = bls.period_at_max_power
transit_model = bls.get_transit_model(period=period)
# Plot original data with model
lc.plot(label='Data')
transit_model.plot(label='Transit Model')import numpy as np
import astropy.units as u
# Define custom frequency range
min_freq = 1 / (30 * u.day)
max_freq = 1 / (0.1 * u.day)
# High-resolution periodogram
pg_hires = lc.to_periodogram(method='lombscargle',
minimum_frequency=min_freq,
maximum_frequency=max_freq,
samples_per_peak=10)# Fold at detected period
folded = lc.fold(period=2.45 * u.day)
folded.plot()
# Bin for cleaner view
folded_binned = folded.bin(bins=50)
folded_binned.plot()
# River plot to check period stability
folded.plot_river()# Look for harmonics of main period
main_period = 5.2 * u.day
harmonics = [main_period / n for n in [1, 2, 3, 4]]
for i, period in enumerate(harmonics):
folded = lc.fold(period=period)
folded.plot(label=f'P/{i+1}')# Analyze peak significance using power values
max_power = pg.max_power
mean_power = pg.power.mean()
power_ratio = max_power / mean_power
print(f"Peak power ratio: {power_ratio:.1f}")
print(f"Maximum power: {max_power:.3f}")# Detailed transit analysis
stats = bls.compute_stats(period=period)
print(f"Transit depth: {stats['depth']:.1f} ppm")
print(f"Transit duration: {stats['duration']:.2f} hours")
print(f"Signal-to-noise: {stats['snr']:.1f}")
# Get individual transit times
transit_times = bls.transit_times(period=period)# Compare LS and BLS for same data
ls_pg = lc.to_periodogram(method='lombscargle')
bls_pg = lc.to_periodogram(method='bls')
# Plot both
import matplotlib.pyplot as plt
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
ls_pg.plot(ax=ax1, title='Lomb-Scargle')
bls_pg.plot(ax=ax2, title='Box Least Squares')Install with Tessl CLI
npx tessl i tessl/pypi-lightkurve