werthmuller.org

a dash of

Travel Maps

06 June 2015

My wife and I were recently tackling the overdue task of finishing some photo albums. I was hunting the web for a simple way to create easily some beautiful maps, showing where we have been. My hunt left me unsatisfied, so I dug out my old Basemap example, and tweaked it to yield the desired figures.

I created a travelmaps-function which adjusts some settings and provides the three functions country, city, and arrow. The settings consist of a tweaked version of the xkcd-style, the colour-cycle from Bayesian Methods for Hackers, and setting the figure.dpi and savefig.dpi to the same value, so the on-screen figures look like the saved pdfs.

The function country is an adapted version from a blogpost by Thomas Lecocq. It plots a country, or a list of countries, with given face- and edge-colours on a given basemap, where I got the country shapefiles from Global Administrative Areas (gadm.org).

The other two functions, city and arrow, are simply matplotlib-plot and -annotate functions, to plot cities and connect them with arrows.

In [1]:
import travelmaps as tm
from adashof import cm2in
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap

(You can find the two functions travelmaps and adashof in my GitHub repo.)

Global Map

This first example is a global map, where a number of countries is highlighted.

In [2]:
fig_g = plt.figure(figsize=(cm2in([12, 8])))

# Create basemap
m_g = Basemap(resolution='i', projection='robin', lon_0=0)

# Make continents grey, and oceans slighty blue
m_g.drawlsmask(land_color='.8', ocean_color='#f7fbff')
m_g.drawcoastlines(color='.8', linewidth=.1)
m_g.drawcountries(color='.8', linewidth=.1)

# Fill visited countries
countries = ['CHN', 'CHE', 'DNK', 'TUR', 'MEX', 'HUN', 'ISL', 'BGR', 'GRC', 'FRA',
             'SVK', 'NOR', 'CZE', 'AUT', 'DEU', 'GBR', 'MAR', 'SRB', 'USA',]
tm.country(countries, m_g)

#plt.savefig('plots/World.png', bbox_inches='tight', pad_inches=0.02)

plt.show()

East Europe Trip

The second example is a local map with several visited countries. Here, the drawlsmask and drawcountries functions of basemap do not yield a satisfying result. I therefore plot the visited as well as the not visited countries with tm.countries, the former in colour and the latter grey.

In [3]:
fig_e = plt.figure(figsize=(cm2in([8, 8])))

# Cities
BUD = [47.4925, 19.051389]   # Budapest
SOF = [42.7, 23.333333]      # Sofia
IST = [41.013611, 28.955]    # Istanbul
PRA = [50.083333, 14.416667] # Prague
BEL = [44.816667, 20.466667] # Belgrade
DRE = [51.033333, 13.733333] # Dresden
BER = [52.516667, 13.383333] # Berlin

# Create basemap
m_e = Basemap(width=2200000, height=2200000, resolution='c',
              projection='tmerc', lat_0=BUD[0], lon_0=BEL[1])

# Fill non-visited countries (fillcontinents does an unsatisfying job)
countries = ['AUT', 'CHE', 'FRA', 'DNK', 'SVK', 'GRC', 'ALB',
             'ITA', 'LIE', 'POL', 'ROU', 'SVN', 'BEL', 'HRV',
             'TUN', 'NLD', 'RUS', 'SWE', 'LUX', 'BLR', 'LTU',
             'EST', 'LVA', 'UKR', 'MDA', 'DZA', 'BIH', 'KO-',
             'MKD', 'MNE',]
tm.country(countries, m_e, fc='.8', ec='.5', lw=.2)

# Fill visited countries
visited = ['TUR', 'BGR', 'SRB', 'HUN', 'CZE', 'DEU',]
tm.country(visited, m_e, ec='b', lw=.5)

# Add cities
offs = [0, .4]
tm.city(BER, 'Berlin', m_e, offs=offs)
tm.city(DRE, 'Dresden', m_e, offs=offs)
tm.city(PRA, 'Prague', m_e, offs=offs)
tm.city(IST, 'Istanbul', m_e, offs=offs)
tm.city(BEL, 'Belgrade', m_e, offs=offs)
tm.city(SOF, 'Sofia', m_e, offs=offs)
tm.city(BUD, 'Budapest', m_e, offs=offs)

# Connect with arrows
tm.arrow(IST, SOF, m_e)
tm.arrow(SOF, BEL, m_e)
tm.arrow(BEL, BUD, m_e)
tm.arrow(BUD, PRA, m_e)
tm.arrow(PRA, DRE, m_e)
tm.arrow(DRE, BER, m_e)

#plt.savefig('plots/EastEurope.png', bbox_inches='tight', pad_inches=0.02)

plt.show()

Scotland

This last examples is another local map one, with only one country this time.

In [4]:
fig_s = plt.figure(figsize=(cm2in([8, 8])))

# Cities
EDI = [55.953056, -3.188889] # Edinburgh
JOG = [58.64, -3.07]         # John o' Groats
ABD = [57.1526, -2.11]       # Aberdeen
INV = [57.4718, -4.2254]     # Inverness
SCR = [58.609722, -3.5525]   # Scrabster
STR = [58.96, -3.3]          # Stromness
ULL = [57.9, -5.166]         # Ullapool
STO = [58.209, -6.387]       # Stornoway
TAR = [57.897749, -6.800595] # Tarbert
UIG = [57.586, -6.357]       # Uig
EID = [57.274028, -5.516111] # Eilean Donan

# Create basemap
m_s = Basemap(width=500000, height=500000, resolution='c',
              projection='tmerc', lat_0=57.65, lon_0=-4.5)

# Fill country
tm.country('GBR', m_s, fc='g', ec='b', lw=.1)

# Add cities
tm.city(EDI, 'Edinburgh', m_s)
tm.city(ABD, 'Aberdeen', m_s)
tm.city(JOG, "John o' Groats", m_s)
tm.city(SCR, '', m_s, halign='right')
tm.city(STR, 'Orkney Islands', m_s, halign='right')
tm.city(ULL, 'Ullapool', m_s)
tm.city(STO, '', m_s)
tm.city(TAR, 'Outer Hebrides', m_s, offs=[-.4, .1], halign='center')
tm.city(UIG, '', m_s)
tm.city(EID, 'Eilean Donan', m_s, offs=[.1, -.2], halign='right')

# Connect with arrows
tm.arrow(EDI, ABD, m_s, fc='r')
tm.arrow(ABD, JOG, m_s, fc='r', rad=-1.2)
tm.arrow(JOG, SCR, m_s, fc='r')
tm.arrow(SCR, STR, m_s, fc='r', rad=.4)
tm.arrow(STR, SCR, m_s, fc='r', rad=.4)
tm.arrow(SCR, ULL, m_s, fc='r', rad=.5)
tm.arrow(ULL, STO, m_s, fc='r')
tm.arrow(STO, TAR, m_s, fc='r', rad=.5)
tm.arrow(TAR, UIG, m_s, fc='r')
tm.arrow(UIG, EID, m_s, fc='r', rad=.3)
tm.arrow(EID, EDI, m_s, fc='r', rad=.3)

#plt.savefig('plots/Scotland.png', bbox_inches='tight', pad_inches=0.02)
    
plt.show()

These are just three examples to show the possibilities. You can find the complete notebooks travelmaps.ipynb and Travel.ipynb with more examples on my GitHub page in the blog-notebooks-repo.