Spaces:
Sleeping
Sleeping
Update src/streamlit_app.py
Browse files- src/streamlit_app.py +9 -13
src/streamlit_app.py
CHANGED
|
@@ -25,36 +25,34 @@ st.markdown("""
|
|
| 25 |
with st.sidebar:
|
| 26 |
st.header("⚙️ 分析參數設定")
|
| 27 |
|
| 28 |
-
# FR1: 時間範圍設定
|
| 29 |
data_fetch_minutes = st.number_input(
|
| 30 |
"獲取過去幾分鐘的資料?",
|
| 31 |
min_value=5, max_value=60, value=15, step=5
|
| 32 |
)
|
| 33 |
|
| 34 |
-
# FR2: STA/LTA 參數設定
|
| 35 |
st.subheader("P波撿拾 (STA/LTA) 參數")
|
| 36 |
sta_window = st.slider("STA 窗長 (秒)", min_value=0.1, max_value=5.0, value=1.0, step=0.1)
|
| 37 |
lta_window = st.slider("LTA 窗長 (秒)", min_value=5.0, max_value=60.0, value=10.0, step=1.0)
|
| 38 |
trigger_threshold = st.slider("觸發門檻值", min_value=1.5, max_value=10.0, value=3.0, step=0.5)
|
| 39 |
off_threshold = st.slider("關閉門檻值", min_value=0.1, max_value=2.0, value=1.5, step=0.1)
|
| 40 |
|
| 41 |
-
# 執行按鈕
|
| 42 |
if 'analysis_results' not in st.session_state:
|
| 43 |
st.session_state.analysis_results = None
|
| 44 |
|
| 45 |
if st.button("獲取最新地震資料並分析", type="primary"):
|
| 46 |
with st.spinner("正在執行分析...請稍候..."):
|
| 47 |
-
# 1. 資料獲取 (FR1)
|
| 48 |
end_time = UTCDateTime.now()
|
| 49 |
start_time = end_time - timedelta(minutes=data_fetch_minutes)
|
| 50 |
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
if stream and inventory:
|
| 54 |
-
# 2. P波自動撿拾 (FR2)
|
| 55 |
p_picks = earthquake_analyzer.pick_p_waves(stream, sta_window, lta_window, trigger_threshold, off_threshold)
|
| 56 |
|
| 57 |
-
# 4. 震源定位 (FR4)
|
| 58 |
location_result = None
|
| 59 |
if len(p_picks) >= 4:
|
| 60 |
st.write(f"找到 {len(p_picks)} 個 P 波觸發,開始定位...")
|
|
@@ -62,7 +60,6 @@ with st.sidebar:
|
|
| 62 |
else:
|
| 63 |
st.write(f"P 波觸發測站數 ({len(p_picks)}) 不足 4 個,無法進行定位。")
|
| 64 |
|
| 65 |
-
# 將所有結果存儲到 session state
|
| 66 |
st.session_state.analysis_results = {
|
| 67 |
"stream": stream,
|
| 68 |
"inventory": inventory,
|
|
@@ -70,7 +67,7 @@ with st.sidebar:
|
|
| 70 |
"location_result": location_result
|
| 71 |
}
|
| 72 |
else:
|
| 73 |
-
st.session_state.analysis_results = None
|
| 74 |
|
| 75 |
st.success("分析完成!")
|
| 76 |
|
|
@@ -83,7 +80,6 @@ if st.session_state.analysis_results:
|
|
| 83 |
|
| 84 |
st.header("📊 分析結果")
|
| 85 |
|
| 86 |
-
# 3. 波形視覺化 (FR3)
|
| 87 |
if p_picks:
|
| 88 |
st.subheader("測站波形與 P 波初達")
|
| 89 |
waveform_fig = visualizer.plot_waveforms_with_picks(p_picks)
|
|
@@ -91,14 +87,13 @@ if st.session_state.analysis_results:
|
|
| 91 |
else:
|
| 92 |
st.info("在所有獲取的波形中,均未成功觸發 P 波。請嘗試調整 STA/LTA 參數或擴大時間範圍。")
|
| 93 |
|
| 94 |
-
# 5. 定位結果視覺化 (FR5)
|
| 95 |
st.subheader("震源定位結果")
|
| 96 |
if len(p_picks) < 4:
|
| 97 |
st.warning("P 波撿拾測站不足(少於4個),無法進行定位。")
|
| 98 |
elif not location_result:
|
| 99 |
st.error("定位計算失敗,可能是測站分佈不佳或資料品質問題。")
|
| 100 |
else:
|
| 101 |
-
col1, col2 = st.columns([2, 1])
|
| 102 |
with col1:
|
| 103 |
st.pydeck_chart(visualizer.plot_event_map(inventory, p_picks, location_result))
|
| 104 |
|
|
@@ -115,4 +110,5 @@ if st.session_state.analysis_results:
|
|
| 115 |
station_list = [p['station'] for p in p_picks]
|
| 116 |
st.text(", ".join(station_list))
|
| 117 |
else:
|
| 118 |
-
st.info("點擊左側的「獲取最新地震資料並分析」按鈕以開始。")
|
|
|
|
|
|
| 25 |
with st.sidebar:
|
| 26 |
st.header("⚙️ 分析參數設定")
|
| 27 |
|
|
|
|
| 28 |
data_fetch_minutes = st.number_input(
|
| 29 |
"獲取過去幾分鐘的資料?",
|
| 30 |
min_value=5, max_value=60, value=15, step=5
|
| 31 |
)
|
| 32 |
|
|
|
|
| 33 |
st.subheader("P波撿拾 (STA/LTA) 參數")
|
| 34 |
sta_window = st.slider("STA 窗長 (秒)", min_value=0.1, max_value=5.0, value=1.0, step=0.1)
|
| 35 |
lta_window = st.slider("LTA 窗長 (秒)", min_value=5.0, max_value=60.0, value=10.0, step=1.0)
|
| 36 |
trigger_threshold = st.slider("觸發門檻值", min_value=1.5, max_value=10.0, value=3.0, step=0.5)
|
| 37 |
off_threshold = st.slider("關閉門檻值", min_value=0.1, max_value=2.0, value=1.5, step=0.1)
|
| 38 |
|
|
|
|
| 39 |
if 'analysis_results' not in st.session_state:
|
| 40 |
st.session_state.analysis_results = None
|
| 41 |
|
| 42 |
if st.button("獲取最新地震資料並分析", type="primary"):
|
| 43 |
with st.spinner("正在執行分析...請稍候..."):
|
|
|
|
| 44 |
end_time = UTCDateTime.now()
|
| 45 |
start_time = end_time - timedelta(minutes=data_fetch_minutes)
|
| 46 |
|
| 47 |
+
# 將 UTCDateTime 物件轉為字串,再傳遞給快取函式
|
| 48 |
+
stream, inventory = earthquake_fetcher.get_earthquake_data(
|
| 49 |
+
start_time_str=str(start_time),
|
| 50 |
+
end_time_str=str(end_time)
|
| 51 |
+
)
|
| 52 |
|
| 53 |
if stream and inventory:
|
|
|
|
| 54 |
p_picks = earthquake_analyzer.pick_p_waves(stream, sta_window, lta_window, trigger_threshold, off_threshold)
|
| 55 |
|
|
|
|
| 56 |
location_result = None
|
| 57 |
if len(p_picks) >= 4:
|
| 58 |
st.write(f"找到 {len(p_picks)} 個 P 波觸發,開始定位...")
|
|
|
|
| 60 |
else:
|
| 61 |
st.write(f"P 波觸發測站數 ({len(p_picks)}) 不足 4 個,無法進行定位。")
|
| 62 |
|
|
|
|
| 63 |
st.session_state.analysis_results = {
|
| 64 |
"stream": stream,
|
| 65 |
"inventory": inventory,
|
|
|
|
| 67 |
"location_result": location_result
|
| 68 |
}
|
| 69 |
else:
|
| 70 |
+
st.session_state.analysis_results = None
|
| 71 |
|
| 72 |
st.success("分析完成!")
|
| 73 |
|
|
|
|
| 80 |
|
| 81 |
st.header("📊 分析結果")
|
| 82 |
|
|
|
|
| 83 |
if p_picks:
|
| 84 |
st.subheader("測站波形與 P 波初達")
|
| 85 |
waveform_fig = visualizer.plot_waveforms_with_picks(p_picks)
|
|
|
|
| 87 |
else:
|
| 88 |
st.info("在所有獲取的波形中,均未成功觸發 P 波。請嘗試調整 STA/LTA 參數或擴大時間範圍。")
|
| 89 |
|
|
|
|
| 90 |
st.subheader("震源定位結果")
|
| 91 |
if len(p_picks) < 4:
|
| 92 |
st.warning("P 波撿拾測站不足(少於4個),無法進行定位。")
|
| 93 |
elif not location_result:
|
| 94 |
st.error("定位計算失敗,可能是測站分佈不佳或資料品質問題。")
|
| 95 |
else:
|
| 96 |
+
col1, col2 = st.columns([2, 1])
|
| 97 |
with col1:
|
| 98 |
st.pydeck_chart(visualizer.plot_event_map(inventory, p_picks, location_result))
|
| 99 |
|
|
|
|
| 110 |
station_list = [p['station'] for p in p_picks]
|
| 111 |
st.text(", ".join(station_list))
|
| 112 |
else:
|
| 113 |
+
st.info("點擊左側的「獲取最新地震資料並分析」按鈕以開始。")
|
| 114 |
+
|