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.

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

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.
Draw a rectangle that corresponds to the area we want to clip. Select the rectangle and the object we want to clip (by holding down Shift). Right click anywhere and click “Set clip…”. Voila! Note that the text under the map here was made in the same way, I copied/duplicated the original map with text. Then used rectangles and “Set clip…” to clip both the map and the text under the map. Thus doing the same for the text under the map on a copy/duplicate of the original map with text we get two objects. One object with text and one with the map. Selecting both the text and the map, and then pressing Ctrl+G will group the two objects into one (to ungroup and edit things, press Ctrl+Shift+G).
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.

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.
Leave a Reply