View Raw SPL
/*****************************************************************************
* *
* FINTEG.SPL Copyright (C) 2007-2012 DSP Development Corporation *
* All Rights Reserved *
* *
* Author: Randy Race *
* *
* Synopsis: frequency domain integration *
* *
* Revisions: 23 May 2007 RRR Creation *
* 10 Nov 2010 RRR integration order *
* 9 Mar 2012 RRR optional high pass filter *
* *
*****************************************************************************/
#if @HELP_FINTEG
FINTEG
Purpose: Performs frequency domain integration.
Syntax: FINTEG(s, n, fc)
s - the input series
n - Optional. An integer, the integration order. Defaults
to 1, first order integration.
fc - Optional. A real, the high pass cutoff frequency. Defaults
to -1, no high pass filtering.
Returns: A series or array.
Example:
W1: gnorm(1000, 1)
W2: integ(W1)
W3: finteg(W1)
W2 contains a standard time domain integration of W1.
W3 contains the integration as performed in the frequency
domain.
Example:
W1: gnorm(10000, 1/1000);setvunits("G")
W2: finteg(W1, 2, 5)
W1 contains data sampled at 1000 Hz. W2 high pass filters the
data with a cutoff frequency of 5 Hz and double integrates the
result.
Example:
n = 1000;
x = extract(linspace(0, 2*pi, n), 1, n-1);
W1: -sin(x + 2*cos(3*x)) * (1-6*sin(3*x))
W2: cos(x + 2*cos(3*x))
W3: finteg(W1)
W4: abs(W2 - W3)
W1 contains 999 samples of the periodic function
-sin(x + 2*cos(3*x)) * (1-6*sin(3*x))
W2 contains the analytic integral of W1
cos(x + 2*cos(3*x))
W3 computes the frequency domain integration and W4 displays the
difference between the analytic and calculated. In this case,
the difference is negligible.
Remarks:
FINTEG performs integration in the frequency domain
by calculating:
F(f)/(2*pi*f*i)
where: F(f) is the FFT of the original series
f is the frequency range of the fft
i = sqrt(-1)
F(1) is set to 0 to demean the result. The integration
calculation is inverse transformed back into the time
domain.
This method performs a de-meaned integration, i.e the DC
offset of both the input and output series are removed.
The result is converted back into the time domain.
To view the result in the frequency domain, try:
spectrum(finteg(s))
finteg(s, n) computes the nth order integration with:
F(f) / (2*pi*f*i)^n
where n is a positive integer.
If fc >= 0, the input data is high passed filtered. The filter
is implemented by zeroing out the frequency domain components
of the input <= fc. See ZHPFILT for more details.
See Also:
Deriv
Fderiv
FFT
Finteg
Integ
Spectrum
Zhpfilt
#endif
/* frequency domain integration */
ITERATE finteg(s, n, fc)
{
local len, df, f, y, w, u, j;
if (argc < 3)
{
if (argc < 2)
{
if (argc < 1) error("finteg - input series required");
n = 1;
}
fc = -1;
}
/* length and delta F */
len = length(s);
df = rate(s) / len;
/* generate frequency values */
if (len % 2 == 0)
{
/* even */
f = df * concat(0..len/2, (-len/2 + 1)..-1);
}
else
{
/* odd */
f = df * concat(0..(len-1)/2, -(len-1)/2..-1);
}
/* set frequency spacing */
f.deltax = df;
/* frequency scaling */
w = (2 * pi * f * i);
if (n != 1) w = w ^ n;
/* frequency domain integration */
y = fft(s) / w;
/* high pass FFT filter */
if (fc >= 0)
{
/* multiply by frequency domain high pass mask */
y *= zhpfilt(s, fc, 1);
}
/* demean - also removes 1/0 pathology */
y[1] = 0;
/* inverse transform */
y = ifft(y);
/* convert to real */
if (isreal(s))
{
y = real(y);
}
/* units */
u = s[1..2];
loop (j = 1..n)
{
u = integ(u);
}
y.vunits = u.vunits;
/* offset */
y.xoffset = s.xoffset;
return(y);
}