File size: 5,588 Bytes
50dea54
a6ec964
50dea54
 
a6ec964
 
 
 
50dea54
84f4007
 
a6ec964
 
 
 
 
 
 
 
 
e4955ba
a6ec964
e4955ba
a6ec964
 
 
50dea54
 
a6ec964
8d21f7b
50dea54
a6ec964
e4955ba
50dea54
e4955ba
50dea54
ca2c43d
84f4007
50dea54
a6ec964
 
 
 
 
 
 
84f4007
 
 
 
 
 
a6ec964
84f4007
a6ec964
 
e4955ba
 
 
 
50526ba
e4955ba
 
 
 
ca2c43d
 
 
 
e4955ba
 
 
 
50526ba
 
e4955ba
 
 
a6ec964
84f4007
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e4955ba
 
84f4007
50dea54
e4955ba
84f4007
 
 
 
 
 
e4955ba
84f4007
e4955ba
 
 
84f4007
e4955ba
 
84f4007
 
e4955ba
84f4007
e4955ba
84f4007
e4955ba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a6ec964
84f4007
e4955ba
50dea54
 
 
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
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)