|
19 | 19 | from stingray.base import StingrayTimeseries, reduce_precision_if_extended |
20 | 20 | import stingray.utils as utils |
21 | 21 | from stingray.exceptions import StingrayError |
22 | | -from scipy.signal import savgol_filter |
23 | 22 | from stingray.gti import ( |
24 | 23 | check_gtis, |
25 | 24 | create_gti_mask, |
@@ -821,7 +820,7 @@ def make_lightcurve(toa, dt, tseg=None, tstart=None, gti=None, mjdref=0, use_his |
821 | 820 | """ |
822 | 821 | Make a light curve out of photon arrival times, with a given time resolution ``dt``. |
823 | 822 | 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! |
825 | 824 |
|
826 | 825 | Parameters |
827 | 826 | ---------- |
@@ -1161,47 +1160,59 @@ def truncate(self, start=0, stop=None, method="index"): |
1161 | 1160 |
|
1162 | 1161 | return super().truncate(start=start, stop=stop, method=method) |
1163 | 1162 |
|
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): |
1165 | 1164 | """ |
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 | +
|
1168 | 1171 | Parameters |
1169 | 1172 | ---------- |
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. |
1178 | 1182 |
|
1179 | 1183 | Returns |
1180 | 1184 | ------- |
1181 | 1185 | 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. |
1183 | 1194 | """ |
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 |
1199 | 1205 |
|
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) |
1202 | 1210 |
|
| 1211 | + smoothed_counts = model.predict(X) |
1203 | 1212 | 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 |
1205 | 1216 |
|
1206 | 1217 | return smoothed_lc |
1207 | 1218 |
|
|
0 commit comments