 Search

# Guide to TimeSynth – A Python Library For Synthetic Time Series Generation ## Introduction

TimeSynth is a powerful open-source Python library for synthetic time series generation, so is its name (Time series Synthesis). It was introduced by J. R. Maat, A. Malali and P. Protopapas as “TimeSynth: A Multipurpose Library for Synthetic Time Series Generation in Python” (available here) in 2017.

Before going into the details of the library, since it is used for generating time series, have a quick overview of what the term ‘time series’ means.

## What is a time series?

Time series is a sequence of data points recorded at successive uniform intervals of time. It is thus a sequence of discrete-time data. It can be taken on any variable that changes over time. As the data is collected at adjacent time periods, the observations are correlated. This is in contrast with cross-sectional data wherein an entity is observed at a single point in time. Some examples of time series data include population records, monthly sunspot observations, heights of ocean tides, stock prices and so on. Visit this page to learn more about time series.

## Overview of TimeSynth library

TimeSynth can generate regular and irregular time series. It enables users to match different signals with various architectures allowing a wide variety of signals to be generated.

NOTE: TimeSynth supports Python 3.6+ versions. It is supported by PyPI

### Signal types available in TimeSynth

The types of signals that can be generated using TimeSynth are as follows:

• Sinusoidal (harmonic) signals: Signals which are periodic functions based on sine or cosine function of trigonometry.
• Signals generated using AR model: In an AutoRegression(AR) model, the variable of interest is forecasted using a linear combination of past values of the variable. The term “auto” regression indicates that it is a regression of the variable against itself (‘auto’ means ‘self’).
• In the AR(1) model (first-order autoregression), the current value of a variable is based on the immediately preceding value
• In the AR(2) model (second-order autoregression), the current value is based on the previous two values.

### Noise types available in TimeSynth

Following two types of noise can be generated using TimeSynth:

• White noise: It is a random signal having equal intensity at various frequencies. In terms of sound, white noise refers to sounds which mask other surrounding sounds in the environment. The noise produced by a whining fan is an example of white noise.
• Red noise: Red noise or Brown/Brownian noise (named after Robert Brown) is a signal having higher energy at lower frequencies. The sound produced by strong waterfalls is an example of red noise.

### Classes available in TimeSynth

The classes associated with the TimeSynth library are as follows:

General classes

• TimeSampler: This class determines how and when samples will be taken from noise and signal.
• TimeSeries: A TimeSeries object is the main interface for sampling time-series data.

Classes for noise generation

• GaussianNoise: This class adds uncorrelated, additive (i.e. white) noise to the signal.
• BaseNoise: It contains the signature of both the noise classes mentioned above.

Classes for signal generation

• BaseSignal: It contains the signature of all the signal classes.
• AutoRegressive: It generates autoregressive (AR) signals. The autoregressive lag is defined by the number of parameters in its ‘ar_param’ parameter. It should only be used with regularly sampled signals.
• CAR: It generates continuously autoregressive signals.
• MackeyGlass: It generates the Mackey-Glass delay differential equation (DDE).
• GaussianProcess: It samples time series from Gaussian Process with the selected kernel (linear, exponential etc).
• NARMA: Non-linear AutoRegressive Moving Average generator
• PseudoPeriodic: It generates pseudo periodic waves.
• Sinusoidal: It generates harmonic(sine) waves.

## Practical implementation of TimeSynth

Here’s a demo of using TimeSynth library in Google Colab with Python version 3.6.9.

Clone the GitHub repository

 !pip install git+https://github.com/TimeSynth/TimeSynth.git

Import the TimeSynth library

import timesynth as ts

Import Matplotlib library for visualizing the outputs

 import matplotlib.pyplot as plt
%matplotlib inline
%config InlineBackend.figure_format = 'retina' 

In the above lines of code,

• %matplotlib inline enables the output of plotting commands to be displayed ‘inline’ i.e. within the frontend (here colab notebook).
• %config InlineBackend.figure_format = ‘retina’ displays the output in ‘retina’ mode i.e. the figures look better with greater resolution

The above steps are common. Steps to generate and plot time series using specific types of signals have been explained below:

### Harmonic signal generation (with white noise)

1. Initialize TimeSampler

time_sampler = ts.TimeSampler(stop_time=20)

Setting stop_time=20 stops the sampling of time series after 20s. (Default value of the parameter is 10).

1. Sampling irregular time samples
irregular_time_samples = time_sampler.sample_irregular_time(num_points=500, keep_percentage=50)

sample_irregular_time() samples irregularly spaced time using num_points (number of points in time series) or resolution (resolution of time series) parameter. Only one of these parameters need to be specified. Here, the time series will have 500 data points. keep_percentage=50 means 50% of the data points (i.e. 250 out of 500) will be retained in the irregular series.

1. Initialize Sinusoidal signal

sinusoid = ts.signals.Sinusoidal(frequency=0.25)

‘frequency’ parameter represents frequency (in Hertz) of the harmonic signal formed. Its default value is 1.0

1. Initialize Gaussian noise for adding white noise to the harmonic signal

white_noise = ts.noise.GaussianNoise(std=0.3)

‘std’ is a float-value parameter representing the standard deviation of the noise. You can optionally specify its mean using the ‘mean’ parameter.

1.  Initialize TimeSeries class with the signal and noise objects
timeseries = ts.TimeSeries(signal_generator=sinusoid, noise_generator=white_noise)

‘signal_generator’ and ‘noise_generator’ are signal object and noise object for the time series respectively. You must specify at least one signal generator while the noise generator is optional.

1.  Sample using the irregular time samples
samples, signals, errors = timeseries.sample(irregular_time_samples)

sample() method samples time from the specified time series (here ‘irregular_time_samples’)

1. Plot the series
 plt.plot(irregular_time_samples, samples, marker='o', markersize=4)
plt.xlabel('Time') #name of variable plotted on X-axis
plt.ylabel('Magnitude') #name of variable on Y-axis
plt.title('Irregularly sampled sinusoid with noise'); #title of the plot 

Output:

### Harmonic signal generation (with red noise)

1.  Initialize Red Noise

red_noise = ts.noise.RedNoise(std=0.5, tau=0.8)

‘std’ is the standard devastation for the noise and ‘tau’ signifies pulse interval in  seconds.

1.  Initialize TimeSeries class with the signal and noise objects

timeseries_corr = ts.TimeSeries(sinusoid, noise_generator=red_noise)

Again, as explained in step (8), ‘signal_generator’ and ‘noise_generator’ are the signal and noise objects for time series creation respectively.

1. Sample using the irregular time samples

samples, signals, errors = timeseries_corr.sample(irregular_time_samples)

sample() method samples the ‘irregular_time_samples’ time series. It returns the samples as well as signals and errors produced from them, which are stored in the respective arrays on the LHS of the above line of code.

1. Plot the samples
 plt.plot(irregular_time_samples, samples, marker='o')
plt.xlabel('Time') #X-axis label
plt.ylabel('Magnitude') #Y-axis label
plt.title('Irregularly sampled sinusoid with red noise') #title of the plot 

Output:

1. Plot the red noise
 plt.plot(irregular_time_samples, errors, marker='o')
plt.xlabel('Time')  #X-axis label
plt.ylabel('Magnitude') #Y-axis label
plt.title('Red noise');  #title of the plot 

Output:

### Pseudoperiodic signal generation

1.  Initialize TimeSampler
 time_sampler_pp = ts.TimeSampler(stop_time=20)
#stop sampling after 20s 
1. Sample irregular time samples
irregular_time_samples_pp = time_sampler_pp.sample_irregular_time(resolution=0.05, keep_percentage=50)

The first parameter represents the resolution of the time series while keep_percentage=50 retains 50% of the total generated data points in the time series.

1. Initialize Pseudoperiodic signal
pseudo_periodic = ts.signals.PseudoPeriodic(frequency=2, freqSD=0.01, ampSD=0.5)

‘frequency’ denotes the frequency of the signal (default 1.0Hz), ‘freqSD’ denotes frequency standard deviation (default 0.1) and ‘ampSD’ is amplitude standard deviation (default 0.1).

1.  Initialize TimeSeries class with the pseudoperiodic signal

timeseries_pp = ts.TimeSeries(pseudo_periodic)

1. Perform sampling using the irregular time samples
samples_pp, signals_pp, errors_pp = timeseries_pp.sample(irregular_time_samples_pp)

samples_pp, signals_pp and errors_pp are the arrays which will store the samples, signals generated from the samples and resulting errors respectively.

1. Plot the series
 plt.plot(irregular_time_samples_pp, samples_pp, marker='o')
plt.xlabel('Time') #X-axis label
plt.ylabel('Magnitude') #Y-axis label
plt.title('Pseudoperiodic signal'); #title of the plot 

Output:

### Gaussian process signal generation

1. Initialize the time sampler

 gp = ts.signals.GaussianProcess(kernel='Matern', nu=3./2)

GaussianProcess() method samples the time series with the specified covariance function (kernel). Here, ‘Matern’ kernel has been used which requires the ‘nu’ parameter to be specified, representing the mean of the variables used in the Gaussian process. Other possible kernel types and required parameter to be specified for each can be found here.

1. Initialize the TimeSampler object with gp as the signal generator

gp_series = ts.TimeSeries(signal_generator=gp)

1. Sample the time series

samples = gp_series.sample(irregular_time_samples)

sample() returns a tuple of three arrays (samples, signals and errors – in this order).  in the above line of code means the first array in the tuple i.e. that of the samples.

1. Plot the signal
 plt.plot(irregular_time_samples, samples, marker='o', markersize=4)
plt.xlabel('Time')  #X-axis label
plt.ylabel('Value')  #Y-axis label
plt.title('Gaussian Process signal with Matern 3/2-kernel');#title of plot 

Output:

### Continuous AutoRegressive (CAR) signal generation

1. Initialize CAR model

car = ts.signals.CAR(ar_param=0.9, sigma=0.01)

‘ar_param’ is a parameter of the AR(1) process. ’sigma’ denotes the standard deviation of the signal. Both the parameters have default value 1.0

1. Instantiate TimeSeries object with ‘car’ as the signal generator

car_series = ts.TimeSeries(signal_generator=car)

1. Sample the time series

samples = car_series.sample(irregular_time_samples)

1. Plot the time series
 plt.plot(irregular_time_samples, samples, marker='o', markersize=4)
plt.xlabel('Time')  #X-axis label
plt.ylabel('Value')  #Y-axis label
plt.title(' Continuous Autoregressive process');  #title of the plot 

Output:

### AR model for regularly sampled timestamps

1. Initialize TimeSampler object
 time_sampler = ts.TimeSampler(stop_time=20)
#sampling stops after 20s 
1. Sample regular time series

regular_time_samples = time_sampler.sample_regular_time(num_points=500)

500 of the total data points will be retained in the time series.

1. Initialize AR(2) model

ar_p = ts.signals.AutoRegressive(ar_param=[1.5, -0.75])

‘ar_param’ is the list containing phi_1 and phi_2 (parameters of the AR(2) process (understand them here))

1. Initialize TimeSeries object with the signal generator

ar_p_series = ts.TimeSeries(signal_generator=ar_p)

1. Perform sampling of the time series

samples = ar_p_series.sample(regular_time_samples)

1. Plot the time series
 plt.plot(regular_time_samples, samples, marker='o', markersize=4)
plt.xlabel('Time') #X-axis label
plt.ylabel('Value') #Y-axis label
plt.title('Autoregressive process - Second order');  #title of the plot 

Output:

### Mackey-Glass signal generation

1. Initialize TimeSampler object
 time_sampler = ts.TimeSampler(stop_time=1500)
#stop sampling after 1500s 
1. Sample irregular time samples
irregular_time_samples = time_sampler.sample_irregular_time(num_points=1500, keep_percentage=75)

1500 data points will be there in the time series out of which 75% i.e. 1125 points will be retained.

1. Instantiate MackeyGlass class

mg = ts.signals.MackeyGlass()

’tau’ can be specified as a delay parameter; omitting it will assume its default value of 17

1. Instantiate GaussianNoise for adding white noise to the signal

noise = ts.noise.GaussianNoise(std=0.1)

‘std’ is the standard deviation for the noise.

1. Initialize TimeSeries object with the signal and noise generators.

mg_series = ts.TimeSeries(signal_generator=mg, noise_generator=noise)

1. Sample the irregular time series

mg_samples, mg_signals, mg_errors = mg_series.sample(irregular_time_samples)

‘mg_samples’ , ‘mg_signals’ and ‘mg_errors’ are errors which store the samples, generated signals and resulting errors respectively.

1. Plot the time series without noise
 plt.plot(irregular_time_samples, mg_signals, marker='o', markersize=4)
plt.xlabel('Time') #X-axis label  #X-axis label
plt.ylabel('Value') #Y-axis label  #Y-axis label
#title of plot
plt.title('Mackey-Glass differential equation with $\\tau=17$');


Output:

1. Plot the time series with noise
 plt.plot(irregular_time_samples, mg_samples, marker='o', markersize=4)
plt.xlabel('Time')  #X-axis label
plt.ylabel('Value')  #Y-axis label
#title of plot
plt.title('Mackey-Glass ($\\tau=17$) with noise ($\\sigma = 0.1$)');  

Output:

### NARMA series

1.  Initialize TimeSampler object
 time_sampler = ts.TimeSampler(stop_time=500)
#sampling stops after 500s 
1. Sample irregular time samples

times = time_sampler.sample_regular_time(resolution=1.)

1. Instantiate NARMA

narma_signal = ts.signals.NARMA(order=10)

‘order’ specifies the order of nonlinear interactions in the NARMA formula given here.

1. Initialize TimeSeries object with ‘narma_signal’ as the signal generator

series = ts.TimeSeries(narma_signal)

1. Perform sampling

samples, signals, errors = series.sample(times)

The samples, signals and errors will be stored in the respective LHS arrays on executing the above line of code.

1. Plot the time series
 plt.plot(times, samples, marker='o', markersize=4)
plt.xlabel('Time')  #X-axis label
plt.ylabel('Magnitude')  #Y-axis label
plt.title('10th-order NARMA Series'); #title of the plot 

Output:

• Google colab notebook with the above types of signals generated using TimeSynth can be found here.

## References

Refer to the following weblinks to dive deeper into the TimeSynth library: A zealous learner aspiring to advance in the domain of AI/ML. Eager to grasp emerging techniques to get insights from data and hence explore realistic Data Science applications as well.