-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtile_handler.py
More file actions
152 lines (127 loc) · 5.92 KB
/
tile_handler.py
File metadata and controls
152 lines (127 loc) · 5.92 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import services
import webapp2
import logging
import cache
import json
import config_creds
import ee_assets
from google.appengine.api import images
from google.appengine.api import urlfetch
EE_TILE_URL = 'https://earthengine.googleapis.com/map/%s/%i/%i/%i?token=%s'
class TileHandler(webapp2.RequestHandler):
def checkCoords(self, z,x,y):
if y<0 or y>=2**z:
return False
else:
return True
def get(self, collection_id, layer_id, z, x, y):
z=int(z)
x=int(x)
y=int(y)
#check tile coords
if self.checkCoords(z,x,y):
while x < 0:
x = x + 2**z
while x >= 2**z:
x = x- 2**z
self.getTile(collection_id, layer_id,z,x,y)
else:
logging.info('Coords out of range, serving blank.')
tile = open('empty.png', 'r').read()
services.writeResult(tile, self.response, format='image/png')
def getTile(self,collection_id, layer_id,z,x,y):
#first try and fetch from cache
tile_key = 'mapotron-maps_%s_%s_%i_%i_%i' % (collection_id, layer_id, int(z), int(x), int(y))
tile_meta_key = 'mapotron-maps_%s_%s' % (collection_id, layer_id)
tile = services.checkCache(tile_key, type='blob')
try:
#test tile image
image = images.Image(image_data=tile)
logging.info("Image format %s" % image.format)
if image.format >= 0:
logging.info('serving image from cache')
services.writeResult(tile, self.response, format = 'image/png')
else:
raise Exception('format','Bad format in blobstore')
except Exception as e:
logging.info(e)
#No tile available, find the latest mapid/token for this key
map_key = 'mapotron-maps_%s_%s' % (collection_id, layer_id)
tile_meta = services.checkCache(map_key, type='json')
if tile_meta is None:
#fetch fresh tile metadata if none
import config_creds
import config
import ee
import ee_services
## this is where I imagine putting .clip(bbox)...
geodesic = ee.Geometry.Rectangle(-180, -60, 180, 85)
bbox = ee.Geometry(geodesic, None, False)
logging.info('No tile meta, generating new map from %s ' % (ee_assets.layers[collection_id]["layers"][layer_id]["id"]))
image = ee.Image(ee_assets.layers[collection_id]["layers"][layer_id]["id"])
tile_meta = ee_services.getMap(
image.mask(image.gt(0)).clip(bbox),
ee_assets.layers[collection_id]["layers"][layer_id]["viz_params"],
tile_meta_key)
services.cacheResult({
"mapid": tile_meta["mapid"],
"token":tile_meta["token"]},
map_key
)
#first try to get it from EE using the mapid/token given
tile_url = EE_TILE_URL % (
tile_meta["mapid"], int(z), int(x), int(y), tile_meta["token"])
logging.info("First try, using cache token -- fetching tile from %s" % tile_url)
#test that it is an image
try:
tile = urlfetch.fetch(tile_url, deadline=60).content
image = images.Image(image_data = tile)
if image.format >= 0 :
logging.info('caching tile')
services.cacheResult(tile, tile_key, type = 'blob')
services.writeResult(tile, self.response, format='image/png')
else:
raise Exception('format','Bad format')
except Exception as e:
#expired, try again
import config_creds
import config
import ee
import ee_services
logging.info('Generating new map from %s ' % (ee_assets.layers[collection_id]["layers"][layer_id]["id"]))
## this is where I imagine putting .clip(bbox)...
geodesic = ee.Geometry.Rectangle(-180, -60, 180, 85)
bbox = ee.Geometry(geodesic, None, False)
image = ee.Image(ee_assets.layers[collection_id]["layers"][layer_id]["id"])
tile_meta = ee_services.getMap(
image.mask(image.gt(0)).clip(bbox),
ee_assets.layers[collection_id]["layers"][layer_id]["viz_params"],
tile_meta_key)
services.cacheResult({
"mapid": tile_meta["mapid"],
"token":tile_meta["token"]},
map_key
)
#first try to get it from EE using the mapid/token given
tile_url = EE_TILE_URL % (
tile_meta["mapid"], int(z), int(x), int(y), tile_meta["token"])
logging.info("Second Try, using new token - Fetching tile from %s" % tile_url)
try:
tile = urlfetch.fetch(tile_url, deadline=60).content
image = images.Image(image_data = tile)
if image.format >0:
services.cacheResult(tile, tile_key, type = 'blob')
services.writeResult(tile, self.response, format='image/png')
else:
raise Exception ('format',image.format)
except Exception as e:
logging.info(e)
services.writeResult(
{"error": "Tile not available, we tried!"},
self.response, format = 'application/json')
application = webapp2.WSGIApplication([
webapp2.Route(r'/api/tile/<collection_id>/<layer_id>/<z>/<x>/<y>.png',
handler='tile_handler.TileHandler:get')],
debug=True)