Since my wife and I moved a bit over the last 10 years I thought about us having these prints to hang on the walls of our current apartment. The idea would be to have one for each city we lived in. These things are popular, and nice. The classic example is the square-mile street network visualization. Numerous posters are for sale showing the street networks of some famous cities in the world.

Square-Mile Street Network Visualization

The page above links to this Jupyter Notebook showing how to do it with OSMnx in Python. So I set about to create a script that produces something nice for me to work with.

A close-up of one early draft of the street map print.

OSMnx Python script

After some experimentation, late night printing-parties I converged at the solution below. I thought it strikes a nice balance between information and art. It is easy to tweak the amount of paths shown by changing the input network_type to ox.plot_figure_ground from 'all' to e.g. 'drive'. This might be preferable if you zoom out even more, using the dist keyword. Anyway, here is the code that I used (in a Jupyter Notebook I might add).

# this is Jupyter-Lab example Python code
# if you run it in Python just remove "%matplotlib inline"
# and add "plt.ion()" after all the imports.
%matplotlib inline 
import osmnx as ox
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np 
from math import *
ox.config(log_file=True, log_console=True, use_cache=True)


def dec2dms(degrees, prettify=True):
    # Convert between decimal degree and 
    # degrees, minutes and seconds (sexadecimal).
    if type(degrees) != 'float':
        try:
            deg = float(degrees)
        except:
            print( '\nERROR: Could not convert {0} to     float.'.format(type(degrees)) ) 
    minutes = degrees%1.0*60
    seconds = minutes%1.0*60
    if prettify:
        return '\n{0:d}°{1:d}\'{2:.2f}"\n'.format( int(floor(degrees)), int(floor(minutes)), seconds )
    else:
        return int(floor(degrees)), int(floor(minutes)), seconds

# customize the line thickness
street_widths = {'footway' : 0.5,
                 'steps' : 0.5,
                 'pedestrian' : 0.5,
                 'path' : 0.5,
                 'track' : 0.5,
                 'service' : 1,
                 'residential' : 2,
                 'primary' : 2,
                 'motorway' : 3,
                 'highway' : 3}

# From here and below is what you change for each 
# street map plot
place = 'Leiden, The Netherlands'
home_coords = [52.15876, 4.49599]

map_settings = dict(
    dist=2500,
    edge_color='k',
    bgcolor='w',
    dpi = 1200,
    point = (52.1597, 4.4923),
    default_width=1,
)

# This is what plots the street network
fig, ax = ox.plot_figure_ground(network_type='all', 
                                street_widths=street_widths, 
                                 **map_settings)

# Put a red dot somewhere interesting
home_lat, home_lon = home_coords
ax.plot(home_lon, home_lat, marker='o', markersize=10, alpha=1, color='#CC3344', zorder=5 )

# Now print out the name and the coordinates of the city
# the font Comfortaa is a Google font available here
# https://fonts.google.com/specimen/Comfortaa
fntprop_coord = mpl.font_manager.FontProperties(family='Comfortaa', size=12)

an1 = ax.annotate("{0[0]:02d}°{0[1]:02d}\'{0[2]:02.0f}\"N {1[0]:03d}°E {1[1]:02d}\'{1[2]:02.0f}\" ".format(dec2dms(home_coords[0], prettify=False), dec2dms(home_coords[1], prettify=False) ), 
            xy=(0.322,0.1),xycoords='figure fraction', 
            ha="center", va='center',
            xytext=(0.5,0.1),textcoords='figure fraction',
            fontproperties=fntprop_coord,
           )

fntprop_name = mpl.font_manager.FontProperties(family='Comfortaa', variant='small-caps', size=30)

an1 = ax.annotate(place, 
            xy=(0.322,0.08),xycoords='figure fraction', 
            ha="center", va='top',
            xytext=(0.5,0.08),textcoords='figure fraction',
            #arrowprops=dict(arrowstyle="]-"),
            fontproperties=fntprop_name,
           )

# the aspect ratio of the figure need to be 1/cosine(latitude)
coslat = np.cos(np.cos(map_settings['point'][1] / 180. * np.pi) )
ax.set_aspect(1/coslat)

fig.set_figwidth(7)
# save the figure in the 'images' folder
fig.savefig('images/leiden.png')
fig
During a few years we lived in the fairly small town of Leiden in The Netherlands. Great beer, fries and friends!

Multiple cities design – Inkscape

After doing this for a few more places we lived. I went into my favorite vector drawing program Inkscape to arrange everything. Once open, Ctrl+Shift+D opens up the Document Properties, click “A4” (or “Letter” if that is your thing). Remember to save the document regularly to not loose any work if something happens.

Now we can edit and align all of the maps we created. Guidelines are toggled with Alt+\, to define them you click+drag from the ruler at the top or left of the drawing area, resulting in blue guides which objects can snap to and make aligning things easier for you. I aligned the prettified maps in a 3×2 grid. Of course, if you want one single big map, just do that (and change document size to whatever you are printing on). The results for me looked like the following image.

After arranging all the maps and texts for the cities/places I wanted, I arranged them in a 3×2 grid. This is now how it will look like on our paper after printing it.

Frame and final results

So now I was ready to print this. I went and bought some nice thick paper, like 180 gram A4, a bit off-white in color. I also went to IKEA and bought a frame (IKEA FORNBRO), the frame is just two sheets of plexi-glass kept together with four screws, it was less than 10 Euros.

Now just pop the printed paper in the frame and you are done! I am pretty happy with the final results. The information/art balance is perhaps a bit information-heavy, so I plan to buy some A3 paper at some point and try to just do one city, but in a large format.

Future outlook – wish list

One of the next steps/ideas I had was to do street network orientation plots (like this and the original academic paper) for these very same cities in a frame next to this.