Spaces:
Runtime error
Runtime error
WIP on section plot
Browse files
app.py
CHANGED
@@ -78,32 +78,89 @@ def mark_phases(waveform):
|
|
78 |
plt.close(fig)
|
79 |
return image
|
80 |
|
81 |
-
|
82 |
-
|
83 |
-
|
|
|
84 |
client = Client(client_name)
|
|
|
85 |
window = radius_km / 111.2
|
86 |
|
87 |
assert eq_lat - window > -90 and eq_lat + window < 90, "Latitude out of bounds"
|
88 |
assert eq_lon - window > -180 and eq_lon + window < 180, "Longitude out of bounds"
|
89 |
|
90 |
starttime = obspy.UTCDateTime(timestamp)
|
91 |
-
endtime =
|
92 |
|
93 |
inv = client.get_stations(network="*", station="*", location="*", channel="*H*",
|
94 |
-
starttime=
|
95 |
-
minlatitude=eq_lat-window, maxlatitude=eq_lat+window,
|
96 |
-
minlongitude=eq_lon-window, maxlongitude=eq_lon+window,
|
97 |
-
level='
|
98 |
|
|
|
99 |
for network in inv:
|
100 |
for station in network:
|
101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
|
103 |
-
|
104 |
-
# starttime=obspy.UTCDateTime(start_date), endtime=obspy.UTCDateTime(end_date))
|
105 |
|
106 |
-
return 0
|
107 |
|
108 |
model = Onset_picker.load_from_checkpoint("./weights.ckpt",
|
109 |
picker=Updated_onset_picker(),
|
@@ -119,10 +176,10 @@ model.eval()
|
|
119 |
with gr.Blocks() as demo:
|
120 |
gr.Markdown("# PhaseHunter")
|
121 |
gr.Markdown("""This app allows one to detect P and S seismic phases along with uncertainty of the detection.
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
with gr.Tab("Default example"):
|
127 |
# Define the input and output types for Gradio
|
128 |
inputs = gr.Dropdown(
|
@@ -163,19 +220,39 @@ with gr.Blocks() as demo:
|
|
163 |
info="Latitude of the earthquake",
|
164 |
interactive=True)
|
165 |
|
166 |
-
|
167 |
label="Longitude",
|
168 |
info="Longitude of the earthquake",
|
169 |
interactive=True)
|
170 |
|
|
|
|
|
|
|
|
|
|
|
171 |
radius_inputs = gr.Slider(minimum=1,
|
172 |
maximum=150,
|
173 |
value=50, label="Radius (km)",
|
174 |
info="Select the radius around the earthquake to download data from",
|
175 |
interactive=True)
|
176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
button = gr.Button("Predict phases")
|
178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
|
180 |
with gr.Tab("Predict on your own waveform"):
|
181 |
gr.Markdown("""
|
@@ -183,6 +260,6 @@ with gr.Blocks() as demo:
|
|
183 |
Your waveform should be sampled at 100 sps and have 3 (Z, N, E) or 1 (Z) channels.
|
184 |
""")
|
185 |
|
186 |
-
|
187 |
|
188 |
demo.launch()
|
|
|
78 |
plt.close(fig)
|
79 |
return image
|
80 |
|
81 |
+
def predict_on_section(client_name, timestamp, eq_lat, eq_lon, radius_km, source_depth_km, velocity_model):
|
82 |
+
distances, t0s, st_lats, st_lons, waveforms = [], [], [], [], []
|
83 |
+
|
84 |
+
taup_model = TauPyModel(model=velocity_model)
|
85 |
client = Client(client_name)
|
86 |
+
|
87 |
window = radius_km / 111.2
|
88 |
|
89 |
assert eq_lat - window > -90 and eq_lat + window < 90, "Latitude out of bounds"
|
90 |
assert eq_lon - window > -180 and eq_lon + window < 180, "Longitude out of bounds"
|
91 |
|
92 |
starttime = obspy.UTCDateTime(timestamp)
|
93 |
+
endtime = starttime + 120
|
94 |
|
95 |
inv = client.get_stations(network="*", station="*", location="*", channel="*H*",
|
96 |
+
starttime=starttime, endtime=endtime,
|
97 |
+
minlatitude=(eq_lat-window), maxlatitude=(eq_lat+window),
|
98 |
+
minlongitude=(eq_lon-window), maxlongitude=(eq_lon+window),
|
99 |
+
level='station')
|
100 |
|
101 |
+
waveforms = []
|
102 |
for network in inv:
|
103 |
for station in network:
|
104 |
+
try:
|
105 |
+
distance = locations2degrees(eq_lat, eq_lon, station.latitude, station.longitude)
|
106 |
+
|
107 |
+
arrivals = taup_model.get_travel_times(source_depth_in_km=source_depth_km,
|
108 |
+
distance_in_degree=distance,
|
109 |
+
phase_list=["P", "S"])
|
110 |
+
|
111 |
+
if len(arrivals) > 0:
|
112 |
+
|
113 |
+
starttime = obspy.UTCDateTime(timestamp) + arrivals[0].time - 15
|
114 |
+
endtime = starttime + 60
|
115 |
+
|
116 |
+
waveform = client.get_waveforms(network=network.code, station=station.code, location="*", channel="*",
|
117 |
+
starttime=starttime, endtime=endtime)
|
118 |
+
|
119 |
+
waveform = waveform.select(channel="H[BH][ZNE]")
|
120 |
+
waveform = waveform.merge(fill_value=0)
|
121 |
+
waveform = waveform[:3]
|
122 |
+
|
123 |
+
len_check = [len(x.data) for x in waveform]
|
124 |
+
if len(set(len_check)) > 1:
|
125 |
+
continue
|
126 |
+
|
127 |
+
if len(waveform) == 3:
|
128 |
+
waveform = prepare_waveform(np.stack([x.data for x in waveform]))
|
129 |
+
|
130 |
+
distances.append(distance)
|
131 |
+
t0s.append(starttime)
|
132 |
+
st_lats.append(station.latitude)
|
133 |
+
st_lons.append(station.longitude)
|
134 |
+
waveforms.append(waveform)
|
135 |
+
|
136 |
+
except (IndexError, FDSNNoDataException, FDSNTimeoutException):
|
137 |
+
continue
|
138 |
+
|
139 |
+
with torch.no_grad():
|
140 |
+
waveforms_torch = torch.vstack(waveforms)
|
141 |
+
output = model(waveforms_torch)
|
142 |
+
|
143 |
+
p_phases = output[:, 0]
|
144 |
+
s_phases = output[:, 1]
|
145 |
+
|
146 |
+
|
147 |
+
print(p_phases.shape)
|
148 |
+
# for i in range(len(waveforms)):
|
149 |
+
# current_P = P_batch[i::len(waveforms)].cpu()
|
150 |
+
# current_S_batch = S_batch[i::len(waveforms)].cpu()
|
151 |
+
# current_Pg_batch = Pg_batch[i::len(waveforms)].cpu()
|
152 |
+
# current_Sg_batch = Sg_batch[i::len(waveforms)].cpu()
|
153 |
+
# current_Pn_batch = Pn_batch[i::len(waveforms)].cpu()
|
154 |
+
# current_Sn_batch = Sn_batch[i::len(waveforms)].cpu()
|
155 |
+
|
156 |
+
fig,ax = plt.subplots()
|
157 |
+
ax.scatter(st_lats, st_lons)
|
158 |
+
fig.canvas.draw()
|
159 |
+
image = np.array(fig.canvas.renderer.buffer_rgba())
|
160 |
+
plt.close(fig)
|
161 |
|
162 |
+
return image
|
|
|
163 |
|
|
|
164 |
|
165 |
model = Onset_picker.load_from_checkpoint("./weights.ckpt",
|
166 |
picker=Updated_onset_picker(),
|
|
|
176 |
with gr.Blocks() as demo:
|
177 |
gr.Markdown("# PhaseHunter")
|
178 |
gr.Markdown("""This app allows one to detect P and S seismic phases along with uncertainty of the detection.
|
179 |
+
The app can be used in three ways: either by selecting one of the sample waveforms;
|
180 |
+
or by selecting an earthquake from the global earthquake catalogue;
|
181 |
+
or by uploading a waveform of interest.
|
182 |
+
""")
|
183 |
with gr.Tab("Default example"):
|
184 |
# Define the input and output types for Gradio
|
185 |
inputs = gr.Dropdown(
|
|
|
220 |
info="Latitude of the earthquake",
|
221 |
interactive=True)
|
222 |
|
223 |
+
eq_lon_inputs = gr.Number(value=-117.605,
|
224 |
label="Longitude",
|
225 |
info="Longitude of the earthquake",
|
226 |
interactive=True)
|
227 |
|
228 |
+
source_depth_inputs = gr.Number(value=10,
|
229 |
+
label="Source depth (km)",
|
230 |
+
info="Depth of the earthquake",
|
231 |
+
interactive=True)
|
232 |
+
|
233 |
radius_inputs = gr.Slider(minimum=1,
|
234 |
maximum=150,
|
235 |
value=50, label="Radius (km)",
|
236 |
info="Select the radius around the earthquake to download data from",
|
237 |
interactive=True)
|
238 |
|
239 |
+
velocity_inputs = gr.Dropdown(
|
240 |
+
choices = ['1066a', '1066b', 'ak135', 'ak135f', 'herrin', 'iasp91', 'jb', 'prem', 'pwdk'],
|
241 |
+
label="1D velocity model",
|
242 |
+
info="Velocity model for station selection",
|
243 |
+
value = "1066a",
|
244 |
+
interactive=True
|
245 |
+
)
|
246 |
+
|
247 |
+
|
248 |
button = gr.Button("Predict phases")
|
249 |
+
outputs_section = gr.outputs.Image(label='Waveforms with Phases Marked', type='numpy')
|
250 |
+
|
251 |
+
button.click(predict_on_section,
|
252 |
+
inputs=[client_inputs, timestamp_inputs,
|
253 |
+
eq_lat_inputs, eq_lon_inputs,
|
254 |
+
radius_inputs, source_depth_inputs, velocity_inputs],
|
255 |
+
outputs=outputs_section)
|
256 |
|
257 |
with gr.Tab("Predict on your own waveform"):
|
258 |
gr.Markdown("""
|
|
|
260 |
Your waveform should be sampled at 100 sps and have 3 (Z, N, E) or 1 (Z) channels.
|
261 |
""")
|
262 |
|
263 |
+
|
264 |
|
265 |
demo.launch()
|