Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,28 +1,22 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import pandas as pd
|
| 3 |
|
| 4 |
-
# --- 1.
|
|
|
|
| 5 |
course_introduction_md = """
|
| 6 |
# 探索地球的脈動:地球物理學與AI應用
|
| 7 |
**課程網頁 (Hugging Face Space)**
|
| 8 |
|
| 9 |
**引言:**
|
| 10 |
-
|
| 11 |
歡迎來到「探索地球的脈動」線上課程!本課程旨在引導您進入地球物理學的迷人世界,從地底深處的震波到廣闊的板塊運動,我們將一同揭開地球的神秘面紗。更令人興奮的是,我們將不僅僅學習理論知識,更將動手實踐,利用最前沿的程式設計與AI工具,將地球科學數據轉化為深刻的洞見。
|
| 12 |
-
|
| 13 |
-
本互動式網頁將作為您的課程地圖,清晰地闡述我們的學習目標、課程安排以及您將掌握的尖端技能。無論您是地球科學的愛好者,還是對程式設計與AI充滿好奇,這門課都將為您開啟一扇通往跨領域知識融合的大門。
|
| 14 |
"""
|
| 15 |
|
| 16 |
course_goals_md = """
|
| 17 |
### 課程目標:培養探索未知的能力與熱情
|
| 18 |
-
|
| 19 |
-
本課程的核心目標是「**培養能力與引發興趣**」。我們期望在課程結束時,您將能夠:
|
| 20 |
-
|
| 21 |
* **地球物理知識**:
|
| 22 |
* 理解折射探勘、重力探勘的核心原理。
|
| 23 |
* 建立板塊構造的宏觀知識體系,並了解其與地震、地磁、地熱的關聯。
|
| 24 |
* 透過專題演講與野外實習,連結理論與實務。
|
| 25 |
-
|
| 26 |
* **資料處理技能**:
|
| 27 |
* **環境建置與雲端協作**: 熟練使用 Python、Colab、GitHub Codespaces 進行開發。
|
| 28 |
* **地球科學數據可視化**: 精通 `PyGMT` 繪製專業地圖與 `ObsPy` 處理地震波形。
|
|
@@ -30,18 +24,14 @@ course_goals_md = """
|
|
| 30 |
* **AI工具應用**: 學會申請與使用 `Gemini API`,並透過 `Dify` 平台快速建構AI應用。
|
| 31 |
"""
|
| 32 |
|
| 33 |
-
# --- 更新後的成績計算方式 ---
|
| 34 |
grading_policy_md = """
|
| 35 |
### 成績計算方式
|
| 36 |
-
|
| 37 |
-
為了清晰地評估您的學習成效,本課程的成績將由以下三部分組成:
|
| 38 |
-
|
| 39 |
* **作業 (50%)**: 包含課程中指派的各項實作任務,例如程式碼練習、數據分析報告、Colab筆記本繳交、以及GitHub Repo的更新紀錄等。這是評量您動手實踐能力的主要依據。
|
| 40 |
* **期中考 (40%)**: 範圍涵蓋前八週的地球物理知識與資料處理技能,用以檢核您對核心概念的理解程度。
|
| 41 |
* **平時成績 (10%)**: 根據您的課堂參與度、提問與互動表現進行評估。積極參與是學習的催化劑!
|
| 42 |
"""
|
| 43 |
|
| 44 |
-
# --- 2.
|
| 45 |
schedule_data = {
|
| 46 |
"週次": [
|
| 47 |
"第一週 (9/10)", "第二週 (9/17)", "第三週 (9/24)", "第四週 (10/1)",
|
|
@@ -67,9 +57,115 @@ schedule_data = {
|
|
| 67 |
}
|
| 68 |
schedule_df = pd.DataFrame(schedule_data)
|
| 69 |
|
| 70 |
-
# --- 3.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
def ai_chatbot_placeholder(message, history):
|
| 72 |
-
"""一個模擬的AI問答機器人,為Dify和Gemini API提供一個簡單範例"""
|
| 73 |
if any(keyword in message.lower() for keyword in ["gmt", "pygmt"]):
|
| 74 |
return "PyGMT 是一個用來繪製地理空間數據的強大 Python 函式庫,我們將在第九、十週深入學習它!"
|
| 75 |
elif any(keyword in message.lower() for keyword in ["obspy"]):
|
|
@@ -79,7 +175,7 @@ def ai_chatbot_placeholder(message, history):
|
|
| 79 |
else:
|
| 80 |
return "你好!我是課程AI助教。你可以問我關於 PyGMT, ObsPy, 或 Dify 的問題,預覽我們將學習的酷炫工具!"
|
| 81 |
|
| 82 |
-
# ---
|
| 83 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"), title="地球物理學與AI應用") as demo:
|
| 84 |
gr.Markdown(course_introduction_md)
|
| 85 |
|
|
@@ -89,20 +185,39 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"),
|
|
| 89 |
|
| 90 |
with gr.TabItem("課程進度"):
|
| 91 |
gr.Markdown("### 每週課程安排")
|
| 92 |
-
gr.DataFrame(schedule_df, wrap=True)
|
| 93 |
|
| 94 |
with gr.TabItem("成績計算"):
|
| 95 |
gr.Markdown(grading_policy_md)
|
| 96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
with gr.TabItem("互動體驗區"):
|
| 98 |
gr.Markdown("### 🤖 AI課程助教 (Dify/Gemini 範例)")
|
| 99 |
gr.Markdown("試著問我關於 `PyGMT`, `ObsPy`, 或 `Dify` 的問題,預覽我們課程的精彩內容!")
|
| 100 |
gr.ChatInterface(
|
| 101 |
ai_chatbot_placeholder,
|
| 102 |
-
chatbot=gr.Chatbot(height=350, avatar_images=(None, "bot.png")),
|
| 103 |
title="課程AI助教",
|
| 104 |
description="由Gradio驅動的簡易問答機器人"
|
| 105 |
)
|
| 106 |
|
| 107 |
-
# ---
|
| 108 |
demo.launch()
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import pandas as pd
|
| 3 |
|
| 4 |
+
# --- 1. 各區塊的 Markdown 內容 ---
|
| 5 |
+
|
| 6 |
course_introduction_md = """
|
| 7 |
# 探索地球的脈動:地球物理學與AI應用
|
| 8 |
**課程網頁 (Hugging Face Space)**
|
| 9 |
|
| 10 |
**引言:**
|
|
|
|
| 11 |
歡迎來到「探索地球的脈動」線上課程!本課程旨在引導您進入地球物理學的迷人世界,從地底深處的震波到廣闊的板塊運動,我們將一同揭開地球的神秘面紗。更令人興奮的是,我們將不僅僅學習理論知識,更將動手實踐,利用最前沿的程式設計與AI工具,將地球科學數據轉化為深刻的洞見。
|
|
|
|
|
|
|
| 12 |
"""
|
| 13 |
|
| 14 |
course_goals_md = """
|
| 15 |
### 課程目標:培養探索未知的能力與熱情
|
|
|
|
|
|
|
|
|
|
| 16 |
* **地球物理知識**:
|
| 17 |
* 理解折射探勘、重力探勘的核心原理。
|
| 18 |
* 建立板塊構造的宏觀知識體系,並了解其與地震、地磁、地熱的關聯。
|
| 19 |
* 透過專題演講與野外實習,連結理論與實務。
|
|
|
|
| 20 |
* **資料處理技能**:
|
| 21 |
* **環境建置與雲端協作**: 熟練使用 Python、Colab、GitHub Codespaces 進行開發。
|
| 22 |
* **地球科學數據可視化**: 精通 `PyGMT` 繪製專業地圖與 `ObsPy` 處理地震波形。
|
|
|
|
| 24 |
* **AI工具應用**: 學會申請與使用 `Gemini API`,並透過 `Dify` 平台快速建構AI應用。
|
| 25 |
"""
|
| 26 |
|
|
|
|
| 27 |
grading_policy_md = """
|
| 28 |
### 成績計算方式
|
|
|
|
|
|
|
|
|
|
| 29 |
* **作業 (50%)**: 包含課程中指派的各項實作任務,例如程式碼練習、數據分析報告、Colab筆記本繳交、以及GitHub Repo的更新紀錄等。這是評量您動手實踐能力的主要依據。
|
| 30 |
* **期中考 (40%)**: 範圍涵蓋前八週的地球物理知識與資料處理技能,用以檢核您對核心概念的理解程度。
|
| 31 |
* **平時成績 (10%)**: 根據您的課堂參與度、提問與互動表現進行評估。積極參與是學習的催化劑!
|
| 32 |
"""
|
| 33 |
|
| 34 |
+
# --- 2. 課程進度表 DataFrame ---
|
| 35 |
schedule_data = {
|
| 36 |
"週次": [
|
| 37 |
"第一週 (9/10)", "第二週 (9/17)", "第三週 (9/24)", "第四週 (10/1)",
|
|
|
|
| 57 |
}
|
| 58 |
schedule_df = pd.DataFrame(schedule_data)
|
| 59 |
|
| 60 |
+
# --- 3. 範例程式碼區塊的內容 ---
|
| 61 |
+
|
| 62 |
+
# ObsPy 範例說明
|
| 63 |
+
obspy_intro_md = """
|
| 64 |
+
### 範例一:使用 ObsPy 分析地震波形
|
| 65 |
+
**情境設定:分析2024年4月3日花蓮 $M_w$ 7.4 地震**
|
| 66 |
+
|
| 67 |
+
這個範例將展示如何使用 `ObsPy` 自動從國際地震數據中心 (IRIS) 下載花蓮地震的波形資料,並進行簡單的訊號處理與繪圖。這是在地震學研究中,取得數據的第一步。
|
| 68 |
+
|
| 69 |
+
**程式碼說明:**
|
| 70 |
+
1. **連接數據中心**: 我們將連接到全球最主要的地震數據來源之一 `IRIS`。
|
| 71 |
+
2. **下載波形資料**: 我們會指定下載全球地震測站網 (`IU`) 中的台北測站 (`TATO`) 在地震發生後的5分鐘的垂直向 (`BHZ`) 地動訊號。
|
| 72 |
+
3. **訊號處理**: 執行 `detrend` (去除長期趨勢) 與 `filter` (帶通濾波),這是讓地震訊號更清晰的標準流程。
|
| 73 |
+
4. **繪製波形**: `ObsPy` 內建的 `plot()` 功能可以快速將地震波形繪製成圖。
|
| 74 |
+
"""
|
| 75 |
+
|
| 76 |
+
obspy_code = """
|
| 77 |
+
import obspy
|
| 78 |
+
from obspy.clients.fdsn import Client
|
| 79 |
+
from obspy import UTCDateTime
|
| 80 |
+
|
| 81 |
+
# --- 1. 定義地震事件時間與要抓取的時間範圍 ---
|
| 82 |
+
# 台灣時間 2024-04-03 07:58:09 (UTC+8) -> UTC 時間 2024-04-02 23:58:09
|
| 83 |
+
event_time = UTCDateTime("2024-04-02T23:58:09")
|
| 84 |
+
start_time = event_time
|
| 85 |
+
end_time = event_time + 5 * 60
|
| 86 |
+
|
| 87 |
+
# --- 2. 連接到 IRIS 數據中心 ---
|
| 88 |
+
client = Client("IRIS")
|
| 89 |
+
|
| 90 |
+
# --- 3. 下載特定測站的波形資料 (Stream object) ---
|
| 91 |
+
try:
|
| 92 |
+
st = client.get_waveforms("IU", "TATO", "00", "BHZ", start_time, end_time)
|
| 93 |
+
|
| 94 |
+
# --- 4. 對波形資料進行簡單的處理 ---
|
| 95 |
+
st_processed = st.copy()
|
| 96 |
+
st_processed.detrend("linear")
|
| 97 |
+
st_processed.filter("bandpass", freqmin=1.0, freqmax=10.0, corners=4, zerophase=True)
|
| 98 |
+
|
| 99 |
+
# --- 5. 繪圖 (在真實環境中會存檔) ---
|
| 100 |
+
# st.plot(outfile="waveform_raw.png")
|
| 101 |
+
# st_processed.plot(outfile="waveform_processed.png")
|
| 102 |
+
print("程式碼執行成功!下方將展示預期的輸出圖片。")
|
| 103 |
+
|
| 104 |
+
except Exception as e:
|
| 105 |
+
print(f"下載資料時發生錯誤: {e}")
|
| 106 |
+
"""
|
| 107 |
+
|
| 108 |
+
obspy_results_md = """
|
| 109 |
+
#### 預期執行結果
|
| 110 |
+
執行程式碼後,將會得到原始波形圖與處理後的波形圖。**注意**:在 Colab 或本地端執行時,程式碼會儲存圖檔;此處為您直接展示結果。
|
| 111 |
+
|
| 112 |
+
1. **原始波形圖 (waveform_raw.png)**: 這是從數據中心直接下載的原始數據,可以看到地震波抵達時振幅的劇烈變化。
|
| 113 |
+
2. **處理後波形圖 (waveform_processed.png)**: 經過濾波處理後,背景雜訊被有效去除,P波與S波的特徵變得非常清晰。
|
| 114 |
+
"""
|
| 115 |
+
|
| 116 |
+
# PyGMT 範例說明
|
| 117 |
+
pygmt_intro_md = """
|
| 118 |
+
### 範例二:使用 PyGMT 繪製震央地圖
|
| 119 |
+
**情境設定:將花蓮地震的震央與測站位置繪製在地圖上**
|
| 120 |
+
|
| 121 |
+
這個範例將展示 `PyGMT` 的強大之處:繪製專業、高品質的地球科學圖資。我們將把上一範例中的地震事件與測站,標示在精美的台灣地形圖上。
|
| 122 |
+
|
| 123 |
+
**程式碼說明:**
|
| 124 |
+
1. **定義座標**: 設定地震震央的經緯度、規模,以及台北測站的經緯度。
|
| 125 |
+
2. **設定地圖參數**: 定義地圖的範圍 (`region`)、投影方式 (`projection`)。
|
| 126 |
+
3. **繪製底圖**: 我們會使用 `pygmt.datasets.load_earth_relief` 載入全球地形資料,並透過 `grdimage` 與 `coast` 繪製出彩色的地形底圖與海岸線。
|
| 127 |
+
4. **標示測站與震央**: 使用 `plot` 指令,將測站位置以**藍色倒三角形**、震央位置以**紅色星星**的標準圖例繪製出來。
|
| 128 |
+
5. **美化地圖**: 最後加上圖例、比例尺、指北針,完成一張資訊完整的地圖。
|
| 129 |
+
"""
|
| 130 |
+
|
| 131 |
+
pygmt_code = """
|
| 132 |
+
import pygmt
|
| 133 |
+
|
| 134 |
+
# --- 1. 定義地震與測站的座標資訊 ---
|
| 135 |
+
event_lon, event_lat, event_mag = 121.666, 23.822, 7.4
|
| 136 |
+
station_lon, station_lat = 121.517, 25.048
|
| 137 |
+
|
| 138 |
+
# --- 2. 建立一個 Figure 物件 ---
|
| 139 |
+
fig = pygmt.Figure()
|
| 140 |
+
|
| 141 |
+
# --- 3. 設定地圖區域與投影 ---
|
| 142 |
+
region = [119, 124, 21, 26]
|
| 143 |
+
with fig.subplot(nrows=1, ncols=1, figsize=("18c", "18c"), frame=["a", "+t花蓮 2024/04/03 Mw 7.4 地震"]):
|
| 144 |
+
# --- 4. 繪製底圖 ---
|
| 145 |
+
grid = pygmt.datasets.load_earth_relief(resolution="01m", region=region)
|
| 146 |
+
fig.grdimage(grid=grid, cmap="geo", projection="M15c", shading=True)
|
| 147 |
+
fig.coast(shorelines="1/0.5p,black", borders="1/0.5p,black", water="skyblue")
|
| 148 |
+
|
| 149 |
+
# --- 5. 繪製測站與震央 ---
|
| 150 |
+
fig.plot(x=station_lon, y=station_lat, style="i1c", fill="blue", pen="black", label="台北測站 (IU.TATO)")
|
| 151 |
+
fig.plot(x=event_lon, y=event_lat, style=f"a{event_mag*0.15}c", fill="red", pen="white", label=f"震央 (Mw {event_mag})")
|
| 152 |
+
|
| 153 |
+
# --- 6. 加上圖例、比例尺、指北針 ---
|
| 154 |
+
fig.legend(position="JTR+jTR+o0.2c", box=True)
|
| 155 |
+
fig.basemap(map_scale="JBL+c24+w100k+f", rose="JTL+w3c+l")
|
| 156 |
+
|
| 157 |
+
# --- 7. 儲存圖片 (在真實環境中會存檔) ---
|
| 158 |
+
# fig.savefig("hualien_earthquake_map.png", dpi=300)
|
| 159 |
+
print("程式碼執行成功!下方將展示預期的輸出圖片。")
|
| 160 |
+
"""
|
| 161 |
+
|
| 162 |
+
pygmt_results_md = """
|
| 163 |
+
#### 預期執行結果
|
| 164 |
+
執行後,您會得到一張名為 `hualien_earthquake_map.png` 的專業地圖。它清晰地展示了台灣的地形地貌,並用標準化的圖例精確標示了地震事件與測站。
|
| 165 |
+
"""
|
| 166 |
+
|
| 167 |
+
# --- 4. AI 聊天機器人 ---
|
| 168 |
def ai_chatbot_placeholder(message, history):
|
|
|
|
| 169 |
if any(keyword in message.lower() for keyword in ["gmt", "pygmt"]):
|
| 170 |
return "PyGMT 是一個用來繪製地理空間數據的強大 Python 函式庫,我們將在第九、十週深入學習它!"
|
| 171 |
elif any(keyword in message.lower() for keyword in ["obspy"]):
|
|
|
|
| 175 |
else:
|
| 176 |
return "你好!我是課程AI助教。你可以問我關於 PyGMT, ObsPy, 或 Dify 的問題,預覽我們將學習的酷炫工具!"
|
| 177 |
|
| 178 |
+
# --- 5. 使用 Gradio 建立使用者介面 ---
|
| 179 |
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="orange"), title="地球物理學與AI應用") as demo:
|
| 180 |
gr.Markdown(course_introduction_md)
|
| 181 |
|
|
|
|
| 185 |
|
| 186 |
with gr.TabItem("課程進度"):
|
| 187 |
gr.Markdown("### 每週課程安排")
|
| 188 |
+
gr.DataFrame(schedule_df, wrap=True)
|
| 189 |
|
| 190 |
with gr.TabItem("成績計算"):
|
| 191 |
gr.Markdown(grading_policy_md)
|
| 192 |
|
| 193 |
+
# ----------- 新增的範例程式碼分頁 -----------
|
| 194 |
+
with gr.TabItem("範例程式碼"):
|
| 195 |
+
gr.Markdown("## 动手做:ObsPy & PyGMT 實戰範例")
|
| 196 |
+
gr.Markdown("這裡展示了課程中兩個核心工具的實際應用。您可以在自己的 Colab 或電腦環境中,安裝好 `obspy` 和 `pygmt` 後,直接執行這些程式碼來重現結果。")
|
| 197 |
+
|
| 198 |
+
with gr.Accordion("範例一:ObsPy 地震波形分析", open=True):
|
| 199 |
+
gr.Markdown(obspy_intro_md)
|
| 200 |
+
gr.Code(value=obspy_code, language="python", label="obspy_example.py")
|
| 201 |
+
gr.Markdown(obspy_results_md)
|
| 202 |
+
with gr.Row():
|
| 203 |
+
gr.Image("https://i.imgur.com/8aE9TqM.png", label="原始波形圖 (示意圖)")
|
| 204 |
+
gr.Image("https://i.imgur.com/rN5uGz8.png", label="處理後波形圖 (示意圖)")
|
| 205 |
+
|
| 206 |
+
with gr.Accordion("範例二:PyGMT 震央地圖繪製", open=True):
|
| 207 |
+
gr.Markdown(pygmt_intro_md)
|
| 208 |
+
gr.Code(value=pygmt_code, language="python", label="pygmt_example.py")
|
| 209 |
+
gr.Markdown(pygmt_results_md)
|
| 210 |
+
gr.Image("https://i.imgur.com/L44p3oF.png", label="PyGMT 地震事件地圖 (示意圖)")
|
| 211 |
+
|
| 212 |
with gr.TabItem("互動體驗區"):
|
| 213 |
gr.Markdown("### 🤖 AI課程助教 (Dify/Gemini 範例)")
|
| 214 |
gr.Markdown("試著問我關於 `PyGMT`, `ObsPy`, 或 `Dify` 的問題,預覽我們課程的精彩內容!")
|
| 215 |
gr.ChatInterface(
|
| 216 |
ai_chatbot_placeholder,
|
| 217 |
+
chatbot=gr.Chatbot(height=350, avatar_images=(None, "bot.png")),
|
| 218 |
title="課程AI助教",
|
| 219 |
description="由Gradio驅動的簡易問答機器人"
|
| 220 |
)
|
| 221 |
|
| 222 |
+
# --- 6. 啟動應用程式 ---
|
| 223 |
demo.launch()
|