Thinking in WarpScript – Detecting a sequence of values

WarpScript is a handy toolkit build for time series manipulation. A common use case could be to detect a sequence of values lasting a given duration

This post describes how to detect in a series of values between 0 and 5, subsequences of value greater or equal to 3 lasting at least 5 seconds.

First step

As a first step, we need a dataset. Here, we will generate a random GTS containing 300 values between 0 and 5 spaced by one second. Of course, you can use your own.

``````NEWGTS                       // Create an empty GTS
0 300 <%                     // for(i = 0; i < 300; i++)
'i' STORE                  // store the current index
NOW \$i 1 s * +             // tick ('now' + 'i seconds')
NaN NaN NaN                // no geo coordinate
RAND 5 * ROUND             // generate the random value
%> FOR                       // close FOR loop macro
'gts' STORE                  // store the result``````

NEWGTS, STORE, FOR, NOW, RAND, ROUND, ADDVALUE, DROP

The result is a random time series:

Second step

Now, we will build a sliding window that navigates across this series in order to detect 5 seconds of values greater or equal to 3:

``````[
\$gts // our random series
<%
'data' STORE      // store the current sliding window data
\$data 0 GET       // current timestamp
\$data 4 GET 0 GET // current lat
\$data 5 GET 0 GET // current long
\$data 6 GET 0 GET // current elev
// in our 5 current points, we keep only those >= 3
// and verify we have 5 in a row
\$data 7 GET <% 3 >= %> FILTERBY SIZE 5 >= // put true or false as value
%> MACROMAPPER // custom mapper

0 // pre window size
-5 s // 5 seconds of post window size
0 // occurrences
] MAP // Sliding window

RANGECOMPACT // keep only changing values
'result' STORE``````

GET, FILTERBY, SIZE, MACROMAPPER, MAP, RANGECOMPACT

Here, we have a sequence of booleans.

Now, we will remove false values:

``[ \$result true mapper.eq 0 0 0 ] MAP 'result' STORE // retain only 'true'``

mapper.eq

Last step

Now, we have our original series and a second boolean series corresponding to subsequences starts:

Last thought

If you want to detect the end of subsequences, you have to invert pre- and post-window sizes of the mapper:

``````[
\$gts
<%
'data' STORE
\$data 0 GET  // Current timestamp
\$data 4 GET 0 GET // Current lat
\$data 5 GET 0 GET // Current long
\$data 6 GET 0 GET // Current elev
// in our 5 current points, we keep only >= 3 and verify we have 5 in a row
\$data 7 GET <% 3 >= %> FILTERBY SIZE 5 >=
%> MACROMAPPER // custom mapper
-5 s
0
0
] MAP``````

You can find the final code and a running example of this sequence of values here: WarpStudio