Compare commits
20 Commits
5ffe050926
...
8860499ecf
Author | SHA1 | Date | |
---|---|---|---|
|
8860499ecf | ||
|
8e156e37b4 | ||
|
20858a6f58 | ||
|
d2bbf1083a | ||
|
d2d31dd803 | ||
|
0f02bc4a06 | ||
|
d17dc7d6e0 | ||
|
4208670245 | ||
|
5dd7297200 | ||
|
f81b319526 | ||
|
a78d82b05b | ||
|
971d7c55a0 | ||
|
6ad5994f67 | ||
|
e6824b23b7 | ||
|
ee685987c8 | ||
|
15415b6956 | ||
|
12db1d59c7 | ||
|
80e61c8c77 | ||
|
dc2090cab7 | ||
|
91e8fc7a36 |
21
.github/workflows/docs.yml
vendored
@@ -1,4 +1,8 @@
|
||||
name: Deploy Docs
|
||||
# Deploy Docs to GitHub Pages using MkDocs
|
||||
# This workflow builds documentation from the 'docs/' folder using mkdocs.yml in the repo root
|
||||
# and deploys the static site to GitHub Pages.
|
||||
|
||||
name: Build and Deploy Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -6,7 +10,7 @@ on:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
build-and-deploy-docs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -14,12 +18,23 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
# Ensure mkdocs.yml exists in the repo root
|
||||
- name: Check for mkdocs.yml in root
|
||||
run: |
|
||||
if [ ! -f mkdocs.yml ]; then
|
||||
echo "Error: mkdocs.yml not found in repository root. Please add it." && exit 1
|
||||
fi
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -r docs/requirements.txt
|
||||
- name: Build docs
|
||||
- name: Build docs with MkDocs
|
||||
run: |
|
||||
mkdocs build
|
||||
- name: List files after build
|
||||
run: |
|
||||
pwd
|
||||
ls -l
|
||||
ls -l site || true
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
|
2
.github/workflows/generate-readme.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
|
||||
- name: Execute the notebook (run all cells)
|
||||
run: |
|
||||
jupyter nbconvert --to notebook --execute notebooks/examples.ipynb --output notebooks/examples.ipynb
|
||||
jupyter nbconvert --to notebook --execute notebooks/examples.ipynb --output examples.ipynb --output-dir notebooks
|
||||
|
||||
- name: Run notebooks_to_readme.sh
|
||||
run: |
|
||||
|
77
README.md
@@ -2,7 +2,9 @@
|
||||
|
||||
A 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.
|
||||
|
||||

|
||||

|
||||
|
||||
# [](https://marceloprates.github.io/prettymaps/) [](https://pypi.org/project/prettymaps/) [](https://www.python.org/) [](LICENSE)
|
||||
|
||||
|
||||
This 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)
|
||||
@@ -17,8 +19,7 @@ This work is [licensed](LICENSE) under a GNU Affero General Public License v3.0
|
||||
<a href='https://ko-fi.com/marceloprates_' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://cdn.ko-fi.com/cdn/kofi1.png?v=3' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
||||
|
||||
## As seen on [Hacker News](https://web.archive.org/web/20210825160918/https://news.ycombinator.com/news):
|
||||

|
||||
|
||||

|
||||
## [prettymaps subreddit](https://www.reddit.com/r/prettymaps_/)
|
||||
## [Google Colaboratory Demo](https://colab.research.google.com/github/marceloprates/prettymaps/blob/master/notebooks/examples.ipynb)
|
||||
|
||||
@@ -70,7 +71,7 @@ import prettymaps
|
||||
plot = prettymaps.plot('Stad van de Zon, Heerhugowaard, Netherlands')
|
||||
```
|
||||
|
||||
Fetching geodataframes took 2.04 seconds
|
||||
Fetching geodataframes took 13.76 seconds
|
||||
|
||||
|
||||
|
||||
@@ -93,7 +94,7 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 0.81 seconds
|
||||
Fetching geodataframes took 4.71 seconds
|
||||
|
||||
|
||||
|
||||
@@ -185,21 +186,11 @@ prettymaps.presets()
|
||||
</tr>
|
||||
<tr>
|
||||
<th>8</th>
|
||||
<td>my-preset</td>
|
||||
<td>{'layers': {'building': {'tags': {'building': ...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>9</th>
|
||||
<td>plotter</td>
|
||||
<td>{'layers': {'perimeter': {}, 'streets': {'widt...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>10</th>
|
||||
<td>pytest-temp-preset</td>
|
||||
<td>{'layers': {'building': {'tags': {'building': ...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>11</th>
|
||||
<th>9</th>
|
||||
<td>tijuca</td>
|
||||
<td>{'layers': {'perimeter': {}, 'streets': {'widt...</td>
|
||||
</tr>
|
||||
@@ -378,7 +369,7 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 15.97 seconds
|
||||
Fetching geodataframes took 28.29 seconds
|
||||
|
||||
|
||||
|
||||
@@ -402,7 +393,7 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 1.28 seconds
|
||||
Fetching geodataframes took 10.83 seconds
|
||||
|
||||
|
||||
|
||||
@@ -422,7 +413,7 @@ plot = prettymaps.plot('Centro Histórico, Porto Alegre', show = False)
|
||||
plot.geodataframes['building']
|
||||
```
|
||||
|
||||
Fetching geodataframes took 1.59 seconds
|
||||
Fetching geodataframes took 11.94 seconds
|
||||
|
||||
|
||||
|
||||
@@ -750,7 +741,7 @@ plot.geodataframes['building'][
|
||||
].geometry[0]
|
||||
```
|
||||
|
||||
/opt/anaconda3/envs/prettymaps/lib/python3.11/site-packages/geopandas/geoseries.py:648: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
|
||||
/opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/geopandas/geoseries.py:648: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]`
|
||||
val = getattr(super(), mtd)(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -797,7 +788,7 @@ for ax,building in zip(np.concatenate(axes),buildings):
|
||||
ax.autoscale(); ax.axis('off'); ax.axis('equal')
|
||||
```
|
||||
|
||||
Fetching geodataframes took 2.01 seconds
|
||||
Fetching geodataframes took 12.50 seconds
|
||||
|
||||
|
||||
|
||||
@@ -828,7 +819,7 @@ _ = plot.ax.set_title(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 3.78 seconds
|
||||
Fetching geodataframes took 12.74 seconds
|
||||
|
||||
|
||||
Use **plotter** mode to export a pen plotter-compatible SVG (thanks to abey79's amazing [vsketch](https://github.com/abey79/vsketch) library)
|
||||
@@ -847,7 +838,7 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 3.89 seconds
|
||||
Fetching geodataframes took 3.91 seconds
|
||||
|
||||
|
||||
|
||||
@@ -871,7 +862,7 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 16.55 seconds
|
||||
Fetching geodataframes took 26.94 seconds
|
||||
|
||||
|
||||
|
||||
@@ -972,14 +963,18 @@ plot = prettymaps.multiplot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 0.97 seconds
|
||||
Fetching geodataframes took 1.15 seconds
|
||||
Fetching geodataframes took 0.79 seconds
|
||||
Fetching geodataframes took 8.62 seconds
|
||||
|
||||
|
||||
Fetching geodataframes took 5.93 seconds
|
||||
|
||||
|
||||
Fetching geodataframes took 8.74 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -1002,15 +997,29 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 24.92 seconds
|
||||
Fetching geodataframes took 47.61 seconds
|
||||
|
||||
|
||||
make: Entering directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
curl -s -o spool/N21/N21W158.hgt.gz.temp https://s3.amazonaws.com/elevation-tiles-prod/skadi/N21/N21W158.hgt.gz && mv spool/N21/N21W158.hgt.gz.temp spool/N21/N21W158.hgt.gz
|
||||
|
||||
|
||||
gunzip spool/N21/N21W158.hgt.gz 2>/dev/null || touch spool/N21/N21W158.hgt
|
||||
gdal_translate -q -co TILED=YES -co COMPRESS=DEFLATE -co ZLEVEL=9 -co PREDICTOR=2 spool/N21/N21W158.hgt cache/N21/N21W158.tif 2>/dev/null || touch cache/N21/N21W158.tif
|
||||
|
||||
|
||||
rm spool/N21/N21W158.hgt
|
||||
make: Leaving directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
make: Entering directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
gdalbuildvrt -q -overwrite SRTM1.vrt cache/N21/N21W158.tif
|
||||
cp SRTM1.vrt SRTM1.5af18c5270144c688522a27abf3b23a0.vrt
|
||||
gdal_translate -q -co TILED=YES -co COMPRESS=DEFLATE -co ZLEVEL=9 -co PREDICTOR=2 -projwin -157.90125854957773 21.364471426268274 -157.81006761682832 21.244615177105377 SRTM1.5af18c5270144c688522a27abf3b23a0.vrt /Users/marceloprates/Projects/Art/07_Data_Visualization_and_Maps/prettymaps/notebooks/elevation.tif
|
||||
rm -f SRTM1.5af18c5270144c688522a27abf3b23a0.vrt
|
||||
make: Leaving directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
make: Entering directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
cp SRTM1.vrt SRTM1.286507e05dd14c97a364976914d44158.vrt
|
||||
make: Leaving directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
make: Entering directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
gdal_translate -q -co TILED=YES -co COMPRESS=DEFLATE -co ZLEVEL=9 -co PREDICTOR=2 -projwin -157.90125854957773 21.364471426268267 -157.81006761682832 21.244615177105388 SRTM1.286507e05dd14c97a364976914d44158.vrt /home/runner/work/prettymaps/prettymaps/notebooks/elevation.tif
|
||||
rm -f SRTM1.286507e05dd14c97a364976914d44158.vrt
|
||||
make: Leaving directory '/home/runner/work/prettymaps/prettymaps/notebooks/SRTM1'
|
||||
|
||||
|
||||
WARNING:matplotlib.axes._base:Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits.
|
||||
@@ -1018,7 +1027,7 @@ plot = prettymaps.plot(
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -1043,7 +1052,7 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 21.47 seconds
|
||||
Fetching geodataframes took 18.23 seconds
|
||||
|
||||
|
||||
|
||||
|
18
docs/api.md
@@ -1,21 +1,7 @@
|
||||
# API Reference
|
||||
|
||||
This page documents the main modules and functions of the `prettymaps` library. The API documentation is auto-generated from the code and includes all public classes and functions.
|
||||
|
||||
## Modules
|
||||
|
||||
- **draw**: Core drawing and plotting functions, including map rendering, layer management, and style handling.
|
||||
- **fetch**: Functions for fetching and processing OpenStreetMap data and elevation.
|
||||
- **utils**: Utility functions for logging, timing, and other helpers.
|
||||
|
||||
---
|
||||
This section is auto-generated from the Prettymaps source code.
|
||||
|
||||
::: prettymaps.draw
|
||||
|
||||
---
|
||||
|
||||
::: prettymaps.fetch
|
||||
|
||||
---
|
||||
|
||||
::: prettymaps.utils
|
||||
::: prettymaps.fetch
|
@@ -1,27 +1,24 @@
|
||||
# prettymaps
|
||||
# Prettymaps Documentation
|
||||
|
||||
A minimal Python library to draw pretty maps from OpenStreetMap data.
|
||||
Welcome to the Prettymaps documentation site.
|
||||
|
||||
- [Usage](usage.md)
|
||||
- [API Reference](api.md)
|
||||
Prettymaps is a minimal Python library to draw beautiful maps from OpenStreetMap data.
|
||||
It allows you to easily generate artistic, customizable maps for any location in the world.
|
||||
|
||||
## Features
|
||||
- Draw beautiful maps from OSM data
|
||||
- Highly customizable layers and styles
|
||||
- Preset management
|
||||
- Keypoint highlighting
|
||||
|
||||
## Installation
|
||||
```bash
|
||||
pip install prettymaps
|
||||
```
|
||||
- Fetches and visualizes OpenStreetMap data with minimal code
|
||||
- Highly customizable layers and styles
|
||||
- Supports elevation, hillshading, and keypoints
|
||||
- Preset system for reusable map styles
|
||||
- Export to PNG, SVG, and plotter-friendly formats
|
||||
|
||||
## Quick Example
|
||||
|
||||
```python
|
||||
import prettymaps
|
||||
prettymaps.plot("Porto Alegre")
|
||||
|
||||
prettymaps.plot("Porto Alegre, Brazil")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Data © OpenStreetMap contributors
|
||||
Explore the [Usage](usage.md) and [API Reference](api.md) for more details.
|
@@ -1,54 +1,41 @@
|
||||
# Usage
|
||||
|
||||
## Installation
|
||||
|
||||
Install Prettymaps and its dependencies:
|
||||
|
||||
```sh
|
||||
pip install prettymaps
|
||||
```
|
||||
|
||||
## Basic Usage
|
||||
|
||||
The main entry point is the `plot()` function:
|
||||
Generate a map for a location:
|
||||
|
||||
```python
|
||||
import prettymaps
|
||||
prettymaps.plot("Porto Alegre")
|
||||
```
|
||||
|
||||
This will generate a map for the given location using default layers and styles.
|
||||
prettymaps.plot("Paris, France")
|
||||
```
|
||||
|
||||
## Customizing Layers and Styles
|
||||
|
||||
You can customize which OpenStreetMap layers are shown and how they are styled:
|
||||
You can customize which map layers to show and their appearance:
|
||||
|
||||
```python
|
||||
layers = {
|
||||
"perimeter": {},
|
||||
"streets": {"width": 8},
|
||||
"buildings": {},
|
||||
"water": {},
|
||||
}
|
||||
style = {
|
||||
"perimeter": {"fc": "#f2efe9"},
|
||||
"streets": {"fc": "#cccccc", "ec": "#333333"},
|
||||
"buildings": {"fc": "#bdbdbd"},
|
||||
"perimeter": {"fc": "#f2efe9", "ec": "#333"},
|
||||
"streets": {"fc": "#cccccc"},
|
||||
"buildings": {"fc": "#b0b0b0"},
|
||||
"water": {"fc": "#aadaff"},
|
||||
}
|
||||
prettymaps.plot("Porto Alegre", layers=layers, style=style)
|
||||
```
|
||||
|
||||
## Using Presets
|
||||
|
||||
Presets are reusable configurations for layers and styles. You can load, save, or update presets:
|
||||
|
||||
```python
|
||||
prettymaps.plot("Porto Alegre", preset="default")
|
||||
```
|
||||
|
||||
You can also create your own presets and save them for later use.
|
||||
|
||||
## Highlighting Keypoints
|
||||
|
||||
You can highlight specific keypoints (e.g., landmarks) on the map:
|
||||
|
||||
```python
|
||||
keypoints = {
|
||||
"tags": {"tourism": "attraction"},
|
||||
"kwargs": {"bbox": {"fc": "yellow"}},
|
||||
}
|
||||
prettymaps.plot("Porto Alegre", keypoints=keypoints)
|
||||
prettymaps.plot("Berlin, Germany", layers=layers, style=style)
|
||||
```
|
||||
|
||||
## Saving Maps
|
||||
@@ -56,9 +43,13 @@ prettymaps.plot("Porto Alegre", keypoints=keypoints)
|
||||
You can save the generated map to a file:
|
||||
|
||||
```python
|
||||
prettymaps.plot("Porto Alegre", save_as="map.png")
|
||||
prettymaps.plot("Tokyo, Japan", save_as="tokyo_map.png")
|
||||
```
|
||||
|
||||
---
|
||||
## Advanced Features
|
||||
|
||||
See the [API Reference](api.md) for details on all functions and parameters.
|
||||
- **Keypoints:** Highlight specific places or features on the map.
|
||||
- **Presets:** Save and reuse your favorite map styles.
|
||||
- **Hillshade:** Add elevation shading for a 3D effect.
|
||||
|
||||
See the [API Reference](api.md) for all available options.
|
Before Width: | Height: | Size: 3.4 MiB After Width: | Height: | Size: 3.6 MiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 2.2 MiB After Width: | Height: | Size: 2.4 MiB |
Before Width: | Height: | Size: 1.5 MiB After Width: | Height: | Size: 1.6 MiB |
BIN
pictures/README/temp_readme_files/temp_readme_33_3.png
Normal file
After Width: | Height: | Size: 779 KiB |
BIN
pictures/README/temp_readme_files/temp_readme_35_5.png
Normal file
After Width: | Height: | Size: 6.2 MiB |
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 2.2 MiB |
Before Width: | Height: | Size: 958 KiB After Width: | Height: | Size: 1.1 MiB |
BIN
pictures/heerhugowaard.png
Normal file
After Width: | Height: | Size: 773 KiB |
@@ -27,7 +27,7 @@ mv "$PICTURES_DIR/temp_readme.md" "$README_FILE"
|
||||
# (No-op if already in place)
|
||||
|
||||
# Update image links in README.md to point to pictures/README/
|
||||
sed -i '' 's|(temp_readme_files/|(pictures/README/temp_readme_files/|g' "$README_FILE"
|
||||
sed -i 's|(temp_readme_files/|(pictures/README/temp_readme_files/|g' "$README_FILE"
|
||||
|
||||
# Optionally, clean up any old temp_readme_files in root
|
||||
# rm -rf temp_readme_files
|
||||
|
6
setup.sh
@@ -15,7 +15,7 @@ if [[ "$OS" == "Linux" ]]; then
|
||||
# Linux (Debian/Ubuntu)
|
||||
echo "Updating package list and installing dependencies for Linux..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential make gcc python3-dev libgdal-dev gdal-bin
|
||||
sudo apt-get install -y build-essential make gcc libgdal-dev gdal-bin
|
||||
sudo apt-get clean
|
||||
|
||||
elif [[ "$OS" == "Darwin" ]]; then
|
||||
@@ -34,14 +34,10 @@ elif [[ "$OS" =~ "MINGW" || "$OS" =~ "MSYS" || "$OS" =~ "CYGWIN" ]]; then
|
||||
echo "- GDAL (https://gdal.org/download.html or via Conda: conda install -c conda-forge gdal)"
|
||||
echo "- Make and GCC (optional, for advanced features)"
|
||||
echo "- Python 3 and pip"
|
||||
echo "Then run: pip install -e ."
|
||||
exit 0
|
||||
else
|
||||
echo "Unsupported OS: $OS"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install Python dependencies
|
||||
pip install -e .
|
||||
|
||||
echo "Setup complete!"
|