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()