Creating your own custom maps

Other Ways to Find and Map Places

Figure 5 shows another map that I created by just copying, and executing without any change, another code sample found on the prettymaps homepage. I am including it here because, besides showing how different these maps can be from each other at the purely visual level, it uses another OSM feature that is worth knowing. The map shows the Lagoa dos Patos in Brazil, and Listing 2 shows the relevant parts of the prettymaps script that generates it.

Figure 5: For this example, a very different map, showing just the physical contours of a geographic object (Lagoa dos Patos, Brazil).

Listing 2

Finding Places by Their OSM Identifier

01  fig, ax = plt.subplots(figsize = (10, 12), constrained_layout = True)
02
03  def postprocessing(layers):
04  layers['perimeter'] = layers['perimeter'].buffer(2000)
05  return layers
06
07  layers = plot(
08  'R2709093',
09   ...
10  postprocessing = postprocessing,
11
12  drawing_kwargs = {
13  'perimeter': {'fill': False, 'ec': '#6da8c2', 'lw': 2, 'zorder': 3},
14  },
15
16  osm_credit = {'x': -.08, 'y': .02, 'color': '#2F3737'}
17  )
18
19  # Set bounds
20  xmin, xmax = ax.get_xlim()
21  ymin, ymax = ax.get_ylim()
22  dx, dy = xmax-xmin, ymax-ymin
23  ax.set_xlim(xmin+.15*dx, xmax-.15*dx)
24  ax.set_ylim(ymin+.0*dy, ymax-.0*dy)

Figure 6 is what the same lagoon looks like inside OpenStreetMap, plus the unique numeric identifier. Inside the OSM database, each "object" has a unique numeric identifier that is visible in the online map when you select that object. As you can see comparing Figure 6 with line 8 of Listing 2, you can use that identifier to directly define places in prettymaps! This capability may be very useful if you start using prettymaps to generate many maps of many places, maybe fetching their identifiers with some other script.

Figure 6: Lagoa dos Patos shown in Figure 5, as seen in OpenStreetMap with its numeric identifier.

Other relevant parts of Listing 2 are lines 4 and 13, which process the perimeter of the map in a different way than Listing 1, and the final six lines, which set the borders of the drawing to make sure that no part of the lagoon is cut off the map. To see in detail how those instruction work, download that example and try to change the numeric constants in lines 23 and 24.

As final proof of the great versatility of prettymaps, check out Figure 7, which was generated from another code sample found on the website. Figure 7 shows a map of three adjacent neighborhoods of the city of Porto Alegre, Brazil (Figure 8), and nothing else. What's more, each neighborhood is painted with different colors.

Figure 7: Drawing adjacent neighborhoods, each with its own style, only takes a little extra effort.
Figure 8: The neighborhoods shown in Figure 7 as they appear in the standard OpenStreetMap view.

The code excerpt in Listing 3 shows how to obtain this result. To begin with, you must define a hash, an associative array in which each element is associated with a key. In Listing 3, that hash is called places (lines 4 to 8). Each line of that array is about one of the places that should be drawn. More specifically, each line defines a list of colors, in the same format described before, associated with a key that is the name of a neighborhood to fetch from OpenStreetMap and then draw. Then, you must wrap the same calls to the plot and drawing_kwargs functions of the previous example in one loop (line 10) that handles one neighborhood at a time. This happens because every iteration of that loop loads one key from the places array, calling it place, and loads the corresponding list of colors into an auxiliary variable called palette. Then, as you can see in lines 12 and 17, each call to plot and drawing_kwargs uses the place name and colors that are currently loaded into those two variables. The autoscale function in the last line ensures, with a different method than that used by Listing 2, that the whole drawing will fit in the image.

Listing 3

Mapping Adjacent Places in Different Styles

01 fig, ax = plt.subplots(figsize = (15, 12), constrained_layout = True)
02 fig.patch.set_facecolor('#F9F8F8')
03
04 places = {
05 - 'Farroupilha, Porto Alegre': ['#EEE4E1', '#E7D8C9', '#E6BEAE'],
06 - 'Cidade Baixa, Porto Alegre': ['#49392C', '#77625C', '#B2B1CF', '#E1F2FE', '#98D2EB'],
07 - 'Bom Fim, Porto Alegre': ['#BA2D0B', '#D5F2E3', '#73BA9B', '#F79D5C'],
08 }
09
10 for i, (place, palette) in enumerate(places.items()):
11 plot(
12 place,
13 ...
14 drawing_kwargs = {
15   'perimeter': {'fill': False, 'lw': 0, 'zorder': 0},
16   'streets': {'fc': '#F1E6D0', 'ec': '#2F3737', 'lw': 1.5, 'zorder': 3},
17   'building': {'palette': palette, 'ec': '#2F3737', 'lw': 1, 'zorder': 4},
18 },
19
20 )
21
22 ax.autoscale()

Try prettymaps!

The examples I have presented are enough to generate thousands of maps, each with a distinct style, with very little effort once you have installed prettymaps and all its dependencies. What's more, you may use Matplotlib's capabilities to add both captions [13] and generic images [14] to all your maps, for any conceivable purpose. It would then be quite easy, for example, to create infographics that show different maps, each associated to charts generated from some statistical data about the same area. Isn't free software wonderful?

The Author

Marco Fioretti (http://mfioretti.com) is a freelance author, trainer, and researcher based in Rome, Italy. He has been working with free/open source software since 1995 and on open digital standards since 2005. Marco also is a Board Member of the Free Knowledge Institute (http://freeknowledge.eu), and blogs about digital rights at https://stop.zona-m.net.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News