charts
Recent British Earthquakes

August 2014

I've been meaning to create a cartographic visualisation for a while now and I wanted to make something with relevance to my home island, Jersey. After coming across the British Geological Survey's website I thought it'd be fun to create a map showing the last 50 earthquakes in the British Isles. As Jersey had just experienced a 4.3 magnitude quake this seemed like the perfect project.


Tech

DataMaps is a library built on top of D3.js, purely for drawing maps, and is very easy to use, so kudos to author @markmarkoh. Getting the relevant map vectors however, provided the steepest learning curve for this project. Mike Bostock has written a great tutorial on installing gdal and topojson, tools needed to manipulate cartographic vector data into a format that we can use with d3.js/Datamaps. Using the 1:10m cultural files, downloaded from Natural Earth, I selected paths of British and Irish sovereignty (granted this also means that territories such as the Falkland islands are included too, but it's no biggy as the final file size is very small and, due to the zoom level of the map, they can't be seen anyway).

 
ogr2ogr \  
-f GeoJSON \
-where "sov_a3 IN ('GB1', 'IRL')" \
britishIsles.json \
ne_10m_admin_0_map_subunits.shp
topojson \  
--id-property adm0_a3 \
-o britishIsles.topo.json \
britishIsles.json

The javascript for plotting the map itself is pretty straight forward. With the correct libraries referenced and using the newly minted britishIsles.topo.json file, I just needed to do the following:

var map = new Datamap({
	element: document.getElementById('map'),
	geographyConfig: {
		dataUrl: 'british-earthquakes/britishIsles.topo.json',
		popupOnHover: false,
		highlightOnHover: false
	},
	scope: 'britishIsles',
	fills: {
		defaultFill: '#6E9489',
		quakeBubble: '#A7EBCA'
	},
	data: {
		'IRL': {
			fillKey: '#bada55'
		}
	},
	setProjection: function(element) {
		var projection = d3.geo.mercator()
			.center([-3.92, 53.16])
			.scale(2200)
			.translate([element.offsetWidth / 2, element.offsetHeight / 2]);
		var path = d3.geo.path().projection(projection);
		return {
			path: path,
			projection: projection
		};
	}
});

Querying the Earthquake Data

The British Geological Survey post a table of the 50 most recent earthquakes in the British Isles. I used import.io to create an extractor to scrape this data from their website; using import.io's api I was then able to programatically retrieve this data as a json object. This is such a great (and free) service for data scientists needing to grab stuff from the structured web, I can't recommend it enough and thoroughly encourage you to give them a go.

With the earthquake data safely in the browser all that's left to do is to plot a 'bubble' for each quake. There is a bubbles plugin for DataMaps which takes care of this; we just need to make sure that we supply a latitude, longitude and size of bubble. I've used the magnitude for the size, initially setting it to:

'radius': Math.pow(10, d.mag_number)

to replicate the logarithmic scale used in the Richter scale (well Seismic moment, really). The huge dynamic range in bubbles meant that (depending on the scaling I chose) the small quakes were invisible or the larger ones took up the whole map. I didn't want to use a linear scale, as it doesn't give such a good feeling as to the relative severities between earthquakes, so after having a play with different formulae I settled on cubing the magnitude:

'radius': Math.pow(d.mag_number, 3)

which works beter, visually. Hover behaviour is baked into the bubble plugin and it's very easy to take values from the dataset and create a popup.

var bubblesConfig = {
	borderWidth: 1,
	strokeWidth: 1,
	borderColor: '#848484',
	popupOnHover: true,
	popupTemplate: function(geography, data) {
		var comment = data.comment || 'n/a';
		return '<div class="hoverinfo"><i>Magnitude : <strong>' + data.magnitude + '</strong></i><br/>' +
			'<i>Depth : </i><strong>' + data.depth + 'km</strong></i><br/>' +
			'<i>Date : </i><strong>' + data.date + ', ' + data.time + '</strong></i><br/>' +
			'<i>Comment : </i><strong>' + comment.replace('...', '') + '</strong></div>';
	},
	fillOpacity: 0.65,
	highlightOnHover: true,
	highlightFillColor: '#6E6E6E',
	highlightBorderColor: '#848484',
	highlightBorderWidth: 1,
	highlightFillOpacity: 0.85
};
map.bubbles(quakes, bubblesConfig);
Update (26 Sep 2014)

I've been having problems with the import.io api call when dynamically getting the quake data, and it only works consitently in chrome. For the time being I have fallen back to using static quake data so that there is still a visualisation to look at.

Please enable JavaScript to view the comments powered by Disqus.