Visualizing Spatiotemporal Data with Kepler.gl: all Critical Mass Essen 2019 bicycle tours

Geodata with timestamps can be beautifully visualized as animated maps. My main tool of choice for creating such maps up to now has been QGIS with the Time Manager plugin (examples see here, here, and here). Some time ago I came across another promising free and open source tool for creating such animations: Kepler.gl. The tool was developed by Uber to visualize and analyze mobility data. It is based on WebGL, a Javascript API for running interactive 2D and 3D applications in a browser. The tool is web hosted but all data remains within the local browser. No registration is required to use the web tool.

The most noticeable about Kepler.gl is its cool futuristic mapping style. Below is a typical example map shown on the Kepler.gl website:

The aspects that contribute to the futuristic appearance are:

  • The use of dark mode, i.e. a black or dark background on which bright content is displayed. (White/light backgrounds and satellite images are also available.)
  • The use of transparency and overlay effects which make the map content appear to emit light and glow on the dark background.
  • The display of 3-dimensional maps, with or without a height dimension, even in cases where a 2-dimensional display would be sufficient.

All these elements can be reconfigured, if a less showy appearance is desired.

The tool is quite easy and intuitive to use. It is still worthwhile to read through the entire user guide to be aware of all available functionalities. The main field of application for the tool seems to be the dynamic visualization of large spatiotemporal data and visual cluster/density analysis.

Point data can be directly visualized as Point or Icon layers. Origin destination data can be visualized as Arc or Line layers. Trajectories can be visualized as a Trip layer in a specific data format. GeoJSON files can be included as Polygon layers. Point data can be spatially aggregated/binned as Grid, S2 (a special kind of grid), Hexbin, and H3 (a special kind of hexbin) layers. The clustering of data points can be shown as Clusters or Heatmaps.

Data can be imported in CSV or GeoJSON formats with Web Mercator (EPSG:3857 – WGS8) coordinates. Own Mapbox styles can be integrated as backgrounds. Maps can be exported as images or as a standalone interactive HTML files. It is not possible to directly export videos. A separate screen recording software I necessary to record a video.

I tested the capabilities of Kepler.gl with a dataset of all critical mass Essen bicycle tours of 2019. This data I logged personally as a participant of these tours. At critical mass events, large numbers of cyclists meet and drive through a city. This serves to raise awareness for cycling as a means of transportation. I have already used such logged tours several times to test different GIS animation technologies.

Here the final resulting animated maps:

Animated maps are fun to look at and to create, but are not always the best way of providing analytical insight. For pure analytical purposes they should be accompanied by static maps, and diagrams showing aggregated values (histograms, sums etc.). I discussed the advantages of animated vs. static maps in a previous blog post here.

Here a discussion of the main patterns that can be seen in these animated maps, and some additional contextual information:

The first animated map in the video shows all 12 tour itineraries. Tours start at 19:15 at the central Willy-Brandt-Platz in Essen and usually end there at about 21:00. Two tours ended at other locations were parties then took place.

The second animation shows the tours as moving dots. The dots are sized according to the number of participants. The number of participants in the months January to December were: 26, 82, 77, 66, 78, 160, 63, 51, 85, 84, 65, 15. These numbers were counted at the beginning of tours. Many particpants do not cycle along for the entire 2 hours. Most cyclists join the tour regularly, with a few infrequent and first-time cyclist joining every month. In cold and rainy weather (here: June, August, December) the number of participants significantly drops. In summer more casual cyclists and children join the tour. The tours that venture furthest away from the city center seem to be ones with a medium number of seasoned participants in decent weather.

The third, fourth, and fifth animation show the density of logged points in different variants. A high density of points was logged for the inner city ring. A trip down the Rüttenscheider Straße to the south is part of most tours. There are lots of restaurants and bars along this street which gives the tour lots of public exposure.

The sixth animation shows the logged speed. Overall speeds tend to be lower in the inner city area. In the outskirts speeds are higher with stops clearly visible at intersections. The slower overall speeds when cycling in the city also contributes to the higher density of logged points seen in the previous animations

The seventh animation shows the logged altitude. A clear south-north slope can be seen with the highest point of about 240 meter above sea level measured in the south, and the lowest point of 85 above seal level in the north. This isn’t much slope compared to other cities, but still makes cycling too exhausting for some inhabitants.

Here a few more notes on the technical details of creating these animations:

The used CSV file contains about 11 000 lines and has a size of 870 kB. The application runs smoothly with a file of this size.

The drawing order/layering on the map seems to be determined by the order in which the points appear in the dataset. So I reordered the raw data according to the timestamp, to make later logged points appear above earlier ones.

A filter needs to be defined for a field with timestamps to enable the time control. This is one of the few things I did not find self-explanatory. The timeline then runs from the earliest to the latest point in time appearing in the data.

I wanted the entire dataset to be successively added to the map, starting with an empty map at the earliest point in time. (In the QGIS Time Manager this is a standard feature called „aggregate features“.) A workaround to achieve this in Kepler.gl is to add a dummy point to the dataset at a much earlier point in time, about the duration of the entire datasets time interval previously, and then adjust the time window to include the entire time interval of the dataset. As this sounds much more complicated than it is, here a screenshot with the resulting time control in the lower right:

Extracting a video in decent quality from the web interface proved to be more difficult than expected. After much tinkering here is the settings I ended up using:

On my small laptop monitor I reduced the scaling from 150 % (recommended default) to 100 % with a screen resolution of 1920 x 1080 px.

I adjusted the scaling in the browser (using Crtl +, Ctr ) and adjusted the zoom level of the web map to display an appropriate map section. There is no clear map window in the Kepler.gl web interface that could be selected for screen recording.

I used CamStudio (a free open source screen recording software) to record the animation running in Kepler.gl. The default unsatisfying codec I replace by the Xvid codec. I set the quality to 70 %, capture frames every 20 milliseconds, playback rate 50 frames/second. I used a fixed region in CamStudio of 1280 x 780 px with no fixed corner. Selecting the region to record manually before every screen capture unfortunately lead to small deviations between recordings. I set the Kepler.gl animation to 0,2x speed, to get a good quality screen recording.

Using Shotcut (a free open source video editing software), I cut the video files, sped them up by a factor of 4, and added the captions. The recording at slow speed and speeding up in postprocessing was the most crucial point in extracting a good quality video.

So, how does Kepler.gl compare to QGIS with the Time Manager Plugin? Kepler.gl seems to be a great tool for ad hoc temporal geodata visualization and visual density analysis. Creating a pretty visualization with the tool is surprisingly simple and fast. It is difficult though to break out of the given visual framework. So, for a visualization that requires the customization of many map elements, I would still prefer QGIS with its full mapping capabilities. The QGIS Time Manager exports frames with time information but no legend. Kepler.gl can show both time and legend on the web interface, but these are not suitably formatted for a screen capture. In my case extracting usable videos from the web interface proved to be quite challenging. This should be less tricky when using more powerful hardware.