Tag Maps rendering with Python and Mapnik

Alexander Dunkel, TU Dresden; Institute of Cartography

TL;DR This notebook illustrates the process for rendering of tag maps shapefiles in Mapnik. This notebook can be run with the jupyter docker for cartography (docker tag jupyterlab:mapnik), which contains the stable Mapnik installation and Python bindings, but must be accessed through the system Python installation (/usr/bin/python3), not the conda environment.

The source files for this notebook are available in https://gitlab.vgiscience.de/ad/tagmaps-mapnik-jupyter.

•••
Out[1]:

Last updated: Jul-29-2022

Preparations

Import dependencies

In [68]:
import sys
import math
import fiona
import rasterio
import numpy as np
import contextily as cx
import mapclassify as mc
import libpysal as lps
from IPython import display
from contextily import Place
from typing import Tuple, Optional
from rasterio.plot import show as rioshow
from pathlib import Path
from esda.getisord import G_Local
from shapely.geometry import shape

We are using a number of helper functions from py/modules/tools.py to classify values.

In [3]:
module_path = str(Path.cwd().parents[0] / "py")
if module_path not in sys.path:
    sys.path.append(module_path)
from modules import tools
In [4]:
%load_ext autoreload
%autoreload 2

Test Mapnik bindings

In [5]:
!/usr/bin/python3 -c "import mapnik;print(mapnik.__file__)"
/usr/lib/python3/dist-packages/mapnik/__init__.py

Global Parameters

Some parameters are used throughout this notebook. Adjust to your needs.

In [6]:
INPUT: Path = Path.cwd().parents[0] / "input" # define path to input and working directory (shapefiles, stylesheets etc.)
OUTPUT: Path = Path.cwd().parents[0] / "output" # define path to output directory (map, notebook html etc.)
TMP: Path = INPUT / "intermediate"
MAP_X: int = 2500 # x dimensions of the final map, in pixels
MAP_Y: int = 1400 # y dimensions of the final map, in pixels
In [61]:
for folder in [OUTPUT, TMP]:
    if not folder.exists():
        folder.mkdir()

Test creating a map

  • Data source: Shapefiles in input/shapefiles, created using TagMaps
    • Original data from Flickr, Twitter and Instagram for the TUD Campus
    • Clustered and aggregated to illustrate collective use of terms (allTagCluster.shp)
    • and overall frequentation of places in the area (allLocationCluster.shp)
  • see this notebook for how to generate these files
  • A mapnik stylesheet input/tagmap_style.xml, containing the style information for how the data should be rendered
  • A python script input/tagmap_xml.py, using Mapnik Python bindings to process data and generate the map

The mapnik renderer can be accessed through Python bindings, available in the system python installation. Below, we use a python script that provides specific instructions to render a map in Mapnik.

In [157]:
%%time
!cd {INPUT} && /usr/bin/python3 tagmap_xml.py
CPU times: user 2.98 s, sys: 1.32 s, total: 4.29 s
Wall time: 2min 27s

Load the generated image to jupyter

In [158]:
display.Image(f"{OUTPUT}/tagmap_style.png")
Out[158]: