File size: 6,024 Bytes
8646273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2ae4679
 
8646273
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Gradio app that takes seismic waveform as input and marks 2 phases on the waveform as output.

import gradio as gr
import numpy as np
from phasehunter.model import Onset_picker, Updated_onset_picker
from phasehunter.data_preparation import prepare_waveform
import torch
from scipy.stats.kde import gaussian_kde

import obspy
from obspy.clients.fdsn import Client
from obspy.clients.fdsn.header import FDSNNoDataException, FDSNTimeoutException, FDSNInternalServerException
from obspy.geodetics.base import locations2degrees
from obspy.taup import TauPyModel
from obspy.taup.helper_classes import SlownessModelError

from obspy.clients.fdsn.header import URL_MAPPINGS

import matplotlib.pyplot as plt

def make_prediction(waveform):
    waveform = np.load(waveform)
    processed_input = prepare_waveform(waveform)
    
    # Make prediction
    with torch.no_grad():
        output = model(processed_input)

    p_phase = output[:, 0]
    s_phase = output[:, 1]

    return processed_input, p_phase, s_phase

def mark_phases(waveform):
    processed_input, p_phase, s_phase = make_prediction(waveform)

    # Create a plot of the waveform with the phases marked
    if sum(processed_input[0][2] == 0): #if input is 1C
        fig, ax = plt.subplots(nrows=2, figsize=(10, 2), sharex=True)

        ax[0].plot(processed_input[0][0])
        ax[0].set_ylabel('Norm. Ampl.')

    else: #if input is 3C
        fig, ax = plt.subplots(nrows=4, figsize=(10, 6), sharex=True)
        ax[0].plot(processed_input[0][0])
        ax[1].plot(processed_input[0][1])
        ax[2].plot(processed_input[0][2])

        ax[0].set_ylabel('Z')
        ax[1].set_ylabel('N')
        ax[2].set_ylabel('E')

    p_phase_plot = p_phase*processed_input.shape[-1]
    p_kde = gaussian_kde(p_phase_plot)
    p_dist_space = np.linspace( min(p_phase_plot)-10, max(p_phase_plot)+10, 500 )
    ax[-1].plot( p_dist_space, p_kde(p_dist_space), color='r')

    s_phase_plot = s_phase*processed_input.shape[-1]
    s_kde = gaussian_kde(s_phase_plot)
    s_dist_space = np.linspace( min(s_phase_plot)-10, max(s_phase_plot)+10, 500 )
    ax[-1].plot( s_dist_space, s_kde(s_dist_space), color='b')

    for a in ax:
        a.axvline(p_phase.mean()*processed_input.shape[-1], color='r', linestyle='--', label='P')
        a.axvline(s_phase.mean()*processed_input.shape[-1], color='b', linestyle='--', label='S')

    ax[-1].set_xlabel('Time, samples')
    ax[-1].set_ylabel('Uncert.')
    ax[-1].legend()

    plt.subplots_adjust(hspace=0., wspace=0.)

    # Convert the plot to an image and return it
    fig.canvas.draw()
    image = np.array(fig.canvas.renderer.buffer_rgba())
    plt.close(fig)
    return image

def download_data(timestamp, eq_lat, eq_lon, client_name, radius_km):
    client = Client(client_name)
    window = radius_km / 111.2

    assert eq_lat - window > -90 and eq_lat + window < 90, "Latitude out of bounds"
    assert eq_lon - window > -180 and eq_lon + window < 180, "Longitude out of bounds"

    # starttime = catalog['DateTime'].apply(lambda x: pd.Timestamp(x)).min()
    # endtime = catalog['DateTime'].apply(lambda x: pd.Timestamp(x)).max()

    return 0

model = Onset_picker.load_from_checkpoint("./weights.ckpt",
                                 picker=Updated_onset_picker(),
                                    learning_rate=3e-4)
model.eval()



# # Create the Gradio interface
# gr.Interface(mark_phases, inputs, outputs, title='PhaseHunter').launch()


with gr.Blocks() as demo:
    gr.Markdown("# PhaseHunter")
    with gr.Tab("Default example"):
        # Define the input and output types for Gradio
        inputs = gr.Dropdown(
            ["data/sample/sample_0.npy", 
            "data/sample/sample_1.npy", 
            "data/sample/sample_2.npy"], 
            label="Sample waveform", 
            info="Select one of the samples",
            value = "data/sample/sample_0.npy"
        )

        button = gr.Button("Predict phases")
        outputs = gr.outputs.Image(label='Waveform with Phases Marked', type='numpy')
    
        button.click(mark_phases, inputs=inputs, outputs=outputs)
        
    with gr.Tab("Select earthquake from catalogue"):
        gr.Markdown('TEST')
        
        client_inputs = gr.Dropdown(
            choices = list(URL_MAPPINGS.keys()), 
            label="FDSN Client", 
            info="Select one of the available FDSN clients",
            value = "IRIS",
            interactive=True
        )
        with gr.Row(): 

            timestamp_inputs = gr.Textbox(value='2019-07-04 17:33:49',
                                placeholder='YYYY-MM-DD HH:MM:SS',
                                label="Timestamp",
                                info="Timestamp of the earthquake",
                                max_lines=1,
                                interactive=True)
                               
            eq_lat_inputs = gr.Number(value=35.766, 
                            label="Latitude", 
                            info="Latitude of the earthquake",
                            interactive=True)
            
            eq_lo_inputs = gr.Number(value=117.605,
                                label="Longitude",
                                info="Longitude of the earthquake",
                                interactive=True)
            
            radius_inputs = gr.Slider(minimum=1, 
                                    maximum=150, 
                                    value=50, label="Radius (km)", 
                                    info="Select the radius around the earthquake to download data from",
                                    interactive=True)
            
        button = gr.Button("Predict phases")

    with gr.Tab("Predict on your own waveform"):
        gr.Markdown("""
        Please upload your waveform in .npy (numpy) format. 
        Your waveform should be sampled at 100 sps and have 3 (Z, N, E) or 1 (Z) channels.
        """)

    button.click(mark_phases, inputs=inputs, outputs=outputs)

demo.launch()