Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,90 +2,61 @@ import gradio as gr
|
|
| 2 |
import numpy as np
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
|
| 5 |
-
# 解決 Matplotlib 中文亂碼問題 (關鍵修正)
|
| 6 |
-
# 指定使用 Noto Sans CJK TC 字體,這是我們透過 packages.txt 安裝的
|
| 7 |
-
plt.rcParams['font.sans-serif'] = ['Noto Sans CJK TC', 'sans-serif']
|
| 8 |
-
# 正常顯示負號,以防未來有需要
|
| 9 |
-
plt.rcParams['axes.unicode_minus'] = False
|
| 10 |
-
|
| 11 |
# --- 核心計算與繪圖函數 ---
|
| 12 |
def plot_seismic_refraction(v1, v2, h, x_max):
|
| 13 |
"""
|
| 14 |
根據輸入的地層參數,計算並繪製折射震測的走時曲線。
|
| 15 |
-
|
| 16 |
-
參數:
|
| 17 |
-
v1 (float): 第一層介質速度 (m/s)
|
| 18 |
-
v2 (float): 第二層介質速度 (m/s)
|
| 19 |
-
h (float): 第一層介質厚度 (m)
|
| 20 |
-
x_max (float): 模擬的最大測線距離 (m)
|
| 21 |
-
|
| 22 |
-
返回:
|
| 23 |
-
matplotlib.figure: 走時曲線圖
|
| 24 |
-
str: 包含計算結果的 Markdown 格式化文字
|
| 25 |
"""
|
| 26 |
# 物理條件檢查:折射必須 V2 > V1
|
| 27 |
if v2 <= v1:
|
| 28 |
-
# 建立一個空的圖表並顯示錯誤訊息
|
| 29 |
fig, ax = plt.subplots(figsize=(10, 6))
|
| 30 |
-
ax.text(0.5, 0.5, '
|
| 31 |
ha='center', va='center', fontsize=12, color='red')
|
| 32 |
-
ax.set_xlabel("
|
| 33 |
-
ax.set_ylabel("
|
| 34 |
ax.grid(True)
|
| 35 |
-
ax.set_title("
|
| 36 |
return fig, "### 參數錯誤\n請確保第二層速度 (V2) 大於第一層速度 (V1)。"
|
| 37 |
|
| 38 |
# 1. 計算關鍵物理量
|
| 39 |
-
# 臨界角 (radians and degrees)
|
| 40 |
theta_c_rad = np.arcsin(v1 / v2)
|
| 41 |
theta_c_deg = np.rad2deg(theta_c_rad)
|
| 42 |
-
|
| 43 |
-
# 截時 (Intercept Time, ti)
|
| 44 |
ti = (2 * h * np.cos(theta_c_rad)) / v1
|
| 45 |
-
|
| 46 |
-
# 交越距離 (Crossover Distance, xc)
|
| 47 |
xc = 2 * h * np.sqrt((v2 + v1) / (v2 - v1))
|
| 48 |
|
| 49 |
# 2. 準備繪圖數據
|
| 50 |
x = np.linspace(0, x_max, 500)
|
| 51 |
-
|
| 52 |
-
# 直達波走時 (Direct Wave)
|
| 53 |
t_direct = x / v1
|
| 54 |
-
|
| 55 |
-
# 折射波走時 (Refracted Wave)
|
| 56 |
t_refracted = (x / v2) + ti
|
| 57 |
-
|
| 58 |
-
# 實際的初達波 (First Arrival)
|
| 59 |
t_first_arrival = np.minimum(t_direct, t_refracted)
|
| 60 |
|
| 61 |
-
# 3. 使用 Matplotlib 繪圖
|
| 62 |
fig, ax = plt.subplots(figsize=(10, 6))
|
| 63 |
|
| 64 |
-
#
|
| 65 |
-
ax.plot(x, t_direct, 'b--', label=f'
|
| 66 |
-
ax.plot(x, t_refracted, 'g--', label=f'
|
| 67 |
-
ax.plot(x, t_first_arrival, 'r-', linewidth=3, label='
|
| 68 |
|
| 69 |
-
# 標示交越距離
|
| 70 |
if xc < x_max:
|
| 71 |
-
ax.axvline(x=xc, color='k', linestyle=':', label=f'
|
| 72 |
-
ax.plot(xc, xc/v1, 'ko')
|
| 73 |
|
| 74 |
-
|
| 75 |
-
ax.plot(0, ti, 'mo', markersize=8, label=f'截時 (Intercept) = {ti*1000:.1f} ms')
|
| 76 |
|
| 77 |
-
#
|
| 78 |
-
ax.set_title("
|
| 79 |
-
ax.set_xlabel("
|
| 80 |
-
ax.set_ylabel("
|
|
|
|
| 81 |
ax.legend()
|
| 82 |
ax.grid(True)
|
| 83 |
ax.set_xlim(0, x_max)
|
| 84 |
ax.set_ylim(0, max(t_direct) * 1.1)
|
| 85 |
-
|
| 86 |
plt.tight_layout()
|
| 87 |
|
| 88 |
-
# 4. 準備輸出的說明文字 (
|
| 89 |
results_md = f"""
|
| 90 |
### 🔬 分析結果
|
| 91 |
|
|
@@ -109,7 +80,7 @@ def plot_seismic_refraction(v1, v2, h, x_max):
|
|
| 109 |
|
| 110 |
return fig, results_md
|
| 111 |
|
| 112 |
-
# --- Gradio 介面設定 ---
|
| 113 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 114 |
gr.Markdown("# 地心震波奇幻之旅:互動折射震測實驗室 🌍")
|
| 115 |
gr.Markdown(
|
|
@@ -149,8 +120,8 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
|
| 149 |
---
|
| 150 |
### 學習重點
|
| 151 |
1. **觀察斜率**: 直達波的斜率是 `1/V1`,折射波的斜率是 `1/V2`。試著調整 `V1` 和 `V2`,看看線條的陡峭程度如何變化?(速度越快,線越陡,斜率越小)。
|
| 152 |
-
2. **觀察截時 (Intercept Time)**: 試著只增加厚度 `h
|
| 153 |
-
3. **觀察交越距離 (Crossover Distance)**: 試著增加 `h` 或減小 `V2` 與 `V1`
|
| 154 |
4. **必要條件**: 試著將 `V2` 調整到比 `V1` 小,看看會發生什麼事?你會發現,臨界折射的現象消失了!
|
| 155 |
|
| 156 |
<footer>
|
|
|
|
| 2 |
import numpy as np
|
| 3 |
import matplotlib.pyplot as plt
|
| 4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
# --- 核心計算與繪圖函數 ---
|
| 6 |
def plot_seismic_refraction(v1, v2, h, x_max):
|
| 7 |
"""
|
| 8 |
根據輸入的地層參數,計算並繪製折射震測的走時曲線。
|
| 9 |
+
圖表內的標籤已改為英文。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
"""
|
| 11 |
# 物理條件檢查:折射必須 V2 > V1
|
| 12 |
if v2 <= v1:
|
|
|
|
| 13 |
fig, ax = plt.subplots(figsize=(10, 6))
|
| 14 |
+
ax.text(0.5, 0.5, 'Error: V2 must be greater than V1 for critical refraction to occur.',
|
| 15 |
ha='center', va='center', fontsize=12, color='red')
|
| 16 |
+
ax.set_xlabel("Distance (m)")
|
| 17 |
+
ax.set_ylabel("Travel Time (s)")
|
| 18 |
ax.grid(True)
|
| 19 |
+
ax.set_title("Travel-Time Curve")
|
| 20 |
return fig, "### 參數錯誤\n請確保第二層速度 (V2) 大於第一層速度 (V1)。"
|
| 21 |
|
| 22 |
# 1. 計算關鍵物理量
|
|
|
|
| 23 |
theta_c_rad = np.arcsin(v1 / v2)
|
| 24 |
theta_c_deg = np.rad2deg(theta_c_rad)
|
|
|
|
|
|
|
| 25 |
ti = (2 * h * np.cos(theta_c_rad)) / v1
|
|
|
|
|
|
|
| 26 |
xc = 2 * h * np.sqrt((v2 + v1) / (v2 - v1))
|
| 27 |
|
| 28 |
# 2. 準備繪圖數據
|
| 29 |
x = np.linspace(0, x_max, 500)
|
|
|
|
|
|
|
| 30 |
t_direct = x / v1
|
|
|
|
|
|
|
| 31 |
t_refracted = (x / v2) + ti
|
|
|
|
|
|
|
| 32 |
t_first_arrival = np.minimum(t_direct, t_refracted)
|
| 33 |
|
| 34 |
+
# 3. 使用 Matplotlib 繪圖 (標籤已改為英文)
|
| 35 |
fig, ax = plt.subplots(figsize=(10, 6))
|
| 36 |
|
| 37 |
+
# --- 英文圖例標籤修改處 ---
|
| 38 |
+
ax.plot(x, t_direct, 'b--', label=f'Direct Wave (Slope 1/{v1:.0f})')
|
| 39 |
+
ax.plot(x, t_refracted, 'g--', label=f'Refracted Wave (Slope 1/{v2:.0f})')
|
| 40 |
+
ax.plot(x, t_first_arrival, 'r-', linewidth=3, label='First Arrival')
|
| 41 |
|
|
|
|
| 42 |
if xc < x_max:
|
| 43 |
+
ax.axvline(x=xc, color='k', linestyle=':', label=f'Crossover Distance = {xc:.1f} m')
|
| 44 |
+
ax.plot(xc, xc/v1, 'ko')
|
| 45 |
|
| 46 |
+
ax.plot(0, ti, 'mo', markersize=8, label=f'Intercept Time = {ti*1000:.1f} ms')
|
|
|
|
| 47 |
|
| 48 |
+
# --- 英文圖表/座標軸標題修改處 ---
|
| 49 |
+
ax.set_title("Interactive Seismic Refraction T-X Plot", fontsize=16)
|
| 50 |
+
ax.set_xlabel("Distance (m)", fontsize=12)
|
| 51 |
+
ax.set_ylabel("Travel Time (s)", fontsize=12)
|
| 52 |
+
|
| 53 |
ax.legend()
|
| 54 |
ax.grid(True)
|
| 55 |
ax.set_xlim(0, x_max)
|
| 56 |
ax.set_ylim(0, max(t_direct) * 1.1)
|
|
|
|
| 57 |
plt.tight_layout()
|
| 58 |
|
| 59 |
+
# 4. 準備輸出的說明文字 (這部分維持中文)
|
| 60 |
results_md = f"""
|
| 61 |
### 🔬 分析結果
|
| 62 |
|
|
|
|
| 80 |
|
| 81 |
return fig, results_md
|
| 82 |
|
| 83 |
+
# --- Gradio 介面設定 (這部分維持中文) ---
|
| 84 |
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
| 85 |
gr.Markdown("# 地心震波奇幻之旅:互動折射震測實驗室 🌍")
|
| 86 |
gr.Markdown(
|
|
|
|
| 120 |
---
|
| 121 |
### 學習重點
|
| 122 |
1. **觀察斜率**: 直達波的斜率是 `1/V1`,折射波的斜率是 `1/V2`。試著調整 `V1` 和 `V2`,看看線條的陡峭程度如何變化?(速度越快,線越陡,斜率越小)。
|
| 123 |
+
2. **觀察截時 (Intercept Time)**: 試著只增加厚度 `h`,看看 Y 軸上的截距有什麼變化?(厚度越厚,截時越大)。
|
| 124 |
+
3. **觀察交越距離 (Crossover Distance)**: 試著增加 `h` 或減小 `V2` 與 `V1` 的速度差,看看交叉點如何向右移動?
|
| 125 |
4. **必要條件**: 試著將 `V2` 調整到比 `V1` 小,看看會發生什麼事?你會發現,臨界折射的現象消失了!
|
| 126 |
|
| 127 |
<footer>
|