Warp10 tutorial - 2025/11/10
Table of Contents
We will study here the basic usage of a Time Series Database. We will base our work on the Warp10 database, and study how to use it from the command line and through its web interface. We will query existing data, inject custom data and build some queries against it, illustrating some features of Warp10.
You are expected to give back a report (1 per pair group), where you will copy the queries and results - do not forget to include the question number. Text content should be inserted as text, not as an image.
Key concepts
Warp10 stores points as GTS (GeoTime Series). A data point is composed of a timestamp, optional geolocation as latitude:longitude, optional elevation information (as millimeters), then a class and different labels to identify the series, then the value. Values can be strings (with single quotes), floats, longs, or booleans, or even multivalued.
Classnames and labels are indexed: Warp10 will quickly query data based on them. They should contain appropriate metadata (source of measurement, sensor id…). In querying, classnames can be queried by extract name, or by regexp - keep that in mind when defining you classnames.
The database can be queried using a query language named WarpScript, which is a RPN (Reverse Polish Notation) language, based on heavy stack usage for both passing parameters or outputting/pushing values. See this Warp10 documentation for illustrated examples. There is also a more conventional language called FLoWS that we will not use in the context of this tutorial.
Data is produced by a producer for an owner by an application. Owner and Producer are 128 bits UUIDs. Application is a string. Data is consumed by an owner within an application.
Setup
We will use the standalone Warp10 version, which only requires java, using basic instructions (more info on the warp10 website).
For settings things up, download static binaries from https://www.warp10.io/download (direct link)
Uncompress the archives, move the directory to $HOME/warp10, and run
the server in a terminal (again: make sure you are in the right
directory):
./bin/warp10.sh init standalone
to initialize the server structure. Data are stored in LevelDB in the leveldb directory
./bin/warp10.sh start
to start the server. It should listen on http://localhost:8080/api/v0
Windows users Note that this is a shell script, not powershell or cmd, so use WSL.
Token generation
Warp10 uses tokens to grant read and write access (with more fine
grained control possible). A token is generated from a .mc2 file in
the tokens directory, that defines the application name (equivalent
to a database - different applications do not see each other's data),
expiry period, etc.
Copy demo-tokengen.mc2 to polytech.mc2 and edit this last file to
change the application name from demo.CHANGEME to tp.polytech
Run ./bin/warp10.sh tokengen tokens/polytech.mc2 to generate access
tokens. They will be printed as JSON on stdout, with 1 token for
reading and 1 for writing. These tokens should be specified for the
different queries/updates that we can do on the server, and are
associated with the given application name.
[Question 1] Copy in the report the generated JSON (actually it is more so that you keep it as a reference)
Note that Tokens are valid for a fixed period of time (configurable in the .mc2 file).
WarpStudio interface
All interaction can be done through the HTTP API (see available
endpoints), but it requires to URL-encode the parameters, which is not
convenient (but can be useful to automate things). In this tutorial,
we will use the WarpStudio web application. Access it through
https://studio.senx.io/ (note: this is the hosted version, you could
also run the studio interface locally).
In the top-left selector, make sure that you are referencing the
http://localhost:8080/api/v0 instance (and not the sandbox one). As
described in the 00-Welcome tutorial, configure the interface to
have the tokens available in every request:
Go to settings (⚙ gear icon) / Warp 10 instances / Click "Edit" on the localhost endpoint and insert the code that stores your tokens as RT (Read Token) and WT (Write Token) in the WarpScript Bootstrap field. This code will be executed before each query to the given server, and give a convenient access to the token values.
'XXX..XX' 'RT' STORE
'YYY..YY' 'WT' STORE
Note These commands simply define the RT and WT variables so that
their values - the tokens - are easily accessible in the queries that
you will do, with the $RT syntax.
Have a look and experiment for 10 minutes with the 01-Basic file to
get a feel of the WarpScript syntax. The book icon (top right) in the
studio gives access to the WarpLib reference guide which gives
detailed information about each function. There is also a CheatSheet
for quick reference.
You can save (Save icon in top right toolbar) your current editor content into the browser storage - do not hesitate to do it frequently with different names for the different steps.
Exploring existing data
We want to analyse the water levels of the Loire river, in Nantes and in Tours. The https://www.hydro.eaufrance.fr/ website presents the river water levels. We will get data for the Loire river in Nantes: https://www.hydro.eaufrance.fr/stationhydro/M800001010/series and in Tours: https://www.hydro.eaufrance.fr/stationhydro/K490003010/series
We want the water levels ("Hauteur instantanée") for the period 01/01/2020 to 01/01/2023. Use the form to query for the data, then in the result page, select "Tableau" and "Export des données au format CSV".
We will need to convert the CSV files to the GTS ingest format (text file, 1 record per line). Write a script (python is the easy choice, but you can pick the language you prefer) to convert from CSV to the appropriate GTS format, described in https://www.warp10.io/content/03_Documentation/03_Interacting_with_Warp_10/03_Ingesting_data/02_GTS_input_format https://www.warp10.io/content/03_Documentation/015_What_is_a_GTSQMk
We will use the classname water.level with the labels station
(containing the id of the station, e.g. M800001010) and the city
label containing the name of the city (Nantes, Tours).
Pay attention to:
- the time unit
- the location information can be found on the website ("Fiche d'identité") but in Lambert93 projection format. Find out the format used by Warp10 and use the https://geofree.fr/gf/coordinateconv.asp website to convert the locations in the appropriate format
- the elevation information should be expressed as a long, in millimeters.
[Question 2] What are the coordinates in the Warp10 format for each station?
If you write the convert script in python, you should use the csv and datetime modules.
[Question 3] Give the source of the conversion script (embedded in the report, or as a separate file in a .tar.gz/.zip file).
Ingest the data into the Warp10 db using curl. Note that you will have
to specify the -X POST option to use the POST method. Use also the
-v option to get a more verbose output and see the response code
(which is 200 if everything went fine).
[Question 4] What is the curl command you used to ingest a GTS file?
Global exploration
To get a first confirmation that you actually uploaded data, go to the Explore tab in the Studio interface, make sure that the localhost server is selected, enter the read token, and check if Explore gives an output.
After reading the 02-find-and-fetch-data tutorial, list the defined
data series (classname+label).
[Question 5] Give the WarpScript query, and its output (hint: FINDSETS)
[Question 6] Give the WarpScript query to fetch the different
timeseries for the class water.level between 2020-01-01T00:00:00 and
2023-01-01T00:00:00 and store it in a ts variable. Add also $ts as
last command to push the GTS on the stack, so that you can visualize
it.
Note: when your output is a GTS or a list of GTS, then the DataViz and Tabular View are available to display the data in different forms.
Since there is a huge number of datapoints, the DataViz component has trouble processing it properly. Notice however the global characteristics for both GTS, and have a look at the timestamps for some datapoints.
Warp10 provides the LTTB / TLTTB functions for downsampling using
the Largest Triangle Three Buckets algorithm (trying to preserve the
overall shape of the data). Try to apply the TLTTB algorithm with a
number of samples of 100, then 1000, then 2000. Observe the
differences in perception of the nature of the data.
You can also explore the different types of chart types that are available (see selector on the right) and also the visualisation of the map along the chart - not very useful here, except to check that your geolocation conversion is OK.
[Question 7] Determine the size (number of points) of each GTS in
number of elements as a list (hint: LMAP - you will have to use a
macro and pay attention to parameters). Give the result and the query.
The number of samples is different between both GTS. To be able to compare them more easily, we will bucketize the data (to align on the same intervals) and fill the missing indexes between both series.
Bucketize the data using 1h interval, using the bucketizer.mean
function. Notice how the timestamps of the datapoints are now aligned
on hour values.
[Question 8] Give the query for bucketizing the list of GTS.
The timestamps are now aligned, but there are many missing values. To
align both series, we may drop the non-matching points (see this blog
post), or fill them with interpolated values. We will try to
interpolate using the filler.spline interpolator.
Note: the FILL command expects 2 GTS on the stack (and not a list of
GTS). To convert from the list of GTS to its components, use LIST->
DROP (because LIST-> outputs the list contents and the number of
elements). Then you can apply the FILL command, and convert the
result back to a list using 2 ->LIST.
[Question 9] Give the query for filling the missing values using the
filler.spline interpolator. Once filling is done, give the number of
samples in each GTS.
Building a dashboard
Warp10 defines a dashboard building stack in the form of web components. The Dashboard components can combine multiple visualizations into a single-page dashboard.
Extend the provided dashboard.html (Right click/Save As) template to build a dashboard displaying water levels in Nantes and Tours, one above the other. Add a statistics panel for each city displaying the min and max values of the data.
[Question 10] Provide the updated dashboard file.
Note that we are only using static data here, but the dashboard components are able to update regularly in order to provide a real-time dashboard.
Bonus question
Until then, we used the default parameters of Warp10, which limits
heap size to 1GB, in order to be able to run on low-end devices (like
Raspberry). For some analyses, we will need more memory. Run
./bin/warp10.sh stop to stop the server, edit the etc/warp-end.sh
file to raise WARP10_HEAP and WARP10_HEAP_MAX to 8g (or more
depending on your available memory). Then restart the server.
The pattern for Nantes looks seasonal - especially compared with Tours, which is upstream. Do you have an idea why?
[Question 12] Use the STL function (Seasonal Trend
decomposition) on the Nantes GTS to determine its different
seasonality parameters.
To go further
We only saw here some basic features of the Warp10 stack. We did not address complex queries, continuous queries, triggering alerts, anomaly detection, forecasting … Feel free to explore.
You can also experiment with more features using the Warp10 Cyclones tutorial to analyze cyclone trajectories and characteristics.
On forecasting, you may want to explore the current trendy LLM models (but beware that for some use cases, they will be less efficient than more traditional approaches) like NeuralForecast or TimesFM.