Signal Processing
The SignalProcessing package has been expanded with new and updated commands.
restart;
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' ):
R['signalplot'];
R['periodogram'];
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' ):
R['unwarpedplot'];
R['warpedplot'];
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:
R['cost'];
28.7505811441736654
In terms of the root mean square error:
R['rmse'];
0.0220493272388582497
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;
f≔sin⁡4⁢t+5t<πor3⁢π<tsin⁡40⁢t10+5otherwise
a,b≔0,4⁢π
n≔16384
( 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;
f≔x,y↦1+sin⁡π⋅x2+3⋅y2
a,b,c,d≔0.,1.0,−0.5,1.5
plot3d( f, a .. b, c .. d );
m, n := 100, 100; dx, dy := evalhf( (b-a) / (m-1) ), evalhf( (d-c) / (n-1) );
m,n≔100,100
dx,dy≔0.0101010101010101019,0.0202020202020202037
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' );
2.09312887784632640
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]' );
X≔−0.170954922213783−0.0703201167497254⁢I0.998983240195409−0.424301310369726⁢I0.0799641980758583+0.413834838645526⁢I−0.763689603106579+0.976835857569961⁢I−0.338342009593391+0.796972275668599⁢I
Y := RealPart( X );
Y≔−0.1709549222137830.9989832401954090.0799641980758583−0.763689603106579−0.338342009593391
Z := ImaginaryPart( X );
Z≔−0.0703201167497254−0.4243013103697260.4138348386455260.9768358575699610.796972275668599
Of course, if you need both the real and imaginary parts, it is best to use the ComplexToReal command:
ComplexToReal( X );
−0.1709549222137830.9989832401954090.0799641980758583−0.763689603106579−0.338342009593391,−0.0703201167497254−0.4243013103697260.4138348386455260.9768358575699610.796972275668599
Insert
The new Insert command can take one signal, and insert it into another at any point. For example:
n := 2^10;
n≔1024
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' ):
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 >;
X≔−51267315−10
FindPeakPoints( X, 'output' = 'plot', 'plotincludepoints' = ['peaks','regular','valleys'], 'gridlines' );
FindPeakPoints( X, 'output' = ['peakindices','valleyindices'] );
246,1357
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 ):
n≔100000
r≔1.0+I
dt≔complex8
tests := 25; CodeTools:-Usage( RootMeanSquareError( X, Y ), 'iterations' = tests ); CodeTools:-Usage( RelativeRootMeanSquareError( X, Y ), 'iterations' = tests );
tests≔25
memory used=16.36KiB, alloc change=0 bytes, cpu time=3.12ms, real time=3.56ms, gc time=0ns
1.15349306481481761
memory used=44.40KiB, alloc change=0 bytes, cpu time=7.48ms, real time=7.20ms, gc time=0ns
1.41397255876189520
Download Help Document