tseda.seasonality
tseda.seasonality
Seasonal period detection for time series.
Public API
- SeasonalityReport
Frozen dataclass with dominant period, candidate list, Fisher G-test, and
is_seasonalflag.- SeasonalityDetector
Stateless detector supporting periodogram (FFT), ACF-peak, and combined strategies.
- class tseda.seasonality.SeasonalityReport(dominant_period, candidate_periods, is_seasonal, method, n_obs, alpha, periodogram_periods, acf_periods, fisher_g_stat, fisher_p_value, strength_scores)[source]
Bases:
objectImmutable seasonality detection result.
- Parameters:
- dominant_period
The single most likely seasonal period (in observations), or
Noneif no seasonality was detected.- Type:
int or None
- candidate_periods
All detected candidate periods as
(period, score)pairs sorted by score descending. Score is normalised to [0, 1].
- is_seasonal
Truewhen the evidence for a dominant seasonal period is statistically significant atalpha.- Type:
- periodogram_periods
Top-k candidate periods from the FFT periodogram, as
(period, normalised_power)pairs.
- acf_periods
Candidate periods from significant ACF peaks, as
(period, acf_value)pairs.
- fisher_p_value
P-value of the Fisher G test. Small values (< alpha) indicate that at least one spectral peak is too strong to be explained by white noise.
- Type:
- __init__(dominant_period, candidate_periods, is_seasonal, method, n_obs, alpha, periodogram_periods, acf_periods, fisher_g_stat, fisher_p_value, strength_scores)
- Parameters:
- Return type:
None
- class tseda.seasonality.SeasonalityDetector[source]
Bases:
objectDetect seasonal periods in a
TimeSeries.The detector is stateless — one instance, many series.
- detect(ts, method, top_k, alpha, min_period, max_period)[source]
Return a
SeasonalityReport.- Parameters:
- Return type:
- test_period(ts, period, alpha)[source]
Test a specific period for significance.
- Parameters:
ts (TimeSeries)
period (int)
alpha (float)
- Return type:
Examples
>>> import numpy as np, pandas as pd >>> from tseda import TimeSeries >>> from tseda.seasonality.detector import SeasonalityDetector
Weekly pattern in daily data:
>>> rng = np.random.default_rng(1) >>> n = 140 >>> seas = np.tile(np.array([0, 1, 2, 2, 1, -1, -2], dtype=float), 20) >>> y = 10 + seas + rng.standard_normal(n) * 0.2 >>> idx = pd.date_range("2020-01-06", periods=n, freq="D") >>> ts = TimeSeries(y, index=idx) >>> r = SeasonalityDetector().detect(ts) >>> r.dominant_period 7
- detect(ts, method='combined', *, top_k=5, alpha=0.05, min_period=2, max_period=None)[source]
Detect seasonal periods in ts.
- Parameters:
ts (TimeSeries) – Input series. NaN values are filled by linear interpolation before spectral analysis.
method (str, optional) –
Detection strategy:
"periodogram"— FFT power spectrum only."acf"— ACF peaks only."combined"— both methods with agreement bonus (default).
top_k (int, optional) – Maximum number of candidate periods to return per method. Default 5.
alpha (float, optional) – Significance level for Fisher G-test and ACF confidence interval. Default 0.05.
min_period (int, optional) – Minimum period to search for. Default 2.
max_period (int, optional) – Maximum period to search for. Defaults to
n // 2.
- Return type:
- Raises:
TypeError – If ts is not a
TimeSeries.ValueError – If method is not recognised, top_k < 1, alpha outside (0, 1), or the series is too short.
Examples
>>> import numpy as np, pandas as pd >>> from tseda import TimeSeries >>> from tseda.seasonality.detector import SeasonalityDetector
Monthly series — detect 12-month period:
>>> rng = np.random.default_rng(0) >>> idx = pd.date_range("2018-01", periods=60, freq="MS") >>> seas = np.tile(np.sin(2 * np.pi * np.arange(12) / 12) * 8, 5) >>> ts = TimeSeries(seas + rng.standard_normal(60) * 0.5, index=idx) >>> r = SeasonalityDetector().detect(ts) >>> r.dominant_period 12
- test_period(ts, period, *, alpha=0.05)[source]
Test whether a specific period is present in ts.
Runs both the periodogram and ACF detectors and checks whether the requested period appears among their significant candidates.
- Parameters:
ts (TimeSeries) – Input series.
period (int) – The period to test (must be >= 2).
alpha (float, optional) – Significance level. Default 0.05.
- Returns:
Keys:
"period"— the period tested."detected"—Trueif the period was found by at least one method."periodogram_detected"—Trueif it appears in the FFT peaks."acf_detected"—Trueif the ACF at this lag is a significant positive peak."strength"— combined strength score in [0, 1]."fisher_p_value"— p-value of the overall Fisher G-test.
- Return type:
- Raises:
TypeError – If ts is not a
TimeSeries.ValueError – If period < 2.
Examples
>>> import numpy as np, pandas as pd >>> from tseda import TimeSeries >>> from tseda.seasonality.detector import SeasonalityDetector
>>> rng = np.random.default_rng(0) >>> idx = pd.date_range("2018-01", periods=60, freq="MS") >>> seas = np.tile(np.sin(2 * np.pi * np.arange(12) / 12) * 8, 5) >>> ts = TimeSeries(seas + rng.standard_normal(60) * 0.5, index=idx) >>> SeasonalityDetector().test_period(ts, 12)["detected"] True
Report
- class tseda.seasonality.detector.SeasonalityReport(dominant_period, candidate_periods, is_seasonal, method, n_obs, alpha, periodogram_periods, acf_periods, fisher_g_stat, fisher_p_value, strength_scores)[source]
Bases:
objectImmutable seasonality detection result.
- Parameters:
- dominant_period
The single most likely seasonal period (in observations), or
Noneif no seasonality was detected.- Type:
int or None
- candidate_periods
All detected candidate periods as
(period, score)pairs sorted by score descending. Score is normalised to [0, 1].
- is_seasonal
Truewhen the evidence for a dominant seasonal period is statistically significant atalpha.- Type:
- periodogram_periods
Top-k candidate periods from the FFT periodogram, as
(period, normalised_power)pairs.
- acf_periods
Candidate periods from significant ACF peaks, as
(period, acf_value)pairs.
- fisher_p_value
P-value of the Fisher G test. Small values (< alpha) indicate that at least one spectral peak is too strong to be explained by white noise.
- Type:
- __init__(dominant_period, candidate_periods, is_seasonal, method, n_obs, alpha, periodogram_periods, acf_periods, fisher_g_stat, fisher_p_value, strength_scores)
- Parameters:
- Return type:
None
Detector
- class tseda.seasonality.detector.SeasonalityDetector[source]
Bases:
objectDetect seasonal periods in a
TimeSeries.The detector is stateless — one instance, many series.
- detect(ts, method, top_k, alpha, min_period, max_period)[source]
Return a
SeasonalityReport.- Parameters:
- Return type:
- test_period(ts, period, alpha)[source]
Test a specific period for significance.
- Parameters:
ts (TimeSeries)
period (int)
alpha (float)
- Return type:
Examples
>>> import numpy as np, pandas as pd >>> from tseda import TimeSeries >>> from tseda.seasonality.detector import SeasonalityDetector
Weekly pattern in daily data:
>>> rng = np.random.default_rng(1) >>> n = 140 >>> seas = np.tile(np.array([0, 1, 2, 2, 1, -1, -2], dtype=float), 20) >>> y = 10 + seas + rng.standard_normal(n) * 0.2 >>> idx = pd.date_range("2020-01-06", periods=n, freq="D") >>> ts = TimeSeries(y, index=idx) >>> r = SeasonalityDetector().detect(ts) >>> r.dominant_period 7
- detect(ts, method='combined', *, top_k=5, alpha=0.05, min_period=2, max_period=None)[source]
Detect seasonal periods in ts.
- Parameters:
ts (TimeSeries) – Input series. NaN values are filled by linear interpolation before spectral analysis.
method (str, optional) –
Detection strategy:
"periodogram"— FFT power spectrum only."acf"— ACF peaks only."combined"— both methods with agreement bonus (default).
top_k (int, optional) – Maximum number of candidate periods to return per method. Default 5.
alpha (float, optional) – Significance level for Fisher G-test and ACF confidence interval. Default 0.05.
min_period (int, optional) – Minimum period to search for. Default 2.
max_period (int, optional) – Maximum period to search for. Defaults to
n // 2.
- Return type:
- Raises:
TypeError – If ts is not a
TimeSeries.ValueError – If method is not recognised, top_k < 1, alpha outside (0, 1), or the series is too short.
Examples
>>> import numpy as np, pandas as pd >>> from tseda import TimeSeries >>> from tseda.seasonality.detector import SeasonalityDetector
Monthly series — detect 12-month period:
>>> rng = np.random.default_rng(0) >>> idx = pd.date_range("2018-01", periods=60, freq="MS") >>> seas = np.tile(np.sin(2 * np.pi * np.arange(12) / 12) * 8, 5) >>> ts = TimeSeries(seas + rng.standard_normal(60) * 0.5, index=idx) >>> r = SeasonalityDetector().detect(ts) >>> r.dominant_period 12
- test_period(ts, period, *, alpha=0.05)[source]
Test whether a specific period is present in ts.
Runs both the periodogram and ACF detectors and checks whether the requested period appears among their significant candidates.
- Parameters:
ts (TimeSeries) – Input series.
period (int) – The period to test (must be >= 2).
alpha (float, optional) – Significance level. Default 0.05.
- Returns:
Keys:
"period"— the period tested."detected"—Trueif the period was found by at least one method."periodogram_detected"—Trueif it appears in the FFT peaks."acf_detected"—Trueif the ACF at this lag is a significant positive peak."strength"— combined strength score in [0, 1]."fisher_p_value"— p-value of the overall Fisher G-test.
- Return type:
- Raises:
TypeError – If ts is not a
TimeSeries.ValueError – If period < 2.
Examples
>>> import numpy as np, pandas as pd >>> from tseda import TimeSeries >>> from tseda.seasonality.detector import SeasonalityDetector
>>> rng = np.random.default_rng(0) >>> idx = pd.date_range("2018-01", periods=60, freq="MS") >>> seas = np.tile(np.sin(2 * np.pi * np.arange(12) / 12) * 8, 5) >>> ts = TimeSeries(seas + rng.standard_normal(60) * 0.5, index=idx) >>> SeasonalityDetector().test_period(ts, 12)["detected"] True