Guralp Systems Limited
MSH-SWA-0001 - Expressions: Virtual streams in Scream - Application note

Chapter 3. Examples

3.1 Conventions

The following examples assume that we have incoming live data from a digitiser with System ID “DEMO” and Serial Number "INP". The digitiser is producing three streams “INPZ2, “INPN2” and “INPE2” for the vertical, North/South and East/West components, respectively.

Note: Although the examples below span multiple lines for legibility, recall that they must be entered on a single line in the expressions section of scream.ini.

3.2 Recipes

3.2.1 Gain

To increase the gain of a stream, use simple multiplication. The expression:

DEMO_OUTZ2 = STREAM_DEMO_INPZ2 * 2 // Doubled

produces a new output stream with amplitude of twice the input, while

DEMO_OUTZ2 = STREAM_DEMO_INPZ2 * 1.02 // +2%

produces a new output stream with a 2% increase in gain.

In both cases, the new output stream will have System ID DEMO and Stream ID OUTZ2. The Instrument, as displayed in Scream's source tree, will be "Doubled" in the first case and "+2%" in the second.

3.2.2 Resultant

The expression

DEMO_OUT3D = SquareRoot( SumOfSquares(
        STREAM_DEMO_INPZ2, STREAM_DEMO_INPN2, STREAM_DEMO_INPE2
)
) // DEMO3D

computes a three-dimensional resultant. A two-dimensional (horizontal) resultant can be computed with

DEMO_OUT2D = SquareRoot( SumOfSquares(
        STREAM_DEMO_INPN2, STREAM_DEMO_INPE2
) ) // DEMO2D

Note that the SquareRoot() and SumOfSquares() functions are computationally cheaper than the equivalent "long-hand" expressions involving ^0.5 and ^2.

3.2.3 Time-shift

To introduce a one-sample offset into a data-stream, use the following expression:

DEMO_OUTZ2 = STREAM_DEMO_INPZ2[-1] // DELAYED

A negative index refers to samples in the past, whilst a positive index refers to samples in the future. Only samples in Scream's stream buffer can be accessed so, for large time offsets, you may need to increase the maximum stream buffer size. Please see the Scream manual, MAN-SWA-0001 for details.

Any offset which can be represented by a 32-bit number can be used but please note that where negative offsets are used, sufficient data must be accumulated before the output can start and, where positive offsets are used, a delay must be imposed on the output.

3.2.4 Differentiation

By using temporal subscripting, complex operations can be easily implemented. Differentiation of the input signal is simply a case of subtracting the previous sample from the current sample (taking the difference), then multiplying by the sample rate.

The following expression converts the input velocity stream to an output acceleration stream:

DEMO_OUTZ2 = ( STREAM_DEMO_INPZ2 – STREAM_DEMO_INPZ2[-1] )
        * STREAMSPS // ACCEL

Note the use of the STREAMSPS token, which will be set to the sample rate of the output data stream. See section 2.3.2.4 for more information about using tokens.

3.2.5 Filtering

There are many techniques which can be used to implement digital filters and a discussion of these is beyond the scope of this document. A simple high-pass filter, however, can be implemented with an expression such as:

DEMO_OUTZ2 = 0.999372076005564 * ( STREAM_DEMO_OUTZ2[-1] +
        STREAM_ DEMO_INPZ2 - STREAM_DEMO_INPZ2[-1] ) // HPF

The constant value, α, (0.999372076005564 in this example) determines the corner frequency of the filter and can be calculated from:

where p is the sample period in seconds (the reciprocal of the sample rate in Hertz) and fc is the desired corner frequency in Hertz.

3.2.6 Rotation

This example uses the functions ROTATEX() and ROTATEY(), which were described in section 2.3.2.4. The two are normally used together.

The following expressions generate N/S and E/W streams which are rotated 32 degrees from the corresponding input streams:

DEMO_OUTN2 = ROTATEX( STREAM_DEMO_INPN2, STREAM_DEMO_INPE2, 32 ) // ROTATED

DEMO_OUTE2 = ROTATEY( STREAM_DEMO_INPN2, STREAM_DEMO_INPE2, 32 ) // ROTATED

The two streams will appear together in Scream's source tree under theinstrument name "ROTATED".

3.2.7 Integration (broken!)

Integration can be usefully simulated using the trapezoidal rule. Geometrically, this approximates the traditional "area under the curve" with a series of trapezoids:

In the example above, the integral of the red curve is approximated by the sum of the areas of the blue trapezoids.

This is particularly convenient with sampled data because the width of each trapezoid can be set to be the sample period, so the area under each trapezoid can be calculated easily from the period and the values of two adjacent samples.

The following expression integrates a velocity stream to produce a displacement stream:

DEMO_OUTZ2 = STREAM_DEMO_OUTZ2[-1] +
        ( STREAM_DEMO_INPZ2 + STREAM_DEMO_INPZ2[-1] )
        / ( STREAMSPS * 2 ) // DISP

Note that the right-hand side of the expression includes a past sample from the virtual stream being generated.

Note: The result of a naive integration like this will over-flow (or under-flow) as the underlying mathematical integral tends towards ±∞. This can be avoided by applying a high-pass filter to the original data and integrating the result in a two-stage process, as described in the following section.

3.2.8 Chained expressions: High-pass filter + Integration

The previous recipe is unusable because any offset in the input stream will result in the output moving to the upper or lower extreme as the underlying integral tends towards infinity. The solution is to apply a high-pass filter to the input data and then derive the integral from the filtered data, rather than from the raw velocity data. This involves chaining two expressions together so that the output of one is the input of the next. This can be achieved using the following syntax:

DEMO_HPFZ2 = 0.999372076005564 * ( STREAM_DEMO_HPFZ2[-1] +
        STREAM_ DEMO_INPZ2 - STREAM_DEMO_INPZ2[-1] ) // HPF

DEMO_OUTZ2 = STREAM_DEMO_OUTZ2[-1] +
        ( STREAM_DEMO_HPFZ2 + STREAM_DEMO_HPFZ2[-1] )
        / ( STREAMSPS * 2 ) // DISP

The first expression high-pass filters the data from DEMO_INPZ2 to create a virtual stream DEMO_HPFZ2. The second expression integrates the result to produce the output stream DEMO_OUTZ2.