cwadayi commited on
Commit
fd63fae
·
verified ·
1 Parent(s): f6fef2d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -34
app.py CHANGED
@@ -2,22 +2,32 @@ import gradio as gr
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)
@@ -29,14 +39,15 @@ def plot_seismic_refraction(v1, v2, h, x_max):
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:
@@ -45,49 +56,59 @@ def plot_seismic_refraction(v1, v2, h, x_max):
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
 
63
  根據您設定的參數,我們計算出以下關鍵物理量:
64
 
65
- - **臨界角 (Critical Angle, θc)**:
66
- - 公式: `θc = arcsin(V1 / V2)`
67
- - 計算: `arcsin({v1:.0f} / {v2:.0f})` = **{theta_c_deg:.2f}°**
68
- - *這是產生「抄捷徑」折射波的關鍵入射角度。*
 
 
 
 
 
 
 
 
 
69
 
70
- - **截時 (Intercept Time, tᵢ)**:
71
- - 公式: `tᵢ = (2 * h * cos(θc)) / V1`
72
- - 計算: `(2 * {h:.0f} * cos({theta_c_deg:.2f}°)) / {v1:.0f}` = **{ti*1000:.1f} ms**
73
- - *這是折射波走時線在時間軸上的截距,它隱含了第一層的厚度資訊。*
74
 
75
  - **交越距離 (Crossover Distance, Xc)**:
76
  - 公式: `Xc = 2 * h * sqrt((V2 + V1) / (V2 - V1))`
77
  - 計算: `2 * {h:.0f} * sqrt(({v2:.0f} + {v1:.0f}) / ({v2:.0f} - {v1:.0f}))` = **{xc:.1f} m**
78
- - *在這個距離上,直達波和折射波會同時抵達。超過這個距離後,折射波會先到。*
79
  """
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(
87
  """
88
- 歡迎來到地球物理小教室!這個互動工具是根據「地心震波奇幻之旅」課程內容設計的。
89
- 您可以透過下方的滑桿來模擬一個簡單的雙層地層模型。調整第一層的速度 `V1`、第二層的速度 `V2` 以及第一層的厚度 `h`,
90
- 觀察右側的「走時-距離圖」如何即時變化,並從中學習折射震測法的核心原理!
91
  """
92
  )
93
 
@@ -110,7 +131,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
110
 
111
  # --- 事件監聽 ---
112
  submit_btn.click(
113
- fn=plot_seismic_refraction,
114
  inputs=[v1_slider, v2_slider, h_slider, xmax_slider],
115
  outputs=[plot_output, results_output]
116
  )
@@ -119,10 +140,11 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
119
  """
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>
128
  <p style="text-align:center; color:grey;">地球物理小教室 &copy; 2025 - 由 Gemini 根據課程文件生成</p>
@@ -131,4 +153,4 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
131
  )
132
 
133
  if __name__ == "__main__":
134
- demo.launch()
 
2
  import numpy as np
3
  import matplotlib.pyplot as plt
4
 
5
+ # --- 核心計算與繪圖函數 (已加入反射波) ---
6
+ def plot_travel_times(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
+ # 即使沒有折射,我們仍然可以顯示直達波和反射波
15
+ x = np.linspace(0, x_max, 500)
16
+ t_direct = x / v1
17
+ t_reflected = np.sqrt(x**2 + (2 * h)**2) / v1 # 反射波計算
18
+
19
+ ax.plot(x, t_direct, 'b--', label='Direct Wave')
20
+ ax.plot(x, t_reflected, 'm-.', label='Reflected Wave') # 反射波繪圖
21
+
22
+ ax.text(0.5, 0.5, 'V2 <= V1: Critical refraction does not occur.\nOnly Direct and Reflected waves are shown.',
23
+ ha='center', va='center', fontsize=12, color='orange')
24
  ax.set_xlabel("Distance (m)")
25
  ax.set_ylabel("Travel Time (s)")
26
  ax.grid(True)
27
+ ax.legend()
28
+ ax.set_title("Travel-Time Curve (No Refraction)")
29
+ results_md = "### 參數錯誤\n請確保第二層速度 (V2) 大於第一層速度 (V1) 才能產生臨界折射現象。"
30
+ return fig, results_md
31
 
32
  # 1. 計算關鍵物理量
33
  theta_c_rad = np.arcsin(v1 / v2)
 
39
  x = np.linspace(0, x_max, 500)
40
  t_direct = x / v1
41
  t_refracted = (x / v2) + ti
42
+ t_reflected = np.sqrt(x**2 + (2 * h)**2) / v1 # <<< 新增:反射波走時計算
43
+ t_first_arrival = np.minimum(t_direct, t_refracted) # 注意:反射波永遠不會是初達波
44
 
45
+ # 3. 使用 Matplotlib 繪圖
46
  fig, ax = plt.subplots(figsize=(10, 6))
47
 
 
48
  ax.plot(x, t_direct, 'b--', label=f'Direct Wave (Slope 1/{v1:.0f})')
49
  ax.plot(x, t_refracted, 'g--', label=f'Refracted Wave (Slope 1/{v2:.0f})')
50
+ ax.plot(x, t_reflected, 'm-.', label='Reflected Wave') # <<< 新增:反射波繪圖指令
51
  ax.plot(x, t_first_arrival, 'r-', linewidth=3, label='First Arrival')
52
 
53
  if xc < x_max:
 
56
 
57
  ax.plot(0, ti, 'mo', markersize=8, label=f'Intercept Time = {ti*1000:.1f} ms')
58
 
59
+ ax.set_title("Interactive Seismic T-X Plot (Reflection + Refraction)", fontsize=16)
 
60
  ax.set_xlabel("Distance (m)", fontsize=12)
61
  ax.set_ylabel("Travel Time (s)", fontsize=12)
62
 
63
  ax.legend()
64
  ax.grid(True)
65
  ax.set_xlim(0, x_max)
66
+ # 優化 Y 軸範圍,確保所有曲線可見
67
+ max_time = np.max([t_direct, t_refracted, t_reflected])
68
+ ax.set_ylim(0, max_time * 1.1)
69
  plt.tight_layout()
70
 
71
+ # 4. 準備輸出的說明文字
72
  results_md = f"""
73
  ### 🔬 分析結果
74
 
75
  根據您設定的參數,我們計算出以下關鍵物理量:
76
 
77
+ - **直達波 (Direct Wave)**:
78
+ - 公式: `t = x / V1`
79
+ - *震波直接沿著地表傳遞,走時圖為一條過原點的直線。*
80
+
81
+ - **反射波 (Reflected Wave)**:
82
+ - 公式: `t = sqrt(x² + (2h)²) / V1`
83
+ - *震波向下傳至界面後反射回地表。走時圖為一條雙曲線,它永遠不會是「初達波」。*
84
+
85
+ - **折射波 (Refracted Wave)**:
86
+ - **臨界角 (Critical Angle, θc)**:
87
+ - 公式: `θc = arcsin(V1 / V2)`
88
+ - 計算: `arcsin({v1:.0f} / {v2:.0f})` = **{theta_c_deg:.2f}°**
89
+ - *產生「抄捷徑」折射波的關鍵入射角度。*
90
 
91
+ - **截時 (Intercept Time, tᵢ)**:
92
+ - 公式: `tᵢ = (2 * h * cos(θc)) / V1`
93
+ - 計算: `(2 * {h:.0f} * cos({theta_c_deg:.2f}°)) / {v1:.0f}` = **{ti*1000:.1f} ms**
94
+ - *折射波走時線在時間軸上的截距,隱含了第一層的厚度資訊。*
95
 
96
  - **交越距離 (Crossover Distance, Xc)**:
97
  - 公式: `Xc = 2 * h * sqrt((V2 + V1) / (V2 - V1))`
98
  - 計算: `2 * {h:.0f} * sqrt(({v2:.0f} + {v1:.0f}) / ({v2:.0f} - {v1:.0f}))` = **{xc:.1f} m**
99
+ - *在此距離上,直達波和折射波同時抵達。超過此距離後,折射波會先到。*
100
  """
101
 
102
  return fig, results_md
103
 
104
+ # --- Gradio 介面設定 (已更新標題與說明) ---
105
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
106
+ gr.Markdown("# 地心震波奇幻之旅:互動震測走時曲線實驗室 🌍")
107
  gr.Markdown(
108
  """
109
+ 歡迎來到地球物理小教室!這個互動工具可以模擬一個簡單的雙層地層模型中的震波傳遞。
110
+ 您可以透過下方的滑桿來調整第一層速度 `V1`、第二層速度 `V2` 以及第一層的厚度 `h`。
111
+ 觀察右側的「走時-距離圖」如何即時變化,並從中學習**直達波 (Direct)**、**反射波 (Reflected)** 與**折射波 (Refracted)** 的核心原理!
112
  """
113
  )
114
 
 
131
 
132
  # --- 事件監聽 ---
133
  submit_btn.click(
134
+ fn=plot_travel_times, # 更新函數名稱
135
  inputs=[v1_slider, v2_slider, h_slider, xmax_slider],
136
  outputs=[plot_output, results_output]
137
  )
 
140
  """
141
  ---
142
  ### 學習重點
143
+ 1. **觀察斜率**: 直達波的斜率是 `1/V1`,折射波的斜率是 `1/V2`。試著調整 `V1` 和 `V2`,看看線條的陡峭程度如何變化?
144
+ 2. **觀察截時 (Intercept Time)**: 試著只增加厚度 `h`,看看折射波在 Y 軸上的截距有什麼變化?
145
  3. **觀察交越距離 (Crossover Distance)**: 試著增加 `h` 或減小 `V2` 與 `V1` 的速度差,看看交叉點如何向右移動?
146
+ 4. **觀察反射波**: 注意反射波(洋紅色點虛線)是一條優美的雙曲線。它的曲率與第一層的厚度 `h` 和速度 `V1` 有關。
147
+ 5. **必要條件**: 試著將 `V2` 調整到比 `V1` 小,看看會發生什麼事?你會發現,臨界折射的現象消失了,只剩下直達波與反射波!
148
 
149
  <footer>
150
  <p style="text-align:center; color:grey;">地球物理小教室 &copy; 2025 - 由 Gemini 根據課程文件生成</p>
 
153
  )
154
 
155
  if __name__ == "__main__":
156
+ demo.launch()