Rendering

Now we come to the fun part of Tracktable: making images and movies from data.

Tracktable supports three kinds of visualization:

  1. A heatmap (2D histogram)

  2. A trajectory map (lines/curves drawn on the map)

  3. A trajectory movie

Note

We render heatmaps directly from points. Trajectory maps and movies require assembled trajectories.

In all cases we render points into a 2D projection. In this section of the user’s guide we will discuss rendering onto a map projection. The procedure for rendering points in Cartesian space is very similar and will be documented Real Soon Now.

We use the Cartopy toolkit for the map projection and Matplotlib for the actual rendering.

Setting Up a Map

The easiest way to create and decorate a map is with the tracktable.render.mapmaker.mapmaker() function. It can create maps of common (named) areas of the world, regions surrounding airports, and user-specified regions.

Predefined Region Map

Here’s an example that will create a map of Australia with coastlines and longitude/latitude graticules rendered every 2 degrees.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 from tracktable.render.mapmaker import mapmaker
 from matplotlib import pyplot

 f = pyplot.figure(figsize=(8, 6), dpi=100)

 (mymap, initial_artists) = mapmaker(domain='terrestrial',
                                     map_name='region:australia',
                                     draw_coastlines=True,
                                     draw_countries=False,
                                     draw_states=False,
                                     draw_lonlat=True,
                                     lonlat_spacing=2,
                                     lonlat_linewidth=0.5)

We always return two values from Mapmaker. The first is the mpl_toolkits.basemap.Basemap instance that will convert points between world coordinates (longitude/latitude) and map coordinates. The second is a list of Matplotlib :py:class:artists <matplotlib.artist.Artist> that define all the decorations added to the map.

There are several predefined map areas. Their names can be retrieved by programmatically calling :py:func:tracktable.render.maps.available_maps() and for the convience of the user guide these maps are:

  • ‘region:conus’:” Continental US

  • ‘region:europe’

  • ‘region:world’

  • ‘region:north_america’

  • ‘region:south_america’

  • ‘region:australia’

Hint

If you would like to have a region included please send us its name and longitude/latitude bounding box. We will gladly add it to the next Tracktable release.

Map of Australia

This map of Australia was generated by passing the map name australia to Mapmaker.

Predefined Airport Map

This next example will render a 200x200 km area around Boston’s Logan International Airport (BOS). Coastlines will be drawn with an extra-thick (2-point-wide) red line. US state borders will be drawn in blue. Land will be filled in using solid white. We use high-resolution borders since we’re zoomed in fairly far.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
 from tracktable.render.mapmaker import mapmaker
 from matplotlib import pyplot

 f = pyplot.figure(size=(8, 6), dpi=100)
 (mymap, initial_artists) = mapmaker(domain='terrestrial',
                                     map_name='airport:BOS',
                                     draw_coastlines=True,
                                     draw_countries=False,
                                     draw_states=True,
                                     draw_lonlat=True,
                                     lonlat_spacing=2,
                                     lonlat_linewidth=0.5,
                                     land_fill_color='white',
                                     coastline_color='red',
                                     coastline_linewidth=2,
                                     state_color='blue',
                                     state_linewidth=1,
                                     region_size=(200, 200))
Map of BOS

This map of the area around Boston’s Logan International Airport was generated by passing the map name airport:BOS to Mapmaker.

Predefined City Map

Note

This functionality will be implemented in a future release.

Custom Map

If we want a map that does not correspond to any of the predefined ones then we can use the ‘custom’ map type. This example will create a map of Japan and the Korean Peninsula with all cities labeled whose population is larger than 2 million.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 from tracktable.render.mapmaker import mapmaker
 from matplotlib import pyplot

 f = pyplot.figure(size=(8, 6), dpi=100)

 # Bounding box is [longitude_min, latitude_min, longitude_max, latitude_max]
 (mymap, initial_artists) = mapmaker(domain='terrestrial',
                                     map_name='custom',
                                     map_bbox = [123.5, 23.5, 148, 48],
                                     draw_cities_larger_than=2000000)
Map of Japan and Korea

This map was generated by passing the map name custom and a longitude/latitude bounding box to Mapmaker.

Note

To define a map area that crosses the discontinuity at longitude +/- 180 degrees, use coordinates that wrap around beyond 180. The bounding boxes (-200, 0, -160, 40) and (160, 0, 200, 40) both define a region that extends from 0 to 40 degrees latitude and 20 degrees to either side of 180 degrees longitude.

Cartesian

Similar to the terrestrial maps described above Tracktable contains the ability to render map projections in the Cartesian domain. The example below will generate a blank cartesian2d that can be filled with points or trajectories.

1
2
3
4
5
6
7
8
 from tracktable.render.mapmaker import mapmaker
 from matplotlib import pyplot

 f = pyplot.figure(figsize=(8, 6), dpi=100)

 (mymap, initial_artists) = mapmaker(domain='cartesian2d',
                                     map_name='custom',
                                     map_bbox = [-100, -100, 100, 100])
Cartesian Map Projection

This map was generated by passing the domain cartesian2d, map name custom and a longitude/latitude bounding box to Mapmaker.

Rendering Onto the Map

Since Tracktable uses Matplotlib as its underlying renderer you can immediately render almost anything you want on top of a map. Remember, however, that Matplotlib does not know about the map projection. In order to draw things that will be properly registered onto the map you need to use the Basemap instance that we got earlier when we set up our map using Mapmaker. By calling the map instance as if it were a function you can convert coordinates from world space (longitude/latitude) to axis space (arbitrary coordinates established by Matplotlib).

There are many ways to draw things like contours, points, curves, glyphs and text directly onto the map. Please refer to the matplotlib example gallery for demonstrations. Tracktable provides code to render two of the most common use cases for trajectory data: heatmaps (2D histograms) and trajectory maps.

Heat Maps

A heat map (Wikipedia page) is a two-dimensional histogram – that is, a density plot. We use heat maps to illustrate the density of points that compose a set of trajectories. We are typically looking for areas of high traffic and areas of coverage.

This release of Tracktable supports heat maps rendered on top of geographic maps using the tracktable.render.histogram2d.geographic class. You must call it with at least two arguments – a Basemap instance and an iterable of points. Other optional arguments will let you control the histogram bin size, color map and where on the map the heatmap is rendered.

A start-to-finish example of how to load points and render a heat map can be found on the heatmap example page.

Note

The tracktable.render.histogram2d.geographic heat map generator only traverses its input data once to keep memory requirements low. You can safely use it with point sets too large to load into memory at once.

Trajectory Maps

A trajectory map is an ordinary map with one or more trajectories drawn on it. We may want to decorate a trajectory with any of the following:

  • Colors defined as a function of some quantity computed for the trajectory such as speed, turn rate or altitude

  • Variable line widths (such as a trajectory that is broad at its head and narrow at its tail)

  • A dot of some color and size at the head of the trajectory to mark the object’s actual position

  • A label at the head of the trajectory to display an object ID

All of this is packaged into the function draw_traffic in the tracktable.render.paths module.

Note

The argument names for that function are slightly misleading. Pay careful attention to the documentation for that function. Specifically, the arguments trajectory_linewidth_generator and trajectory_scalar_generator seem to indicate by their names that you must compute the linewidths and scalars at render time. This is fine for single images. For movies, we find it more useful to compute as much as we can before rendering and then pass an accessor function in as the generator.

Similar to heat maps, a start-to-finish example how to load points and generate trajectory maps can be found on the trajectory map example page.

Making Movies

To a first approximation, making a movie is the same as making a single image many, many times. The part that takes some care is minimizing the number of times we perform expensive operations such as loading data and configuring/decorating a map.

As with heat maps and trajectory maps a start-to-finish example how to load points and generate trajectory movies can be found on the movie rendering example page.