Reorganized repo structure, added github workflows
0
.devcontainer/devcontainer.json
Normal file → Executable file
0
.github/FUNDING.yml
vendored
Normal file → Executable file
27
.github/workflows/docs.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Deploy Docs
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install -r docs/requirements.txt
|
||||
- name: Build docs
|
||||
run: |
|
||||
mkdocs build
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./site
|
||||
55
.github/workflows/generate-readme.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Generate README
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
jobs:
|
||||
generate-readme:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Install nbconvert
|
||||
run: |
|
||||
pip install nbconvert
|
||||
|
||||
- name: Install jupyter
|
||||
run: |
|
||||
pip install jupyter
|
||||
|
||||
- name: Install package
|
||||
run: |
|
||||
pip install -e .
|
||||
|
||||
- name: Execute the notebook (run all cells)
|
||||
run: |
|
||||
jupyter nbconvert --to notebook --execute notebooks/examples.ipynb --output notebooks/examples.ipynb
|
||||
|
||||
- name: Run notebooks_to_readme.sh
|
||||
run: |
|
||||
bash scripts/notebooks_to_readme.sh
|
||||
|
||||
- name: Git add generated files
|
||||
run: |
|
||||
git add README.md notebooks/examples.ipynb pictures/README/*.png
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git config --global user.name "github-actions[bot]"
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git commit -m "Update README, notebook, and images from CI" || echo "No changes to commit"
|
||||
|
||||
- name: Push changes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
git push origin HEAD:${GITHUB_REF#refs/heads/}
|
||||
0
.github/workflows/publish-package.yml
vendored
Normal file → Executable file
44
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Run Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["**"]
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.10"]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- name: Install package and dependencies
|
||||
run: |
|
||||
pip install -e .
|
||||
pip install pytest
|
||||
|
||||
- name: Run tests with pytest
|
||||
run: pytest --junitxml=pytest-results.xml tests
|
||||
|
||||
- name: Upload pytest results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pytest-results
|
||||
path: pytest-results.xml
|
||||
50
.gitignore
vendored
Normal file → Executable file
@@ -1,3 +1,49 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
*.py[cod]
|
||||
*.egg-info
|
||||
cache
|
||||
__pycache__/
|
||||
|
||||
# Distribution / packaging
|
||||
*.egg-info/
|
||||
build/
|
||||
dist/
|
||||
prettymaps.egg-info/
|
||||
|
||||
# Caches and logs
|
||||
cache/
|
||||
outputs/
|
||||
.DS_Store
|
||||
*.log
|
||||
*.bak
|
||||
*.dat
|
||||
*.sqlite
|
||||
|
||||
# Data
|
||||
/data/
|
||||
|
||||
# Ignore all notebooks except examples.ipynb
|
||||
notebooks/*
|
||||
!notebooks/examples.ipynb
|
||||
|
||||
# Exclude etc folder
|
||||
etc/
|
||||
|
||||
# Documentation images and archives
|
||||
/docs/images/
|
||||
/docs/archive/
|
||||
|
||||
# Scripts (if you want to ignore generated or temp files in scripts)
|
||||
/scripts/*.pyc
|
||||
/scripts/__pycache__/
|
||||
|
||||
# Ignore SRTM1 data
|
||||
SRTM1/
|
||||
|
||||
# Ignore OS and editor files
|
||||
*.swp
|
||||
*~
|
||||
.vscode/
|
||||
.devcontainer/
|
||||
|
||||
# Ignore test and temp files
|
||||
*.tmp
|
||||
*.tmp.png
|
||||
|
||||
0
MANIFEST.in
Normal file → Executable file
103
README.md
@@ -2,13 +2,8 @@
|
||||
|
||||
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.
|
||||
|
||||
# Prettymaps is now available as a streamlit app!
|
||||

|
||||
|
||||
[](https://prettymaps.streamlit.app/)
|
||||
|
||||
[](https://prettymaps.streamlit.app/)
|
||||
|
||||
<!---->
|
||||
|
||||
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)
|
||||
|
||||
@@ -16,7 +11,7 @@ This work is [licensed](LICENSE) under a GNU Affero General Public License v3.0
|
||||
- Please keep the printed message on the figures crediting my repository and OpenStreetMap ([mandatory by their license](https://www.openstreetmap.org/copyright)).
|
||||
- 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.
|
||||
- **I do not authorize in any way this project to be used for selling NFTs**, although I cannot legally enforce it. **Respect the creator**.
|
||||
- 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](etc/NFT_theft_AeternaCivitas.jpg), [geoartnft](etc/NFT_theft_geoart.jpg).
|
||||
- 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).
|
||||
- **I have closed my other generative art projects on Github and won't be sharing new ones as open source to protect me from the NFT community**.
|
||||
|
||||
<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>
|
||||
@@ -24,12 +19,6 @@ This work is [licensed](LICENSE) under a GNU Affero General Public License v3.0
|
||||
## As seen on [Hacker News](https://web.archive.org/web/20210825160918/https://news.ycombinator.com/news):
|
||||

|
||||
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=marceloprates/prettymaps&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=marceloprates/prettymaps&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=star-history/star-history&type=Date" />
|
||||
</picture>
|
||||
|
||||
## [prettymaps subreddit](https://www.reddit.com/r/prettymaps_/)
|
||||
## [Google Colaboratory Demo](https://colab.research.google.com/github/marceloprates/prettymaps/blob/master/notebooks/examples.ipynb)
|
||||
|
||||
@@ -81,9 +70,12 @@ import prettymaps
|
||||
plot = prettymaps.plot('Stad van de Zon, Heerhugowaard, Netherlands')
|
||||
```
|
||||
|
||||
Fetching geodataframes took 2.04 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -101,9 +93,12 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 0.81 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -200,6 +195,11 @@ prettymaps.presets()
|
||||
</tr>
|
||||
<tr>
|
||||
<th>10</th>
|
||||
<td>pytest-temp-preset</td>
|
||||
<td>{'layers': {'building': {'tags': {'building': ...</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>11</th>
|
||||
<td>tijuca</td>
|
||||
<td>{'layers': {'perimeter': {}, 'streets': {'widt...</td>
|
||||
</tr>
|
||||
@@ -378,9 +378,12 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 15.97 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -399,9 +402,12 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 1.28 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -416,6 +422,9 @@ plot = prettymaps.plot('Centro Histórico, Porto Alegre', show = False)
|
||||
plot.geodataframes['building']
|
||||
```
|
||||
|
||||
Fetching geodataframes took 1.59 seconds
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -741,7 +750,7 @@ plot.geodataframes['building'][
|
||||
].geometry[0]
|
||||
```
|
||||
|
||||
/home/marcelo/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/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]`
|
||||
val = getattr(super(), mtd)(*args, **kwargs)
|
||||
|
||||
|
||||
@@ -749,7 +758,7 @@ plot.geodataframes['building'][
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -788,9 +797,12 @@ for ax,building in zip(np.concatenate(axes),buildings):
|
||||
ax.autoscale(); ax.axis('off'); ax.axis('equal')
|
||||
```
|
||||
|
||||
Fetching geodataframes took 2.01 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -816,6 +828,9 @@ _ = plot.ax.set_title(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 3.78 seconds
|
||||
|
||||
|
||||
Use **plotter** mode to export a pen plotter-compatible SVG (thanks to abey79's amazing [vsketch](https://github.com/abey79/vsketch) library)
|
||||
|
||||
|
||||
@@ -832,9 +847,12 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 3.89 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -853,9 +871,12 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 16.55 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -951,9 +972,14 @@ plot = prettymaps.multiplot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 0.97 seconds
|
||||
Fetching geodataframes took 1.15 seconds
|
||||
Fetching geodataframes took 0.79 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -976,21 +1002,15 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
The autoreload extension is already loaded. To reload it, use:
|
||||
%reload_ext autoreload
|
||||
make: Entering directory '/home/marcelo/.cache/elevation/SRTM1'
|
||||
make: Nothing to be done for 'download'.
|
||||
make: Leaving directory '/home/marcelo/.cache/elevation/SRTM1'
|
||||
make: Entering directory '/home/marcelo/.cache/elevation/SRTM1'
|
||||
make: Nothing to be done for 'all'.
|
||||
make: Leaving directory '/home/marcelo/.cache/elevation/SRTM1'
|
||||
make: Entering directory '/home/marcelo/.cache/elevation/SRTM1'
|
||||
cp SRTM1.vrt SRTM1.2d5b6f11e0e74b44a9386ba897fb0852.vrt
|
||||
make: Leaving directory '/home/marcelo/.cache/elevation/SRTM1'
|
||||
make: Entering directory '/home/marcelo/.cache/elevation/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.2d5b6f11e0e74b44a9386ba897fb0852.vrt /home/marcelo/Projects/Art/prettymaps/notebooks/elevationa.tif
|
||||
rm -f SRTM1.2d5b6f11e0e74b44a9386ba897fb0852.vrt
|
||||
make: Leaving directory '/home/marcelo/.cache/elevation/SRTM1'
|
||||
Fetching geodataframes took 24.92 seconds
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
WARNING:matplotlib.axes._base:Ignoring fixed y limits to fulfill fixed data aspect with adjustable data limits.
|
||||
@@ -998,7 +1018,7 @@ plot = prettymaps.plot(
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
@@ -1023,8 +1043,11 @@ plot = prettymaps.plot(
|
||||
)
|
||||
```
|
||||
|
||||
Fetching geodataframes took 21.47 seconds
|
||||
|
||||
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 3.6 MiB |
|
Before Width: | Height: | Size: 3.6 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100.0" height="100.0" viewBox="-51.23032682800001 -30.034281028 0.0006073560000103839 0.0008053559999900983" preserveAspectRatio="xMinYMin meet"><g transform="matrix(1,0,0,-1,0,-60.067756700000004)"><path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="1.6107119999801965e-05" opacity="0.6" d="M -51.2298412,-30.03353870000001 L -51.2298154,-30.033540599999984 L -51.2298126,-30.0335408 L -51.2298129,-30.033544300000003 L -51.2297808,-30.033546699999988 L -51.2297805,-30.033544400000007 L -51.2297758,-30.0335447 L -51.2297562,-30.0335462 L -51.2297493,-30.033546700000002 L -51.2297572,-30.033626999999992 L -51.22975770000001,-30.033632 L -51.2298302,-30.03362630000001 L -51.2298538,-30.033865000000006 L -51.2298442,-30.0338658 L -51.2298477,-30.033909500000004 L -51.2298412,-30.03390990000001 L -51.2298357,-30.03390249999999 L -51.2298133,-30.033912799999996 L -51.2298168,-30.0339188 L -51.2297959,-30.0339406 L -51.2297906,-30.033938999999993 L -51.2297826,-30.0339586 L -51.2297866,-30.033959199999998 L -51.2297957,-30.034019000000004 L -51.2297902,-30.034021400000004 L -51.229800700000006,-30.0340417 L -51.2298073,-30.0340393 L -51.2298344,-30.034053999999994 L -51.2298319,-30.034065200000004 L -51.2298509,-30.0340704 L -51.2298558,-30.034059600000003 L -51.2298704,-30.0340585 L -51.2298741,-30.034097 L -51.2298921,-30.034095599999993 L -51.2298985,-30.03416019999999 L -51.2298609,-30.034163 L -51.2298683,-30.03423859999999 L -51.2299531,-30.0342322 L -51.2299549,-30.0342512 L -51.2301846,-30.034234 L -51.2301825,-30.0342134 L -51.2302643,-30.03420729999999 L -51.2302569,-30.034132200000002 L -51.2302241,-30.034134599999994 L -51.2302178,-30.0340702 L -51.2302266,-30.0340694 L -51.2302229,-30.034030399999995 L -51.2302285,-30.03403000000001 L -51.230236500000004,-30.0340294 L -51.2302396,-30.034038299999995 L -51.230256600000004,-30.034034099999996 L -51.2302532,-30.0340242 L -51.230280900000004,-30.034001600000003 L -51.2302902,-30.0340033 L -51.23029700000001,-30.033981200000003 L -51.2302871,-30.0339784 L -51.2302841,-30.033920999999996 L -51.2302898,-30.033919600000008 L -51.2302806,-30.0338995 L -51.2302726,-30.033902400000002 L -51.2302486,-30.0338856 L -51.2302511,-30.033877399999994 L -51.2302264,-30.033868700000003 L -51.2302198,-30.033880699999997 L -51.2302148,-30.033878999999995 L -51.230213000000006,-30.033838099999997 L -51.2302054,-30.033838700000004 L -51.2301818,-30.0336 L -51.2302499,-30.033594899999997 L -51.2302471,-30.033566499999996 L -51.2302452,-30.033566699999998 L -51.2302423,-30.0335373 L -51.2302448,-30.033537100000004 L -51.2302419,-30.0335085 L -51.2302051,-30.0335112 L -51.2302053,-30.033513599999992 L -51.2301756,-30.0335159 L -51.2301752,-30.033512399999992 L -51.23014450000001,-30.033514699999994 L -51.2301449,-30.033518200000003 L -51.2300854,-30.033522700000002 L -51.2300843,-30.033511399999984 L -51.2300823,-30.0335115 L -51.2300635,-30.033512799999997 L -51.2300628,-30.033505500000008 L -51.2300334,-30.0335078 L -51.2300336,-30.03350989999999 L -51.2300339,-30.033513 L -51.22995280000001,-30.033519099999996 L -51.229952600000004,-30.033516999999996 L -51.2299524,-30.0335151 L -51.2299225,-30.03351729999999 L -51.2299228,-30.033520499999998 L -51.2298995,-30.03352229999999 L -51.2299009,-30.033537 L -51.2298443,-30.033541300000003 L -51.229844,-30.0335385 L -51.2298412,-30.03353870000001 z" /></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100.0" height="100.0" viewBox="-51.23032682800001 -30.034281028 0.0006073560000103839 0.0008053559999900983" preserveAspectRatio="xMinYMin meet"><g transform="matrix(1,0,0,-1,0,-60.067756700000004)"><path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="1.6107119999801965e-05" opacity="0.6" d="M -51.2298412,-30.03353870000001 L -51.2298154,-30.033540599999984 L -51.2298126,-30.0335408 L -51.2298129,-30.033544300000003 L -51.2297808,-30.033546700000002 L -51.2297805,-30.033544400000007 L -51.2297758,-30.0335447 L -51.2297562,-30.0335462 L -51.2297493,-30.033546699999995 L -51.2297572,-30.033627 L -51.22975770000001,-30.033632 L -51.2298302,-30.033626299999995 L -51.2298538,-30.033865 L -51.2298442,-30.033865799999994 L -51.2298477,-30.033909500000004 L -51.2298412,-30.03390990000001 L -51.2298357,-30.03390249999999 L -51.2298133,-30.033912799999996 L -51.2298168,-30.0339188 L -51.2297959,-30.0339406 L -51.2297906,-30.033939 L -51.2297826,-30.03395859999999 L -51.2297866,-30.033959199999998 L -51.2297957,-30.034019000000004 L -51.2297902,-30.034021399999997 L -51.229800700000006,-30.0340417 L -51.2298073,-30.0340393 L -51.2298344,-30.034053999999994 L -51.2298319,-30.034065200000008 L -51.2298509,-30.034070399999994 L -51.2298558,-30.034059600000003 L -51.2298704,-30.0340585 L -51.2298741,-30.034097 L -51.2298921,-30.034095599999993 L -51.2298985,-30.03416019999999 L -51.2298609,-30.034163 L -51.2298683,-30.034238599999984 L -51.2299531,-30.0342322 L -51.2299549,-30.0342512 L -51.2301846,-30.034234 L -51.2301825,-30.03421339999999 L -51.2302643,-30.03420729999999 L -51.2302569,-30.034132200000002 L -51.2302241,-30.034134599999994 L -51.2302178,-30.0340702 L -51.2302266,-30.034069400000007 L -51.2302229,-30.034030399999995 L -51.2302285,-30.03403000000001 L -51.230236500000004,-30.0340294 L -51.2302396,-30.034038299999995 L -51.230256600000004,-30.03403409999999 L -51.2302532,-30.0340242 L -51.230280900000004,-30.034001599999996 L -51.2302902,-30.0340033 L -51.23029700000001,-30.03398119999999 L -51.2302871,-30.0339784 L -51.2302841,-30.033920999999992 L -51.2302898,-30.033919600000008 L -51.2302806,-30.0338995 L -51.2302726,-30.033902399999995 L -51.2302486,-30.033885599999994 L -51.2302511,-30.033877399999998 L -51.2302264,-30.033868700000003 L -51.2302198,-30.033880699999987 L -51.2302148,-30.033878999999995 L -51.230213000000006,-30.03383810000001 L -51.2302054,-30.033838700000004 L -51.2301818,-30.0336 L -51.2302499,-30.033594899999997 L -51.2302471,-30.033566499999996 L -51.2302452,-30.033566699999998 L -51.2302423,-30.0335373 L -51.2302448,-30.033537100000004 L -51.2302419,-30.0335085 L -51.2302051,-30.033511199999992 L -51.2302053,-30.03351359999999 L -51.2301756,-30.0335159 L -51.2301752,-30.033512399999992 L -51.23014450000001,-30.0335147 L -51.2301449,-30.033518200000003 L -51.2300854,-30.033522699999995 L -51.2300843,-30.03351139999999 L -51.2300823,-30.0335115 L -51.2300635,-30.033512799999997 L -51.2300628,-30.033505500000008 L -51.2300334,-30.0335078 L -51.2300336,-30.03350989999999 L -51.2300339,-30.033513 L -51.22995280000001,-30.033519100000003 L -51.229952600000004,-30.033516999999996 L -51.2299524,-30.0335151 L -51.2299225,-30.03351729999999 L -51.2299228,-30.033520499999998 L -51.2298995,-30.03352229999999 L -51.2299009,-30.033536999999992 L -51.2298443,-30.033541300000003 L -51.229844,-30.0335385 L -51.2298412,-30.03353870000001 z" /></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100.0" height="100.0" viewBox="-51.23032682800001 -30.034281028 0.0006073560000103839 0.0008053559999900983" preserveAspectRatio="xMinYMin meet"><g transform="matrix(1,0,0,-1,0,-60.067756700000004)"><path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="1.6107119999801965e-05" opacity="0.6" d="M -51.2298412,-30.03353870000001 L -51.2298154,-30.033540599999984 L -51.2298126,-30.0335408 L -51.2298129,-30.033544300000003 L -51.2297808,-30.033546700000002 L -51.2297805,-30.033544400000007 L -51.2297758,-30.0335447 L -51.2297562,-30.0335462 L -51.2297493,-30.033546699999995 L -51.2297572,-30.033627 L -51.22975770000001,-30.033632 L -51.2298302,-30.033626299999995 L -51.2298538,-30.033865 L -51.2298442,-30.033865799999994 L -51.2298477,-30.033909500000004 L -51.2298412,-30.03390990000001 L -51.2298357,-30.03390249999999 L -51.2298133,-30.033912799999996 L -51.2298168,-30.0339188 L -51.2297959,-30.0339406 L -51.2297906,-30.033939 L -51.2297826,-30.03395859999999 L -51.2297866,-30.033959199999998 L -51.2297957,-30.034019000000004 L -51.2297902,-30.034021399999997 L -51.229800700000006,-30.0340417 L -51.2298073,-30.0340393 L -51.2298344,-30.034053999999994 L -51.2298319,-30.034065200000008 L -51.2298509,-30.034070399999994 L -51.2298558,-30.034059600000003 L -51.2298704,-30.0340585 L -51.2298741,-30.034097 L -51.2298921,-30.034095599999993 L -51.2298985,-30.03416019999999 L -51.2298609,-30.034163 L -51.2298683,-30.034238599999984 L -51.2299531,-30.0342322 L -51.2299549,-30.0342512 L -51.2301846,-30.034234 L -51.2301825,-30.03421339999999 L -51.2302643,-30.03420729999999 L -51.2302569,-30.034132200000002 L -51.2302241,-30.034134599999994 L -51.2302178,-30.0340702 L -51.2302266,-30.034069400000007 L -51.2302229,-30.034030399999995 L -51.2302285,-30.03403000000001 L -51.230236500000004,-30.0340294 L -51.2302396,-30.034038299999995 L -51.230256600000004,-30.03403409999999 L -51.2302532,-30.0340242 L -51.230280900000004,-30.034001599999996 L -51.2302902,-30.0340033 L -51.23029700000001,-30.03398119999999 L -51.2302871,-30.0339784 L -51.2302841,-30.033920999999992 L -51.2302898,-30.033919600000008 L -51.2302806,-30.0338995 L -51.2302726,-30.033902399999995 L -51.2302486,-30.033885599999994 L -51.2302511,-30.033877399999998 L -51.2302264,-30.033868700000003 L -51.2302198,-30.033880699999987 L -51.2302148,-30.033878999999995 L -51.230213000000006,-30.03383810000001 L -51.2302054,-30.033838700000004 L -51.2301818,-30.0336 L -51.2302499,-30.033594899999997 L -51.2302471,-30.033566499999996 L -51.2302452,-30.033566699999998 L -51.2302423,-30.0335373 L -51.2302448,-30.033537100000004 L -51.2302419,-30.0335085 L -51.2302051,-30.033511199999992 L -51.2302053,-30.03351359999999 L -51.2301756,-30.0335159 L -51.2301752,-30.033512399999992 L -51.23014450000001,-30.0335147 L -51.2301449,-30.033518200000003 L -51.2300854,-30.033522699999995 L -51.2300843,-30.03351139999999 L -51.2300823,-30.0335115 L -51.2300635,-30.033512799999997 L -51.2300628,-30.033505500000008 L -51.2300334,-30.0335078 L -51.2300336,-30.03350989999999 L -51.2300339,-30.033513 L -51.22995280000001,-30.033519100000003 L -51.229952600000004,-30.033516999999996 L -51.2299524,-30.0335151 L -51.2299225,-30.03351729999999 L -51.2299228,-30.033520499999998 L -51.2298995,-30.03352229999999 L -51.2299009,-30.033536999999992 L -51.2298443,-30.033541300000003 L -51.229844,-30.0335385 L -51.2298412,-30.03353870000001 z" /></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 65 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100.0" height="100.0" viewBox="-51.23032682800001 -30.034281028 0.0006073560000103839 0.0008053559999900983" preserveAspectRatio="xMinYMin meet"><g transform="matrix(1,0,0,-1,0,-60.067756700000004)"><path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="1.6107119999801965e-05" opacity="0.6" d="M -51.2298412,-30.03353870000001 L -51.2298154,-30.033540599999984 L -51.2298126,-30.0335408 L -51.2298129,-30.033544300000003 L -51.2297808,-30.033546700000002 L -51.2297805,-30.033544400000007 L -51.2297758,-30.0335447 L -51.2297562,-30.0335462 L -51.2297493,-30.033546699999995 L -51.2297572,-30.033627 L -51.22975770000001,-30.033632 L -51.2298302,-30.033626299999995 L -51.2298538,-30.033865 L -51.2298442,-30.033865799999994 L -51.2298477,-30.033909500000004 L -51.2298412,-30.03390990000001 L -51.2298357,-30.03390249999999 L -51.2298133,-30.033912799999996 L -51.2298168,-30.0339188 L -51.2297959,-30.0339406 L -51.2297906,-30.033939 L -51.2297826,-30.03395859999999 L -51.2297866,-30.033959199999998 L -51.2297957,-30.034019000000004 L -51.2297902,-30.034021399999997 L -51.229800700000006,-30.0340417 L -51.2298073,-30.0340393 L -51.2298344,-30.034053999999994 L -51.2298319,-30.034065200000008 L -51.2298509,-30.034070399999994 L -51.2298558,-30.034059600000003 L -51.2298704,-30.0340585 L -51.2298741,-30.034097 L -51.2298921,-30.034095599999993 L -51.2298985,-30.03416019999999 L -51.2298609,-30.034163 L -51.2298683,-30.034238599999984 L -51.2299531,-30.0342322 L -51.2299549,-30.0342512 L -51.2301846,-30.034234 L -51.2301825,-30.03421339999999 L -51.2302643,-30.03420729999999 L -51.2302569,-30.034132200000002 L -51.2302241,-30.034134599999994 L -51.2302178,-30.0340702 L -51.2302266,-30.034069400000007 L -51.2302229,-30.034030399999995 L -51.2302285,-30.03403000000001 L -51.230236500000004,-30.0340294 L -51.2302396,-30.034038299999995 L -51.230256600000004,-30.03403409999999 L -51.2302532,-30.0340242 L -51.230280900000004,-30.034001599999996 L -51.2302902,-30.0340033 L -51.23029700000001,-30.03398119999999 L -51.2302871,-30.0339784 L -51.2302841,-30.033920999999992 L -51.2302898,-30.033919600000008 L -51.2302806,-30.0338995 L -51.2302726,-30.033902399999995 L -51.2302486,-30.033885599999994 L -51.2302511,-30.033877399999998 L -51.2302264,-30.033868700000003 L -51.2302198,-30.033880699999987 L -51.2302148,-30.033878999999995 L -51.230213000000006,-30.03383810000001 L -51.2302054,-30.033838700000004 L -51.2301818,-30.0336 L -51.2302499,-30.033594899999997 L -51.2302471,-30.033566499999996 L -51.2302452,-30.033566699999998 L -51.2302423,-30.0335373 L -51.2302448,-30.033537100000004 L -51.2302419,-30.0335085 L -51.2302051,-30.033511199999992 L -51.2302053,-30.03351359999999 L -51.2301756,-30.0335159 L -51.2301752,-30.033512399999992 L -51.23014450000001,-30.0335147 L -51.2301449,-30.033518200000003 L -51.2300854,-30.033522699999995 L -51.2300843,-30.03351139999999 L -51.2300823,-30.0335115 L -51.2300635,-30.033512799999997 L -51.2300628,-30.033505500000008 L -51.2300334,-30.0335078 L -51.2300336,-30.03350989999999 L -51.2300339,-30.033513 L -51.22995280000001,-30.033519100000003 L -51.229952600000004,-30.033516999999996 L -51.2299524,-30.0335151 L -51.2299225,-30.03351729999999 L -51.2299228,-30.033520499999998 L -51.2298995,-30.03352229999999 L -51.2299009,-30.033536999999992 L -51.2298443,-30.033541300000003 L -51.229844,-30.0335385 L -51.2298412,-30.03353870000001 z" /></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 5.4 MiB |
|
Before Width: | Height: | Size: 5.4 MiB |
|
Before Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 1.6 MiB |
|
Before Width: | Height: | Size: 5.2 MiB |
|
Before Width: | Height: | Size: 5.2 MiB |
|
Before Width: | Height: | Size: 780 KiB |
|
Before Width: | Height: | Size: 779 KiB |
|
Before Width: | Height: | Size: 6.2 MiB |
|
Before Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 6.2 MiB |
|
Before Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 2.2 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.1 MiB |
21
docs/api.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 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.
|
||||
|
||||
---
|
||||
|
||||
::: prettymaps.draw
|
||||
|
||||
---
|
||||
|
||||
::: prettymaps.fetch
|
||||
|
||||
---
|
||||
|
||||
::: prettymaps.utils
|
||||
27
docs/index.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# prettymaps
|
||||
|
||||
A minimal Python library to draw pretty maps from OpenStreetMap data.
|
||||
|
||||
- [Usage](usage.md)
|
||||
- [API Reference](api.md)
|
||||
|
||||
## Features
|
||||
- Draw beautiful maps from OSM data
|
||||
- Highly customizable layers and styles
|
||||
- Preset management
|
||||
- Keypoint highlighting
|
||||
|
||||
## Installation
|
||||
```bash
|
||||
pip install prettymaps
|
||||
```
|
||||
|
||||
## Quick Example
|
||||
```python
|
||||
import prettymaps
|
||||
prettymaps.plot("Porto Alegre")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Data © OpenStreetMap contributors
|
||||
4
docs/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
mkdocs
|
||||
mkdocs-material
|
||||
mkdocstrings
|
||||
mkdocstrings-python
|
||||
64
docs/usage.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Usage
|
||||
|
||||
## Basic Usage
|
||||
|
||||
The main entry point is the `plot()` function:
|
||||
|
||||
```python
|
||||
import prettymaps
|
||||
prettymaps.plot("Porto Alegre")
|
||||
```
|
||||
|
||||
This will generate a map for the given location using default layers and styles.
|
||||
|
||||
## Customizing Layers and Styles
|
||||
|
||||
You can customize which OpenStreetMap layers are shown and how they are styled:
|
||||
|
||||
```python
|
||||
layers = {
|
||||
"perimeter": {},
|
||||
"streets": {"width": 8},
|
||||
"buildings": {},
|
||||
}
|
||||
style = {
|
||||
"perimeter": {"fc": "#f2efe9"},
|
||||
"streets": {"fc": "#cccccc", "ec": "#333333"},
|
||||
"buildings": {"fc": "#bdbdbd"},
|
||||
}
|
||||
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)
|
||||
```
|
||||
|
||||
## Saving Maps
|
||||
|
||||
You can save the generated map to a file:
|
||||
|
||||
```python
|
||||
prettymaps.plot("Porto Alegre", save_as="map.png")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
See the [API Reference](api.md) for details on all functions and parameters.
|
||||
21
mkdocs.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
site_name: prettymaps
|
||||
site_url: https://yourusername.github.io/prettymaps/
|
||||
docs_dir: docs
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Usage: usage.md
|
||||
- API Reference: api.md
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
primary: indigo
|
||||
accent: pink
|
||||
plugins:
|
||||
- search
|
||||
- mkdocstrings:
|
||||
handlers:
|
||||
python:
|
||||
options:
|
||||
show_root_heading: true
|
||||
show_source: true
|
||||
docstring_style: google
|
||||
168
notebooks/examples.ipynb
Normal file → Executable file
0
packages.txt
Normal file → Executable file
0
etc/NFT_theft_AeternaCivitas.jpg → pictures/NFT_theft_AeternaCivitas.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 168 KiB |
0
etc/NFT_theft_geoart.jpg → pictures/NFT_theft_geoart.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
BIN
pictures/README/temp_readme_files/temp_readme_15_1.png
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
BIN
pictures/README/temp_readme_files/temp_readme_17_1.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
1
pictures/README/temp_readme_files/temp_readme_21_1.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100.0" height="100.0" viewBox="-51.23032682800001 -30.034281028 0.0006073560000103839 0.0008053559999900983" preserveAspectRatio="xMinYMin meet"><g transform="matrix(1,0,0,-1,0,-60.067756700000004)"><path fill-rule="evenodd" fill="#66cc99" stroke="#555555" stroke-width="1.6107119999801965e-05" opacity="0.6" d="M -51.2298412,-30.03353870000001 L -51.2298154,-30.033540599999984 L -51.2298126,-30.0335408 L -51.2298129,-30.033544300000003 L -51.2297808,-30.033546700000002 L -51.2297805,-30.033544400000007 L -51.2297758,-30.033544699999993 L -51.2297562,-30.033546199999993 L -51.2297493,-30.033546699999995 L -51.2297572,-30.033627000000006 L -51.22975770000001,-30.033632000000008 L -51.2298302,-30.033626299999995 L -51.2298538,-30.033865 L -51.2298442,-30.033865799999994 L -51.2298477,-30.033909500000004 L -51.2298412,-30.03390990000001 L -51.2298357,-30.03390249999999 L -51.2298133,-30.033912799999996 L -51.2298168,-30.0339188 L -51.2297959,-30.0339406 L -51.2297906,-30.033939 L -51.2297826,-30.0339586 L -51.2297866,-30.033959199999998 L -51.2297957,-30.034019000000004 L -51.2297902,-30.03402139999999 L -51.229800700000006,-30.0340417 L -51.2298073,-30.034039299999986 L -51.2298344,-30.034053999999994 L -51.2298319,-30.034065200000008 L -51.2298509,-30.034070399999994 L -51.2298558,-30.034059600000003 L -51.2298704,-30.0340585 L -51.2298741,-30.034097 L -51.2298921,-30.034095599999993 L -51.2298985,-30.034160200000002 L -51.2298609,-30.034163 L -51.2298683,-30.034238599999984 L -51.2299531,-30.0342322 L -51.2299549,-30.0342512 L -51.2301846,-30.034234 L -51.2301825,-30.03421339999999 L -51.2302643,-30.03420729999999 L -51.2302569,-30.034132200000002 L -51.2302241,-30.0341346 L -51.2302178,-30.0340702 L -51.2302266,-30.034069400000007 L -51.2302229,-30.034030399999995 L -51.2302285,-30.03403 L -51.230236500000004,-30.0340294 L -51.2302396,-30.034038299999995 L -51.230256600000004,-30.03403409999999 L -51.2302532,-30.0340242 L -51.230280900000004,-30.034001599999996 L -51.2302902,-30.0340033 L -51.23029700000001,-30.033981199999996 L -51.2302871,-30.0339784 L -51.2302841,-30.033920999999992 L -51.2302898,-30.033919600000008 L -51.2302806,-30.0338995 L -51.2302726,-30.033902399999995 L -51.2302486,-30.033885599999994 L -51.2302511,-30.033877399999998 L -51.2302264,-30.033868700000003 L -51.2302198,-30.03388069999999 L -51.2302148,-30.033878999999995 L -51.230213000000006,-30.03383809999999 L -51.2302054,-30.033838700000004 L -51.2301818,-30.0336 L -51.2302499,-30.033594899999997 L -51.2302471,-30.033566499999996 L -51.2302452,-30.033566699999998 L -51.2302423,-30.0335373 L -51.2302448,-30.033537100000004 L -51.2302419,-30.0335085 L -51.2302051,-30.033511199999992 L -51.2302053,-30.03351359999999 L -51.2301756,-30.0335159 L -51.2301752,-30.033512399999992 L -51.23014450000001,-30.033514699999994 L -51.2301449,-30.03351820000001 L -51.2300854,-30.033522700000002 L -51.2300843,-30.03351139999999 L -51.2300823,-30.033511500000007 L -51.2300635,-30.033512799999997 L -51.2300628,-30.033505500000008 L -51.2300334,-30.0335078 L -51.2300336,-30.03350989999999 L -51.2300339,-30.033513 L -51.22995280000001,-30.033519100000003 L -51.229952600000004,-30.033516999999996 L -51.2299524,-30.0335151 L -51.2299225,-30.03351729999999 L -51.2299228,-30.033520499999998 L -51.2298995,-30.03352229999999 L -51.2299009,-30.033536999999992 L -51.2298443,-30.033541300000003 L -51.229844,-30.0335385 L -51.2298412,-30.03353870000001 z" /></g></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
BIN
pictures/README/temp_readme_files/temp_readme_23_1.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
pictures/README/temp_readme_files/temp_readme_27_1.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
pictures/README/temp_readme_files/temp_readme_29_1.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
pictures/README/temp_readme_files/temp_readme_33_1.png
Normal file
|
After Width: | Height: | Size: 691 KiB |
BIN
pictures/README/temp_readme_files/temp_readme_35_2.png
Normal file
|
After Width: | Height: | Size: 5.6 MiB |
BIN
pictures/README/temp_readme_files/temp_readme_37_1.png
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
pictures/README/temp_readme_files/temp_readme_7_1.png
Normal file
|
After Width: | Height: | Size: 2.0 MiB |
BIN
pictures/README/temp_readme_files/temp_readme_9_1.png
Normal file
|
After Width: | Height: | Size: 958 KiB |
0
prettymaps/__init__.py
Normal file → Executable file
21
prettymaps/draw.py
Normal file → Executable file
@@ -16,16 +16,19 @@ You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
import cv2
|
||||
# Standard library imports
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
import pathlib
|
||||
import warnings
|
||||
from copy import deepcopy
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
|
||||
|
||||
# Third-party imports
|
||||
import cv2
|
||||
import geopandas as gp
|
||||
import matplotlib
|
||||
import numpy as np
|
||||
@@ -47,8 +50,11 @@ from shapely.geometry import (
|
||||
box,
|
||||
)
|
||||
from shapely.geometry.base import BaseGeometry
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
from thefuzz import fuzz
|
||||
import shutil
|
||||
|
||||
# Local imports
|
||||
from .fetch import get_gdfs, obtain_elevation, get_keypoints
|
||||
from .utils import log_execution_time
|
||||
|
||||
@@ -539,7 +545,6 @@ def draw_hillshade(
|
||||
ls = LightSource(azdeg=azdeg, altdeg=altdeg)
|
||||
hillshade = ls.hillshade(elevation_data, vert_exag=vert_exag, dx=dx, dy=dy)
|
||||
# Convert hillshade to RGBA
|
||||
from sklearn.preprocessing import MinMaxScaler
|
||||
|
||||
# hillshade = np.clip(hillshade, 0, np.inf)
|
||||
# hillshade = MinMaxScaler((0, 1)).fit_transform(hillshade)
|
||||
@@ -562,6 +567,15 @@ def draw_hillshade(
|
||||
ax.set_xlim(min_x, max_x)
|
||||
ax.set_ylim(min_y, max_y)
|
||||
|
||||
# Delete the ./SRTM1 folder after drawing hillshade
|
||||
srtm1_dir = os.path.join(os.getcwd(), "SRTM1")
|
||||
if os.path.isdir(srtm1_dir):
|
||||
try:
|
||||
shutil.rmtree(srtm1_dir)
|
||||
except Exception as e:
|
||||
if logging:
|
||||
print(f"Warning: Failed to delete {srtm1_dir}: {e}")
|
||||
|
||||
|
||||
@log_execution_time
|
||||
def create_background(
|
||||
@@ -1178,7 +1192,10 @@ def plot(
|
||||
layers = override_args(layers, circle, dilate, logging=logging)
|
||||
|
||||
# 4. Fetch geodataframes
|
||||
start_time = time.time()
|
||||
gdfs = get_gdfs(query, layers, radius, dilate, -rotation, logging=logging)
|
||||
fetch_time = time.time() - start_time
|
||||
print(f"Fetching geodataframes took {fetch_time:.2f} seconds")
|
||||
|
||||
# 5. Apply transformations to GeoDataFrames (translation, scale, rotation)
|
||||
gdfs = transform_gdfs(gdfs, x, y, scale_x, scale_y, rotation, logging=logging)
|
||||
|
||||
0
prettymaps/fetch.py
Normal file → Executable file
0
prettymaps/presets/abraca-redencao.json
Normal file → Executable file
0
prettymaps/presets/barcelona-plotter.json
Normal file → Executable file
0
prettymaps/presets/barcelona.json
Normal file → Executable file
0
prettymaps/presets/cb-bf-f.json
Normal file → Executable file
0
prettymaps/presets/default.json
Normal file → Executable file
0
prettymaps/presets/heerhugowaard.json
Normal file → Executable file
0
prettymaps/presets/macao.json
Normal file → Executable file
0
prettymaps/presets/minimal.json
Normal file → Executable file
0
prettymaps/presets/plotter.json
Normal file → Executable file
0
prettymaps/presets/tijuca.json
Normal file → Executable file
0
prettymaps/utils.py
Normal file → Executable file
|
Before Width: | Height: | Size: 985 KiB |
|
Before Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 773 KiB |
0
requirements.txt
Normal file → Executable file
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Resolve all dependencies that the application requires to run.
|
||||
|
||||
# Stop on errors
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
pip3 install -e .
|
||||
35
scripts/notebooks_to_readme.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Exit on error
|
||||
set -e
|
||||
|
||||
NOTEBOOKS_DIR="notebooks"
|
||||
README_FILE="README.md"
|
||||
EXAMPLES_NOTEBOOK="$NOTEBOOKS_DIR/examples.ipynb"
|
||||
PICTURES_DIR="pictures/README"
|
||||
|
||||
# Check if examples.ipynb exists
|
||||
if [ ! -f "$EXAMPLES_NOTEBOOK" ]; then
|
||||
echo "examples.ipynb not found in $NOTEBOOKS_DIR. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create pictures/README directory if it doesn't exist
|
||||
mkdir -p "$PICTURES_DIR"
|
||||
|
||||
# Export examples.ipynb to markdown, putting images in pictures/README
|
||||
jupyter nbconvert --to markdown "$EXAMPLES_NOTEBOOK" --output temp_readme --output-dir "$PICTURES_DIR"
|
||||
|
||||
# Move the markdown file to the root as README.md
|
||||
mv "$PICTURES_DIR/temp_readme.md" "$README_FILE"
|
||||
|
||||
# Move all images to pictures/README (they are already there, but this ensures they stay organized)
|
||||
# (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"
|
||||
|
||||
# Optionally, clean up any old temp_readme_files in root
|
||||
# rm -rf temp_readme_files
|
||||
|
||||
echo "README.md has been replaced with the markdown export of $EXAMPLES_NOTEBOOK, and images are in $PICTURES_DIR."
|
||||
53
setup.sh
Normal file → Executable file
@@ -1,18 +1,47 @@
|
||||
#! /bin/bash
|
||||
#!/bin/bash
|
||||
|
||||
# Change permissions for STRM folder
|
||||
chmod -R 755 ./SRTM1
|
||||
set -e
|
||||
|
||||
# Update package list
|
||||
apt-get update
|
||||
# Detect OS
|
||||
OS="$(uname)"
|
||||
echo "Detected OS: $OS"
|
||||
|
||||
# Install essential build tools including make and gcc
|
||||
apt-get install -y build-essential make gcc
|
||||
# Change permissions for SRTM1 folder (Linux/macOS only)
|
||||
if [ -d "./SRTM1" ]; then
|
||||
chmod -R 755 ./SRTM1
|
||||
fi
|
||||
|
||||
# Optionally install other dependencies (e.g., for elevation or other libraries)
|
||||
apt-get install -y python3-dev libgdal-dev
|
||||
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 clean
|
||||
|
||||
# Clean up to reduce the image size
|
||||
apt-get clean
|
||||
elif [[ "$OS" == "Darwin" ]]; then
|
||||
# macOS
|
||||
echo "Installing dependencies for macOS (requires Homebrew)..."
|
||||
if ! command -v brew &>/dev/null; then
|
||||
echo "Homebrew not found. Please install Homebrew first: https://brew.sh/"
|
||||
exit 1
|
||||
fi
|
||||
brew update
|
||||
brew install gdal make gcc
|
||||
|
||||
pip install git+https://github.com/marceloprates/prettymaps.git
|
||||
elif [[ "$OS" =~ "MINGW" || "$OS" =~ "MSYS" || "$OS" =~ "CYGWIN" ]]; then
|
||||
# Windows (Git Bash, MSYS, Cygwin)
|
||||
echo "Windows detected. Please install the following manually:"
|
||||
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!"
|
||||
300
tests/test.py
Normal file
@@ -0,0 +1,300 @@
|
||||
import pytest
|
||||
import prettymaps
|
||||
import osmnx as ox
|
||||
import geopandas as gpd
|
||||
|
||||
# Helper to get a GeoDataFrame for a given query
|
||||
def get_gdf(query = "Bom Fim, Porto Alegre, Brasil"):
|
||||
return ox.geocode_to_gdf(query)
|
||||
|
||||
# Test that presets() returns a DataFrame with known presets
|
||||
def test_presets():
|
||||
df = prettymaps.presets()
|
||||
assert not df.empty
|
||||
assert 'preset' in df.columns
|
||||
assert 'params' in df.columns
|
||||
assert 'default' in df['preset'].values
|
||||
|
||||
# Test that preset() returns a Preset object with params
|
||||
def test_preset():
|
||||
p = prettymaps.preset('default')
|
||||
assert hasattr(p, 'params')
|
||||
assert isinstance(p.params, dict)
|
||||
assert 'layers' in p.params
|
||||
assert 'style' in p.params
|
||||
|
||||
# Test create_preset and reading it back
|
||||
def test_create_and_read_preset(tmp_path):
|
||||
name = 'pytest-temp-preset'
|
||||
layers = {'building': {'tags': {'building': True}}}
|
||||
style = {'building': {'fc': '#fff'}}
|
||||
prettymaps.create_preset(name, layers=layers, style=style)
|
||||
p = prettymaps.preset(name)
|
||||
assert p.params['layers'] == layers
|
||||
assert p.params['style'] == style
|
||||
|
||||
# Test Subplot class
|
||||
def test_subplot():
|
||||
s = prettymaps.Subplot('Porto Alegre', style={'building': {'fc': '#fff'}})
|
||||
assert s.query == 'Porto Alegre'
|
||||
assert 'style' in s.kwargs
|
||||
|
||||
# Test plot() basic call returns expected attributes (mocked heavy work)
|
||||
def test_plot_smoke(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
assert hasattr(result, 'fig')
|
||||
assert hasattr(result, 'ax')
|
||||
|
||||
# Test multiplot() with two subplots (mocked)
|
||||
def test_multiplot_smoke(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'plot', lambda *a, **k: type('FakePlot', (), {'geodataframes': {}, 'fig': None, 'ax': None, 'background': None, 'keypoints': None})())
|
||||
s1 = prettymaps.Subplot('Cidade Baixa, Porto Alegre')
|
||||
s2 = prettymaps.Subplot('Bom Fim, Porto Alegre')
|
||||
prettymaps.multiplot(s1, s2, figsize=(4,4))
|
||||
|
||||
# Test plot() with a (lat, lon) tuple as query (mocked)
|
||||
def test_plot_latlon_tuple(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot((41.39, 2.17), show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
assert hasattr(result, 'fig')
|
||||
assert hasattr(result, 'ax')
|
||||
|
||||
# Test plot() with custom layers and style (mocked)
|
||||
def test_plot_custom_layers_style(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
layers = {'building': {'tags': {'building': True}}}
|
||||
style = {'building': {'fc': '#fff'}}
|
||||
result = prettymaps.plot('Porto Alegre', layers=layers, style=style, show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with radius set to False (mocked)
|
||||
def test_plot_radius_false(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', radius=False, show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with keypoints argument (mocked)
|
||||
def test_plot_keypoints(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: 'mocked_keypoints')
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
keypoints = {'tags': {'natural': ['beach']}, 'specific': {'pedra branca': {'tags': {'natural': ['peak']}}}}
|
||||
result = prettymaps.plot('Garopaba', keypoints=keypoints, show=False)
|
||||
assert result.keypoints == 'mocked_keypoints'
|
||||
|
||||
# Test plot() with postprocessing function (mocked)
|
||||
def test_plot_postprocessing(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
def postproc(gdfs):
|
||||
gdfs['custom'] = 123
|
||||
return gdfs
|
||||
result = prettymaps.plot('Porto Alegre', postprocessing=postproc, show=False)
|
||||
assert result.geodataframes['custom'] == 123
|
||||
|
||||
# Test plot() with save_as argument (mocked file save)
|
||||
def test_plot_save_as(monkeypatch, tmp_path):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
monkeypatch.setattr('matplotlib.pyplot.savefig', lambda *a, **k: None)
|
||||
save_path = tmp_path / 'out.png'
|
||||
result = prettymaps.plot('Porto Alegre', save_as=str(save_path), show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with circle, radius, and dilate arguments (mocked)
|
||||
def test_plot_circle_radius_dilate(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', circle=True, radius=1000, dilate=50, show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with mode='plotter' (mocked vsketch)
|
||||
def test_plot_mode_plotter(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
class DummyVsk:
|
||||
def display(self):
|
||||
pass
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'init_plot', lambda *a, **k: (None, None, DummyVsk()))
|
||||
result = prettymaps.plot('Porto Alegre', mode='plotter', show=True)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test multiplot() with custom Subplot styles (mocked)
|
||||
def test_multiplot_custom_subplots(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'plot', lambda *a, **k: type('FakePlot', (), {'geodataframes': {}, 'fig': None, 'ax': None, 'background': None, 'keypoints': None})())
|
||||
s1 = prettymaps.Subplot('Cidade Baixa, Porto Alegre', style={'building': {'palette': ['#49392C']}})
|
||||
s2 = prettymaps.Subplot('Bom Fim, Porto Alegre', style={'building': {'palette': ['#BA2D0B']}})
|
||||
prettymaps.multiplot(s1, s2, figsize=(4,4))
|
||||
|
||||
# Test plot() returns object with all expected attributes (mocked)
|
||||
def test_plot_types(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
assert hasattr(result, 'fig')
|
||||
assert hasattr(result, 'ax')
|
||||
assert hasattr(result, 'background')
|
||||
assert hasattr(result, 'keypoints')
|
||||
|
||||
# Test plot() with credit argument (mocked)
|
||||
def test_plot_credit(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
credit = {'text': 'Test credit'}
|
||||
result = prettymaps.plot('Porto Alegre', credit=credit, show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with custom figsize argument (mocked)
|
||||
def test_plot_custom_figsize(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', figsize=(5,5), show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with x, y, scale_x, scale_y, rotation params (mocked)
|
||||
def test_plot_transform_params(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', x=1, y=2, scale_x=0.5, scale_y=0.5, rotation=45, show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with show=True and show=False (mocked plt.show)
|
||||
def test_plot_show_true_false(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
monkeypatch.setattr('matplotlib.pyplot.show', lambda *a, **k: None)
|
||||
prettymaps.plot('Porto Alegre', show=True)
|
||||
prettymaps.plot('Porto Alegre', show=False)
|
||||
|
||||
# Test plot() with update_preset argument (mocked)
|
||||
def test_plot_update_preset(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'manage_presets', lambda *a, **k: ({'building': {}}, {}, None, None, None))
|
||||
result = prettymaps.plot('Porto Alegre', update_preset='default', show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with semantic=True (mocked)
|
||||
def test_plot_semantic(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', semantic=True, show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
|
||||
# Test plot() with adjust_aspect_ratio=False (mocked)
|
||||
def test_plot_adjust_aspect_ratio(monkeypatch):
|
||||
import prettymaps.draw as draw
|
||||
monkeypatch.setattr(draw, 'get_gdfs', lambda *a, **k: {'perimeter': get_gdf(), 'building': get_gdf()})
|
||||
monkeypatch.setattr(draw, 'create_background', lambda *a, **k: (None, 0,0,0,0,0,0))
|
||||
monkeypatch.setattr(draw, 'draw_layers', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_keypoints', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_background', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_credit', lambda *a, **k: None)
|
||||
monkeypatch.setattr(draw, 'draw_hillshade', lambda *a, **k: None)
|
||||
result = prettymaps.plot('Porto Alegre', adjust_aspect_ratio=False, show=False)
|
||||
assert hasattr(result, 'geodataframes')
|
||||
23
tests/test_app_runs.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
|
||||
def test_streamlit_app_runs():
|
||||
# Start the Streamlit app in headless mode
|
||||
proc = subprocess.Popen(
|
||||
[sys.executable, "-m", "streamlit", "run", os.path.abspath("app.py"), "--server.headless", "true"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
try:
|
||||
# Wait a few seconds to see if it crashes
|
||||
time.sleep(10)
|
||||
# Check if the process is still running (should be)
|
||||
assert proc.poll() is None, "Streamlit app crashed on startup"
|
||||
finally:
|
||||
proc.terminate()
|
||||
try:
|
||||
proc.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
proc.kill()
|
||||