giswqs pre-commit-ci[bot] commited on
Commit
24eacbb
·
unverified ·
1 Parent(s): 53d3b0b

Add gradio app (#1)

Browse files

* Add gradio app

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

Files changed (7) hide show
  1. .github/workflows/sync-hf.yml +20 -0
  2. .gitignore +2 -2
  3. .pre-commit-config.yaml +32 -0
  4. Dockerfile +14 -0
  5. README.md +12 -0
  6. main.py +96 -0
  7. requirements.txt +4 -0
.github/workflows/sync-hf.yml ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Sync to Hugging Face hub
2
+ on:
3
+ push:
4
+ branches: [main]
5
+
6
+ # to run this workflow manually from the Actions tab
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ sync-to-hub:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+ lfs: true
17
+ - name: Push to hub
18
+ env:
19
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
20
+ run: git push --force https://giswqs:[email protected]/spaces/giswqs/ee-tile-request main
.gitignore CHANGED
@@ -174,9 +174,9 @@ cython_debug/
174
  .abstra/
175
 
176
  # Visual Studio Code
177
- # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
178
  # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
179
- # and can be added to the global gitignore or merged into this file. However, if you prefer,
180
  # you could uncomment the following to ignore the enitre vscode folder
181
  # .vscode/
182
 
 
174
  .abstra/
175
 
176
  # Visual Studio Code
177
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
178
  # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
179
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
180
  # you could uncomment the following to ignore the enitre vscode folder
181
  # .vscode/
182
 
.pre-commit-config.yaml ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: check-toml
6
+ - id: check-yaml
7
+ - id: end-of-file-fixer
8
+ types: [python]
9
+ - id: trailing-whitespace
10
+ - id: requirements-txt-fixer
11
+ - id: check-added-large-files
12
+ args: ["--maxkb=500"]
13
+
14
+ - repo: https://github.com/psf/black
15
+ rev: 25.1.0
16
+ hooks:
17
+ - id: black-jupyter
18
+
19
+ - repo: https://github.com/codespell-project/codespell
20
+ rev: v2.4.1
21
+ hooks:
22
+ - id: codespell
23
+ args:
24
+ [
25
+ "--ignore-words-list=aci,acount,acounts,fallow,ges,hart,hist,nd,ned,ois,wqs,watermask,tre,mape",
26
+ "--skip=*.csv,*.geojson,*.json,*.yml*.js,*.html,*cff,*.pdf",
27
+ ]
28
+
29
+ - repo: https://github.com/kynan/nbstripout
30
+ rev: 0.8.1
31
+ hooks:
32
+ - id: nbstripout
Dockerfile ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12-slim
2
+
3
+ RUN apt-get update && apt-get install -y curl git npm && rm -rf /var/lib/apt/lists/*
4
+
5
+ WORKDIR /app
6
+
7
+ COPY requirements.txt .
8
+ COPY main.py .
9
+
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
+
12
+ EXPOSE 7860
13
+
14
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Ee Tile Request
3
+ emoji: 😻
4
+ colorFrom: pink
5
+ colorTo: gray
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ short_description: Earth Engine Tile URL Generator
10
+ ---
11
+
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
main.py ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import ee
4
+ import geemap
5
+ import gradio as gr
6
+ from fastapi import FastAPI, HTTPException
7
+ from pydantic import BaseModel
8
+ from geemap.ee_tile_layers import _get_tile_url_format, _validate_palette
9
+ from starlette.middleware.cors import CORSMiddleware
10
+
11
+ # Earth Engine auth
12
+ if "EARTHENGINE_TOKEN" not in os.environ:
13
+ raise RuntimeError("EARTHENGINE_TOKEN environment variable not found")
14
+
15
+ try:
16
+ geemap.ee_initialize()
17
+ except Exception as e:
18
+ raise RuntimeError(f"Earth Engine authentication failed: {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)
26
+ else:
27
+ data_dict = ee.data.getAsset(asset_id)
28
+ data_type = data_dict["type"]
29
+ if data_type == "IMAGE":
30
+ ee_object = ee.Image(asset_id)
31
+ elif data_type == "IMAGE_COLLECTION":
32
+ ee_object = ee.ImageCollection(asset_id)
33
+ elif data_type in ["TABLE", "TABLE_COLLECTION"]:
34
+ ee_object = ee.FeatureCollection(asset_id)
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):
41
+ if len(vis_params) == 0:
42
+ vis_params = "{}"
43
+ if vis_params.startswith("{") and vis_params.endswith("}"):
44
+ vis_params = json.loads(vis_params)
45
+ else:
46
+ raise ValueError(f"Unsupported vis_params type: {type(vis_params)}")
47
+ elif isinstance(vis_params, dict):
48
+ pass
49
+ else:
50
+ raise ValueError(f"Unsupported vis_params type: {type(vis_params)}")
51
+
52
+ if "palette" in vis_params:
53
+ vis_params["palette"] = _validate_palette(vis_params["palette"])
54
+
55
+ url = _get_tile_url_format(ee_object, vis_params)
56
+ return url
57
+ except Exception as e:
58
+ return f"Error: {str(e)}"
59
+
60
+
61
+ # ---- FastAPI ----
62
+ app = FastAPI()
63
+ app.add_middleware(
64
+ CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]
65
+ )
66
+
67
+
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}
79
+
80
+
81
+ # ---- Gradio UI ----
82
+ gradio_ui = gr.Interface(
83
+ fn=get_tile,
84
+ inputs=[
85
+ gr.Textbox(label="Earth Engine Asset ID", placeholder="e.g., USGS/SRTMGL1_003"),
86
+ gr.Textbox(
87
+ label="Visualization Parameters (JSON)",
88
+ placeholder='{"min":0,"max":5000,"palette":"terrain"}',
89
+ ),
90
+ ],
91
+ outputs="text",
92
+ title="Earth Engine Tile URL Generator",
93
+ description="Supports ee.Image, ee.ImageCollection, ee.FeatureCollection. Tile URL is suitable for basemap usage.",
94
+ )
95
+
96
+ app = gr.mount_gradio_app(app, gradio_ui, path="/")
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi
2
+ git+https://github.com/gee-community/geemap.git
3
+ gradio
4
+ uvicorn