prettymaps
Librarymarceloprates/prettymaps
Draw pretty maps from OpenStreetMap data using matplotlib.
Overview
A minimal Python library for creating customized maps from OpenStreetMap data. Built on osmnx, matplotlib, and shapely, it supports layers, styles, and presets for generative art and cartography.
README Preview
# prettymaps\n\nA minimal Python library to draw customized maps from [OpenStreetMap](https://www.openstreetmap.org/#map=12/11.0733/106.3078) created using the [osmnx](https://github.com/gboeing/osmnx), [matplotlib](https://matplotlib.org/), [shapely](https://shapely.readthedocs.io/en/stable/index.html) and [vsketch](https://github.com/abey79/vsketch) packages.\n\n\n\n# [](https://marceloprates.github.io/prettymaps/) [](https://pypi.org/project/prettymaps/) [](https://www.python.org/) [](LICENSE)\n\n\nThis work is [licensed](LICENSE) under a GNU Affero General Public License v3.0 (you can make commercial use, distribute and modify this project, but must **disclose** the source code with the license and copyright notice)\n\n## Note about crediting and NFTs:\n- Please keep the printed message on the figures crediting my repository and OpenStreetMap ([mandatory by their license](https://www.openstreetmap.org/copyright)).\n- I am personally **against** NFTs for their [environmental impact](https://earth.org/nfts-environmental-impact/), the fact that they're a [giant money-laundering pyramid scheme](https://twitter.com/smdiehl/status/1445795667826208770) and the structural incentives they create for [theft](https://twitter.com/NFTtheft) in the open source and generative art communities.\n- **I do not authorize in any way this project to be used for selling NFTs**, although I cannot legally enforce it. **Respect the creator**.\n- The [AeternaCivitas](https://magiceden.io/marketplace/aeterna_civitas) and [geoartnft](https://www.geo-nft.com/) projects have used this work to sell NFTs and refused to credit it. See how they reacted after being exposed: [AeternaCivitas](https://github.com/marceloprates/prettymaps/raw/main/pictures/NFT_theft_AeternaCivitas.jpg), [geoartnft](https://github.com/marceloprates/prettymaps/raw/main/pictures/NFT_theft_geoart.jpg).\n- **I have closed my other generative art projects on Github and won't be sharing new ones as open source to protect me f
FAQ (5)
TroubleshootingHow to fix a blank SVG file when using `save_as` in prettymaps plotter mode?
This was a bug in prettymaps' plotter mode, not a problem with your plotting parameters. It was fixed in commit 3f3b8be. Update to a version containing that fix, then rerun the plot. In Google Colab, install the fixed version with:
!pip install git+https://github.com/marceloprates/prettymaps.git@3f3b8be
Restart the runtime if prompted, then run your code again, for example:
prettymaps.plot(..., mode='plotter', save_as='barcelona_plot.svg')
The generated SVG should no longer be blank.
TroubleshootingWhy does the first Prettymaps render take about 10 minutes while using almost no CPU?
The delay is caused by OSMnx waiting on the public Overpass API, which throttles requests. Enable logging with ox.config(log_file=True) and look for messages such as Pausing 56 seconds before making HTTP POST request. The first fetch is therefore network-bound, not CPU-bound. OSM responses are cached on disk, so subsequent renders of the same area should be much faster. Keep the cache between runs, update to a version containing the disk-cache fix, and reduce the map area or number of OSM layers to minimize Overpass requests.
TroubleshootingHow to fix missing river or water geometry when plotting a city by name in prettymaps?
This is caused by the geometry-perimeter intersection dropping OSM features that cross the named area's boundary. As a workaround, plot with coordinates and a radius instead of a place name:
plot((48.8534, 2.3397), radius=7000, ...)
To keep the named perimeter, patch get_geometries() in prettymaps/fetch.py. Replace:
geometries = geometries.intersection(perimeter)
with:
geometries = [geo.intersection(perimeter).buffer(0) for geo in geometries.geometry]
The .buffer(0) call repairs invalid intersection results and preserves multiple polygons. Alternatively, upgrade to a prettymaps release containing the fix tracked in issue #51 / the "Fix geometry-perimeter intersection" PR.
TroubleshootingHow do I prevent a Python package with many dependencies from breaking my existing Python installation?
Install the package inside an isolated virtual environment instead of your system Python. For venv, run: python3 -m venv .venv, then activate it with source .venv/bin/activate on Linux/macOS or .venv\Scripts\activate on Windows, and install the package with pip install <package-name>. With Conda, run: conda create -n myenv python=3.11 -y, then conda activate myenv, and install the package using pip install <package-name> or conda install <package-name>. This keeps dependency versions separate from your OS Python and avoids version conflicts.
TroubleshootingHow can I color bridges or specific OSM street tags differently without changing road width?
Plot the bridges as a separate layer and apply a per-layer style. For bridge structures, define a layer such as "bridge": {"tags": {"man_made": "bridge"}}. For bridge-tagged highway segments, use a separate road layer with a custom_filter that selects ways with bridge=yes. Give this layer a different color and higher zorder/z-height so it renders above the normal road layer, while leaving the base highway layer's width configuration unchanged. If the styling API requires explicit values, set the bridge layer to the same line-width mapping used by the road layer.