Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 3 additions & 16 deletions examples/2-complex_systems.ipynb
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "initial_id",
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
""
]
}
],
"cells": [],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"display_name": "aeon",
"language": "python",
"name": "python3"
},
Expand All @@ -29,7 +16,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
"version": "3.11.9"
}
},
"nbformat": 4,
Expand Down
2 changes: 1 addition & 1 deletion s2generator/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

__version__ = "0.0.10"
__version__ = "0.0.11"

__all__ = [
"Node",
Expand Down
50 changes: 38 additions & 12 deletions s2generator/excitation/forecast_pfn.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ def make_series_trend(
days = (dates - dates[0]).days
if series.scale.linear is not None:
values += shift_axis(days, series.offset.linear) * series.scale.linear

if series.scale.exp is not None:
values *= np.power(series.scale.exp, shift_axis(days, series.offset.exp))

Expand Down Expand Up @@ -368,11 +369,16 @@ def make_series(
if random_walk:
values = get_random_walk_series(rng=rng, length=len(dates))
else:
# generate the trend component of the series
values_trend = make_series_trend(series=series, dates=dates)

# generate the seasonal component of the series and multiply it with the trend
values_seasonal = make_series_seasonal(rng=rng, series=series, dates=dates)

# combine the trend and seasonal components to get the base series values
values = values_trend * values_seasonal["seasonal"]

# generate the noise term of the series and add it to the base series values
weibull_noise_term = weibull_noise(
rng=rng,
k=series.noise_config.k,
Expand Down Expand Up @@ -424,24 +430,20 @@ def __init__(
transition: Optional[bool] = True,
start_time: Optional[str] = "1885-01-01",
end_time: Optional[str] = None,
exp_trend: Optional[bool] = True,
random_walk: bool = False,
dtype: np.dtype = np.float64,
) -> None:
"""
Initializes the time series generator with configuration parameters.

:param is_sub_day: Enable sub-daily frequency components (minutes/hours)
:type is_sub_day: Optional[bool]
:param transition: Enable smooth transitions between frequency components
:type transition: Optional[bool]
:param start_time: Start timestamp for generated series (ISO format: YYYY-MM-DD)
:type start_time: Optional[str]
:param end_time: End timestamp for generated series. Uses current date if None.
:type end_time: Optional[str]
:param random_walk: Enable random walk transformation for non-stationary series
:type random_walk: bool
:param exp_trend: Enable exponential trend transformation
:param dtype: Numerical precision for output series
:type dtype: np.dtype
"""
super().__init__(dtype=dtype)
self.is_sub_day = is_sub_day
Expand Down Expand Up @@ -484,6 +486,9 @@ def __init__(
# Global series configuration
self._time_series_config: Optional[SeriesConfig] = None

# Whether to apply exponential trend transformation
self.exp_trend = exp_trend

def __call__(
self,
rng: np.random.RandomState,
Expand Down Expand Up @@ -748,7 +753,7 @@ def generate_series(
freq_index: int = None,
start: pd.Timestamp = None,
options: Optional[dict] = None,
random_walk: bool = False, # TODO: 是否可以添加为类属性
random_walk: bool = False,
) -> Dict[str, Union[pd.Series, np.ndarray, pd.DataFrame, DatetimeIndex]]:
"""
Function to construct synthetic series configs and generate synthetic series.
Expand Down Expand Up @@ -793,7 +798,9 @@ def generate_series(
self._scale_config = self.get_component_scale_config(
base=1.0,
linear=rng.normal(loc=0.0, scale=0.01),
exp=rng.normal(loc=1.0, scale=0.005 / timescale),
exp=rng.normal(loc=1.0, scale=0.001 / timescale)
if self.exp_trend
else None,
annual=self._annual,
monthly=self._monthly,
weekly=self._weekly,
Expand All @@ -805,7 +812,7 @@ def generate_series(
self._offset_config = self.get_component_scale_config(
base=0.0,
linear=rng.normal(loc=-0.1, scale=0.5),
exp=rng.normal(loc=-0.1, scale=0.5),
exp=rng.normal(loc=-0.1, scale=0.5 / timescale),
annual=self._annual,
monthly=self._monthly,
weekly=self._weekly,
Expand Down Expand Up @@ -859,6 +866,9 @@ def _select_ndarray_from_dict(
:param options: Options dict for generating series.
:return: The selected time series data with `np.ndarray`.
"""

# Generate two time series segments using the `generate_series` method.
# These segments will be used to create a transition series if the transition option is enabled.
series1 = self.generate_series(
rng=rng,
length=length,
Expand All @@ -867,7 +877,6 @@ def _select_ndarray_from_dict(
options=options,
random_walk=self.random_walk,
)

series2 = self.generate_series(
rng=rng,
length=length,
Expand All @@ -877,6 +886,9 @@ def _select_ndarray_from_dict(
random_walk=self.random_walk,
)

# If transition is enabled,
# compute the transition coefficients and create a blended series that transitions from series1 to series2.
# Otherwise, use series1 directly.
if self.transition:
coefficients = get_transition_coefficients(context_length=length)
values = (
Expand Down Expand Up @@ -930,14 +942,28 @@ def generate(
)

# Generate each dimension independently
for i in range(input_dimension):
time_series[:, i] = self._select_ndarray_from_dict(
index = 0
while index < input_dimension:
generated_series = self._select_ndarray_from_dict(
rng=rng,
length=n_inputs_points,
freq_index=freq_index,
start=start,
options=options,
)

# Here, we check if NaN values ​​exist.
# If they do, we regenerate until no NaN values ​​are found.
if np.any(np.isnan(generated_series)):
continue # Skip this iteration and regenerate the series

# If the generated series does not contain NaN values,
# assign them to the output array and continue generating the next dimension.
time_series[:, index] = generated_series

# Increment the index to generate the next dimension
index += 1

return time_series

@property
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
setuptools.setup(
name="S2Generator",
packages=setuptools.find_packages(),
version="0.0.10",
version="0.0.11",
description="A series-symbol (S2) dual-modality data generation mechanism, enabling the unrestricted creation of high-quality time series data paired with corresponding symbolic representations.", # 包的简短描述
url="https://github.com/wwhenxuan/S2Generator",
author="whenxuan, johnfan12, changewam",
Expand Down
1 change: 1 addition & 0 deletions tests/test_augmentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,5 +258,6 @@ def test_wiener_filter(self) -> None:
msg="Filtered series is identical to original series in `test_wiener_filter` method",
)


if __name__ == "__main__":
unittest.main()