e-vca / app.py
rapsoj's picture
Upload 4 files
84f4007 verified
Raw
History Blame Contribute Delete
5.59 kB
import gradio as gr
import importlib
import os
from data.options import iso_options, rp_options
from data.geometry import fetch_gis_subdivisions, has_associated_features
from data.hotosm import download_hotosm_data
from data.ckan import download_resource_ckan
from analysis import run_analyses
# Discover available hazard modules dynamically
def get_available_hazards():
hazard_dir = "hazards"
files = os.listdir(hazard_dir)
hazards = [
f.replace(".py", "") for f in files
if f.endswith(".py") and f != "__init__.py"
]
return sorted([(h.capitalize(), h) for h in hazards])
hazard_options = get_available_hazards()
# Gradio app
with gr.Blocks(title="Hazard Raster Downloader") as demo:
gr.Markdown("## eVCA Hazard and Exposure Data Downloader\nSelect a country, hazard, and return period to generate hazard rasters and supporting exposure data.")
with gr.Row():
hazard_input = gr.Dropdown(choices=hazard_options, label="Hazard", value="flood", interactive=True)
iso_input = gr.Dropdown(choices=iso_options, label="Country", interactive=True, value=None)
rp_input = gr.Dropdown(choices=rp_options, label="Return Period (years)", value=10)
subdivision_input = gr.Dropdown(choices=[], label="Subdivision", interactive=True, visible=False)
generate_btn = gr.Button("Generate Raster", visible=False)
status_text = gr.Markdown("")
file_output = gr.Files(label="Downloads", interactive=False)
analysis_output = gr.Markdown("", label="Analysis Results")
def wrapper(hazard, iso, rp, subdivision):
# Dynamic import of selected hazard module
try:
hazard_module = importlib.import_module(f"hazards.{hazard}")
generate_func = getattr(hazard_module, f"generate_{hazard}_raster")
except (ModuleNotFoundError, AttributeError):
return [], f"❌ Error: No raster generation function found for hazard '{hazard}'."
# Extract just the subdivision name if it's not the country-level option
subdivision_name = None
if subdivision and not subdivision.endswith("(Country level)"):
subdivision_name = subdivision
# Generate raster
raster_path, msg = generate_func(iso, rp, subdivision_name)
iso3 = iso.split(",")[-1].strip() if "," in iso else iso
# HOTOSM Downloads
pp_path = download_hotosm_data(iso3, feature_type="populated_places", geometry="points")
roads_path = download_hotosm_data(iso3, feature_type="roads", geometry="lines")
buildings_path = download_hotosm_data(iso3, feature_type="buildings", geometry="polygons")
# CKAN Downloads
pop_paths = download_resource_ckan(iso3, dataset_prefix="cod-ps")
admin_path = download_resource_ckan(iso3, dataset_prefix="cod-ab")
files = []
if raster_path:
files.append(raster_path)
if pp_path:
files.append(pp_path)
if roads_path:
files.append(roads_path)
if buildings_path:
files.append(buildings_path)
if admin_path:
files.extend(admin_path)
if pop_paths:
files.extend(pop_paths)
# Run all available analyses
analysis_results = run_analyses(
raster_path=raster_path,
pp_path=pp_path,
roads_path=roads_path,
buildings_path=buildings_path,
admin_path=admin_path,
pop_paths=pop_paths
)
if analysis_results:
analysis_msg = analysis_results
else:
analysis_msg = "βœ… No analyses could be run."
if not files:
msg += " ⚠️ No data could be downloaded."
return files, msg, analysis_msg
def get_subdivision_options(iso_code):
has_features, data = has_associated_features(iso_code)
subdivisions = fetch_gis_subdivisions(iso_code)
# Lookup the country name from iso_options
country_name = next((name for name, code in iso_options if code == iso_code), iso_code)
if not has_features:
# Only subdivisions available
return (
gr.update(choices=subdivisions, visible=True, value=None),
gr.update(visible=False),
gr.update(value=f"βœ… Subdivisions loaded for {country_name}. Please select one.")
)
else:
# Add the whole country as the first option
country_option = f"{country_name} (Country level)"
return (
gr.update(choices=[country_option] + subdivisions, visible=True, value=country_option),
gr.update(visible=False),
gr.update(value=f"βœ… Country and subdivisions loaded for {country_name}. You may choose either.")
)
iso_input.change(
fn=lambda iso: gr.update(value="πŸ”„ Loading subdivisions..."),
inputs=iso_input,
outputs=status_text
).then(
fn=get_subdivision_options,
inputs=iso_input,
outputs=[subdivision_input, generate_btn, status_text]
)
subdivision_input.change(
fn=lambda s: gr.update(visible=True) if s else gr.update(visible=False),
inputs=subdivision_input,
outputs=generate_btn
)
generate_btn.click(
fn=wrapper,
inputs=[hazard_input, iso_input, rp_input, subdivision_input],
outputs=[file_output, status_text, analysis_output]
)
if __name__ == "__main__":
demo.launch(share=True)