cwadayi commited on
Commit
69a9699
·
verified ·
1 Parent(s): e4e12de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +19 -151
app.py CHANGED
@@ -2,6 +2,16 @@ import gradio as gr
2
  import random
3
  import textwrap # 用於處理程式碼字串的縮排
4
 
 
 
 
 
 
 
 
 
 
 
5
  # 1. 專案資料 (帶有 Emoji)
6
  projects_data = {
7
  "🌊 地震與波形展示": [
@@ -46,160 +56,18 @@ def recommend_project():
46
  [**點此立即前往 🚀**]({recommendation['url']})
47
  """
48
 
49
- # 3. 教學範例程式碼 (Level 1 - 基礎)
50
- TUTORIAL_CODE_BASIC = textwrap.dedent("""
51
- import gradio as gr
52
-
53
- # 1. 知識庫 (你的地科字典)
54
- geo_dict = {
55
- "板塊構造 (Plate Tectonics)": "地球的岩石圈被分成許多稱為「板塊」的巨大板塊,這些板塊在軟流圈上緩慢移動,彼此碰撞或分離,形成了火山、地震和山脈。",
56
- "地震波 (Seismic Wave)": "地震時從震源向四面方方傳播的能量波。主要分為 P 波(壓縮波,速度快)和 S 波(剪力波,速度慢),它們是我們研究地球內部的主要工具。",
57
- "海嘯 (Tsunami)": "由海底地震、火山爆發或山崩引起的巨大海浪。它在深海中傳播速度極快(可達時速 800 公里),但波高很低;當它靠近淺海岸時,速度減慢,波高則急遽增加。"
58
- }
59
-
60
- # 2. 定義介面函式
61
- def get_definition(term):
62
- return geo_dict.get(term, "查無此名詞")
63
-
64
- # 3. 建立 Gradio 介面
65
- with gr.Blocks(title="我的地科字典") as demo:
66
- gr.Markdown("# 🚀 我的第一個地科 App (Level 1)")
67
-
68
- dropdown = gr.Dropdown(
69
- label="請選擇一個地科名詞",
70
- choices=list(geo_dict.keys())
71
- )
72
-
73
- output_textbox = gr.Textbox(
74
- label="名詞解釋",
75
- lines=5,
76
- interactive=False
77
- )
78
-
79
- dropdown.change(
80
- fn=get_definition,
81
- inputs=dropdown,
82
- outputs=output_textbox
83
- )
84
-
85
- demo.launch()
86
- """)
87
-
88
- # 4. [新增] requirements.txt 範例內容
89
  TUTORIAL_REQUIREMENTS = textwrap.dedent("""
90
  gradio
91
  obspy
92
  folium
93
  """)
94
 
95
- # 5. [新增] 教學範例程式碼 (Level 2 - 進階)
96
- TUTORIAL_CODE_ADVANCED = textwrap.dedent("""
97
- import gradio as gr
98
- import folium
99
- from obspy.clients.fdsn import Client
100
- from obspy import UTCDateTime
101
-
102
- # 1. 定義核心函式:搜尋並繪圖
103
- def fetch_and_plot_events(min_mag, days_ago):
104
- try:
105
- # 設定 FDSN 客戶端 (IRIS)
106
- client = Client("IRIS")
107
-
108
- # 設定時間
109
- endtime = UTCDateTime.now()
110
- starttime = endtime - (days_ago * 24 * 3600)
111
-
112
- # 搜尋地震目錄
113
- catalog = client.get_events(
114
- starttime=starttime,
115
- endtime=endtime,
116
- minmagnitude=min_mag
117
- )
118
-
119
- # 建立 Folium 地圖
120
- m = folium.Map(location=[0, 0], zoom_start=2)
121
-
122
- if len(catalog) == 0:
123
- return "<p>在此條件下查無地震資料,請嘗試放寬搜尋條件。</p>"
124
-
125
- # 將每個地震事件加到地圖上
126
- for event in catalog:
127
- origin = event.preferred_origin()
128
- mag = event.preferred_magnitude().mag
129
-
130
- lat = origin.latitude
131
- lon = origin.longitude
132
- depth_km = origin.depth / 1000.0
133
-
134
- # 依據地震深度給予不同顏色
135
- if depth_km < 70:
136
- color = "green"
137
- elif depth_km < 300:
138
- color = "orange"
139
- else:
140
- color = "red"
141
-
142
- popup_html = f"""
143
- <b>時間:</b> {origin.time.strftime('%Y-%m-%d %H:%M:%S')}<br>
144
- <b>規模 (M):</b> {mag:.1f}<br>
145
- <b>深度 (km):</b> {depth_km:.1f}<br>
146
- <b>位置:</b> ({lat:.2f}, {lon:.2f})
147
- """
148
-
149
- folium.CircleMarker(
150
- location=[lat, lon],
151
- radius=mag * 1.5, # 圓圈大小與規模成正比
152
- popup=folium.Popup(popup_html, max_width=300),
153
- color=color,
154
- fill=True,
155
- fill_color=color,
156
- fill_opacity=0.6
157
- ).add_to(m)
158
-
159
- # [關鍵] 將 Folium 地圖物件轉換為 HTML 字串
160
- return m._repr_html_()
161
-
162
- except Exception as e:
163
- return f"<p>發生錯誤:{e}</p>"
164
-
165
- # 2. 建立 Gradio 介面
166
- with gr.Blocks(title="進階地震地圖") as demo:
167
- gr.Markdown("# 🚀 我的進階地科 App (Level 2)")
168
- gr.Markdown("使用 ObsPy 從 IRIS FDSN 搜尋即時地震資料,並用 Folium 繪製互動式地圖。")
169
-
170
- with gr.Row():
171
- mag_slider = gr.Slider(
172
- minimum=4.0,
173
- maximum=8.0,
174
- value=5.0,
175
- step=0.1,
176
- label="最小地震規模 (M)"
177
- )
178
- days_slider = gr.Slider(
179
- minimum=1,
180
- maximum=30,
181
- value=7,
182
- step=1,
183
- label="搜尋天數 (過去幾天)"
184
- )
185
-
186
- search_button = gr.Button("搜尋並繪製地圖 🌍", variant="primary")
187
-
188
- # 輸出元件:使用 gr.HTML 來渲染 Folium 地圖
189
- map_output = gr.HTML(label="地震分佈圖")
190
-
191
- # 3. 綁定互動
192
- search_button.click(
193
- fn=fetch_and_plot_events,
194
- inputs=[mag_slider, days_slider],
195
- outputs=map_output
196
- )
197
-
198
- demo.launch()
199
- """)
200
-
201
 
202
- # 6. 自訂 CSS 樣式
203
  css = """
204
  /* 標頭樣式 */
205
  #main-header {
@@ -299,7 +167,7 @@ css = """
299
  #footer { text-align: center; color: #777; font-size: 0.9rem; margin-top: 2rem; }
300
  """
301
 
302
- # 7. 使用 gr.Blocks() 建構介面
303
  with gr.Blocks(css=css, title="地球物理 x Hugging Face 專案展示") as demo:
304
 
305
  # 標頭區
@@ -400,7 +268,7 @@ with gr.Blocks(css=css, title="地球物理 x Hugging Face 專案展示") as dem
400
  """
401
  )
402
 
403
- # --- [新增] Level 2: 進階教學 ---
404
  with gr.Accordion("Level 2: 進階地震地圖 App 🌍 (點我展開)", open=False):
405
  gr.Markdown(
406
  """
@@ -497,13 +365,13 @@ with gr.Blocks(css=css, title="地球物理 x Hugging Face 專案展示") as dem
497
  """
498
  )
499
 
500
- # 8. 綁定按鈕點擊事件
501
  recommend_btn.click(
502
  fn=recommend_project,
503
  inputs=None,
504
  outputs=recommend_out
505
  )
506
 
507
- # 9. 啟動應用程式
508
  if __name__ == "__main__":
509
  demo.launch()
 
2
  import random
3
  import textwrap # 用於處理程式碼字串的縮排
4
 
5
+ # [修復] 我們將從外部 .py 檔案讀取教學程式碼,以避免解析錯誤
6
+ def load_code_from_file(filename):
7
+ try:
8
+ with open(filename, 'r', encoding='utf-8') as f:
9
+ return f.read()
10
+ except FileNotFoundError:
11
+ return f"# 錯誤:找不到範例檔案 {filename}\n# 請確認您已上傳此檔案到 Space。"
12
+ except Exception as e:
13
+ return f"# 讀取時發生錯誤:{e}"
14
+
15
  # 1. 專案資料 (帶有 Emoji)
16
  projects_data = {
17
  "🌊 地震與波形展示": [
 
56
  [**點此立即前往 🚀**]({recommendation['url']})
57
  """
58
 
59
+ # 3. requirements.txt 範例內容
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  TUTORIAL_REQUIREMENTS = textwrap.dedent("""
61
  gradio
62
  obspy
63
  folium
64
  """)
65
 
66
+ # 4. [修復] 從外部檔案載入教學程式碼
67
+ TUTORIAL_CODE_BASIC = load_code_from_file("tutorial_basic.py")
68
+ TUTORIAL_CODE_ADVANCED = load_code_from_file("tutorial_advanced.py")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
+ # 5. 自訂 CSS 樣式
71
  css = """
72
  /* 標頭樣式 */
73
  #main-header {
 
167
  #footer { text-align: center; color: #777; font-size: 0.9rem; margin-top: 2rem; }
168
  """
169
 
170
+ # 6. 使用 gr.Blocks() 建構介面
171
  with gr.Blocks(css=css, title="地球物理 x Hugging Face 專案展示") as demo:
172
 
173
  # 標頭區
 
268
  """
269
  )
270
 
271
+ # --- Level 2: 進階教學 ---
272
  with gr.Accordion("Level 2: 進階地震地圖 App 🌍 (點我展開)", open=False):
273
  gr.Markdown(
274
  """
 
365
  """
366
  )
367
 
368
+ # 7. 綁定按鈕點擊事件
369
  recommend_btn.click(
370
  fn=recommend_project,
371
  inputs=None,
372
  outputs=recommend_out
373
  )
374
 
375
+ # 8. 啟動應用程式
376
  if __name__ == "__main__":
377
  demo.launch()