-
Notifications
You must be signed in to change notification settings - Fork 0
/
MC_SSA.m
150 lines (125 loc) · 4.19 KB
/
MC_SSA.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
function[surrVals] = MC_SSA(ts, M, algorithm, singVecs, MC, noise, varargin)
%% Runs a Monte Carlo singular spectrum analysis. Generates surrogate eigenvalues.
%
% [surrVals, iterSigVals, iterTrueConf] = MC_SSA(tsm0, M, algorithm, singVecs, MC, noise)
% Conducts an MC-SSA significance test on a set of singular vectors.
% Returns the set of surrogate singular values as well as surrogate
% eigenvalues at the significance level for each iteration.
%
% MC_SSA(..., 'parallel')
% To speed up runtime, runs the Monte Carlo process in parallel using
% MATLAB's default settings. If the Distributed Computing Toolbox is not
% licensed, reverts to serial computing.
%
% MC_SSA(..., 'showProgress')
% Displays a progress bar showing the progress through the Monte Carlo
% iterations. This option is disabled when computing in parallel.
%
% MC_SSA(..., 'estimateRuntime')
% Estimates total runtime based on the number of iterations and available
% workers in the computing pool.
%
%
% ----- Inputs -----
%
% ts: A time series.
%
% M: The embedding dimension / sampling window.
%
% algorithm: The algorithm used to build SSA trajectories
% 'BK': Broomhead-King
% 'VG': Vautard-Ghil
%
% singVecs: The singular vectors for the time series.
%
% MC: The number of Monte Carlo iterations in the MC-SSA
%
% noise: A flag for the noise used in the Rule N significance test
% 'red' (Default): AR(1) noise with added white noise
% 'white': white Gaussian noise. (mean = 0, variance = 1)
%
%
% ----- Outputs -----
%
% surrVals: The matrix of surrogate singular values
% Parse inputs. Error Check. Setup.
[parallel, showProgress, estimateRuntime] = setup(ts, MC, varargin{:});
% Preallocate surrogate singular values
surrVals = NaN(MC, M);
% Initialize the parallel pool if computing in parallel
nWorkers = 1;
if parallel
pool = gcp;
pause(3);
nWorkers = pool.NumWorkers;
end
% Get the noise properties
[~, noiseArgs] = randNoiseSeries(ts, noise);
% Initialize the progress bar if displaying
if showProgress
progressbar(0);
end
% Run the first iteration. Estimate runtime if desired
if estimateRuntime
startTime = tic;
end
surrVals(1,:) = mcssaStep( noiseArgs, M, algorithm, singVecs );
if estimateRuntime
time = toc(startTime);
time = time*MC/nWorkers;
h = time / 360;
m = mod(time,360)/60;
s = mod(time,60);
fprintf('Estimated runtime: %0.f hour(s), %0.f minute(s), %0.f seconds \r\n',h,m,s);
end
% Run the MC-SSA
if parallel % In parallel
parfor k = 2:MC
surrVals(k,:) = mcssaStep( noiseArgs, M, algorithm, singVecs );
end
else % In serial
for k = 2:MC
surrVals(k,:) = mcssaStep( noiseArgs, M, algorithm, singVecs );
% Update progress bar if displaying
if showProgress
progressbar(k/MC);
end
end
end
end
%%%%% Helper functions %%%%%%
function[parallel, showProgress, estimateRuntime] = setup(ts, MC, varargin)
% Parse the optional inputs
[parallel, showProgress, estimateRuntime] = parseInputs( varargin, ...
{'parallel','showProgress','estimateRuntime'},{false, false, false},{'b','b','b'} );
% Ensure tsm0 is a vector
if ~isvector(ts)
error('ts must be a vector');
end
% Ensure MC is positive
if MC < 1 || mod(MC,1)~=0
error('Monte Carlo number must be a positive integer');
end
% If parallel, check for Distributed Computing Toolbox
if parallel
if ~license('test', 'Distrib_Computing_Toolbox')
warning( sprintf('The Distributed Computing Toolbox is not licensed on this computer.\r\nCannot run in parallel. Reverting to default serial mode...')); %#ok<SPWRN>
parallel = false;
end
end
% Disable 'showProgress' for parallel computing
if parallel && showProgress
warning('Cannot display progress for parallel computations.');
showProgress = false;
end
end
function[surrVals] = mcssaStep(noiseArgs, M, algorithm, singVecs)
% Build a surrogate time series
surrTS = randNoiseSeries( noiseArgs);
% Get the covariance matrix
[~,surrC] = getTandC( surrTS, M, algorithm);
% Project onto data eigenvector basis
surrProj = singVecs' * surrC * singVecs;
% Extract the diagonals elements. These are the surrogate singular values
surrVals = diag( surrProj );
end