Spaces:
Runtime error
Runtime error
Commit ·
285c304
1
Parent(s): 26071fc
update UI to improve Ground Truth image handling and adjust height for better alignment
Browse files
app.py
CHANGED
|
@@ -634,7 +634,7 @@ def create_intensity_map(pga_list, target_names, epicenter_lat=None, epicenter_l
|
|
| 634 |
zoom_start=7,
|
| 635 |
tiles='OpenStreetMap',
|
| 636 |
width='100%',
|
| 637 |
-
height='
|
| 638 |
)
|
| 639 |
|
| 640 |
# 如果有震央位置,標記震央
|
|
@@ -759,6 +759,16 @@ def load_ground_truth_image(event_name):
|
|
| 759 |
return None
|
| 760 |
|
| 761 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 762 |
def create_input_station_map(selected_stations, epicenter_lat, epicenter_lon):
|
| 763 |
"""創建輸入測站分布地圖:顯示所有測站 + 突顯被選中的 25 個"""
|
| 764 |
import folium
|
|
@@ -770,7 +780,7 @@ def create_input_station_map(selected_stations, epicenter_lat, epicenter_lon):
|
|
| 770 |
zoom_start=8,
|
| 771 |
tiles='OpenStreetMap',
|
| 772 |
width='100%',
|
| 773 |
-
height='
|
| 774 |
)
|
| 775 |
|
| 776 |
# 建立被選中測站的 set(用於快速查詢)
|
|
@@ -882,9 +892,12 @@ def create_input_station_map(selected_stations, epicenter_lat, epicenter_lon):
|
|
| 882 |
return m
|
| 883 |
|
| 884 |
|
| 885 |
-
def load_and_display_waveform(event_name, start_time,
|
| 886 |
"""載入並顯示波形,讓使用者確認範圍"""
|
| 887 |
try:
|
|
|
|
|
|
|
|
|
|
| 888 |
# 1. 載入完整的 mseed 檔案
|
| 889 |
logger.info(f"載入地震事件: {event_name}")
|
| 890 |
st = load_waveform(event_name)
|
|
@@ -905,7 +918,8 @@ def load_and_display_waveform(event_name, start_time, end_time, epicenter_lon, e
|
|
| 905 |
station_map_html = station_map._repr_html_()
|
| 906 |
|
| 907 |
info_text = f"✅ 已載入波形資料\n"
|
| 908 |
-
info_text += f"
|
|
|
|
| 909 |
info_text += f"震央位置: ({epicenter_lon:.4f}, {epicenter_lat:.4f})\n"
|
| 910 |
info_text += f"選擇了 {len(selected_stations)} 個最近的測站\n"
|
| 911 |
info_text += f"請確認波形範圍後,點擊「執行預測」按鈕"
|
|
@@ -920,9 +934,12 @@ def load_and_display_waveform(event_name, start_time, end_time, epicenter_lon, e
|
|
| 920 |
return None, None, f"錯誤: {str(e)}", gr.update(interactive=False)
|
| 921 |
|
| 922 |
|
| 923 |
-
def predict_intensity(event_name, start_time,
|
| 924 |
"""執行震度預測"""
|
| 925 |
try:
|
|
|
|
|
|
|
|
|
|
| 926 |
# 1. 載入完整的 mseed 檔案
|
| 927 |
logger.info(f"載入地震事件: {event_name}")
|
| 928 |
st = load_waveform(event_name)
|
|
@@ -1018,9 +1035,11 @@ def predict_intensity(event_name, start_time, end_time, epicenter_lon, epicenter
|
|
| 1018 |
# 10. 統計資訊
|
| 1019 |
max_intensity = max([calculate_intensity(pga, label=True) for pga in pga_list])
|
| 1020 |
stats = f"✅ 預測完成!\n"
|
| 1021 |
-
stats += f"
|
|
|
|
| 1022 |
stats += f"震央位置: ({epicenter_lon:.4f}, {epicenter_lat:.4f})\n"
|
| 1023 |
stats += f"使用測站數: {len(waveforms)} / 25\n"
|
|
|
|
| 1024 |
stats += f"預測最大震度: {max_intensity}"
|
| 1025 |
|
| 1026 |
logger.info("預測完成!")
|
|
@@ -1066,8 +1085,8 @@ with gr.Blocks(title="TTSAM 震度預測系統") as demo:
|
|
| 1066 |
)
|
| 1067 |
|
| 1068 |
with gr.Row():
|
| 1069 |
-
start_slider = gr.Slider(0, 300, value=0, step=1, label="
|
| 1070 |
-
|
| 1071 |
|
| 1072 |
gr.Markdown("### 震央位置")
|
| 1073 |
with gr.Row():
|
|
@@ -1095,7 +1114,12 @@ with gr.Blocks(title="TTSAM 震度預測系統") as demo:
|
|
| 1095 |
# 左下:Ground Truth
|
| 1096 |
with gr.Column(scale=1):
|
| 1097 |
gr.Markdown("## Ground Truth 震度分布")
|
| 1098 |
-
ground_truth_image = gr.Image(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1099 |
|
| 1100 |
# 右下:預測震度地圖
|
| 1101 |
with gr.Column(scale=1):
|
|
@@ -1103,17 +1127,24 @@ with gr.Blocks(title="TTSAM 震度預測系統") as demo:
|
|
| 1103 |
intensity_map = gr.HTML(label="互動式震度地圖", elem_id="intensity_map")
|
| 1104 |
|
| 1105 |
# 綁定事件
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1106 |
# 第一步:載入波形
|
| 1107 |
load_waveform_btn.click(
|
| 1108 |
fn=load_and_display_waveform,
|
| 1109 |
-
inputs=[event_dropdown, start_slider,
|
| 1110 |
outputs=[input_station_map, waveform_plot, info_output, predict_btn]
|
| 1111 |
)
|
| 1112 |
|
| 1113 |
# 第二步:執行預測
|
| 1114 |
predict_btn.click(
|
| 1115 |
fn=predict_intensity,
|
| 1116 |
-
inputs=[event_dropdown, start_slider,
|
| 1117 |
outputs=[ground_truth_image, intensity_map, stats_output]
|
| 1118 |
)
|
| 1119 |
|
|
|
|
| 634 |
zoom_start=7,
|
| 635 |
tiles='OpenStreetMap',
|
| 636 |
width='100%',
|
| 637 |
+
height='800px' # 設定固定高度 800,與 Ground Truth 圖片匹配
|
| 638 |
)
|
| 639 |
|
| 640 |
# 如果有震央位置,標記震央
|
|
|
|
| 759 |
return None
|
| 760 |
|
| 761 |
|
| 762 |
+
def on_event_select(event_name):
|
| 763 |
+
"""當選擇事件時立即載入 Ground Truth 圖片"""
|
| 764 |
+
ground_truth_path = load_ground_truth_image(event_name)
|
| 765 |
+
if ground_truth_path:
|
| 766 |
+
return ground_truth_path
|
| 767 |
+
else:
|
| 768 |
+
# 如果找不到圖片,返回 None(Gradio 會顯示空白)
|
| 769 |
+
return None
|
| 770 |
+
|
| 771 |
+
|
| 772 |
def create_input_station_map(selected_stations, epicenter_lat, epicenter_lon):
|
| 773 |
"""創建輸入測站分布地圖:顯示所有測站 + 突顯被選中的 25 個"""
|
| 774 |
import folium
|
|
|
|
| 780 |
zoom_start=8,
|
| 781 |
tiles='OpenStreetMap',
|
| 782 |
width='100%',
|
| 783 |
+
height='800px'
|
| 784 |
)
|
| 785 |
|
| 786 |
# 建立被選中測站的 set(用於快速查詢)
|
|
|
|
| 892 |
return m
|
| 893 |
|
| 894 |
|
| 895 |
+
def load_and_display_waveform(event_name, start_time, duration, epicenter_lon, epicenter_lat):
|
| 896 |
"""載入並顯示波形,讓使用者確認範圍"""
|
| 897 |
try:
|
| 898 |
+
# 計算結束時間
|
| 899 |
+
end_time = start_time + duration
|
| 900 |
+
|
| 901 |
# 1. 載入完整的 mseed 檔案
|
| 902 |
logger.info(f"載入地震事件: {event_name}")
|
| 903 |
st = load_waveform(event_name)
|
|
|
|
| 918 |
station_map_html = station_map._repr_html_()
|
| 919 |
|
| 920 |
info_text = f"✅ 已載入波形資料\n"
|
| 921 |
+
info_text += f"開始時間: {start_time:.1f} 秒\n"
|
| 922 |
+
info_text += f"時間長度: {duration:.1f} 秒 ({start_time:.1f} - {end_time:.1f})\n"
|
| 923 |
info_text += f"震央位置: ({epicenter_lon:.4f}, {epicenter_lat:.4f})\n"
|
| 924 |
info_text += f"選擇了 {len(selected_stations)} 個最近的測站\n"
|
| 925 |
info_text += f"請確認波形範圍後,點擊「執行預測」按鈕"
|
|
|
|
| 934 |
return None, None, f"錯誤: {str(e)}", gr.update(interactive=False)
|
| 935 |
|
| 936 |
|
| 937 |
+
def predict_intensity(event_name, start_time, duration, epicenter_lon, epicenter_lat):
|
| 938 |
"""執行震度預測"""
|
| 939 |
try:
|
| 940 |
+
# 計算結束時間
|
| 941 |
+
end_time = start_time + duration
|
| 942 |
+
|
| 943 |
# 1. 載入完整的 mseed 檔案
|
| 944 |
logger.info(f"載入地震事件: {event_name}")
|
| 945 |
st = load_waveform(event_name)
|
|
|
|
| 1035 |
# 10. 統計資訊
|
| 1036 |
max_intensity = max([calculate_intensity(pga, label=True) for pga in pga_list])
|
| 1037 |
stats = f"✅ 預測完成!\n"
|
| 1038 |
+
stats += f"開始時間: {start_time:.1f} 秒\n"
|
| 1039 |
+
stats += f"時間長度: {duration:.1f} 秒 ({start_time:.1f} - {end_time:.1f})\n"
|
| 1040 |
stats += f"震央位置: ({epicenter_lon:.4f}, {epicenter_lat:.4f})\n"
|
| 1041 |
stats += f"使用測站數: {len(waveforms)} / 25\n"
|
| 1042 |
+
stats += f"預測目標點數: {len(all_target_names)}\n"
|
| 1043 |
stats += f"預測最大震度: {max_intensity}"
|
| 1044 |
|
| 1045 |
logger.info("預測完成!")
|
|
|
|
| 1085 |
)
|
| 1086 |
|
| 1087 |
with gr.Row():
|
| 1088 |
+
start_slider = gr.Slider(0, 300, value=0, step=1, label="開始時間 (秒)")
|
| 1089 |
+
duration_slider = gr.Slider(1, 60, value=30, step=1, label="時間長度 (秒)")
|
| 1090 |
|
| 1091 |
gr.Markdown("### 震央位置")
|
| 1092 |
with gr.Row():
|
|
|
|
| 1114 |
# 左下:Ground Truth
|
| 1115 |
with gr.Column(scale=1):
|
| 1116 |
gr.Markdown("## Ground Truth 震度分布")
|
| 1117 |
+
ground_truth_image = gr.Image(
|
| 1118 |
+
label="實際觀測震度",
|
| 1119 |
+
type="filepath",
|
| 1120 |
+
height=800,
|
| 1121 |
+
value=load_ground_truth_image(list(EARTHQUAKE_EVENTS.keys())[0]) # 初始載入第一個事件的 Ground Truth
|
| 1122 |
+
)
|
| 1123 |
|
| 1124 |
# 右下:預測震度地圖
|
| 1125 |
with gr.Column(scale=1):
|
|
|
|
| 1127 |
intensity_map = gr.HTML(label="互動式震度地圖", elem_id="intensity_map")
|
| 1128 |
|
| 1129 |
# 綁定事件
|
| 1130 |
+
# 第零步:選擇事件時立即載入 Ground Truth
|
| 1131 |
+
event_dropdown.change(
|
| 1132 |
+
fn=on_event_select,
|
| 1133 |
+
inputs=[event_dropdown],
|
| 1134 |
+
outputs=[ground_truth_image]
|
| 1135 |
+
)
|
| 1136 |
+
|
| 1137 |
# 第一步:載入波形
|
| 1138 |
load_waveform_btn.click(
|
| 1139 |
fn=load_and_display_waveform,
|
| 1140 |
+
inputs=[event_dropdown, start_slider, duration_slider, epicenter_lon_input, epicenter_lat_input],
|
| 1141 |
outputs=[input_station_map, waveform_plot, info_output, predict_btn]
|
| 1142 |
)
|
| 1143 |
|
| 1144 |
# 第二步:執行預測
|
| 1145 |
predict_btn.click(
|
| 1146 |
fn=predict_intensity,
|
| 1147 |
+
inputs=[event_dropdown, start_slider, duration_slider, epicenter_lon_input, epicenter_lat_input],
|
| 1148 |
outputs=[ground_truth_image, intensity_map, stats_output]
|
| 1149 |
)
|
| 1150 |
|