Thinking in WarpScript™ – Detecting a sequence of values

Thinking in WarpScript: Detecting a sequence of values

WarpScript is a handy toolkit built for time series manipulation. A common use case is 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
  ADDVALUE                   // add the data point to gts
%> FOR                       // close FOR loop macro
'gts' STORE                  // store the result

Read more about:
NEWGTS, STORE, FOR, NOW, RAND, ROUND, ADDVALUE, DROP

The result is a random time series:

Second step

Now, we will build a sliding window which navigates across this series in order to detect 5 seconds of values greater or equals 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

Read more about:
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'

Read more about:
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 here: WarpStudio

Share