Collection of practical utils, such as deterministic and stochastic signals generators and a collection of recorded biological signals, see Signal Catalog. This utils are intended to accelerate algorithm development and/or for educative purposes.
Module Content
Signal Generators
Introductory Example
Deterministic Signal Generators
Random Signal Generators
Signal Modifiers
Helper Functions and Miscellaneous
Test Signal Catalog (Collection of Recorded Bio-Signals)
Signal Catalog
Signal Catalog Access Functions
API (moudle: utils)
Class of (test) signal generators for often used signals.
Example demonstrates use of signal generators in a explanatory (longer) or a compact (shorter) version.
import matplotlib.pyplot as plt from lmlib.utils.generator import * # -------- Explanatory (longer) version ---------- K = 500 # number of sample of the signal N = 5 # number of unit impulses K_sin = 20 # number of sample of the sinusoidal signal k_period = 20 # number of samples for one period sigma = 0.05 # standard deviation of weight Gaussian noise y_dirac = gen_rand_pulse(K, n_pulses=N) # random unit impulse generation y_sin = gen_sinusoidal(K_sin, k_period) # sinusoidal signal generation y_noise = gen_wgn(K, sigma) # weight Gaussian noise generation y_baseline = gen_baseline_sin(K, k_period=int(K/2)) # stochastic baseline generation y = gen_convolve(y_dirac, y_sin) + y_noise + 2*y_baseline # design new signal # -------- Compact (shorter) version ---------- K = 500 y = gen_convolve(gen_rand_pulse(K, n_pulses=N), gen_sinusoidal(K=20, k_period=20)) \ + gen_wgn(K, sigma=0.05) \ + 2*gen_baseline_sin(K, k_period=int(K/2)) # -------- Plotting ---------- fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y') ax.plot(range(K), y) plt.tight_layout() plt.show()
(Source code, png, hires.png, pdf)
gen_sinusoidal
Sinusoidal signal generator
gen_rectangle
Rectangular (pulse wave) signal generator
gen_triangle
Triangular signal generator
gen_slope
Slope signal generator
gen_unit_impulse
Unit impulse signal generator
gen_baseline_sin
Baseline signal generator
gen_exponential
Exponentially decaying signal generator
gen_steps
Step signal generator
gen_slopes
Slopes signal generator
gen_wgn
White Gaussian noise signal generator
gen_rand_slopes
Random ramps signal generator
gen_rand_pulse
Random pulse signal generator
gen_rand_walk
Random walk generator
gen_convolve
Convolves two signals.
k_period_to_omega
Converts sample base period (samples per cycle) to the normalized frequency
The test signal catalog is a collection of recorded biological (e.g., electrocardiograms) and other signals, intended for development and educative purposes. The collection is extendable and each record is saved as a single .csv file in the directory lmlib/utils/data/.
lmlib/utils/data/
The signal catalog is found here: Signal Catalog.
The files are directly available via Signal Catalog Access Functions.
load_single_channel
Loads a single channel signal from the signal catalog, see Signal Catalog.
load_multi_channel
Loading a multi channel signal
K (int) – Signal length
k_period (int) – signal periodicity in number samples per period.
k0 (int) – time index of first zero-crossing of sinusoidal signal
out (numpy.ndarray) – Sinusoidal signal of length K.
numpy.ndarray
Example
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_sinusoidal(K, k_period=36, k0=0) fig, ax = plt.subplots(figsize=(6,3)) ax.set(xlabel='k', ylabel='y', title='Sinusoidal Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
k_period (int) – periodicity, number of samples per period
k_on (int) – Number of samples of value 1, followed by k_period-k_on samples of value 0.
out (ndarray, shape=(K,)) – Returns a rectangular wave signal of length K.
ndarray
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_rectangle(K, k_period=30, k_on=20) fig, ax = plt.subplots(figsize=(6,3)) ax.set(xlabel='k', ylabel='y', title='Rectangle Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
out (ndarray, shape=(K,)) – Returns a triangular signal of length K with k_period samples per triangle. Amplitudes aer normalize from 0 to 1.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_triangle(K, k_period=30) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Triangle Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
out (ndarray, shape=(K,)) – Returns a repetitive slope signal of length K. Amplitudes are normalize from 0 to 1.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_slope(K, k_period=23) fig, ax = plt.subplots(figsize=(6,3)) ax.set(xlabel='k', ylabel='y', title='Slope Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
ks (list) – Time indices of unit impulses
out (ndarray, shape=(K,)) – Returns a unit impulse signal trail of length K with values at indices ks set to 1, all others to 0.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 65 y = gen_unit_impulse(K, ks=[10, 17, 59, 33]) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Unit Impulse Signal Generation') ax.stem(range(K), y, use_line_collection=True) plt.tight_layout() plt.show()
The baseline is formed by the product of 4 sinusoidal. The highest frequency is given py k_period samples per cycle. The lower 3 frequencies are linear spaced from k_period to K. Each sinusoidal is weighted with its samples/period divided by K.
k_period (int) – Normalized period of the highest frequency in the baseline in samples per cycle
out (ndarray, shape=(K,)) – Returns a baseline signal shaped by 4 sinusoidal of length K
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_baseline_sin(K, k_period=50) fig, ax = plt.subplots(figsize=(6,3)) ax.set(xlabel='k', ylabel='y', title='Sinusoidal Baseline Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
\(y_k = \gamma^{k-k_0}\)
decay (float) – decay factor \(\gamma\)
k0 (int) – index shift \(k_0\); it follows that \(y_{k_0} = 1\)
out (numpy.ndarray) – Returns an exponential decaying signal of length K, normalized to 1 at index k0.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 70 decay = 0.95 k = 20 y = gen_exponential(K, decay, k) fig, ax = plt.subplots(figsize=(6,3)) ax.set(xlabel='k', ylabel='y', title='Exponential Signal Generation') ax.plot(range(K), y) ax.scatter(k, y[k]) plt.tight_layout() plt.show()
ks (list) – Amplitude step locations (indeces)
deltas (list) – Relative step amplitudes at indeces ks
out (ndarray, shape=(K,)) – Returns a step signal of length K with steps of relative amplitudes deltas at indeces ks.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 ks = [5, 33, 50, 60, 77] deltas = [-0.3, 0.6, 0.2, -0.5, -0.5] y = gen_steps(K, ks, deltas) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Steps Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
ks (list) – Indices of slope change
deltas (list) – Slope start to end difference at each index in ks
out (ndarray, shape=(K,)) – Returns a signal of length K with chances in slope by the values deltas at indeces ks.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 ks = [15, 33, 50, 60, 77] deltas = [5, -2.5, -1, -3, 2] y = gen_slopes(K, ks, deltas) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Slopes Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
sigma (float) – Sample variance
seed (int, None) – random number generator seed, default = None.
out (ndarray, shape=(K,)) – Returns a white Gaussian noise signal of length K and variance sigma.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_wgn(K, sigma=0.5) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='White Gaussian Noise Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
Note: If seed is set to None, gen_rand_ramps() provides a random signal where the minimal distance between two edges is np.floor(0.05 * K) samples.
gen_rand_ramps()
n_slopes (int) – Number of slope changes in the signal
out (ndarray, shape=(K,)) – Returns a signal of length K with N random changes in slope.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_rand_slopes(K, n_slopes=4) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Random Slopes Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
n_pulses (int) – Number of pulses in the signal
length (int) – pulse length (number of samples per pulse set to 1)
out (ndarray, shape=(K,)) – Returns signal of length K with exactly N unity pulses of length N at random positions.
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 150 y = gen_rand_pulse(K, n_pulses=5, length=10) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Random Pulse Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
out (ndarray, shape=(K,)) – Returns a signal of length K with a random walk
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 100 y = gen_rand_walk(K) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Random Walk Signal Generation') ax.plot(range(K), y) plt.tight_layout() plt.show()
Convolves two signals. The output signal shape (number of channels and signal length) is preserved from the base signal.
base (array_like) – Base signal to be convolved, either single- or multi-channel.
template (array_like) – Signal template to be convolved with base, either a single- or multi-channel. If base is multi-channel, the number of channels has to correspond to the number of channels of base.
out (ndarray, shape=(K,)) – If template is a sigle-channel signal, the convolution is applied to each channel of base, otherwise the convolution between base and template is applied per-channel. The output signal is of the same dimension as base signal, cf. numpy.convolve(..., mode='same').
numpy.convolve(..., mode='same')
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 200 y_impulse = gen_rand_pulse(K, n_pulses=4) y_template = gen_sinusoidal(K=10, k_period=10) y = gen_convolve(y_impulse, y_template) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title='Convolve Random Unit Impulse Signal with Sinusoidal') ax.plot(range(K), y) plt.tight_layout() plt.show()
name (str) – Signal name (from signal catalog)
K (int) – Length of signal to be loaded or -1 to load until end of file. If K is larger than the maximal signal length, an assertion is raised.
k (int) – Signal load start index. If k is larger than the maximal signal length, an assertion is raised.
ch_select (int) – Selects channel index to be loaded from multi-channel signals. 0 <= ch_select < M, where M is the number of channel in the filename.
out (ndarray, shape=(K,)) – Single-channel signal with shape=(K,)
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 6000 file_name = 'EECG_BASELINE_1CH_10S_FS2400HZ.csv' y = load_single_channel(file_name, K) fig, ax = plt.subplots(figsize=(6, 3)) ax.set(xlabel='k', ylabel='y', title=file_name) ax.plot(range(K), y) plt.tight_layout() plt.show()
ch_select (list, None) – List of channels to be loaded. Selects channel indeces to be loaded from multi-channel signals. 0 <= ch_select < M, where M is the number of channel in the filename. If set to None, all channels are loaded.
out (ndarray, shape=(K, M)) – Multi-channel signal of shape=(K, M), where M is the number of channels
import matplotlib.pyplot as plt from lmlib.utils.generator import * K = 6000 file_name = 'EECG_BASELINE_9CH_10S_FS2400HZ.csv' cs = [0, 1, 2] y = load_multi_channel(file_name, K, ch_select=cs) fig, axs = plt.subplots(len(cs), 1, figsize=(6, 6)) for n, ch in enumerate(cs): axs[n].set(xlabel='k', ylabel=f'channel {ch}') axs[n].plot(range(K), y[:, n]) axs[0].set_title(file_name) plt.tight_layout() plt.show()
k_period (int) – number of samples per period
w (float) – Normalized frequency, \(\omega = {2 \pi}/{k_\mathrm{period}}\)