File size: 4,986 Bytes
c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f e997ca2 c60428f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | import gradio as gr
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
# --- 核心物理模擬函數 ---
def calculate_gravity_anomalies(mountain_height, subsurface_density, subsurface_position):
"""
根據地形和地下異常體,計算並繪製重力異常曲線。
(All plot labels are in English to prevent font issues on cloud platforms.)
"""
# 1. 建立空間座標 (模擬一條 100 公里的測線)
x = np.linspace(-50, 50, 500)
# 2. 建立地形 (用高斯函數模擬一座山)
mountain_width = 15 # 山的寬度 (固定)
topography = mountain_height * np.exp(-(x**2) / (2 * mountain_width**2))
# 確保地表最低點為 0
topography[topography < 0.01] = 0
# 3. 建立地下的「真實」重力異常訊號 (布格異常)
# 同樣用高斯函數模擬一個球體造成的重力異常
body_width = 8 # 地下異常體的寬度 (固定)
# 核心:布格異常只反映地下的情況
bouguer_anomaly = subsurface_density * np.exp(-((x - subsurface_position)**2) / (2 * body_width**2))
# 4. 計算布格校正 (Bouguer Correction)
# 根據講義公式 BC = 0.112 * h
bouguer_correction = 0.112 * topography
# 5. 計算自由空間重力異常 (Free-air Anomaly)
# 核心:自由空間重力異常 = 地下真實訊號 + 地形影響
# FAA = BA + BC
free_air_anomaly = bouguer_anomaly + bouguer_correction
# --- Matplotlib 繪圖 (English Labels) ---
fig, ax1 = plt.subplots(figsize=(12, 8))
# 設定主 Y 軸 (重力異常)
ax1.set_xlabel('Profile Position (km)', fontsize=14)
ax1.set_ylabel('Gravity Anomaly (mGal)', color='tab:red', fontsize=14)
ax1.tick_params(axis='y', labelcolor='tab:red')
ax1.grid(True, linestyle='--', alpha=0.6)
# 繪製重力曲線
ax1.plot(x, free_air_anomaly, 'b--', label='Free-air Anomaly ($\Delta g_{fa}$)', linewidth=2)
ax1.plot(x, bouguer_anomaly, 'r-', label='Bouguer Anomaly ($\Delta g_{B}$)', linewidth=3, alpha=0.9)
ax1.legend(loc='upper left', fontsize=12)
ax1.set_ylim(-35, 85) # 固定 Y 軸範圍以便比較
# 設定次 Y 軸 (地形/深度)
ax2 = ax1.twinx()
ax2.set_ylabel('Elevation / Depth (m)', color='tab:green', fontsize=14)
ax2.tick_params(axis='y', labelcolor='tab:green')
# 繪製地形
ax2.fill_between(x, 0, topography, color='saddlebrown', alpha=0.4, label='Topography')
# 繪製地下異常體
subsurface_depth = -200 # 固定深度
body_color = 'darkred' if subsurface_density >= 0 else 'darkblue'
body_alpha = min(1.0, 0.2 + abs(subsurface_density)/50.0) # 密度越大顏色越深
circle = Circle((subsurface_position, subsurface_depth), radius=body_width*0.8, color=body_color, alpha=body_alpha)
ax2.add_patch(circle)
ax2.set_ylim(-500, 1500) # 固定地形/深度軸範圍
fig.suptitle('Interactive Bouguer Anomaly Lab', fontsize=20, weight='bold')
plt.tight_layout(rect=[0, 0.03, 1, 0.95]) # 調整佈局以容納標題
# 關閉 matplotlib 的自動顯示,將 figure 物件交給 Gradio 處理
plt.close(fig)
return fig
# --- Gradio 介面設定 (UI remains in Chinese) ---
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown(
"""
# ⛰️ 布格異常互動實驗室 ⛏️
歡迎來到重力探勘互動實驗室!在這裡,你可以親手操作變數,理解地球物理學家如何「看透」地表。
### 操作指南:
1. **調整「山脈高度」滑桿:** 觀察藍色虛線 (Free-air Anomaly) 如何緊緊跟隨地形變化。
2. **調整「地下異常體密度」與「位置」:** 觀察紅色實線 (Bouguer Anomaly) 如何只反映地下物質的變化,幾乎不受地表高山的影響。
**核心思想:** 布格校正的目的,就是從充滿地形雜訊的「自由空間重力異常」中,減去地形的影響,得到能真正反映地下密度的「布格異常」。
"""
)
with gr.Row():
with gr.Column(scale=1):
mountain_slider = gr.Slider(minimum=0, maximum=500, value=300, step=10, label="山脈高度 (公尺, h)")
density_slider = gr.Slider(minimum=-30, maximum=50, value=30, step=2, label="地下異常體密度 (mGal, 代表質量異常)")
position_slider = gr.Slider(minimum=-30, maximum=30, value=10, step=1, label="地下異常體水平位置 (km)")
with gr.Column(scale=3):
output_plot = gr.Plot()
# 將滑桿與函數連接
inputs = [mountain_slider, density_slider, position_slider]
for slider in inputs:
slider.change(fn=calculate_gravity_anomalies, inputs=inputs, outputs=output_plot)
# 頁面載入時先執行一次
demo.load(fn=calculate_gravity_anomalies, inputs=inputs, outputs=output_plot)
# 啟動應用
demo.launch()
|