crimeacs commited on
Commit
d4306c7
·
1 Parent(s): 05d0cc5

WIP on section plot

Browse files
Files changed (1) hide show
  1. app.py +96 -19
app.py CHANGED
@@ -78,32 +78,89 @@ def mark_phases(waveform):
78
  plt.close(fig)
79
  return image
80
 
81
- #??
82
-
83
- def download_data(timestamp, eq_lat, eq_lon, client_name, radius_km):
 
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 = startime + 120
92
 
93
  inv = client.get_stations(network="*", station="*", location="*", channel="*H*",
94
- starttime=obspy.UTCDateTime(starttime), endtime=endtime,
95
- minlatitude=eq_lat-window, maxlatitude=eq_lat+window,
96
- minlongitude=eq_lon-window, maxlongitude=eq_lon+window,
97
- level='channel')
98
 
 
99
  for network in inv:
100
  for station in network:
101
- print(station)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
- # waveform = client.get_waveforms(network=network.code, station=station.code, location="*", channel="*",
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
- The app can be used in three ways: either by selecting one of the sample waveforms;
123
- or by selecting an earthquake from the global earthquake catalogue;
124
- or by uploading a waveform of interest.
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
- eq_lo_inputs = gr.Number(value=117.605,
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
- button.click(mark_phases, inputs=inputs, outputs=outputs)
 
 
 
 
 
 
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
- button.click(download_data, inputs=[timestamp_inputs, eq_lat_inputs,eq_lo_inputs, radius_inputs], outputs=outputs)
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()