giswqs commited on
Commit
8dbd528
·
unverified ·
1 Parent(s): 1411614

Add date range and bbox filter (#4)

Browse files

* Add date range and bbox filter

* Update README

Files changed (2) hide show
  1. README.md +210 -0
  2. main.py +39 -2
README.md CHANGED
@@ -10,4 +10,214 @@ license: mit
10
  short_description: Earth Engine Tile URL Generator
11
  ---
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
10
  short_description: Earth Engine Tile URL Generator
11
  ---
12
 
13
+ # Earth Engine Tile URL Generator
14
+
15
+ A FastAPI service that generates tile URLs for Google Earth Engine assets, suitable for use with web mapping libraries like Leaflet, Mapbox, or OpenLayers.
16
+
17
+ ## Features
18
+
19
+ - Generate tile URLs for Earth Engine Images, ImageCollections, and FeatureCollections
20
+ - Optional date range filtering for ImageCollections
21
+ - Optional bounding box filtering for spatial subsetting
22
+ - Customizable visualization parameters
23
+ - REST API and web UI (Gradio)
24
+ - FastAPI auto-generated documentation
25
+
26
+ ## Setup
27
+
28
+ ### Prerequisites
29
+
30
+ - Python 3.12+
31
+ - Google Earth Engine account with authentication token
32
+
33
+ ### Installation
34
+
35
+ 1. Clone the repository:
36
+ ```bash
37
+ git clone <repository-url>
38
+ cd ee-tile-request
39
+ ```
40
+
41
+ 2. Install dependencies:
42
+ ```bash
43
+ pip install -r requirements.txt
44
+ ```
45
+
46
+ 3. Set your Earth Engine token:
47
+ ```bash
48
+ export EARTHENGINE_TOKEN="your_token_here"
49
+ ```
50
+
51
+ ## Running the App
52
+
53
+ ### Local Development
54
+
55
+ ```bash
56
+ uvicorn main:app --host 0.0.0.0 --port 7860 --reload
57
+ ```
58
+
59
+ ### Docker
60
+
61
+ ```bash
62
+ docker build -t ee-tile-request .
63
+ docker run -p 7860:7860 -e EARTHENGINE_TOKEN="your_token" ee-tile-request
64
+ ```
65
+
66
+ ### Access Points
67
+
68
+ - **Web UI**: http://localhost:7860
69
+ - **API Documentation**: http://localhost:7860/docs
70
+ - **API Endpoint**: POST http://localhost:7860/tile
71
+
72
+ ## API Usage
73
+
74
+ ### Endpoint
75
+
76
+ `POST /tile`
77
+
78
+ ### Request Parameters
79
+
80
+ | Parameter | Type | Required | Description |
81
+ |-----------|------|----------|-------------|
82
+ | `asset_id` | string | Yes | Earth Engine asset ID (e.g., "USGS/SRTMGL1_003") or ee expression |
83
+ | `vis_params` | object | No | Visualization parameters (min, max, palette, bands, etc.) |
84
+ | `start_date` | string | No | Start date for filtering (format: "YYYY-MM-DD") |
85
+ | `end_date` | string | No | End date for filtering (format: "YYYY-MM-DD") |
86
+ | `bbox` | array | No | Bounding box [west, south, east, north] in degrees |
87
+
88
+ ### Examples
89
+
90
+ #### Basic Request
91
+
92
+ ```bash
93
+ curl -X POST "http://localhost:7860/tile" \
94
+ -H "Content-Type: application/json" \
95
+ -d '{
96
+ "asset_id": "USGS/SRTMGL1_003",
97
+ "vis_params": {
98
+ "min": 0,
99
+ "max": 5000,
100
+ "palette": ["blue", "green", "red"]
101
+ }
102
+ }'
103
+ ```
104
+
105
+ #### With Date Range Filtering
106
+
107
+ Filter Sentinel-2 imagery to a specific time period:
108
+
109
+ ```bash
110
+ curl -X POST "http://localhost:7860/tile" \
111
+ -H "Content-Type: application/json" \
112
+ -d '{
113
+ "asset_id": "COPERNICUS/S2_SR",
114
+ "start_date": "2023-06-01",
115
+ "end_date": "2023-08-31",
116
+ "vis_params": {
117
+ "bands": ["B4", "B3", "B2"],
118
+ "min": 0,
119
+ "max": 3000
120
+ }
121
+ }'
122
+ ```
123
+
124
+ #### With Bounding Box Filtering
125
+
126
+ Filter to San Francisco Bay Area:
127
+
128
+ ```bash
129
+ curl -X POST "http://localhost:7860/tile" \
130
+ -H "Content-Type: application/json" \
131
+ -d '{
132
+ "asset_id": "COPERNICUS/S2_SR",
133
+ "bbox": [-122.5, 37.5, -122.0, 38.0],
134
+ "vis_params": {
135
+ "bands": ["B4", "B3", "B2"],
136
+ "min": 0,
137
+ "max": 3000
138
+ }
139
+ }'
140
+ ```
141
+
142
+ #### Combined Filters
143
+
144
+ Date range and spatial filtering together:
145
+
146
+ ```bash
147
+ curl -X POST "http://localhost:7860/tile" \
148
+ -H "Content-Type: application/json" \
149
+ -d '{
150
+ "asset_id": "COPERNICUS/S2_SR",
151
+ "start_date": "2023-07-01",
152
+ "end_date": "2023-07-31",
153
+ "bbox": [-122.5, 37.5, -122.0, 38.0],
154
+ "vis_params": {
155
+ "bands": ["B4", "B3", "B2"],
156
+ "min": 0,
157
+ "max": 3000
158
+ }
159
+ }'
160
+ ```
161
+
162
+ ### Response
163
+
164
+ ```json
165
+ {
166
+ "tile_url": "https://earthengine.googleapis.com/v1/projects/.../maps/.../tiles/{z}/{x}/{y}"
167
+ }
168
+ ```
169
+
170
+ ### Using with Web Mapping Libraries
171
+
172
+ #### Leaflet
173
+
174
+ ```javascript
175
+ const tileUrl = response.tile_url;
176
+ L.tileLayer(tileUrl, {
177
+ attribution: 'Google Earth Engine',
178
+ maxZoom: 18
179
+ }).addTo(map);
180
+ ```
181
+
182
+ #### Mapbox GL JS
183
+
184
+ ```javascript
185
+ map.addSource('ee-tiles', {
186
+ 'type': 'raster',
187
+ 'tiles': [response.tile_url],
188
+ 'tileSize': 256
189
+ });
190
+
191
+ map.addLayer({
192
+ 'id': 'ee-layer',
193
+ 'type': 'raster',
194
+ 'source': 'ee-tiles'
195
+ });
196
+ ```
197
+
198
+ ## Web UI (Gradio)
199
+
200
+ Access the web interface at http://localhost:7860 to:
201
+ - Enter Earth Engine asset IDs
202
+ - Specify visualization parameters as JSON
203
+ - Get tile URLs instantly
204
+ - No need to write code
205
+
206
+ ## Supported Data Types
207
+
208
+ - **Images** (`ee.Image`): Single images with optional clipping to bbox
209
+ - **ImageCollections** (`ee.ImageCollection`): Filtered by date and/or bbox
210
+ - **FeatureCollections** (`ee.FeatureCollection`): Filtered by bbox
211
+
212
+ ## Notes
213
+
214
+ - Date filtering only works with ImageCollections
215
+ - Bounding box format: `[west, south, east, north]` in WGS84 degrees
216
+ - All filtering parameters are optional and backward compatible
217
+ - Check the FastAPI docs at `/docs` for interactive API testing
218
+
219
+ ## License
220
+
221
+ MIT
222
+
223
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
main.py CHANGED
@@ -19,7 +19,7 @@ except Exception as e:
19
 
20
 
21
  # ---- Shared Tile Logic ----
22
- def get_tile(asset_id, vis_params=None):
23
  try:
24
  if asset_id.startswith("ee."):
25
  ee_object = eval(asset_id)
@@ -35,6 +35,38 @@ def get_tile(asset_id, vis_params=None):
35
  else:
36
  raise ValueError(f"Unsupported data type: {data_type}")
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  if vis_params is None:
39
  vis_params = {}
40
  if isinstance(vis_params, str):
@@ -68,11 +100,16 @@ app.add_middleware(
68
  class TileRequest(BaseModel):
69
  asset_id: str
70
  vis_params: dict | None = None
 
 
 
71
 
72
 
73
  @app.post("/tile")
74
  def get_tile_api(req: TileRequest):
75
- result = get_tile(req.asset_id, req.vis_params)
 
 
76
  if isinstance(result, str) and result.startswith("Error"):
77
  raise HTTPException(status_code=400, detail=result)
78
  return {"tile_url": result}
 
19
 
20
 
21
  # ---- Shared Tile Logic ----
22
+ def get_tile(asset_id, vis_params=None, start_date=None, end_date=None, bbox=None):
23
  try:
24
  if asset_id.startswith("ee."):
25
  ee_object = eval(asset_id)
 
35
  else:
36
  raise ValueError(f"Unsupported data type: {data_type}")
37
 
38
+ # Apply date range filtering for ImageCollections
39
+ if start_date or end_date:
40
+ if isinstance(ee_object, ee.ImageCollection):
41
+ if start_date and end_date:
42
+ ee_object = ee_object.filterDate(start_date, end_date)
43
+ elif start_date:
44
+ ee_object = ee_object.filterDate(start_date, "2100-01-01")
45
+ elif end_date:
46
+ ee_object = ee_object.filterDate("1970-01-01", end_date)
47
+ else:
48
+ raise ValueError(
49
+ "Date filtering is only supported for ImageCollections"
50
+ )
51
+
52
+ # Apply bounding box filtering
53
+ if bbox:
54
+ if len(bbox) != 4:
55
+ raise ValueError(
56
+ "bbox must be a list of 4 values: [west, south, east, north]"
57
+ )
58
+ geometry = ee.Geometry.BBox(*bbox)
59
+ if isinstance(ee_object, ee.ImageCollection):
60
+ ee_object = ee_object.filterBounds(geometry)
61
+ elif isinstance(ee_object, ee.FeatureCollection):
62
+ ee_object = ee_object.filterBounds(geometry)
63
+ elif isinstance(ee_object, ee.Image):
64
+ ee_object = ee_object.clip(geometry)
65
+ else:
66
+ raise ValueError(
67
+ f"Bounding box filtering not supported for {type(ee_object)}"
68
+ )
69
+
70
  if vis_params is None:
71
  vis_params = {}
72
  if isinstance(vis_params, str):
 
100
  class TileRequest(BaseModel):
101
  asset_id: str
102
  vis_params: dict | None = None
103
+ start_date: str | None = None
104
+ end_date: str | None = None
105
+ bbox: list[float] | None = None # [west, south, east, north]
106
 
107
 
108
  @app.post("/tile")
109
  def get_tile_api(req: TileRequest):
110
+ result = get_tile(
111
+ req.asset_id, req.vis_params, req.start_date, req.end_date, req.bbox
112
+ )
113
  if isinstance(result, str) and result.startswith("Error"):
114
  raise HTTPException(status_code=400, detail=result)
115
  return {"tile_url": result}