-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapp.py
78 lines (63 loc) · 2.22 KB
/
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from flask import Flask, send_file
from flask import make_response
from io import BytesIO
from PIL import Image
import requests
import mapbox_vector_tile
from shapely.geometry import shape, MultiPolygon
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from matplotlib.collections import PatchCollection
from matplotlib.colors import Normalize
from palettable.colorbrewer.sequential import PuBu_9
from descartes import PolygonPatch
app = Flask(__name__)
BASE_S3_URL = 'https://s3.us-east-2.amazonaws.com/eviction-lab-tilesets/fake'
@app.route('/<tiles>/<int:z>/<int:x>/<int:y>.png')
def serve_tile(tiles, z, x, y):
res = requests.get('{}/{}/{}/{}/{}.pbf'.format(BASE_S3_URL, tiles, z, x, y))
vector_data = mapbox_vector_tile.decode(res.content)
mp = MultiPolygon(
[shape(f['geometry']) for f in vector_data['cities']['features']]
)
# TODO: Make the data property a parameter
data_vals = [f['properties']['population-2010'] for f in vector_data['cities']['features']]
cmap = PuBu_9.mpl_colormap
norm = Normalize(vmin=min(data_vals), vmax=max(data_vals))
patches = []
for idx, p in enumerate(mp):
data = vector_data['cities']['features'][idx]['properties']['population-2010']
if isinstance(data, str):
color = '#000000'
else:
color = cmap(norm(data))
patches.append(PolygonPatch(
p, fc=color, ec='#555555', alpha=1., zorder=1, linewidth=0)
)
fig = plt.figure()
ax = fig.add_subplot(111)
# Setting bounds based on vector tile coordinates
ax.set_xlim(0, 4096)
ax.set_ylim(0, 4096)
ax.set_aspect(1)
ax.add_collection(PatchCollection(patches, match_original=True))
ax.set_xticks([])
ax.set_yticks([])
ax.axis('off')
buf = BytesIO()
plt.savefig(
buf, bbox_inches='tight', pad_inches=0, transparent=True, dpi=450, format='png'
)
plt.close()
buf.seek(0)
size = 258, 258
im = Image.open(buf)
im.thumbnail(size)
im_buf = BytesIO()
im.crop((1, 1, 257, 257)).save(im_buf, 'PNG')
response = make_response(im_buf.getvalue())
response.headers['Content-Type'] = 'image/png'
return response
if __name__ == '__main__':
app.run()