add code to generate member map
This commit is contained in:
parent
4d92a749f7
commit
e2b6c2b3b6
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
__pycache__
|
||||
*.png
|
||||
*json
|
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@ -0,0 +1,20 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG PLZ_DATA=Postleitzahlengebiete_-_OSM.geojson
|
||||
ARG PLZ_HIGHLIGHT=wtf_member_plz_prefixes.json
|
||||
|
||||
# Set up environment with dependencies
|
||||
RUN apt-get update && apt-get install libblas-dev python3-pip libgeos-dev wget -y
|
||||
COPY requirements.txt ./
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# Copy all relevant data
|
||||
COPY $PLZ_DATA ./
|
||||
COPY $PLZ_HIGHLIGHT ./
|
||||
|
||||
# Render map
|
||||
COPY main.py ./
|
||||
RUN python3 main.py --plz-data $PLZ_DATA --plz-highlight $PLZ_HIGHLIGHT --out /tmp/map.png
|
||||
|
||||
# Output map; use with "docker build -t wtf-map . && docker run wtf-map > map.png"
|
||||
CMD ["cat", "/tmp/map.png"]
|
36
README.md
36
README.md
@ -1,3 +1,35 @@
|
||||
# member-map
|
||||
# Map of Germany with highlighted WTF member locations
|
||||
|
||||
Generate a map of Germany with highlighted WTF member locations.
|
||||
## Docker Usage
|
||||
|
||||
Download the Germany PLZ dataset in the GeoJSON format from
|
||||
https://opendata-esri-de.opendata.arcgis.com/datasets/5b203df4357844c8a6715d7d411a8341_0
|
||||
and place the file in the root of this repository.
|
||||
|
||||
Place a JSON file containing a list of PLZ prefixes as `wtf_member_plz_prefixes.json` in
|
||||
the root of this repository.
|
||||
The file contents should look like `["121", "635"]` for PLZ data that is anonymized to
|
||||
the first three digits.
|
||||
|
||||
The following will build a Docker image and render the map with the default
|
||||
configuration for the WTF member PLZ prefix data:
|
||||
```
|
||||
docker build -t wtf-map .
|
||||
docker run wtf-map > map.png
|
||||
```
|
||||
|
||||
Note, the build command already renders the map and thus can take a moment.
|
||||
The run command just outputs the already rendered image to be piped into any target
|
||||
file on the host system.
|
||||
|
||||
## Script Usage
|
||||
|
||||
In case you'd like custom colors or use different data, you are encouraged to use the
|
||||
script explicity.
|
||||
To get all relevant requirements, you can `pip install -r requirements.txt`, but note,
|
||||
you might need to install BLAS and GEOS libraries on your system.
|
||||
|
||||
The following will tell you all about what you can adjust for a custom visualization:
|
||||
```
|
||||
python main.py --help
|
||||
```
|
||||
|
103
main.py
Normal file
103
main.py
Normal file
@ -0,0 +1,103 @@
|
||||
import argparse
|
||||
import json
|
||||
|
||||
import cartopy.crs as ccrs
|
||||
import geopandas as gpd
|
||||
import geoplot
|
||||
import geoplot.crs as gcrs
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
def main(
|
||||
plz_data_path: str,
|
||||
plz_prefixes_path: str,
|
||||
output_file_path: str,
|
||||
map_background_color: str,
|
||||
map_accent_color: str,
|
||||
image_background_color: str,
|
||||
):
|
||||
if not output_file_path.endswith(".png"):
|
||||
raise ValueError(f"Output file needs to be a .png but is {output_file_path}")
|
||||
|
||||
with open(plz_prefixes_path, "r") as fh:
|
||||
plz_prefixes = json.load(fh)
|
||||
with open(plz_data_path, "r") as fh:
|
||||
plz_geojson_data = json.load(fh)
|
||||
|
||||
data = gpd.GeoDataFrame.from_features(plz_geojson_data["features"])
|
||||
data["highlighted"] = False
|
||||
for plz_prefix in plz_prefixes:
|
||||
data.loc[data["plz"].str.startswith(plz_prefix), "highlighted"] = True
|
||||
|
||||
ax = plt.axes(projection=ccrs.TransverseMercator())
|
||||
geoplot.polyplot(
|
||||
data,
|
||||
projection=gcrs.TransverseMercator(),
|
||||
edgecolor=map_background_color,
|
||||
facecolor=map_background_color,
|
||||
linewidth=0.3,
|
||||
ax=ax,
|
||||
)
|
||||
geoplot.polyplot(
|
||||
data[data["highlighted"]],
|
||||
projection=gcrs.TransverseMercator(),
|
||||
edgecolor=map_accent_color,
|
||||
facecolor=map_accent_color,
|
||||
linewidth=0.3,
|
||||
ax=ax,
|
||||
)
|
||||
|
||||
ax.set_facecolor(image_background_color)
|
||||
plt.tight_layout()
|
||||
plt.savefig(
|
||||
output_file_path, dpi=300, facecolor=image_background_color, edgecolor="none"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"--plz-data",
|
||||
required=True,
|
||||
help="A GEOJSON file with a 'plz' feature, like the one for Germany that can be"
|
||||
+ " downloaded from "
|
||||
+ "https://opendata-esri-de.opendata.arcgis.com/datasets/5b203df4357844c8a6715d7d411a8341_0",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--plz-highlight",
|
||||
required=True,
|
||||
help="A JSON file with a list of PLZ (prefixes) that should be highlighted.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--out",
|
||||
required=True,
|
||||
help="A .png file path where the generated image should be stored.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--img-bg-color",
|
||||
type=str,
|
||||
default="#EDEFEB",
|
||||
help="Color outside of the map, the image file background.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--map-bg-color",
|
||||
type=str,
|
||||
default="#202020",
|
||||
help="Color code for the background map, non highlighted areas.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--map-accent-color",
|
||||
type=str,
|
||||
default="#EF7C21",
|
||||
help="Color code for the highlighted areas on the map.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
main(
|
||||
plz_data_path=args.plz_data,
|
||||
plz_prefixes_path=args.plz_highlight,
|
||||
output_file_path=args.out,
|
||||
map_background_color=args.map_bg_color,
|
||||
map_accent_color=args.map_accent_color,
|
||||
image_background_color=args.img_bg_color,
|
||||
)
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
geopandas==0.11.1
|
||||
geoplot==0.5.1
|
Loading…
Reference in New Issue
Block a user