Animating Toronto Parking Enforcement with heatmap.js

by Justin Pierre – Geovis course project for SA8905, Fall 2015 (Dr. Rinner)

Heatmap.js is a project developed by Patrick Wied to create heatmaps online using JSON data and javascript. It’s lightweight, free to use and comes with tons of great customization options.

For my geovisualization project for SA8905 I created an animated heat map of parking tickets issued in Toronto during the 24 hour period of May 1st 2014. Parking ticket data is supplied on the Toronto Open Data Portal.

Thursday May 1st, 2014 was one of the busiest days of the year for parking tickets. There were 9,559 issued in 24 hours. 6am was the safest time with only 25 tickets issued and 9am was the busiest with 1,451.

To create the heatmap I  geocoded the Toronto parking ticket data using the city of Toronto street data with address ranges. About 10% of the records had to be manually geocoded to intersections, which was a time consuming process! Once I had the locations, it was simple to create a JSON object for each hour in excel, like this:

var h=[ {
 max: 100000,
 data: [
{lat: 43.667229, lng: -79.382666, count: 1},
{lat: 43.728744, lng: -79.30461, count: 1},
{lat: 43.778933, lng: -79.418283, count: 1},
{lat: 43.647378, lng: -79.418484, count: 1},

etc…

h is an array where each element is a JSON object containing the lats and lngs of each traffic ticket. The count is required for the heatmapping function and is always 1, unless you’re this driver:

Using heatmap.js is super straightforward. Initialize your web map in leaflet or openlayers (I used leaflet), configure some simple parameters:

var cfg = {
 "radius": .008,           //set for interpolation radius
 "maxOpacity": .8,         //set to .8 to show the basedata
 "scaleRadius": true,      //recalibrate radius for zoom
 "useLocalExtrema": true,  //reset data maximum based on view
 latField: 'lat',          //where is latitude referenced 
 lngField: 'lng',          //where is longitude referenced
 valueField: 'count'       //where is the numerical field
 };

Attach that to your heatmap object and point it at your datasource like so:

heatmapLayer = new HeatmapOverlay(cfg);
map.addLayer(heatmapLayer);
i=0;
heatmapLayer.setData(h[i]);

Remember that h[] is the array where the ticket data is stored and so h[0] is the first hour of data, midnight to 1am. This will create a static heatmap like this:

Screenshot

Now comes the part where we cycle through the hours of data with a setInterval() function:

setInterval(function(){ 
 i+=1;
 if (i>23) i=0;
 $( ".heatmap-canvas" ).fadeOut( "slow", function() 
   {heatmapLayer.setData(h[i]);
   heatmapLayer._draw();
   $( "#hour").html(i);
 });
 $( ".heatmap-canvas" ).fadeIn( "slow", function() {
 });
}, 2000);

Every 2,000 milliseconds (2 seconds) the page will fade out the heatmap layer, switch the data for the next hour and fade it back in. If the cycle has reached the end of the day it resets. The $( “#hour”).html(i) bit refers to changing the hour printed on the webpage itself.

You can check out the finished project at http://justinpierre.ca/tools/heatmap/ and be sure to let me know what you think at https://twitter.com/jpierre001.