Signal Processing
The SignalProcessing package has been expanded with new and updated commands.
|
SignalProcessing
|
|
>
|
with( SignalProcessing ):
|
|
GenerateSignal
|
|
The new GenerateSignal command is useful for creating signals, filters, and windows from algebraic expressions. For example:
>
|
X := GenerateSignal( 3 * sin(t) + cos(2*t), t = 0 .. 4 * Pi, 100 );
|
The command also packages many related features and data for the signal:
>
|
sample_rate, Times, Signal := GenerateSignal( t * exp(-t), t = 0 .. 5, 10^3, 'output' = ['samplerate','times','signal'] );
|
>
|
R := GenerateSignal( t / (1+t^2), t = 0 .. 4, 2^10, 'noisetype' = 'additive', 'noisedeviation' = 0.01, 'output' = 'record' ):
|
|
|
DynamicTimeWarping
|
|
The DynamicTimeWarping command, which has many applications including speech recognition and genetic sequencing, determines the best match between two signals by varying the sampling rates dynamically. For example:
>
|
X := GenerateSignal( 5 + sqrt(1-(t-1)^4), t = 0 .. 2, 200, 'mirror' = 'antisymmetric', 'copies' = 4 ):
|
>
|
Y := GenerateSignal( 6 - abs(t-1), t = 0 .. 2, 200, 'mirror' = 'antisymmetric', 'copies' = 4 ):
|
>
|
R := DynamicTimeWarping( X, Y, 'compiled', 'output' = 'record' ):
|
The match is computed by inserting zero or more copies of each sample for both signals in such a way that the cost with respect to the metric (taxicab, by default) is minimal. For this example:
| (1.2.1) |
In terms of the root mean square error:
| (1.2.2) |
|
|
DifferentiateData
|
|
The new DifferentiateData command offers the standard methods, namely Backward, Central, and Forward Difference, and also features spectral differentiation. For example:
>
|
f := piecewise( t < Pi or t > 3 * Pi, sin(4*t) + 5, 1/10 * sin(40*t) + 5 );
a, b := 0, 4 * Pi;
n := 2^14;
|
| |
>
|
( dt, T, X ) := GenerateSignal( f, t = a .. b, n, 'includefinishtime' = 'false', 'output' = ['timestep','times','signal'] ):
|
>
|
DX := DifferentiateData( X, 1, 'step' = dt, 'method' = 'spectral', 'extrapolation' = 'periodic' ):
|
>
|
dataplot( T, [X,DX], 'style' = 'line', 'color' = ['red','blue'], 'legend' = ["Signal","First derivative"], 'size' = [500,250] );
|
|
|
IntegrateData and IntegrateData2D
|
|
The IntegrateData2D command provides a fast and accurate way of finding the volume under a two-dimensional dataset. For example:
>
|
f := (x,y) -> sqrt( 1 + sin( Pi * ( x^2 + 3 * y^2 ) ) );
a, b, c, d := 0.0, 1.0, -0.5, 1.5;
|
| |
| (1.4.1) |
>
|
plot3d( f, a .. b, c .. d );
|
>
|
m, n := 100, 100;
dx, dy := evalhf( (b-a) / (m-1) ), evalhf( (d-c) / (n-1) );
|
| (1.4.2) |
>
|
X := Vector( m, i -> evalhf( a + (i-1) * dx ), 'datatype' = 'float[8]' ):
Y := Vector( n, j -> evalhf( c + (j-1) * dy ), 'datatype' = 'float[8]' ):
Z := Matrix( m, n, (i,j) -> evalhf( f( X[i], Y[i] ) ), 'datatype' = 'float[8]' );
|
>
|
IntegrateData2D( X, Y, Z, 'uniform', 'compiled', 'method' = 'simpson' );
|
| (1.4.3) |
This command supports both uniform (regular) and non-uniform (irregular) data. The option uniform tells the algorithm to skip the check for uniformity and use the uniform version of Simpson's Rule, which is quicker. The existing (added in Maple 2021) one-dimensional version of the command, IntegrateData, has been updated to include the compiled and uniform options.
|
|
RealPart and ImaginaryPart
|
|
The new RealPart and ImaginaryPart commands complement the existing ComplexToReal command. They, respectively, take a complex[8] container and quickly create a float[8] container for the real part and imaginary part. For example:
>
|
X := LinearAlgebra:-RandomVector( 5, 'generator' = -1.0 - 1.0 * I .. 1.0 + 1.0 * I, 'datatype' = 'complex[8]' );
|
| (1.5.1) |
| (1.5.2) |
>
|
Z := ImaginaryPart( X );
|
| (1.5.3) |
Of course, if you need both the real and imaginary parts, it is best to use the ComplexToReal command:
| (1.5.4) |
|
|
Insert
|
|
The new Insert command can take one signal, and insert it into another at any point. For example:
>
|
X := GenerateSignal( sin(4*t) + 5, t = 0 .. 2 * Pi, n, 'includefinishtime' = 'false' ):
|
>
|
SignalPlot( X, 'view' = ['DEFAULT',0..10], 'color' = 'blue' );
|
>
|
Y := GenerateSignal( 1/10 * sin(40*t) + 5, t = 0 .. 2 * Pi, n, 'includefinishtime' = 'false' ):
|
>
|
SignalPlot( Y, 'view' = ['DEFAULT',0..10], 'color' = 'blue' );
|
>
|
Insert( X, floor(n/2) + 1, Y, 'inplace' ):
|
>
|
SignalPlot( X, 'view' = ['DEFAULT',0..10], 'color' = 'blue' );
|
|
|
FindPeakPoints
|
|
The FindPeakPoints command now has output options for the indices of the peaks and valleys. For example:
>
|
X := < -5, 12, 6, 7, 3, 15, -10 >;
|
>
|
FindPeakPoints( X, 'output' = 'plot', 'plotincludepoints' = ['peaks','regular','valleys'], 'gridlines' );
|
>
|
FindPeakPoints( X, 'output' = ['peakindices','valleyindices'] );
|
|
|
RootMeanSquareError and RelativeRootMeanSquareError
|
|
The RootMeanSquareError and RelativeRootMeanSquareError commands have been sped up for large data containers. For example:
>
|
n := 10^5;
r := 1.0 + 1.0 * I;
dt := 'complex[8]';
X := LinearAlgebra:-RandomVector( n, 'generator' = -r .. r, 'datatype' = dt ):
Y := LinearAlgebra:-RandomVector( n, 'generator' = -r .. r, 'datatype' = dt ):
|
>
|
tests := 25;
CodeTools:-Usage( RootMeanSquareError( X, Y ), 'iterations' = tests );
CodeTools:-Usage( RelativeRootMeanSquareError( X, Y ), 'iterations' = tests );
|
memory used=16.36KiB, alloc change=0 bytes, cpu time=3.12ms, real time=3.56ms, gc time=0ns
| |
memory used=44.40KiB, alloc change=0 bytes, cpu time=7.48ms, real time=7.20ms, gc time=0ns
| |
| (1.8.2) |
|
|
|