cwadayi commited on
Commit
9f4f09a
·
verified ·
1 Parent(s): 576e90d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -37
app.py CHANGED
@@ -3,10 +3,11 @@ 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:
@@ -17,100 +18,122 @@ def plot_seismic_refraction(v1, v2, h, x_max):
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
 
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
 
94
  with gr.Row():
95
  with gr.Column(scale=1):
96
- gr.Markdown("### ⚙️ 調整地層參數")
97
  v1_slider = gr.Slider(label="V1: 第一層速度 (m/s)", minimum=300, maximum=3000, value=800, step=50)
98
  v2_slider = gr.Slider(label="V2: 第二層速度 (m/s)", minimum=500, maximum=6000, value=2500, step=50)
99
  h_slider = gr.Slider(label="h: 第一層厚度 (m)", minimum=5, maximum=100, value=20, step=1)
100
  xmax_slider = gr.Slider(label="最大觀測距離 (m)", minimum=100, maximum=500, value=250, step=10)
101
 
102
- submit_btn = gr.Button("產生圖表", variant="primary")
103
 
104
  with gr.Column(scale=2):
105
- gr.Markdown("### 📊 走時-距離圖 (T-X Plot)")
106
  plot_output = gr.Plot()
107
 
108
  with gr.Row():
109
- results_output = gr.Markdown("### 🔬 分析結果\n請調整參數並點擊按鈕以顯示計算結果。")
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
  )
@@ -118,17 +141,21 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
118
  gr.Markdown(
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>
129
- </footer>
130
  """
131
  )
 
 
 
 
 
 
 
132
 
133
  if __name__ == "__main__":
134
  demo.launch()
 
3
  import matplotlib.pyplot as plt
4
 
5
  # --- 核心計算與繪圖函數 ---
6
+ def plot_seismic_exploration(v1, v2, h, x_max):
7
  """
8
+ 根據輸入的地層參數,計算並繪製震測的走時曲線。
9
+ *** 新增了反射波的模擬 ***
10
+ 圖表內的標籤為英文。
11
  """
12
  # 物理條件檢查:折射必須 V2 > V1
13
  if v2 <= v1:
 
18
  ax.set_ylabel("Travel Time (s)")
19
  ax.grid(True)
20
  ax.set_title("Travel-Time Curve")
21
+ return fig, "### 參數錯誤\n請確保第二層速度 (V2) 大於第一層速度 (V1),否則無法產生臨界折射現象。"
22
 
23
  # 1. 計算關鍵物理量
24
+ # 折射波相關
25
  theta_c_rad = np.arcsin(v1 / v2)
26
  theta_c_deg = np.rad2deg(theta_c_rad)
27
  ti = (2 * h * np.cos(theta_c_rad)) / v1
28
  xc = 2 * h * np.sqrt((v2 + v1) / (v2 - v1))
29
 
30
+ # 反射波相關
31
+ t0 = (2 * h) / v1
32
+
33
  # 2. 準備繪圖數據
34
  x = np.linspace(0, x_max, 500)
35
+ # 直達波
36
  t_direct = x / v1
37
+ # 折射波
38
  t_refracted = (x / v2) + ti
39
+ # 反射波 (新增)
40
+ t_reflected = np.sqrt(t0**2 + (x / v1)**2)
41
+ # 初達波
42
  t_first_arrival = np.minimum(t_direct, t_refracted)
43
 
44
+ # 3. 使用 Matplotlib 繪圖
45
  fig, ax = plt.subplots(figsize=(10, 6))
46
 
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:', linewidth=2, label='Reflected Wave (Hyperbola)') # 新增反射波
51
+ ax.plot(x, t_first_arrival, 'r-', linewidth=3, label='First Arrival (Refraction)')
52
 
53
+ # 標示交越距離
54
  if xc < x_max:
55
  ax.axvline(x=xc, color='k', linestyle=':', label=f'Crossover Distance = {xc:.1f} m')
56
  ax.plot(xc, xc/v1, 'ko')
57
 
58
+ # 標示截時
59
+ ax.plot(0, ti, 'go', markersize=8, label=f'Refraction Intercept = {ti*1000:.1f} ms')
60
+ # 標示雙程走時 (新增)
61
+ ax.plot(0, t0, 'mo', markersize=8, label=f'Reflection Two-Way Time = {t0*1000:.1f} ms')
62
 
63
+ # 設定圖表樣式
64
+ ax.set_title("Interactive Seismic Exploration T-X Plot", fontsize=16)
65
  ax.set_xlabel("Distance (m)", fontsize=12)
66
  ax.set_ylabel("Travel Time (s)", fontsize=12)
67
 
68
  ax.legend()
69
  ax.grid(True)
70
  ax.set_xlim(0, x_max)
71
+ # 自動調整 Y 軸,確保能看到所有曲線
72
+ y_max = max(np.max(t_direct), np.max(t_reflected))
73
+ ax.set_ylim(0, y_max * 1.1)
74
  plt.tight_layout()
75
 
76
+ # 4. 準備輸出的說明文字
77
  results_md = f"""
78
  ### 🔬 分析結果
79
 
80
+ 根據您設計的地層模型,我們計算出以下關鍵物理量:
81
 
82
+ #### 折射波 (Refracted Wave)
83
  - **臨界角 (Critical Angle, θc)**:
84
  - 公式: `θc = arcsin(V1 / V2)`
85
  - 計算: `arcsin({v1:.0f} / {v2:.0f})` = **{theta_c_deg:.2f}°**
86
  - *這是產生「抄捷徑」折射波的關鍵入射角度。*
 
87
  - **截時 (Intercept Time, tᵢ)**:
88
  - 公式: `tᵢ = (2 * h * cos(θc)) / V1`
89
  - 計算: `(2 * {h:.0f} * cos({theta_c_deg:.2f}°)) / {v1:.0f}` = **{ti*1000:.1f} ms**
90
+ - *折射波走時線在時間軸上的截距,隱含了第一層的厚度資訊。*
 
91
  - **交越距離 (Crossover Distance, Xc)**:
92
  - 公式: `Xc = 2 * h * sqrt((V2 + V1) / (V2 - V1))`
93
  - 計算: `2 * {h:.0f} * sqrt(({v2:.0f} + {v1:.0f}) / ({v2:.0f} - {v1:.0f}))` = **{xc:.1f} m**
94
+ - *在此距離之後,折射波會比直達波先抵達。*
 
95
 
96
+ ---
97
+ #### 反射波 (Reflected Wave)
98
+ - **雙程走時 (Two-Way Time, t₀)**:
99
+ - 公式: `t₀ = 2 * h / V1`
100
+ - 計算: `2 * {h:.0f} / {v1:.0f}` = **{t0*1000:.1f} ms**
101
+ - *這是震波垂直向下傳播並返回地表所需的時間,也是反射波雙曲線的頂點。*
102
+ """
103
  return fig, results_md
104
 
105
+ # --- Gradio 介面設定 ---
106
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
 
107
  gr.Markdown(
108
  """
109
+ # 地心震波奇幻之旅:地球物理遊樂場 🌍
110
+ > 創意的發揮是一種學習,過程中,每個人同時是學生也是老師。
111
+
112
+ 這個實驗室就是你的遊樂場。透過親手調整地層的參數,你將不只是在學習地球物理,更是在**創造和發現**地底下的物理法則。
113
+ 你既是設計模型的老師,也是觀察結果的學生。動動手,看看你能發現什麼秘密!
114
  """
115
  )
116
 
117
  with gr.Row():
118
  with gr.Column(scale=1):
119
+ gr.Markdown("### ⚙️ 設計你的地層模型")
120
  v1_slider = gr.Slider(label="V1: 第一層速度 (m/s)", minimum=300, maximum=3000, value=800, step=50)
121
  v2_slider = gr.Slider(label="V2: 第二層速度 (m/s)", minimum=500, maximum=6000, value=2500, step=50)
122
  h_slider = gr.Slider(label="h: 第一層厚度 (m)", minimum=5, maximum=100, value=20, step=1)
123
  xmax_slider = gr.Slider(label="最大觀測距離 (m)", minimum=100, maximum=500, value=250, step=10)
124
 
125
+ submit_btn = gr.Button("🚀 開始探勘!", variant="primary")
126
 
127
  with gr.Column(scale=2):
128
+ gr.Markdown("### 📊 觀測走時-距離圖 (T-X Plot)")
129
  plot_output = gr.Plot()
130
 
131
  with gr.Row():
132
+ results_output = gr.Markdown("### 🔬 分析結果\n請設計你的地層模型並點擊「開始探勘!」以顯示計算結果。")
133
 
134
  # --- 事件監聽 ---
135
  submit_btn.click(
136
+ fn=plot_seismic_exploration,
137
  inputs=[v1_slider, v2_slider, h_slider, xmax_slider],
138
  outputs=[plot_output, results_output]
139
  )
 
141
  gr.Markdown(
142
  """
143
  ---
144
+ ### 🚀 探索與發現 (Exploration & Discovery)
145
+ 試著回答下面的問題,你就是自己的老師!
146
+ 1. **折射 vs. 反射**: 在近距離 (X 接近 0) 時,哪一種波(直達波、反射波)最先抵達?為什麼?
147
+ 2. **速度的影響**: 如果把 V1 V2 的速度差距拉得更大,折射波的走時線(綠色)會變得更陡還是更平緩?這對交越距離又有什麼影響?
148
+ 3. **厚度的秘密**: 如果你只增加地層厚度 `h`,反射波的雙曲線(紫色)和折射波的截時 `tᵢ` 會如何變化?它們之間有什麼數學關聯嗎?
149
+ 4. **消失的折射波**: 在什麼條件下,折射波(綠色線)會完全消失,或是永遠比直達波(藍色線)還慢?
 
 
 
150
  """
151
  )
152
+
153
+ gr.HTML("""
154
+ <footer style="text-align:center; margin-top: 30px; color:grey;">
155
+ <p>「創意的發揮是一種學習,過程中,每個人同時是學生也是老師。」</p>
156
+ <p>地球物理遊樂場 &copy; 2025 - 由 Gemini 根據課程文件與靈感生成</p>
157
+ </footer>
158
+ """)
159
 
160
  if __name__ == "__main__":
161
  demo.launch()