Add uvicorn
Browse files
app.py
CHANGED
|
@@ -22,9 +22,6 @@ from urllib.parse import unquote
|
|
| 22 |
from pydantic import BaseModel, HttpUrl
|
| 23 |
|
| 24 |
|
| 25 |
-
# class FileUrlRequest(BaseModel):
|
| 26 |
-
# url: HttpUrl
|
| 27 |
-
|
| 28 |
app = FastAPI()
|
| 29 |
|
| 30 |
# --- Helper Functions ---
|
|
@@ -382,37 +379,51 @@ def process_and_display(file_obj, url_str, buffer_m, progress=gr.Progress()):
|
|
| 382 |
progress(1, desc="Done!")
|
| 383 |
return m._repr_html_(), None, stats_df, dem_html, slope_html, geometry_json, buffer_geometry_json
|
| 384 |
|
|
|
|
| 385 |
@app.get("/api/geometry")
|
| 386 |
def calculate_geometry_metrics(file_url: str):
|
| 387 |
"""
|
| 388 |
-
Accepts a URL to a KML/GeoJSON file
|
| 389 |
-
|
| 390 |
-
found, and returns the results in JSON format.
|
| 391 |
"""
|
| 392 |
try:
|
| 393 |
-
|
|
|
|
|
|
|
|
|
|
| 394 |
input_gdf = get_gdf_from_url(decoded_url)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 395 |
input_gdf = preprocess_gdf(input_gdf)
|
|
|
|
|
|
|
| 396 |
geometry_gdf = next((input_gdf.iloc[[i]] for i in range(len(input_gdf)) if is_valid_polygon(input_gdf.iloc[[i]])), None)
|
| 397 |
-
geometry_gdf = to_best_crs(geometry_gdf)
|
| 398 |
|
| 399 |
-
|
| 400 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 401 |
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
"
|
|
|
|
| 405 |
}
|
| 406 |
-
|
| 407 |
-
return payload
|
| 408 |
-
|
| 409 |
except ValueError as e:
|
| 410 |
-
# Handle
|
| 411 |
raise HTTPException(status_code=400, detail=str(e))
|
| 412 |
except Exception as e:
|
| 413 |
-
# Handle unexpected
|
| 414 |
-
|
| 415 |
-
|
| 416 |
|
| 417 |
def calculate_indices(
|
| 418 |
geometry_json, buffer_geometry_json, veg_indices, evi_vars, date_range,
|
|
@@ -807,8 +818,11 @@ with gr.Blocks(theme=theme, title="Kamlan: KML Analyzer") as demo:
|
|
| 807 |
""")
|
| 808 |
|
| 809 |
|
|
|
|
|
|
|
|
|
|
| 810 |
|
| 811 |
if __name__ == "__main__":
|
| 812 |
-
|
| 813 |
-
#
|
| 814 |
-
|
|
|
|
| 22 |
from pydantic import BaseModel, HttpUrl
|
| 23 |
|
| 24 |
|
|
|
|
|
|
|
|
|
|
| 25 |
app = FastAPI()
|
| 26 |
|
| 27 |
# --- Helper Functions ---
|
|
|
|
| 379 |
progress(1, desc="Done!")
|
| 380 |
return m._repr_html_(), None, stats_df, dem_html, slope_html, geometry_json, buffer_geometry_json
|
| 381 |
|
| 382 |
+
|
| 383 |
@app.get("/api/geometry")
|
| 384 |
def calculate_geometry_metrics(file_url: str):
|
| 385 |
"""
|
| 386 |
+
Accepts a URL to a KML/GeoJSON file, calculates the area and
|
| 387 |
+
perimeter of the first valid polygon, and returns the results.
|
|
|
|
| 388 |
"""
|
| 389 |
try:
|
| 390 |
+
# Decode URL-encoded characters (e.g., %2F for /)
|
| 391 |
+
decoded_url = unquote(file_url)
|
| 392 |
+
|
| 393 |
+
# Fetch and parse the spatial data
|
| 394 |
input_gdf = get_gdf_from_url(decoded_url)
|
| 395 |
+
if input_gdf is None or input_gdf.empty:
|
| 396 |
+
raise ValueError("Could not read geometry from the provided URL.")
|
| 397 |
+
|
| 398 |
+
# Clean up geometries (e.g., fix invalid polygons)
|
| 399 |
input_gdf = preprocess_gdf(input_gdf)
|
| 400 |
+
|
| 401 |
+
# Find the first valid polygon in the GeoDataFrame
|
| 402 |
geometry_gdf = next((input_gdf.iloc[[i]] for i in range(len(input_gdf)) if is_valid_polygon(input_gdf.iloc[[i]])), None)
|
|
|
|
| 403 |
|
| 404 |
+
if geometry_gdf is None:
|
| 405 |
+
raise ValueError("No valid polygon found in the provided file.")
|
| 406 |
+
|
| 407 |
+
# Project to a suitable CRS for accurate measurements
|
| 408 |
+
projected_gdf = to_best_crs(geometry_gdf)
|
| 409 |
+
|
| 410 |
+
# Calculate area (in hectares) and perimeter (in meters)
|
| 411 |
+
area_hectares = projected_gdf.area.item() / 10000
|
| 412 |
+
perimeter_meters = projected_gdf.length.item()
|
| 413 |
|
| 414 |
+
# Return the results in a JSON response
|
| 415 |
+
return {
|
| 416 |
+
"area_hectares": round(area_hectares, 4),
|
| 417 |
+
"perimeter_meters": round(perimeter_meters, 4),
|
| 418 |
}
|
| 419 |
+
|
|
|
|
|
|
|
| 420 |
except ValueError as e:
|
| 421 |
+
# Handle specific errors like bad URLs, no polygons, etc. with a 400 Bad Request
|
| 422 |
raise HTTPException(status_code=400, detail=str(e))
|
| 423 |
except Exception as e:
|
| 424 |
+
# Handle any other unexpected errors with a 500 Internal Server Error
|
| 425 |
+
print(f"An unexpected error occurred in /api/geometry: {e}")
|
| 426 |
+
raise HTTPException(status_code=500, detail="An unexpected server error occurred.")
|
| 427 |
|
| 428 |
def calculate_indices(
|
| 429 |
geometry_json, buffer_geometry_json, veg_indices, evi_vars, date_range,
|
|
|
|
| 818 |
""")
|
| 819 |
|
| 820 |
|
| 821 |
+
# Mount the Gradio app onto the FastAPI app
|
| 822 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
| 823 |
+
|
| 824 |
|
| 825 |
if __name__ == "__main__":
|
| 826 |
+
import uvicorn
|
| 827 |
+
# This allows running the app with `python App.py`
|
| 828 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|