Skip to content

Time Series Generator

timecave.data_generation.time_series_generation.TimeSeriesGenerator(functions, length=100, noise_level=0.1, weights=None, parameter_values=None)

A class for generating time series data using provided functions.

This class enables the generation of multiple time series by combining various functions with parameters. It allows customization of the time series length, noise level, weights for functions, and parameter values.

Parameters:

Name Type Description Default
functions List[Callable]

A list of functions used to generate the time series.

required
length int

The length of the time series to be generated.

100
noise_level float

The standard deviation of the Gaussian noise added to the time series.

0.1
weights List[float]

A list of weights corresponding to each function.

None
parameter_values list[Dict]

A list of dictionaries containing parameter values for each function. Each dictionary contains parameter names as keys and either single values, tuples (for discrete choices), or lists (for continuous ranges) as values, representing the possible values or ranges for each parameter.

None

Attributes:

Name Type Description
time_series list[ndarray]

The generated time series.

Methods:

Name Description
generate

Generate time series data.

plot

Plot the generated time series.

Raises:

Type Description
ValueError

If the lengths of 'functions', 'parameter_values', and 'weights' don't match.

Source code in timecave/data_generation/time_series_generation.py
def __init__(
    self,
    functions: List[Callable],
    length: int = 100,
    noise_level: float or int = 0.1,
    weights: List[float] = None,
    parameter_values: list[Dict] = None,
) -> None:
    self._check_functions(functions)
    self._check_length(length)
    self._check_noise_level(noise_level)
    self._check_weights(weights)
    self._check_parameter_values(parameter_values)

    if len(functions) != len(parameter_values):

        raise ValueError(
            "Lengths of 'functions', 'parameter_values', and 'weights' must match."
        )
    if weights is not None and (
        len(weights) != len(parameter_values) or len(functions) != len(weights)
    ):

        raise ValueError(
            "Lengths of 'functions', 'parameter_values', and 'weights' must match."
        )

    self._functions = functions
    self._length = length
    self._noise_level = noise_level
    self._parameter_values = parameter_values
    self._weights = weights
    self.time_series = []
    if weights is None:
        self._weights = [1.0] * len(functions)

generate(nb_sim, og_seed=1)

Generate time series data.

Parameters:

Name Type Description Default
nb_sim int

Number of simulations to generate.

required
og_seed int

The original seed for generating random numbers.

1

Returns:

Type Description
List[array]

A list of numpy arrays containing generated time series data.

Warning

The number_samples parameter is inferred from the length parameter. Therefore, it should not be passed to the method using the parameter_values argument.

Examples:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from timecave.data_generation.time_series_functions import linear_ts, indicator_ts, exponential_ts
>>> from timecave.data_generation.time_series_generation import TimeSeriesGenerator

Generate 3 time series using a combination of linear, indicator, and exponential functions:

>>> gen = TimeSeriesGenerator([linear_ts, indicator_ts, exponential_ts],
...                            length=10,
...                            parameter_values=[{"max_interval_size": [10, 10], "slope": [1, 5]}, # A random slope between 1 and 5 will be generated.
...                                              {"start_index": 2, "end_index": 6},
...                                              {"max_interval_size": [10, 10], "decay_rate": [0.1, 10]}]); # 'max_interval_size' will always be 10.
>>> ts = gen.generate(3);
>>> ts
[array([ 1.1550022 ,  5.08763814, 10.75491998, 15.05675456, 19.71847986,
       24.3300877 , 28.65378249, 32.42146755, 36.97335225, 41.32569794]), array([ 1.090524  ,  3.94981031,  7.7498048 , 10.77923442, 13.51272171,
       16.82720927, 19.84383981, 21.52150532, 24.56596177, 27.69603248]), array([ 1.03173452,  4.41648421,  9.72828385, 13.96528833, 18.37799188,
       22.61230447, 26.9295597 , 30.32151586, 34.57860333, 38.94221321])]
Source code in timecave/data_generation/time_series_generation.py
def generate(self, nb_sim: int, og_seed: int = 1):
    """
    Generate time series data.

    Parameters
    ----------
    nb_sim : int
        Number of simulations to generate.

    og_seed : int, default=1
        The original seed for generating random numbers.

    Returns
    -------
    List[np.array]
        A list of numpy arrays containing generated time series data.

    Warning
    -------
    The `number_samples` parameter is inferred from the `length` parameter. 
    Therefore, it should not be passed to the method using the `parameter_values` argument.

    Examples
    --------
    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from timecave.data_generation.time_series_functions import linear_ts, indicator_ts, exponential_ts
    >>> from timecave.data_generation.time_series_generation import TimeSeriesGenerator

    Generate 3 time series using a combination of linear, indicator, and exponential functions:

    >>> gen = TimeSeriesGenerator([linear_ts, indicator_ts, exponential_ts],
    ...                            length=10,
    ...                            parameter_values=[{"max_interval_size": [10, 10], "slope": [1, 5]}, # A random slope between 1 and 5 will be generated.
    ...                                              {"start_index": 2, "end_index": 6},
    ...                                              {"max_interval_size": [10, 10], "decay_rate": [0.1, 10]}]); # 'max_interval_size' will always be 10.
    >>> ts = gen.generate(3);
    >>> ts
    [array([ 1.1550022 ,  5.08763814, 10.75491998, 15.05675456, 19.71847986,
           24.3300877 , 28.65378249, 32.42146755, 36.97335225, 41.32569794]), array([ 1.090524  ,  3.94981031,  7.7498048 , 10.77923442, 13.51272171,
           16.82720927, 19.84383981, 21.52150532, 24.56596177, 27.69603248]), array([ 1.03173452,  4.41648421,  9.72828385, 13.96528833, 18.37799188,
           22.61230447, 26.9295597 , 30.32151586, 34.57860333, 38.94221321])]
    """

    seeds = _generate_seeds(og_seed, nb_sim)

    for seed in seeds:
        np.random.seed(seed)
        ts = np.zeros(self._length)
        for i in range(len(self._functions)):
            parameters = _generate_random_parameters(
                self._parameter_values[i], seed=seed
            )
            ts += self._weights[i] * self._functions[i](self._length, **parameters)

        ts += np.random.normal(scale=self._noise_level, size=self._length)

        self.time_series.append(ts)

    return self.time_series

plot(indexes=None)

Plot the generated time series.

Parameters:

Name Type Description Default
indexes array or list or range

Indexes of time series to plot. None by default.

None
Warning

This method should only be called once the generate method has been run.

Examples:

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from timecave.data_generation.time_series_generation import TimeSeriesGenerator
>>> from timecave.data_generation.time_series_functions import linear_ts, scaled_right_indicator_ts, exponential_ts, sinusoid_ts

Generate 5 time series using a combination of linear and indicator functions:

>>> gen = TimeSeriesGenerator([linear_ts, scaled_right_indicator_ts],
...                            length=200,
...                            parameter_values=[{"max_interval_size": [10, 10], "slope": [1, 10]},
...                                              {"idx": 100, "constant": [5, 100]}]);
>>> ts = gen.generate(5);
>>> gen.plot([0, 1, 2, 3, 4]);

gen_plots

Using a combination of exponential functions and sinusoids instead:

>>> gen2 = TimeSeriesGenerator([exponential_ts, sinusoid_ts],
...                             length=1000,
...                             parameter_values=[{"max_interval_size": [10, 10], "decay_rate": [1, 10], "initial_value": [1, 10]},
...                                               {"max_interval_size": [10, 10], "amplitude": [0.5, 3], "frequency": [0.1, 5]}]);
>>> ts2 = gen2.generate(5);
>>> gen2.plot([0, 1, 2, 3, 4]);

gen_plots2

Source code in timecave/data_generation/time_series_generation.py
def plot(self, indexes: np.array or list or range = None):
    """
    Plot the generated time series.

    Parameters
    ----------
    indexes : np.array or list or range, optional
        Indexes of time series to plot. None by default.

    Warning
    -------
    This method should only be called once the `generate` method has been run.

    Examples
    --------
    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from timecave.data_generation.time_series_generation import TimeSeriesGenerator
    >>> from timecave.data_generation.time_series_functions import linear_ts, scaled_right_indicator_ts, exponential_ts, sinusoid_ts

    Generate 5 time series using a combination of linear and indicator functions:

    >>> gen = TimeSeriesGenerator([linear_ts, scaled_right_indicator_ts],
    ...                            length=200,
    ...                            parameter_values=[{"max_interval_size": [10, 10], "slope": [1, 10]},
    ...                                              {"idx": 100, "constant": [5, 100]}]);
    >>> ts = gen.generate(5);
    >>> gen.plot([0, 1, 2, 3, 4]);

    ![gen_plots](../../../images/Gen_plots1.png)

    Using a combination of exponential functions and sinusoids instead:

    >>> gen2 = TimeSeriesGenerator([exponential_ts, sinusoid_ts],
    ...                             length=1000,
    ...                             parameter_values=[{"max_interval_size": [10, 10], "decay_rate": [1, 10], "initial_value": [1, 10]},
    ...                                               {"max_interval_size": [10, 10], "amplitude": [0.5, 3], "frequency": [0.1, 5]}]);
    >>> ts2 = gen2.generate(5);
    >>> gen2.plot([0, 1, 2, 3, 4]);

    ![gen_plots2](../../../images/Gen_plots2.png)
    """
    if indexes is None:
        indexes = range(len(self.time_series))
    elif isinstance(indexes, int):
        indexes = [indexes]

    for idx in indexes:
        plt.plot(self.time_series[idx], label=f"Time Series {idx}")

    plt.xlabel("Time")
    plt.ylabel("Value")
    plt.title("Generated Time Series")
    plt.legend()
    plt.show()