-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathaslt.m
180 lines (152 loc) · 5.81 KB
/
aslt.m
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ADAPTIVE SUPERRESOLUTION WAVELET (SUPERLET) TRANSFORM
%
% AUTHOR: Harald Bârzan
% DATE: April 2019
% DESCRIPTION:
%
% Computes the adaptive superresolution wavelet (superlet) transform on
% input data to produce a time-frequency representation. For each
% frequency of interest, the closest integer order from the order
% interval will be chosen to produce each superlet. A superlet is a set
% of wavelets with the same center frequency but different number of
% cycles.
%
% REFERENCE:
%
% Superlets: time-frequency super-resolution using wavelet sets
% Moca, V.V., Nagy-Dãbâcan, A., Bârzan, H., Mure?an, R.C.
% https://www.biorxiv.org/content/10.1101/583732v1.full
%
% NOTES:
%
% If the input data consists of multiple buffers, a wavelet spectrum will
% be computed for each of the buffers and averaged to produce the final
% result.
% If the order parameter (ord) is empty, this function will return the
% standard CWT (one wavelet per frequency of interest).
%
% INPUT:
% > input - [buffers x samples] matrix
% > Fs - sampling frequency in Hz
% > F - frequency-of-interest buffer
% > Ncyc - number of initial wavelet cycles
% > ord - [1 x 2] interval of superresolution orders (optional)
% > mult - specifies the use of multiplicative superresolution
% (0 - additive, != 0 - multiplicative)
%
% OUTPUT:
% > wtresult - [frequencies x samples] superlet spectrum
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [wtresult] = aslt(input, Fs, F, Ncyc, ord, mult)
% check frequency of interest parameter
if (isempty(F))
error('frequencies not defined');
end
% check order parameter and initialize the order used at each frequency.
% if empty, go with an order of 1 for each frequency (single wavelet per
% set)
if (~isempty(ord))
order_ls = fix(linspace(ord(1), ord(2), numel(F)));
else
order_ls = ones(numel(F), 1);
end
% validate input buffer
if (isempty(input))
error('input is empty');
end
% if input is a column vector, turn it into a row vector instead
if (size(input, 2) == 1 && size(input, 1) > 1)
input = input';
end
% get the input size
[Nbuffers, Npoints] = size(input);
% the padding will be size of the lateral zero-pads, which serve to avoid
% border effects during convolution
padding = 0;
% the wavelet sets
wavelets = cell(numel(F), max(ord));
% initialize wavelet sets for either additive or multiplicative
% superresolution
if (mult ~= 0)
for i_freq = 1 : numel(F)
for i_ord = 1 : order_ls(i_freq)
% each new wavelet has Ncyc extra cycles (multiplicative
% superresolution)
wavelets{i_freq, i_ord} = cxmorlet(F(i_freq), Ncyc * i_ord, Fs);
% the margin will be the half-size of the largest wavelet
padding = max(padding, fix(numel(wavelets{i_freq, i_ord}) / 2));
end
end
else
for i_freq = 1 : numel(F)
for i_ord = 1 : order_ls(i_freq)
% each new wavelet has an extra cycle (additive superresolution)
wavelets{i_freq, i_ord} = cxmorlet(F(i_freq), Ncyc + (i_ord - 1), Fs);
% the margin will be the half-size of the largest wavelet
padding = max(padding, fix(numel(wavelets{i_freq, i_ord}) / 2));
end
end
end
% the zero-padded buffer
buffer = zeros(Npoints + 2 * padding, 1);
% the output scalogram
wtresult = zeros(numel(F), Npoints);
% convenience indexers for the zero-padded buffer
bufbegin = padding + 1;
bufend = padding + Npoints;
% loop over the input buffers
for i_buf = 1 : Nbuffers
for i_freq = 1 : numel(F)
% pooling buffer, starts with 1 because we're doing geometric mean
temp = ones(1, Npoints);
% fill the central part of the buffer with input data
buffer(bufbegin : bufend) = input(i_buf, :);
% compute the convolution of the buffer with each wavelet in the
% current set
for i_ord = 1 : order_ls(i_freq)
% restricted convolution (input size == output size)
tempcx = conv(buffer, wavelets{i_freq, i_ord}, 'same');
% accumulate the magnitude (times 2 to get the full spectral
% energy
temp = temp .* (2 .* abs(tempcx(bufbegin : bufend)) .^ 2)';
end
% compute the power of the geometric mean
root = 1 / order_ls(i_freq);
temp = temp .^ root;
% accumulate the current FOI to the result spectrum
wtresult(i_freq, :) = wtresult(i_freq, :) + temp;
end
end
% scale the output by the number of input buffers
wtresult = wtresult ./ Nbuffers;
return
% computes the complex Morlet wavelet for the desired center frequency Fc
% with Nc cycles, with a sampling frequency Fs.
function w = cxmorlet(Fc, Nc, Fs)
%we want to have the last peak at 2.5 SD
sd = (Nc / 2) * (1 / Fc) / 2.5;
wl = 2 * floor(fix(6 * sd * Fs)/2) + 1;
w = zeros(wl, 1);
gi = 0;
off = fix(wl / 2);
for i = 1 : wl
t = (i - 1 - off) / Fs;
w(i) = bw_cf(t, sd, Fc);
gi = gi + gauss(t, sd);
end
w = w ./ gi;
return
% compute the complex wavelet coefficients for the desired time point t,
% bandwidth bw and center frequency cf
function res = bw_cf(t, bw, cf)
cnorm = 1 / (bw * sqrt(2 * pi));
exp1 = cnorm * exp(-(t^2) / (2 * bw^2));
res = exp(2i * pi * cf * t) * exp1;
return;
% compute the gaussian coefficient for the desired time point t and
% standard deviation sd
function res = gauss(t, sd)
cnorm = 1 / (sd * sqrt(2 * pi));
res = cnorm * exp(-(t^2) / (2 * sd^2));
return;