![](/profiles/wavemetrics/themes/wavemetrics/logo.png)
SSA in IGOR
![](/sites/default/files/styles/thumbnail/public/default_images/Artboard%201_1.png?itok=jeHOCIXy)
klamb
I'm trying to find a way to perform singular spectrum analysis in IGOR. I have a large number (thousands) of time series to analyze, so speed is pretty important. The SSA code that I've written seems to work on some example cases, but it's significantly slowing down my analysis when I try to apply it for analyzing many time series. I was wondering if there is a built-in function for SSA or if anyone has ideas about how I can make this code run faster?
function ssa(timeseries,timeseries_rc,wlength,nrc)
wave timeseries,timeseries_rc // input: timeseries; output: reconstructed timeseries_rc
variable wlength // specific window length for embedding dimension
variable nrc // number of components to use in reconstruction
variable N, mm
mm=0
N=numpnts(timeseries)
MatrixOP/o matY=zeroMat(N-wlength+1,wlength,4)
make/o/n=(N-wlength+1) currwindow
do
currwindow =timeseries[p+mm]
matY[][mm]=currwindow[p]
mm+=1
while(mm<(wlength))
// calculate covariance matrix (trajectory approach)
MatrixOp/o Cemb=(matY^t)x(matY)/(N-wlength+1)
// Calculate eigenvalues and eigenvectors
MatrixEigenV/o/Sym/Evec Cemb
//MatrixSchur Cemb
Wave W_eigenvalues,M_eigenvectors
//Calculate principal components PC
MatrixOp/o pc=(matY)x(M_eigenvectors)
// Calculate reconstructed components RC
timeseries_rc=0.0
MatrixOP/o RC=zeroMat(N,wlength,4)
variable nn=1
string rcname
mm=0
make/o/n=(N) rcvals
do
MatrixOp/o pccol=col(PC,mm)
MatrixOp/o rhocol=col(M_eigenvectors,mm)
MatrixOp/o buf=(pccol)x(rhocol^t)
MatrixOp/o bufr=reverseRows(buf)
nn=1
do
MatrixOp/o bufdiag=getDiag(bufr,-(N-wlength+1)+nn)
RC[nn-1][mm]=mean(bufdiag)
nn+=1
while(nn
rcname="rc"+num2str(mm)
rcvals=RC[p][mm]
duplicate/o rcvals,$rcname
if (mm>(wlength-nrc-1))
timeseries_rc+=rcvals
endif
mm+=1
while(mm
end
First of all check each section of your code to figure out what is slowing you down. You can do this using
StartMSTimer/StopMSTimer()
:My guess is that your first while loop is very slow:
To me it looks like your are combining 1D subsections of timeseries to generate a 2D matrix matY. You could probably speed this up using
Duplicate
andImagetransform putCol
. Something along the lines of:Using wave assignments with p, q and r are usually very slow. Whenever you have the option to use
MatrixOP, FastOP or Imagetransform
do that insteadAnother option would be to use
MatrixOP WaveMap
and skip the while loop alltogether. Especially if you can use the same map for multiple time series this could be quite fast. You should also look intoMultiThread MyWave[]=xxxx
andThreadSafe
functionsMay 24, 2018 at 01:34 am - Permalink
May 24, 2018 at 01:48 am - Permalink
#include <FunctionProfiling>
to the procedure window and then open the FunctionProfiling ipf, there are instructions for running the profiler. There's more info here: http://www.igorexchange.com/project/FuncProfiling
May 24, 2018 at 09:17 am - Permalink
May 24, 2018 at 01:27 pm - Permalink
MatrixOp/o/FREE bufdiag=getDiag(bufr,-(N-wlength+1)+nn)
. Otherwise the parallel instances of reconstruct_multi will all work on the same bufdiag wave and overwrite each other.You might consider multithreading your parent function ssa_multi instead. That should be more effective than only multithreading a subsection of it.
May 25, 2018 at 12:50 am - Permalink