forked from GiangTTran/SparseRandomModeDecomposition
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
133 lines (104 loc) · 4.21 KB
/
utils.py
File metadata and controls
133 lines (104 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
"""Helpers for SRMD
Hosts the helper functions for generating the features used by SRMD
generate_features(N, t):
Generates N random features on the time points t.
features_from_parameters(t, tau, frq, phs):
Generates features from the given parameters
window(t, w):
Creates a Gaussian window function of width w on the time points t.
"""
__all__ = ['generate_features', 'features_from_parameters', 'window']
import numpy as np
from .constants import twopi, default_w, default_r, default_min_samples
def generate_features(N, t, max_frq=None, w=default_w, seed=None):
"""Generates N random features.
Given the desired number of features N, generates windowed sinusoidal
features with random time-shifts, frequencies, and phases evaluated at the
time points t.
Inputs
------
N : int
The number of features to generate.
t : numpy array
The time points to compute the value of the features
Parameters
----------
max_frq : float, (default: None)
Maximum possible frequency a feature could have. If None is given, will
use half the sample rate: 0.5 * (len(t)+1) / (t[-1] - t[0])
w : float, (default: 0.1)
Window size of the features in seconds. Defaults to 0.1s or 100ms.
seed : int, (default: None)
Seed to use in the random generation of the features. This is useful for
repeatability. If None is given, a random seed will be used.
Outputs
-------
features : numpy array, features.shape == (m, N)
The value of the features at time points t.
(tau, frq, phs) : tuple of numpy arrays,
Time-shifts, frequencies, and phases of the features used in the
representation of the input y. Arrays have shape (N,).
"""
# Constants and argument parsing
L = t[-1] - t[0]
if max_frq is None:
m = len(t)
max_frq = 0.5 * (m+1) / L # using m+1 to be slightly above Nyquist rate
# Generate random times, frequencies, and phases
rng = np.random.default_rng(seed)
tau = rng.random((1, N)) * L + t[0]
frq = rng.random((1, N)) * max_frq
phs = rng.random((1, N)) * twopi
_t = np.reshape(t, (-1, 1))
features = window(_t - tau, w) * np.sin(twopi*frq*_t + phs)
# Reshape from (1, N) to (N,)
tau = tau.squeeze()
frq = frq.squeeze()
phs = phs.squeeze()
return features, (tau, frq, phs)
def features_from_parameters(t, tau, frq, phs, w=default_w):
"""Generates features from the given parameters
Given time-shifts, frequencies, and phases, construct windowed sinusoidal
features sampled at the time point t.
Inputs
------
t : numpy array
Time points to sampled the features at
tau, frq, phs : numpy arrays
Time-shifts, frequencies, and phases of the features desired. All arrays
should have the same length.
w : float, (default: 0.1)
Window size of the features in seconds. Defaults to 0.1s or 100ms
Outputs
-------
features : numpy array, features.shape == (len(t), len(tau))
The value of the features at time points t.
"""
if not len(tau) == len(frq) == len(phs):
raise ValueError(f'tau, frq, phs should have the same length. Received '
f'{len(tau)}, {len(frq)}, {len(phs)}')
tau, frq, phs = map(lambda x: np.reshape(x, (1, -1)), [tau, frq, phs])
t = np.reshape(t, (-1, 1))
features = window(t-tau, w) * np.sin(twopi*frq*t + phs)
return features
def window(t, w=default_w):
"""Creates a truncated gaussian window.
The window has a maximum value of 1, mean at 0, and standard deviation w/2.
Time points outside of three standard deviations are set to zero.
Parameters
----------
t : numpy array
Time points to evaluate the window.
w : float
Width of the gaussian window or twice its standard deviation. Should be
given in the sames units as t and not number of samples.
Returns
-------
numpy array
The values of the window at t
"""
# Standard deviation s. Half of the window width w
s = w / 2
# Zero time values outside three standard deviations
domain = (np.sign(3*s + t) + np.sign(3*s - t)) / 2
return np.exp(-0.5 * (t/s)**2) * domain