File size: 4,041 Bytes
69b7b27
 
 
 
6b931cd
69b7b27
 
 
 
6b931cd
69b7b27
 
 
6b931cd
 
 
 
 
69b7b27
 
 
 
 
 
 
 
6b931cd
69b7b27
 
6b931cd
 
69b7b27
 
6b931cd
69b7b27
6b931cd
 
 
 
 
 
 
 
 
 
 
 
 
 
69b7b27
6b931cd
69b7b27
 
 
 
 
 
6b931cd
 
69b7b27
 
 
 
 
 
 
6b931cd
69b7b27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6b931cd
69b7b27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6b931cd
69b7b27
 
 
 
 
 
 
 
6b931cd
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import plotly.graph_objects as go
import pandas as pd
import pydeck as pdk
from obspy import UTCDateTime
import numpy as np  # 我們需要 numpy 來輔助定位註釋

def plot_waveforms_with_picks(p_picks):
    """
    為每個成功撿拾到P波的測站繪製波形圖並標示P波。
    (已修正 TypeError)
    """
    fig = go.Figure()
    
    # 為了讓Y軸範圍更好看,找到所有波形的最大振幅
    max_amplitude = 0
    if p_picks:
        max_amplitude = max(np.max(np.abs(p['trace'].data)) for p in p_picks)

    for i, pick in enumerate(p_picks):
        tr = pick['trace']
        time_axis = [t.datetime for t in tr.times("utcdatetime")]
        
        fig.add_trace(go.Scatter(
            x=time_axis,
            y=tr.data,
            mode='lines',
            name=tr.stats.station
        ))
        
        # --- 變更開始 ---
        # 步驟 1: 畫垂直線 (不帶註釋)
        fig.add_vline(
            x=pick['p_arrival_time'].datetime,
            line_width=1.5,
            line_dash="dash",
            line_color="red"
        )
        
        # 步驟 2: 單獨添加文字註釋,以獲得更好的控制並避免 bug
        fig.add_annotation(
            x=pick['p_arrival_time'].datetime,
            y=max_amplitude * 0.9,  # 將註釋放在圖表頂部附近
            yref="y",
            text=f"<b>{tr.stats.station} P</b>", # 使用簡短、粗體的文字
            showarrow=False,
            font=dict(color="red", size=11),
            bgcolor="rgba(255, 255, 255, 0.7)", # 半透明背景
            xshift=5, # 稍微向右移動以避免與線重疊
            yshift=15  # 稍微向上移動
        )
        # --- 變更結束 ---
        
    fig.update_layout(
        title="測站波形與 P 波初達標示",
        xaxis_title="時間 (UTC)",
        yaxis_title="振幅 (Counts)",
        legend_title="測站",
        height=500,
        yaxis_range=[-max_amplitude*1.1, max_amplitude*1.1] # 設定一個對稱且略大的Y軸範圍
    )
    return fig


def plot_event_map(inventory, p_picks, location_result):
    """
    在地圖上呈現測站、P波撿拾站點及震央位置。
    (此函式無須變更)
    """
    station_data = []
    picked_stations_codes = [p['station'] for p in p_picks]

    for net in inventory:
        for sta in net:
            if sta.code in picked_stations_codes:
                color = [0, 0, 255, 160] # Blue
            else:
                color = [128, 128, 128, 80] # Grey
                
            station_data.append({
                "name": f"測站: {sta.code}",
                "coordinates": [sta.longitude, sta.latitude],
                "color": color,
            })
            
    station_df = pd.DataFrame(station_data)

    if location_result:
        epicenter_df = pd.DataFrame([{
            "name": f"震央\n緯度: {location_result['latitude']:.3f}\n經度: {location_result['longitude']:.3f}\n深度: {location_result['depth_km']:.1f} km",
            "coordinates": [location_result['longitude'], location_result['latitude']],
            "color": [255, 0, 0, 255], # Red
        }])

    station_layer = pdk.Layer(
        "ScatterplotLayer",
        data=station_df,
        get_position="coordinates",
        get_fill_color="color",
        get_radius=200,
        pickable=True,
        auto_highlight=True,
    )
    
    layers = [station_layer]
    
    if location_result:
        epicenter_layer = pdk.Layer(
            "ScatterplotLayer",
            data=epicenter_df,
            get_position="coordinates",
            get_fill_color="color",
            get_radius=500,
            pickable=True,
        )
        layers.append(epicenter_layer)

    view_state = pdk.ViewState(
        latitude=23.9,
        longitude=121.0,
        zoom=6.5,
        pitch=45,
    )

    tooltip = {"text": "{name}"}

    deck = pdk.Deck(layers=layers, initial_view_state=view_state, map_style='mapbox://styles/mapbox/light-v9', tooltip=tooltip)
    return deck