cwadayi commited on
Commit
a00010c
·
verified ·
1 Parent(s): 1ecc7cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -16
app.py CHANGED
@@ -18,8 +18,10 @@ def plot_seismic_exploration(v1, v2, h, x_max, num_receivers, gain):
18
  if v2 <= v1:
19
  fig1, ax1 = plt.subplots(figsize=(10, 6))
20
  ax1.text(0.5, 0.5, 'Error: V2 must be greater than V1', ha='center', va='center', color='red')
 
21
  fig2, ax2 = plt.subplots(figsize=(10, 5))
22
- ax2.text(0.5, 0.5, 'Please ensure V2 > V1', ha='center', va='center', color='red')
 
23
  return fig1, fig2, "### 參數錯誤\n請確保第二層速度 (V2) 大於第一層速度 (V1)。"
24
 
25
  theta_c_rad = np.arcsin(v1 / v2)
@@ -53,7 +55,7 @@ def plot_seismic_exploration(v1, v2, h, x_max, num_receivers, gain):
53
 
54
  # === PART 3: 繪製視覺化震測剖面圖 (Plot 2) ===
55
  fig2, ax2 = plt.subplots(figsize=(10, 5))
56
- receiver_x = np.linspace(0, x_max, num_receivers)
57
 
58
  # 計算每個測站的抵達時間
59
  t_direct_rx = receiver_x / v1
@@ -64,16 +66,16 @@ def plot_seismic_exploration(v1, v2, h, x_max, num_receivers, gain):
64
  wavelet_duration = 0.08
65
  wavelet_t = np.linspace(0, wavelet_duration, 100)
66
 
67
- for i in range(num_receivers):
68
- # 繪製反射波震波 (最重要,因為剖面主要看反射)
69
  wavelet_amp_refl = ricker_wavelet(wavelet_t, f=40) * gain
70
  x_trace_refl = receiver_x[i] + wavelet_amp_refl
71
  y_trace_refl = t_reflected_rx[i] - wavelet_duration/2 + wavelet_t
72
  ax2.plot(x_trace_refl, y_trace_refl, 'k-', linewidth=1)
73
  ax2.fill_betweenx(y_trace_refl, receiver_x[i], x_trace_refl, where=(x_trace_refl > receiver_x[i]), color='black')
74
 
75
- # 繪製初達波震波 (通常能量較強)
76
- wavelet_amp_first = ricker_wavelet(wavelet_t, f=30) * gain * 1.2 # 讓它振幅稍大
77
  x_trace_first = receiver_x[i] + wavelet_amp_first
78
  y_trace_first = t_first_arrival_rx[i] - wavelet_duration/2 + wavelet_t
79
  ax2.plot(x_trace_first, y_trace_first, 'r-', linewidth=1.5)
@@ -84,7 +86,7 @@ def plot_seismic_exploration(v1, v2, h, x_max, num_receivers, gain):
84
  ax2.plot(0, 0, 'r*', markersize=20, label='Source')
85
  ax2.plot(receiver_x, np.zeros_like(receiver_x), 'kv', markersize=8, label='Receivers')
86
 
87
- ax2.set_title(f"2. Visualized Seismic Profile ({num_receivers} Traces)", fontsize=16, loc='left')
88
  ax2.set_xlabel("Distance (m)")
89
  ax2.set_ylabel("Two-Way Time (s)")
90
  ax2.set_xlim(-x_max * 0.05, x_max * 1.05)
@@ -95,13 +97,32 @@ def plot_seismic_exploration(v1, v2, h, x_max, num_receivers, gain):
95
  fig1.tight_layout()
96
 
97
  # === PART 4: 準備輸出的說明文字 ===
98
- results_md = "..." # (與前版相同,此處省略以節省空間)
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  return fig1, fig2, results_md
100
 
101
  # --- Gradio 介面設定 ---
102
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
103
- gr.Markdown("# 地心震波奇幻之旅:地球物理遊樂場 🌍")
104
- # ... (開頭說明文字)
 
 
 
 
 
 
105
 
106
  with gr.Row():
107
  with gr.Column(scale=1):
@@ -113,7 +134,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
113
  gr.Markdown("### ⚙️ 2. 佈放儀器與顯示設定")
114
  xmax_slider = gr.Slider(label="最大觀測距離 (m)", minimum=100, maximum=500, value=250, step=10)
115
  receivers_slider = gr.Slider(label="測站數量", minimum=5, maximum=100, value=40, step=1)
116
- gain_slider = gr.Slider(label="剖面增益 (Display Gain)", minimum=1, maximum=20, value=5, step=1) # 新增增益滑桿
117
 
118
  submit_btn = gr.Button("🚀 開始探勘!", variant="primary")
119
 
@@ -122,19 +143,22 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
122
  plot_output1 = gr.Plot(label="走時-距離圖 (T-X Plot)")
123
  plot_output2 = gr.Plot(label="視覺化震測剖面圖 (Visualized Seismic Profile)")
124
 
125
- # ... (分析結果顯示區塊)
 
126
 
127
  # --- 事件監聽 ---
 
 
128
  submit_btn.click(
129
  fn=plot_seismic_exploration,
130
- inputs=[v1_slider, v2_slider, h_slider, xmax_slider, receivers_slider, gain_slider], # 加入 gain_slider
131
- outputs=[plot_output1, plot_output2, demo.outputs[-1]] # 確保結果正確輸出
132
  )
133
 
134
  gr.Markdown(
135
  """
136
  ---
137
- ### 📖 剖面圖是如何誕生的? (全新解說)
138
  下方的 **視覺化震測剖面圖** 完美模擬了真實的探勘情境。每一條黑色的垂直線代表一個**測站 (Receiver)**,它記錄到的訊號就是一條帶有**震波 (Wiggle)** 的**震波線 (Trace)**。
139
 
140
  - **紅色震波** 代表 **初達波 (First Arrival)**,是能量最早抵達的波。
@@ -142,7 +166,7 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
142
 
143
  地球物理學家最重要的工作,就是在成千上萬條震波線中,**尋找並追蹤這些連續排列的震波(稱為「同相軸」)**。例如,圖中那條優美的黑色雙曲線同相軸,就清楚地標示出了地下第一層介面的位置!
144
 
145
- ### 🚀 探索與發現 (全新挑戰)
146
  1. **增益的效果**: 試著調整「剖面增益」,看看震波的振幅如何變化。在真實資料中,深層的反射信號很微弱,就需要提高增益才能看清楚。
147
  2. **看見雙曲線**: 專注觀察剖面圖中的黑色震波。當你增加「測站數量」時,是不是能更清楚地「描繪」出那條對應到上方 T-X 圖的紫色雙曲線?
148
  3. **初達波的威力**: 紅色的初達波在剖面圖中形成了一條明顯的分界線。觀察它的轉折點,思考一下這個轉折點(交越距離)告訴了我們關於地下速度結構的什麼資訊?
 
18
  if v2 <= v1:
19
  fig1, ax1 = plt.subplots(figsize=(10, 6))
20
  ax1.text(0.5, 0.5, 'Error: V2 must be greater than V1', ha='center', va='center', color='red')
21
+ ax1.set_title("Travel-Time Curve")
22
  fig2, ax2 = plt.subplots(figsize=(10, 5))
23
+ ax2.text(0.5, 0.5, 'Please ensure V2 > V1 to generate a valid model.', ha='center', va='center', color='red')
24
+ ax2.set_title("Visualized Seismic Profile")
25
  return fig1, fig2, "### 參數錯誤\n請確保第二層速度 (V2) 大於第一層速度 (V1)。"
26
 
27
  theta_c_rad = np.arcsin(v1 / v2)
 
55
 
56
  # === PART 3: 繪製視覺化震測剖面圖 (Plot 2) ===
57
  fig2, ax2 = plt.subplots(figsize=(10, 5))
58
+ receiver_x = np.linspace(0, x_max, int(num_receivers))
59
 
60
  # 計算每個測站的抵達時間
61
  t_direct_rx = receiver_x / v1
 
66
  wavelet_duration = 0.08
67
  wavelet_t = np.linspace(0, wavelet_duration, 100)
68
 
69
+ for i in range(int(num_receivers)):
70
+ # 繪製反射波震波
71
  wavelet_amp_refl = ricker_wavelet(wavelet_t, f=40) * gain
72
  x_trace_refl = receiver_x[i] + wavelet_amp_refl
73
  y_trace_refl = t_reflected_rx[i] - wavelet_duration/2 + wavelet_t
74
  ax2.plot(x_trace_refl, y_trace_refl, 'k-', linewidth=1)
75
  ax2.fill_betweenx(y_trace_refl, receiver_x[i], x_trace_refl, where=(x_trace_refl > receiver_x[i]), color='black')
76
 
77
+ # 繪製初達波震波
78
+ wavelet_amp_first = ricker_wavelet(wavelet_t, f=30) * gain * 1.2
79
  x_trace_first = receiver_x[i] + wavelet_amp_first
80
  y_trace_first = t_first_arrival_rx[i] - wavelet_duration/2 + wavelet_t
81
  ax2.plot(x_trace_first, y_trace_first, 'r-', linewidth=1.5)
 
86
  ax2.plot(0, 0, 'r*', markersize=20, label='Source')
87
  ax2.plot(receiver_x, np.zeros_like(receiver_x), 'kv', markersize=8, label='Receivers')
88
 
89
+ ax2.set_title(f"2. Visualized Seismic Profile ({int(num_receivers)} Traces)", fontsize=16, loc='left')
90
  ax2.set_xlabel("Distance (m)")
91
  ax2.set_ylabel("Two-Way Time (s)")
92
  ax2.set_xlim(-x_max * 0.05, x_max * 1.05)
 
97
  fig1.tight_layout()
98
 
99
  # === PART 4: 準備輸出的說明文字 ===
100
+ results_md = f"""
101
+ ### 🔬 分析結果
102
+
103
+ 根據您設計的地層模型,我們計算出以下關鍵物理量:
104
+
105
+ #### 折射波 (Refracted Wave)
106
+ - **臨界角 (Critical Angle, θc)**: `arcsin({v1:.0f} / {v2:.0f})` = **{theta_c_deg:.2f}°**
107
+ - **截時 (Intercept Time, tᵢ)**: `(2 * {h:.0f} * cos({theta_c_deg:.2f}°)) / {v1:.0f}` = **{ti*1000:.1f} ms**
108
+ - **交越距離 (Crossover Distance, Xc)**: `2 * {h:.0f} * sqrt(...)` = **{xc:.1f} m**
109
+
110
+ ---
111
+ #### 反射波 (Reflected Wave)
112
+ - **雙程走時 (Two-Way Time, t₀)**: `2 * {h:.0f} / {v1:.0f}` = **{t0*1000:.1f} ms**
113
+ """
114
  return fig1, fig2, results_md
115
 
116
  # --- Gradio 介面設定 ---
117
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
118
+ gr.Markdown(
119
+ """
120
+ # 地心震波奇幻之旅:地球物理遊樂場 🌍
121
+ > 創意的發揮是一種學習,過程中,每個人同時是學生也是老師。
122
+
123
+ 這個實驗室就是你的遊樂場。透過親手設計地層模型、佈放虛擬測站,你將不只是學習,更是在**創造和發現**地底下的物理法則。
124
+ """
125
+ )
126
 
127
  with gr.Row():
128
  with gr.Column(scale=1):
 
134
  gr.Markdown("### ⚙️ 2. 佈放儀器與顯示設定")
135
  xmax_slider = gr.Slider(label="最大觀測距離 (m)", minimum=100, maximum=500, value=250, step=10)
136
  receivers_slider = gr.Slider(label="測站數量", minimum=5, maximum=100, value=40, step=1)
137
+ gain_slider = gr.Slider(label="剖面增益 (Display Gain)", minimum=1, maximum=20, value=5, step=1)
138
 
139
  submit_btn = gr.Button("🚀 開始探勘!", variant="primary")
140
 
 
143
  plot_output1 = gr.Plot(label="走時-距離圖 (T-X Plot)")
144
  plot_output2 = gr.Plot(label="視覺化震測剖面圖 (Visualized Seismic Profile)")
145
 
146
+ with gr.Row():
147
+ results_output = gr.Markdown("### 🔬 分析結果\n請設計你的地層模型並點擊「開始探勘!」以顯示計算結果。")
148
 
149
  # --- 事件監聽 ---
150
+ # 【*** THIS IS THE FIX ***】
151
+ # The incorrect 'demo.outputs[-1]' has been replaced with the correct variable name 'results_output'.
152
  submit_btn.click(
153
  fn=plot_seismic_exploration,
154
+ inputs=[v1_slider, v2_slider, h_slider, xmax_slider, receivers_slider, gain_slider],
155
+ outputs=[plot_output1, plot_output2, results_output]
156
  )
157
 
158
  gr.Markdown(
159
  """
160
  ---
161
+ ### 📖 剖面圖是如何誕生的?
162
  下方的 **視覺化震測剖面圖** 完美模擬了真實的探勘情境。每一條黑色的垂直線代表一個**測站 (Receiver)**,它記錄到的訊號就是一條帶有**震波 (Wiggle)** 的**震波線 (Trace)**。
163
 
164
  - **紅色震波** 代表 **初達波 (First Arrival)**,是能量最早抵達的波。
 
166
 
167
  地球物理學家最重要的工作,就是在成千上萬條震波線中,**尋找並追蹤這些連續排列的震波(稱為「同相軸」)**。例如,圖中那條優美的黑色雙曲線同相軸,就清楚地標示出了地下第一層介面的位置!
168
 
169
+ ### 🚀 探索與發現
170
  1. **增益的效果**: 試著調整「剖面增益」,看看震波的振幅如何變化。在真實資料中,深層的反射信號很微弱,就需要提高增益才能看清楚。
171
  2. **看見雙曲線**: 專注觀察剖面圖中的黑色震波。當你增加「測站數量」時,是不是能更清楚地「描繪」出那條對應到上方 T-X 圖的紫色雙曲線?
172
  3. **初達波的威力**: 紅色的初達波在剖面圖中形成了一條明顯的分界線。觀察它的轉折點,思考一下這個轉折點(交越距離)告訴了我們關於地下速度結構的什麼資訊?