jimmy60504 commited on
Commit
69dde6d
·
1 Parent(s): 8d4cef3

docs: refine specifications for clarity and consistency in core rules and examples

Browse files
Files changed (3) hide show
  1. .github/spec-template.md +9 -7
  2. spec/spec.md +0 -135
  3. spec/task.md +0 -111
.github/spec-template.md CHANGED
@@ -19,7 +19,7 @@
19
  - **版本與相容性**:如何識別破壞性變更、遷移策略(若有)。
20
 
21
  ## 4. 不變條件與限制(Invariants & Limits)
22
- - **核心規則**:業務邏輯中不可破壞的假設(如取樣率、窗口長度、測站數上限等)。
23
  - **邊界情境與降級**:資料不足/缺漏/格式錯誤時的行為(退回/佔位/跳過/重試)。
24
  - **資源上限**:記憶體/時間/API 配額(語義層級,具體值置於設定檔)。
25
 
@@ -58,18 +58,20 @@
58
 
59
  | 項目 | 預設值 | 來源 |
60
  |------|--------|------|
61
- | 取樣率 | 100 Hz | 硬編 |
62
- | 窗口長度 | 30 | 模型輸入約束 |
63
- | 最大測站數 | 25 | 批次上限 |
64
- | 預設 Vs30 | 600 m/s | 降級用 |
65
 
66
  ---
67
 
68
  ## 附錄 B:資料欄位(可選)
69
 
70
  ### 輸入欄位範例
71
- - `station/site_info.csv`: `[Station, Latitude, Longitude, Elevation, ...]`
72
- - `station/eew_target.csv`: `[station, latitude, longitude, elevation, ...]`
 
 
 
73
 
74
  ---
75
 
 
19
  - **版本與相容性**:如何識別破壞性變更、遷移策略(若有)。
20
 
21
  ## 4. 不變條件與限制(Invariants & Limits)
22
+ - **核心規則**:業務邏輯中不可破壞的假設(如資料採樣率、處理窗口大小、並行數量上限等)。
23
  - **邊界情境與降級**:資料不足/缺漏/格式錯誤時的行為(退回/佔位/跳過/重試)。
24
  - **資源上限**:記憶體/時間/API 配額(語義層級,具體值置於設定檔)。
25
 
 
58
 
59
  | 項目 | 預設值 | 來源 |
60
  |------|--------|------|
61
+ | 常數 1 | A | 硬編/約束/降級 |
62
+ | 常數 2 | B | 硬編/約束/降級 |
63
+ | 常數 N | N | 硬編/約束/降級 |
 
64
 
65
  ---
66
 
67
  ## 附錄 B:資料欄位(可選)
68
 
69
  ### 輸入欄位範例
70
+ - `[源 1 路徑]`: `[欄位 A, 欄位 B, 欄位 C, ...]`
71
+ - `[源 2 路徑]`: `[欄位 D, 欄位 E, 欄位 F, ...]`
72
+
73
+ ### 輸出欄位範例
74
+ - `[輸出格式]`: `[欄位 1, 欄位 2, 欄位 3, ...]`
75
 
76
  ---
77
 
spec/spec.md DELETED
@@ -1,135 +0,0 @@
1
- # TTSAM 規格與設計說明(spec.md)
2
-
3
- 本文件記錄 TTSAM(Taiwan Transformer-based Shake Alert Model)的設計理念、需求規格、資料流程、核心不變條件(invariants)、常數及可擴充點,用來指導未來的需求討論與程式碼產生。撰寫新功能、修正 bug、或重構前,請先確認是否符合此文件。
4
-
5
- — 最後更新:2025-10-25
6
-
7
-
8
- ## 1. 專案目標與範疇
9
- - 目標
10
- - 從地震波形資料(MSEED 或即時串流)與測站場址參數推估全台各目標測站的 PGA 與震度分布。
11
- - 提供互動式地圖與圖表,協助快速比對「預測結果」與「實際觀測」。
12
- - 非目標
13
- - 不是地震檢測與定位系統(震央位置需由使用者/上游系統提供)。
14
- - 不負責資料蒐集(即時系統中由 Earthworm/外部來源提供)。
15
-
16
-
17
- ## 2. 使用者故事(User Stories)與驗收標準
18
- 1) 作為地震分析人員,我想用 GUI 選擇歷史事件、時間窗與震央位置,快速看到波形與預測震度圖。
19
- - 驗收:
20
- - 可於 UI 選擇事件、start、duration、震央經緯度。
21
- - 載入後顯示:輸入測站分布、所選時間窗的波形(距離排序)、並可再按一次「執行預測」。
22
-
23
- 2) 作為預警作業人員,我想看到「預測震度圖」與「實際震度圖」對照,並有清楚統計摘要。
24
- - 驗收:
25
- - 右側顯示互動式預測地圖(固定高度 800px),左側顯示實際震度圖或空白占位。
26
- - 提供文字摘要:使用測站數、缺分量統計、目標點數、最大震度、時間窗資訊。
27
-
28
- 3) 作為系統維運人員,我需要在測站資料或 Vs30 缺漏時系統仍可運作,並清楚告知降級模式。
29
- - 驗收:
30
- - 站點欄位缺漏或找不到時跳過(或降級處理),持續運行並記錄 log。
31
- - Vs30 查詢失敗時使用使用者預設值(預設 600 m/s),記 log。
32
-
33
- 4) 作為開發者,我想新增更多目標測站/事件,不需要改模型或核心流程。
34
- - 驗收:
35
- - 在 `station/eew_target.csv`、`EARTHQUAKE_EVENTS` 增補資料,即可被 UI/預測流程正確使用。
36
-
37
-
38
- ## 3. 架構與資料流程(高層)
39
- - Gradio 應用(`app.py`)
40
- - 載入事件 MSEED(ObsPy) → 選 25 近站(`site_info.csv`) → 訊號處理(去平均、10 Hz 低通)→ 波形/站點打包 → 模型預測 → Folium 地圖輸出。
41
- - 以 Hugging Face 下載臺灣 Vs30 NetCDF,失敗時降級使用使用者輸入值。
42
- - 分批對目標站(`eew_target.csv`)做推論,每批最多 25 點。
43
- - 模型(內建於 `app.py`)
44
- - CNN 特徵擷取 + 位置/場址(lat, lon, elev, Vs30)Positional Embedding → Transformer Encoder → MLP → MDN → PGA 期望值。
45
- - 即時系統(`ttsam_realtime.py`,輔助參考)
46
- - Earthworm→Flask/SocketIO 顯示,流程與核心概念一致,但非本 GUI 的執行主體。
47
-
48
-
49
- ## 4. 核心不變條件(Invariants)與常數
50
- - 取樣率與窗口
51
- - 取樣率固定為 100 Hz。
52
- - 模型輸入固定長度 30 秒 → 3000 點;若小於 30 秒,尾段以 0 遮罩補齊。
53
- - 測站數
54
- - 輸入測站最多 25 個;若不足 25 仍可推論並在 UI 顯示警告。
55
- - 目標測站以 25 點為一批分批推論,最後合併。
56
- - 缺分量處理
57
- - N/E 缺失時以 Z 分量代替,並統計缺分站數於輸出摘要。
58
- - 震度定義
59
- - 依 PGA 門檻(log10 m/s^2)映射至 0,1,2,3,4,5-,5+,6-,6+,7 十級。
60
- - 地圖與圖表
61
- - Folium 地圖高度固定 800px(輸入測站地圖與預測地圖一致),實際震度圖缺失時以空白占位。
62
- - VS30 來源與降級
63
- - 預設從 `SeisBlue/TaiwanVs30` 下載,失敗或查無資料時使用預設/使用者輸入值(預設 600 m/s),記錄 log。
64
- - 檔案欄位要求
65
- - `station/site_info.csv` 必備欄位:`Station, Latitude, Longitude, Elevation`。
66
- - `station/eew_target.csv` 必備欄位:`station, latitude, longitude, elevation`。
67
-
68
-
69
- ## 5. 介面與資料契約(Contracts)
70
- - 模型輸入張量(單批):
71
- - waveform: shape (1, 25, 3000, 3);若不足 25 以 0 padding。
72
- - station: shape (1, 25, 4);欄位 [lat, lon, elev, vs30];不足 25 以 0 padding。
73
- - target: shape (1, 25, 4);欄位 [lat, lon, elev, vs30];不足 25 以 0 padding(但僅取有效目標數的輸出)。
74
- - 模型輸出:
75
- - weight, sigma, mu → 經 `sum(weight*mu, axis=gaussians)` 得每目標點 PGA(log 值單位依訓練定義,現行流程以此值映射至震度)。
76
- - 訊號處理:
77
- - detrend(常數去平均)→ 10 Hz Butterworth 低通(4 階,SOS)→ 正規化與模型處理流程。
78
- - 最近站選取:
79
- - 以 site_info 座標與震央經緯度的平面距離排序,取前 25;去重複(同站不同分量)後以站為單位。
80
-
81
-
82
- ## 6. 錯誤處理與 Log 原則
83
- - 不因單站/單檔錯誤中止全流程,盡量降級繼續:
84
- - 缺站欄位、找不到波形分量、Vs30 查詢失敗等,一律記錄 log 並採取替代方案。
85
- - 使用 loguru;關鍵節點需有 INFO/WARNING/ERROR 訊息,註解請對齊本規格並說明降級策略。
86
-
87
-
88
- ## 7. 檔案與資源
89
- - app.py:Gradio 應用與推論主流程。
90
- - ttsam_realtime.py:即時系統樣板(非 GUI 主流程)。
91
- - station/site_info.csv:輸入測站表(去重複至「站」層級)。
92
- - station/eew_target.csv:目標測站表。
93
- - waveform/*.mseed:事件波形檔。
94
- - intensity_map/YYYYMMDD.png:實際震度圖;缺失時由 UI 呈現空白。
95
- - Hugging Face:SeisBlue/TaiwanVs30(NetCDF)。
96
-
97
-
98
- ## 8. 擴充與維護
99
- - 新增事件:
100
- - 將 MSEED 放入 `waveform/`,並於 `EARTHQUAKE_EVENTS` 新增鍵值;若有實際震度圖,放到 `intensity_map/`,檔名對應日期。
101
- - 新增目標測站:
102
- - 於 `station/eew_target.csv` 追加列,欄位齊全。
103
- - 新增輸入測站:
104
- - 於 `station/site_info.csv` 追加列,欄位齊全;同站不同分量不必新增多列。
105
- - 調整 UI:
106
- - 地圖高度固定 800px;新增元件時保持資訊對稱與清晰;不可移除不變條件檢查。
107
-
108
-
109
- ## 9. 開發環境與相依
110
- - Python 建議版本:3.10–3.11(實測相容性佳)。
111
- - 主要套件:gradio, obspy, numpy, matplotlib, xarray, netCDF4, scipy, pandas, loguru, huggingface_hub, folium, torch。
112
- - GPU 非必需;若可用則自動使用 CUDA。
113
-
114
-
115
- ## 10. 測試建議(最低門檻)
116
- - 快速冒煙測試:
117
- - 可成功載入預設事件;可顯示輸入測站地圖、波形圖。
118
- - 能按「執行預測」產生預測地圖與統計摘要;實際震度圖存在與不存在皆能正常呈現。
119
- - 邊界情境:
120
- - 少於 25 個可用站、N/E 缺分、Vs30 載入失敗、`site_info.csv`/`eew_target.csv` 欄位缺漏、duration < 30 秒。
121
-
122
-
123
- ## 11. 變更紀錄(Decision Log)
124
- - 2025-10-25:建立初版規格,整理 UI、資料流程與模型契約,明確化不變條件與錯誤降級策略。
125
-
126
-
127
- ## 12. 範例:新增規格項(模板)
128
- - 規格標題
129
- - 動機:...
130
- - 行為:...
131
- - 契約(輸入/輸出/限制):...
132
- - 邊界情境與降級:...
133
- - UI 顯示:...
134
- - 驗收:...
135
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
spec/task.md DELETED
@@ -1,111 +0,0 @@
1
- # Task: 將「時間長度」滑桿限制為 0–30 秒(與模型輸入窗口一致)
2
-
3
- - Task ID: T-20251025-duration-slider-0-30
4
- - Owner: <name>
5
- - Date: 2025-10-25
6
- - Status: Planning
7
-
8
- ## 背景與目標
9
- - 背景:模型輸入固定為 30 秒(3000 samples @ 100 Hz),超過 30 秒並無實質效益,且小於 30 秒時會於尾段 0 填充。現行 UI 的「時間長度」滑桿範圍為 1–60 秒,與不變條件不一致,可能造成誤解。
10
- - 目標:將 UI 的「時間長度 (秒)」滑桿範圍調整為 0–30 秒(含 0),與模型契約一致;0 代表完全依賴 0 填充(極端測試/早期秒數)。
11
- - 不在範圍:不調整「開始時間」滑桿範圍;不改變內部資料管線與模型契約;不新增後端 API。
12
-
13
- ## 相關文件與位置
14
- - 規格:`spec/spec.md`(Section 4, 5, 8)
15
- - 主程式:`app.py`(Gradio UI:`duration_slider`)
16
- - 即時樣板:`ttsam_realtime.py`(不需改)
17
- - 站台資料:`station/site_info.csv`, `station/eew_target.csv`(不需改)
18
- - 其他:`change-log.md`
19
-
20
- ## 不變條件與約束(對齊 spec 要點)
21
- - 取樣率固定 100 Hz;模型輸入固定 30 秒(3000 samples)。不足 30 秒時尾段 0 填充。
22
- - 輸入測站最多 25 站;少於 25 站允許,需在 UI 顯示警告,且仍可推論。
23
- - N/E 分量缺失時一律以 Z 分量代替,並統計缺分站數於輸出摘要。
24
- - 目標測站需分批推論,每批最多 25 站,最後合併全部結果。
25
- - Folium 地圖高度固定 800px;實際震度圖缺失時以空白占位並記錄警告。
26
- - Vs30 來自 SeisBlue/TaiwanVs30;查詢/下載失敗時改用使用者預設值(預設 600 m/s),且記錄 log。
27
- - `station/site_info.csv` 欄位:Station, Latitude, Longitude, Elevation。
28
- - `station/eew_target.csv` 欄位:station, latitude, longitude, elevation。
29
-
30
- > 本任務僅限 UI 範圍,不改動上述契約與流程。
31
-
32
- ## 任務拆解(可勾選,可跨對話沿用)
33
- - [ ] 子任務 1:調整 UI 滑桿範圍(變更檔案:`app.py`)
34
- - 將 `duration_slider = gr.Slider(1, 60, value=30, step=1, label="時間長度 (秒)")` 改為 `gr.Slider(0, 30, value=30, step=1, label="時間長度 (秒)")`。
35
- - 驗收標準:UI 顯示範圍為 0–30;預設值 30;無法選到 31–60;可選 0。
36
- - 測試/冒煙:啟動 UI,檢查滑桿邊界值(0、30)與步階 1。
37
- - [ ] 子任務 2:在 UI 增補說明文字(變更檔案:`app.py`)
38
- - 在滑桿附近新增說明:「模型最多 30 秒;小於 30 秒會自動以 0 填充」。
39
- - 驗收標準:說明文字出現在參數區域,語意清楚不遮蓋元件。
40
- - 測試/冒煙:視覺檢查文字呈現;暗色/亮色主題下可讀性良好。
41
- - [ ] 子任務 3:邊界秒數冒煙測試與 log 檢查(無程式碼變更)
42
- - 使用 `duration=0, 5, 30` 分別跑「載入波形」與「執行預測」。
43
- - 驗收標準:
44
- - UI 不崩潰,能產出地圖與統計;輸入波形圖正常標註選取範圍(0 長度時兩條紅線重合)。
45
- - Log 出現「時間長度 X 秒 < 30 秒,將以 0 遮罩補齊至 30 秒」訊息(X=0 或 5)。
46
- - `stats_output` 包含開始/長度/震央資訊、使用測站數、缺分量統計、目標點數、最大震度。
47
- - [ ] 子任務 4:文件同步與變更摘要(變更檔案:`spec/spec.md`, `change-log.md`)
48
- - `spec/spec.md` Section 8「調整 UI」補充:時間長度滑桿限制 0–30 秒(與不變條件一致)。
49
- - `change-log.md` 新增條目:說明 UI 變更與不變條件對齊,無破壞性行為變更。
50
- - 驗收標準:文件語意清楚;不影響既有契約描述。
51
-
52
- > 建議每個子任務都能在 1 小時內完成並可獨立驗收。
53
-
54
- ## 介面與資料形狀變更評估
55
- - UI 影響:僅限滑桿範圍與說明文字;不新增欄位;不移除現有功能。
56
- - I/O shape:不變。模型仍接收 (1, 25, 3000, 3) 的 waveform 與對應 station/target。
57
- - 向後相容:是。先前可選擇 >30 秒的行為被 UI 限制,但屬於與契約對齊的矯正;後端早已固定裁切/補齊至 30 秒,故無破壞性變更。
58
-
59
- ## 降級與記錄策略
60
- - 可能失敗點:無新增失敗點;仍沿用既有的 Vs30 下載失敗、缺分量、測站不足等。
61
- - 降級方案:
62
- - duration < 30 秒:尾段 0 填充(現有行為)。
63
- - 實際震度圖缺失:顯示空白占位並記錄 warning(現有行為)。
64
- - Logging:維持 `extract_waveforms_from_stream` 對不足 30 秒的 INFO 訊息與缺分量統計。
65
-
66
- ## 測試與驗收
67
- - 單元/整合測試:本變更屬 UI 層;暫無自動化測試,採手動冒煙。
68
- - 手動冒煙:
69
- - 啟動方式:
70
- - `./run_local.sh`(若已設定)或
71
- - `python app.py`
72
- - 驗收步驟:
73
- 1) 確認「時間長度」滑桿範圍為 0–30,預設 30。
74
- 2) 分別設定 duration=0、5、30,按「📊 載入波形」,檢查波形圖與範圍標註。
75
- 3) 按「🔮 執行預測」,檢查預測地圖、`stats_output` 文字摘要、log 訊息。
76
- - 預期結果:
77
- - 0/5 秒均能正常運作並顯示補齊提示;30 秒顯示完整窗口。
78
- - 對目標測站分批推論正常,地圖高度為 800px。
79
- - 品質檢查(最低):
80
- - [ ] Build/型別/格式檢查通過
81
- - [ ] 關鍵邊界情境可正確降級並記錄 log(duration=0,5)
82
- - [ ] 與 `spec/spec.md` 之契約一致(0–30 秒 UI 約束)
83
-
84
- ## 風險、回滾與後續
85
- - 風險:
86
- - 使用者既有習慣可能嘗試 >30 秒,需透過說明文字降低困惑。
87
- - 回滾:
88
- - 若需回復,可將滑桿範圍改回 1–60(單一行變更),不影響後端。
89
- - 後續工作:
90
- - 視需求新增「快速鍵/按鈕」切換常用窗口(如 5s/10s/20s/30s)。
91
- - 可考慮將 0–30 秒改為步階 0.5 秒,提供更細控制(需再評估)。
92
-
93
- ## 進度紀錄(跨對話追蹤)
94
- - 2025-10-25 10:00:建立 task 草案,確認不影響後端契約與流程。
95
-
96
- ---
97
-
98
- 附錄 A:Commit 信息模板
99
-
100
- ```
101
- feat(task T-20251025-duration-slider-0-30): limit duration slider to 0–30 seconds
102
-
103
- - UI: change gr.Slider range to 0–30, default 30
104
- - Docs: update spec UI note; add change-log entry
105
-
106
- Refs: T-20251025-duration-slider-0-30
107
- ```
108
-
109
- 附錄 B:分支/PR 命名
110
- - 分支:`feature/T-20251025-duration-slider-0-30`
111
- - PR 標題:`T-20251025-duration-slider-0-30: limit duration slider to 0–30 seconds`