Isochrones are concentric and connected shapes which show all of the locations reachable from a central point given an amount of travel time. If not for terrain and for transportation networks, those shapes would be circular. But in cities, they tend to stretch along the primary networks of travel. At any given time of day, an isochrone will show how far in every direction a person could travel from any single place. When isochrones are created at different times of the day and compared, the contraction of a single ischrone shows that a shorter distance can be traveled in the same amount of time, usually as a result of traffic volumes.

Atlas Obscura recently wrote about a resurgence in isochrone mapping, partially due to an increase in the availability of traffic data in urban areas./

There are several tutorials on how to create an animated isochrone map, like the one I created in Dublin below.

I followed this tutorial from the blog Digital Geography which uses the Here travel times API, Python, and QGIS + the Time Manager plugin to create a gif.

Here is the Python codeI used to create the isochrones. Follow the instructions in the previous link to get your own HERE id codes and plug them into the following code. The location corresponds to Trinity College front gate on College Green.

from PyQt4.QtCore import *
import urllib2, json
appcode ="your code from HERE"
appID = "your id from HERE"
 
coordinates = "52.471868,-1.897253"
"#create the containing layer:"
vl = QgsVectorLayer("Polygon?crs=EPSG:102013", "temporary_polygons", "memory")
pr = vl.dataProvider()
# add fields
pr.addAttributes([QgsField("time", QVariant.Int),
                 QgsField("departure", QVariant.String),
                 QgsField("area", QVariant.Double)])
vl.updateFields()
#let's define some projection magic to get equal area:
 
src_crs = QgsCoordinateReferenceSystem(4326)
dest_crs = QgsCoordinateReferenceSystem(102013)
xform = QgsCoordinateTransform(src_crs, dest_crs)
 
#iterate through the times:
for hour in range(0,24):
     for halfhrs in (0,3):
         if hour<10:
                 timestamp='2018-02-01T0' + str(hour) + ':'+str(halfhrs)+'0:00Z01'
         else:
                 timestamp='2018-02-01T' + str(hour) + ':'+str(halfhrs)+'0:00Z01'
         print('timestamp: '+timestamp)
         url = "https://isoline.route.cit.api.here.com/routing/7.2/calculateisoline.json?app_id=" + appID + "&app_code=" + appcode + "&mode=shortest;car;traffic:enabled&start=geo!" + coordinates + "&maxpoints=500&departure=" + timestamp + "&range=600,1200,1800&rangetype=time&jsonAttributes=41"
         response = urllib2.urlopen(url)
         data = json.load(response)
         print("data: "+str(data))
         #parse the polys:
         for polygon in reversed(data['response']['isoline']):
             pointArray = []
             for ind in range(0,len(polygon['component'][0]['shape'])):
                 if ind%2 == 1:
                     pointArray.append(xform.transform(QgsPoint(polygon['component'][0]['shape'][ind], polygon['component'][0]['shape'][ind-1])))
             #combine to polygon:
             feature = QgsFeature()
             feature.setGeometry(QgsGeometry.fromPolygon([pointArray]))
             feature.setAttributes([polygon['range'], timestamp[0:16], feature.geometry().area()/1000000])
             pr.addFeatures([feature])
 
QgsMapLayerRegistry.instance().addMapLayer(vl)