Skip to content

Commit a0f5460

Browse files
committed
smothening using spline and poission regression
1 parent 81269a5 commit a0f5460

File tree

2 files changed

+44
-32
lines changed

2 files changed

+44
-32
lines changed

docs/changes/906.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added method to smoothen lightcurve using spline transformation `sklearn.preprocessing.SplineTransformer` with poisson regression `sklearn.linear_model.PoissonRegressor`

stingray/lightcurve.py

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from stingray.base import StingrayTimeseries, reduce_precision_if_extended
2020
import stingray.utils as utils
2121
from stingray.exceptions import StingrayError
22-
from scipy.signal import savgol_filter
2322
from stingray.gti import (
2423
check_gtis,
2524
create_gti_mask,
@@ -821,7 +820,7 @@ def make_lightcurve(toa, dt, tseg=None, tstart=None, gti=None, mjdref=0, use_his
821820
"""
822821
Make a light curve out of photon arrival times, with a given time resolution ``dt``.
823822
Note that ``dt`` should be larger than the native time resolution of the instrument
824-
that has taken the data.
823+
that has taken the data, and possibly a multiple!
825824
826825
Parameters
827826
----------
@@ -1161,47 +1160,59 @@ def truncate(self, start=0, stop=None, method="index"):
11611160

11621161
return super().truncate(start=start, stop=stop, method=method)
11631162

1164-
def smothen(self,window_length=101,polyorder=3, method="savgol", normalize=False):
1163+
def smothen(self, n_knots=15, degree=3, alpha=0.1):
11651164
"""
1166-
Smoothens the light curve by removing short-term fluctuations.
1167-
1165+
Smooths the light curve using a spline-based Poisson regression model.
1166+
1167+
This method fits a Poisson regression model with a spline transformer to the light curve data,
1168+
producing a smoothed version of the original light curve. The method retains the same time bins
1169+
while adjusting the counts to a smoother representation.
1170+
11681171
Parameters
11691172
----------
1170-
window_length : int
1171-
The length of the smoothing window (must be an odd integer).
1172-
polyorder : int
1173-
The polynomial order for the Savitzky-Golay filter (must be < window_length).
1174-
method : str, optional
1175-
Smoothing method to use. Options: "savgol" (Savitzky-Golay) or "moving_avg".
1176-
normalize : bool, optional
1177-
If True, normalizes the output light curve.
1173+
n_knots : int, optional
1174+
The number of knots used for the spline transformation. More knots allow finer details
1175+
to be captured but may lead to overfitting. Default is 20.
1176+
degree : int, optional
1177+
The degree of the spline function. A higher degree allows for more flexibility in the
1178+
smoothing but may introduce unwanted oscillations. Default is 3.
1179+
alpha : float, optional
1180+
Regularization strength for the Poisson regression model. Higher values lead to stronger
1181+
smoothing. Default is 0.1.
11781182
11791183
Returns
11801184
-------
11811185
smoothed_lc : Lightcurve
1182-
A new Lightcurve object with the smoothed data.
1186+
A new Lightcurve object with the same time bins but with smoothed count values.
1187+
1188+
Notes
1189+
-----
1190+
- This method assumes that the light curve follows Poisson statistics and applies a
1191+
Poisson regression model for smoothing.
1192+
- The `SplineTransformer` is used to transform time data into a spline basis, which
1193+
allows flexible smoothing of the count rates.
11831194
"""
1184-
if window_length % 2 == 0:
1185-
raise ValueError("window_length must be an odd integer.")
1186-
1187-
if len(self.counts) < window_length:
1188-
raise ValueError("window_length must be smaller than the number of data points.")
1189-
1190-
if polyorder >= window_length:
1191-
raise ValueError("polyorder must be smaller than window_length.")
1192-
1193-
if method == "savgol":
1194-
trend = savgol_filter(self.counts, window_length, polyorder)
1195-
elif method == "moving_avg":
1196-
trend = np.convolve(self.counts, np.ones(window_length)/window_length, mode="same")
1197-
else:
1198-
raise ValueError("Invalid method. Use 'savgol' or 'moving_avg'.")
1195+
try:
1196+
import sklearn
1197+
except ImportError:
1198+
raise ImportError(
1199+
"You need to install sickit-learn to use this method try pip install -U scikit-learn"
1200+
)
1201+
1202+
from sklearn.linear_model import PoissonRegressor
1203+
from sklearn.preprocessing import SplineTransformer
1204+
from sklearn.pipeline import make_pipeline
11991205

1200-
if normalize:
1201-
trend /= np.nanmedian(trend)
1206+
X = self.time.reshape(-1, 1)
1207+
spline = SplineTransformer(n_knots=n_knots, degree=degree, extrapolation="constant")
1208+
model = make_pipeline(spline, PoissonRegressor(alpha=alpha, max_iter=1000))
1209+
model.fit(X, self.counts)
12021210

1211+
smoothed_counts = model.predict(X)
12031212
smoothed_lc = copy.deepcopy(self)
1204-
smoothed_lc.counts = trend
1213+
smoothed_lc.counts = smoothed_counts
1214+
smoothed_lc.err_dist = "gauss"
1215+
smoothed_lc.err = smoothed_counts - self.counts
12051216

12061217
return smoothed_lc
12071218

0 commit comments

Comments
 (0)