zhuwq0 commited on
Commit
06d33b4
·
1 Parent(s): b201659

add quakeflow demo

Browse files
Files changed (1) hide show
  1. quakeflow.ipynb +881 -0
quakeflow.ipynb ADDED
@@ -0,0 +1,881 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 1,
6
+ "metadata": {
7
+ "id": "wGgBzZbXuajb"
8
+ },
9
+ "outputs": [],
10
+ "source": [
11
+ "from collections import defaultdict\n",
12
+ "import numpy as np\n",
13
+ "import pandas as pd\n",
14
+ "import time\n",
15
+ "import requests\n",
16
+ "import json\n",
17
+ "import obspy\n",
18
+ "from obspy.clients.fdsn import Client"
19
+ ]
20
+ },
21
+ {
22
+ "cell_type": "markdown",
23
+ "metadata": {
24
+ "id": "D3rP1Gu3R8wf"
25
+ },
26
+ "source": [
27
+ "## 1. Configuration"
28
+ ]
29
+ },
30
+ {
31
+ "cell_type": "code",
32
+ "execution_count": 2,
33
+ "metadata": {
34
+ "id": "W98ancI1u1-T"
35
+ },
36
+ "outputs": [],
37
+ "source": [
38
+ "region_name = \"Ridgecrest_demo\"\n",
39
+ "center = (-117.504, 35.705)\n",
40
+ "horizontal_degree = 1.0\n",
41
+ "vertical_degree = 1.0\n",
42
+ "starttime = obspy.UTCDateTime(\"2019-07-04T17\")\n",
43
+ "endtime = obspy.UTCDateTime(\"2019-07-04T18\")\n",
44
+ "client = \"SCEDC\"\n",
45
+ "network_list = [\"CI\"]\n",
46
+ "# channel_list = \"HH*,BH*,EH*,HN*\"\n",
47
+ "channel_list = \"HH*,BH*,EH*\"\n",
48
+ "\n",
49
+ "config = {}\n",
50
+ "config[\"region\"] = region_name\n",
51
+ "config[\"center\"] = center\n",
52
+ "config[\"xlim_degree\"] = [center[0] - horizontal_degree / 2, center[0] + horizontal_degree / 2]\n",
53
+ "config[\"ylim_degree\"] = [center[1] - vertical_degree / 2, center[1] + vertical_degree / 2]\n",
54
+ "config[\"starttime\"] = starttime.datetime.isoformat()\n",
55
+ "config[\"endtime\"] = endtime.datetime.isoformat()\n",
56
+ "config[\"networks\"] = network_list\n",
57
+ "config[\"channels\"] = channel_list\n",
58
+ "config[\"client\"] = client"
59
+ ]
60
+ },
61
+ {
62
+ "cell_type": "code",
63
+ "execution_count": 3,
64
+ "metadata": {},
65
+ "outputs": [
66
+ {
67
+ "data": {
68
+ "text/plain": [
69
+ "{'region': 'Ridgecrest_demo',\n",
70
+ " 'center': (-117.504, 35.705),\n",
71
+ " 'xlim_degree': [-118.004, -117.004],\n",
72
+ " 'ylim_degree': [35.205, 36.205],\n",
73
+ " 'starttime': '2019-07-04T17:00:00',\n",
74
+ " 'endtime': '2019-07-04T18:00:00',\n",
75
+ " 'networks': ['CI'],\n",
76
+ " 'channels': 'HH*,BH*,EH*',\n",
77
+ " 'client': 'SCEDC'}"
78
+ ]
79
+ },
80
+ "execution_count": 3,
81
+ "metadata": {},
82
+ "output_type": "execute_result"
83
+ }
84
+ ],
85
+ "source": [
86
+ "config"
87
+ ]
88
+ },
89
+ {
90
+ "cell_type": "markdown",
91
+ "metadata": {
92
+ "id": "m6ftaZ7HSCxG"
93
+ },
94
+ "source": [
95
+ "## 2. Download event information"
96
+ ]
97
+ },
98
+ {
99
+ "cell_type": "code",
100
+ "execution_count": 4,
101
+ "metadata": {
102
+ "id": "DltZ-s2vtzDo"
103
+ },
104
+ "outputs": [],
105
+ "source": [
106
+ "events = Client(\"iris\").get_events(\n",
107
+ " starttime=config[\"starttime\"],\n",
108
+ " endtime=config[\"endtime\"],\n",
109
+ " minlongitude=config[\"xlim_degree\"][0],\n",
110
+ " maxlongitude=config[\"xlim_degree\"][1],\n",
111
+ " minlatitude=config[\"ylim_degree\"][0],\n",
112
+ " maxlatitude=config[\"ylim_degree\"][1],\n",
113
+ ")"
114
+ ]
115
+ },
116
+ {
117
+ "cell_type": "markdown",
118
+ "metadata": {
119
+ "id": "gfMajl0jS82C"
120
+ },
121
+ "source": [
122
+ "## 3. Download station information"
123
+ ]
124
+ },
125
+ {
126
+ "cell_type": "code",
127
+ "execution_count": 5,
128
+ "metadata": {
129
+ "id": "6PaJGUf0vGHL"
130
+ },
131
+ "outputs": [],
132
+ "source": [
133
+ "stations = Client(config[\"client\"]).get_stations(\n",
134
+ " network=\",\".join(config[\"networks\"]),\n",
135
+ " station=\"*\",\n",
136
+ " starttime=config[\"starttime\"],\n",
137
+ " endtime=config[\"endtime\"],\n",
138
+ " minlongitude=config[\"xlim_degree\"][0],\n",
139
+ " maxlongitude=config[\"xlim_degree\"][1],\n",
140
+ " minlatitude=config[\"ylim_degree\"][0],\n",
141
+ " maxlatitude=config[\"ylim_degree\"][1],\n",
142
+ " channel=config[\"channels\"],\n",
143
+ " level=\"response\",\n",
144
+ ")"
145
+ ]
146
+ },
147
+ {
148
+ "cell_type": "markdown",
149
+ "metadata": {
150
+ "id": "muvw2-CjTCPI"
151
+ },
152
+ "source": [
153
+ "## 3.1 Convert station information into csv"
154
+ ]
155
+ },
156
+ {
157
+ "cell_type": "code",
158
+ "execution_count": 6,
159
+ "metadata": {
160
+ "id": "HZpJxfSnvVjD"
161
+ },
162
+ "outputs": [],
163
+ "source": [
164
+ "station_locs = defaultdict(dict)\n",
165
+ "for network in stations:\n",
166
+ " for station in network:\n",
167
+ " for chn in station:\n",
168
+ " sid = f\"{network.code}.{station.code}.{chn.location_code}.{chn.code[:-1]}\"\n",
169
+ " if sid in station_locs:\n",
170
+ " station_locs[sid][\"component\"] += f\",{chn.code[-1]}\"\n",
171
+ " station_locs[sid][\"response\"] += f\",{chn.response.instrument_sensitivity.value:.2f}\"\n",
172
+ " else:\n",
173
+ " component = f\"{chn.code[-1]}\"\n",
174
+ " response = f\"{chn.response.instrument_sensitivity.value:.2f}\"\n",
175
+ " dtype = chn.response.instrument_sensitivity.input_units.lower()\n",
176
+ " tmp_dict = {}\n",
177
+ " tmp_dict[\"longitude\"], tmp_dict[\"latitude\"], tmp_dict[\"elevation_m\"] = (\n",
178
+ " chn.longitude,\n",
179
+ " chn.latitude,\n",
180
+ " chn.elevation,\n",
181
+ " )\n",
182
+ " tmp_dict[\"component\"], tmp_dict[\"response\"], tmp_dict[\"unit\"] = component, response, dtype\n",
183
+ " station_locs[sid] = tmp_dict\n",
184
+ "\n",
185
+ "station_locs = pd.DataFrame.from_dict(station_locs, orient='index')\n",
186
+ "station_locs[\"station_id\"] = station_locs.index"
187
+ ]
188
+ },
189
+ {
190
+ "cell_type": "markdown",
191
+ "metadata": {
192
+ "id": "5ZQdfPRgTNa8"
193
+ },
194
+ "source": [
195
+ "## 4. Download waveform"
196
+ ]
197
+ },
198
+ {
199
+ "cell_type": "code",
200
+ "execution_count": 7,
201
+ "metadata": {
202
+ "id": "NwfJw3f9vmyr"
203
+ },
204
+ "outputs": [],
205
+ "source": [
206
+ "client = Client(config[\"client\"])\n",
207
+ "interval = 30 #s\n",
208
+ "# interval = 3600 #s\n",
209
+ "\n",
210
+ "# for event in events:\n",
211
+ "def downlad(event, stations):\n",
212
+ " starttime = event[\"origins\"][0].time\n",
213
+ " endtime = starttime + interval\n",
214
+ "\n",
215
+ " max_retry = 10\n",
216
+ " stream = obspy.Stream()\n",
217
+ " num_sta = 0\n",
218
+ " for network in stations:\n",
219
+ " for station in network:\n",
220
+ " print(f\"********{network.code}.{station.code}********\")\n",
221
+ " retry = 0\n",
222
+ " while retry < max_retry:\n",
223
+ " try:\n",
224
+ " tmp = client.get_waveforms(\n",
225
+ " network.code, station.code, \"*\", config[\"channels\"], starttime, endtime\n",
226
+ " )\n",
227
+ " for trace in tmp:\n",
228
+ " if trace.stats.sampling_rate != 100:\n",
229
+ " # print(trace)\n",
230
+ " trace = trace.interpolate(100, method=\"linear\")\n",
231
+ " # trace = trace.detrend(\"spline\", order=2, dspline=5*trace.stats.sampling_rate)\n",
232
+ " # stream.append(trace)\n",
233
+ " stream += tmp\n",
234
+ " num_sta += len(tmp)\n",
235
+ " break\n",
236
+ " except Exception as err:\n",
237
+ " print(\"Error {}.{}: {}\".format(network.code, station.code, err))\n",
238
+ " message = \"No data available for request.\"\n",
239
+ " if str(err)[: len(message)] == message:\n",
240
+ " break\n",
241
+ " retry += 1\n",
242
+ " time.sleep(5)\n",
243
+ " continue\n",
244
+ " if retry == max_retry:\n",
245
+ " print(f\"{fname}: MAX {max_retry} retries reached : {network.code}.{station.code}\")\n",
246
+ "\n",
247
+ " # stream.attach_response(stations)\n",
248
+ " # stream = stream.remove_sensitivity()\n",
249
+ " return stream"
250
+ ]
251
+ },
252
+ {
253
+ "cell_type": "code",
254
+ "execution_count": 8,
255
+ "metadata": {
256
+ "colab": {
257
+ "base_uri": "https://localhost:8080/"
258
+ },
259
+ "id": "js21MWgZv3b9",
260
+ "outputId": "c4727cff-ad03-4dc1-9980-0d29950b6e38"
261
+ },
262
+ "outputs": [
263
+ {
264
+ "name": "stdout",
265
+ "output_type": "stream",
266
+ "text": [
267
+ "********CI.CCC********\n",
268
+ "********CI.CLC********\n",
269
+ "********CI.DTP********\n",
270
+ "********CI.JRC2********\n",
271
+ "********CI.LRL********\n",
272
+ "********CI.MPM********\n",
273
+ "********CI.SLA********\n",
274
+ "********CI.SRT********\n",
275
+ "********CI.TOW2********\n",
276
+ "********CI.WBM********\n",
277
+ "********CI.WCS2********\n",
278
+ "********CI.WMF********\n",
279
+ "********CI.WNM********\n",
280
+ "********CI.WRC2********\n",
281
+ "********CI.WRV2********\n",
282
+ "********CI.WVP2********\n"
283
+ ]
284
+ }
285
+ ],
286
+ "source": [
287
+ "mseed = downlad(events[0], stations)"
288
+ ]
289
+ },
290
+ {
291
+ "cell_type": "markdown",
292
+ "metadata": {
293
+ "id": "nZ12RlV3UlR9"
294
+ },
295
+ "source": [
296
+ "## 5. Convert waveform to numpy"
297
+ ]
298
+ },
299
+ {
300
+ "cell_type": "code",
301
+ "execution_count": 9,
302
+ "metadata": {
303
+ "id": "z5YUt8FN1Mxe"
304
+ },
305
+ "outputs": [],
306
+ "source": [
307
+ "sampling_rate = 100\n",
308
+ "n_channel = 3\n",
309
+ "dtype = \"float32\"\n",
310
+ "amplitude = True\n",
311
+ "remove_resp = True\n",
312
+ "\n",
313
+ "def convert_mseed(mseed, station_locs):\n",
314
+ " try:\n",
315
+ " mseed = mseed.detrend(\"spline\", order=2, dspline=5 * mseed[0].stats.sampling_rate)\n",
316
+ " except:\n",
317
+ " logging.error(f\"Error: spline detrend failed at file {fname}\")\n",
318
+ " mseed = mseed.detrend(\"demean\")\n",
319
+ " mseed = mseed.merge(fill_value=0)\n",
320
+ " starttime = min([st.stats.starttime for st in mseed])\n",
321
+ " endtime = max([st.stats.endtime for st in mseed])\n",
322
+ " mseed = mseed.trim(starttime, endtime, pad=True, fill_value=0)\n",
323
+ "\n",
324
+ " for i in range(len(mseed)):\n",
325
+ " if mseed[i].stats.sampling_rate != sampling_rate:\n",
326
+ " logging.warning(\n",
327
+ " f\"Resampling {mseed[i].id} from {mseed[i].stats.sampling_rate} to {sampling_rate} Hz\"\n",
328
+ " )\n",
329
+ " mseed[i] = mseed[i].interpolate(sampling_rate, method=\"linear\")\n",
330
+ "\n",
331
+ " order = ['3', '2', '1', 'E', 'N', 'Z']\n",
332
+ " order = {key: i for i, key in enumerate(order)}\n",
333
+ " comp2idx = {\"3\": 0, \"2\": 1, \"1\": 2, \"E\": 0, \"N\": 1, \"Z\": 2}\n",
334
+ "\n",
335
+ " nsta = len(station_locs)\n",
336
+ " nt = max(len(mseed[i].data) for i in range(len(mseed)))\n",
337
+ " data = []\n",
338
+ " station_id = []\n",
339
+ " t0 = []\n",
340
+ " for i in range(nsta):\n",
341
+ " trace_data = np.zeros([nt, n_channel], dtype=dtype)\n",
342
+ " empty_station = True\n",
343
+ " # sta = station_locs.iloc[i][\"station\"]\n",
344
+ " sta = station_locs.index[i]\n",
345
+ " comp = station_locs.iloc[i][\"component\"].split(\",\")\n",
346
+ " if remove_resp:\n",
347
+ " resp = station_locs.iloc[i][\"response\"].split(\",\")\n",
348
+ " # resp = station_locs.iloc[i][\"response\"]\n",
349
+ "\n",
350
+ " for j, c in enumerate(sorted(comp, key=lambda x: order[x[-1]])):\n",
351
+ "\n",
352
+ " resp_j = float(resp[j])\n",
353
+ " if len(comp) != 3: ## less than 3 component\n",
354
+ " j = comp2idx[c]\n",
355
+ "\n",
356
+ " if len(mseed.select(id=sta + c)) == 0:\n",
357
+ " print(f\"Empty trace: {sta+c} {starttime}\")\n",
358
+ " continue\n",
359
+ " else:\n",
360
+ " empty_station = False\n",
361
+ "\n",
362
+ " tmp = mseed.select(id=sta + c)[0].data.astype(dtype)\n",
363
+ " trace_data[: len(tmp), j] = tmp[:nt]\n",
364
+ "\n",
365
+ " if station_locs.iloc[i][\"unit\"] == \"m/s**2\":\n",
366
+ " tmp = mseed.select(id=sta + c)[0]\n",
367
+ " tmp = tmp.integrate()\n",
368
+ " tmp = tmp.filter(\"highpass\", freq=1.0)\n",
369
+ " tmp = tmp.data.astype(dtype)\n",
370
+ " trace_data[: len(tmp), j] = tmp[:nt]\n",
371
+ " elif station_locs.iloc[i][\"unit\"] == \"m/s\":\n",
372
+ " tmp = mseed.select(id=sta + c)[0].data.astype(dtype)\n",
373
+ " trace_data[: len(tmp), j] = tmp[:nt]\n",
374
+ " else:\n",
375
+ " print(\n",
376
+ " f\"Error in {station_locs.iloc[i]['station']}\\n{station_locs.iloc[i]['unit']} should be m/s**2 or m/s!\"\n",
377
+ " )\n",
378
+ "\n",
379
+ " if remove_resp:\n",
380
+ " trace_data[:, j] /= resp_j\n",
381
+ "\n",
382
+ " if not empty_station:\n",
383
+ " data.append(trace_data)\n",
384
+ " station_id.append(sta)\n",
385
+ " t0.append(starttime.strftime(\"%Y-%m-%dT%H:%M:%S.%f\")[:-3])\n",
386
+ "\n",
387
+ " data = np.stack(data)\n",
388
+ "\n",
389
+ " meta = {\"data\": data, \"t0\": t0, \"station_id\": station_id, \"fname\": station_id}\n",
390
+ "\n",
391
+ "\n",
392
+ " return meta"
393
+ ]
394
+ },
395
+ {
396
+ "cell_type": "code",
397
+ "execution_count": 10,
398
+ "metadata": {
399
+ "id": "hNaM-pt7VEev"
400
+ },
401
+ "outputs": [],
402
+ "source": [
403
+ "meta = convert_mseed(mseed, station_locs)"
404
+ ]
405
+ },
406
+ {
407
+ "cell_type": "markdown",
408
+ "metadata": {
409
+ "id": "3dpQquouVKya"
410
+ },
411
+ "source": [
412
+ "## 6. Pick P/S picks using PhaseNet"
413
+ ]
414
+ },
415
+ {
416
+ "cell_type": "code",
417
+ "execution_count": 11,
418
+ "metadata": {
419
+ "colab": {
420
+ "base_uri": "https://localhost:8080/",
421
+ "height": 408
422
+ },
423
+ "id": "UDPpI9rl02Kv",
424
+ "outputId": "acdd4ebc-82c3-4549-ce15-581c82afafc4"
425
+ },
426
+ "outputs": [
427
+ {
428
+ "name": "stdout",
429
+ "output_type": "stream",
430
+ "text": [
431
+ "PhaseNet picks station_id phase_time phase_score phase_type dt\n",
432
+ "0 CI.CCC..BH 2019-07-04T17:58:07.368 0.952 P 0.01\n",
433
+ "1 CI.CCC..BH 2019-07-04T17:58:10.978 0.891 S 0.01\n",
434
+ "2 CI.CCC..HH 2019-07-04T17:58:07.398 0.952 P 0.01\n",
435
+ "3 CI.CCC..HH 2019-07-04T17:58:11.008 0.798 S 0.01\n",
436
+ "4 CI.CLC..BH 2019-07-04T17:58:05.478 0.959 P 0.01\n",
437
+ ".. ... ... ... ... ...\n",
438
+ "57 CI.WRC2..HH 2019-07-04T17:58:08.038 0.983 P 0.01\n",
439
+ "58 CI.WRC2..HH 2019-07-04T17:58:12.048 0.803 S 0.01\n",
440
+ "59 CI.WRV2..EH 2019-07-04T17:58:10.948 0.959 P 0.01\n",
441
+ "60 CI.WRV2..EH 2019-07-04T17:58:17.068 0.551 S 0.01\n",
442
+ "61 CI.WVP2..EH 2019-07-04T17:58:09.578 0.352 P 0.01\n",
443
+ "\n",
444
+ "[62 rows x 5 columns]\n"
445
+ ]
446
+ }
447
+ ],
448
+ "source": [
449
+ "# PHASENET_API_URL = \"http://127.0.0.1:8000\"\n",
450
+ "PHASENET_API_URL = \"https://ai4eps-eqnet.hf.space\"\n",
451
+ "\n",
452
+ "\n",
453
+ "batch = 4\n",
454
+ "phasenet_picks = []\n",
455
+ "for j in range(0, len(meta[\"station_id\"]), batch):\n",
456
+ " req = {\"id\": [[x] for x in meta[\"station_id\"][j:j+batch]],\n",
457
+ " \"timestamp\": meta[\"t0\"][j:j+batch],\n",
458
+ " \"vec\": meta[\"data\"][j:j+batch].tolist()}\n",
459
+ "\n",
460
+ " resp = requests.post(f'{PHASENET_API_URL}/predict', json=req)\n",
461
+ " phasenet_picks.extend(resp.json())\n",
462
+ "\n",
463
+ "print('PhaseNet picks', pd.DataFrame(phasenet_picks))\n"
464
+ ]
465
+ },
466
+ {
467
+ "cell_type": "markdown",
468
+ "metadata": {
469
+ "id": "5JX6AppkV1b0"
470
+ },
471
+ "source": [
472
+ "## 7. Associate picks using GaMMA"
473
+ ]
474
+ },
475
+ {
476
+ "cell_type": "code",
477
+ "execution_count": 12,
478
+ "metadata": {
479
+ "colab": {
480
+ "base_uri": "https://localhost:8080/",
481
+ "height": 228
482
+ },
483
+ "id": "YEkupkaa3JmD",
484
+ "outputId": "9b40951c-ed12-4031-ddbc-7ada6c4e09e5"
485
+ },
486
+ "outputs": [
487
+ {
488
+ "name": "stdout",
489
+ "output_type": "stream",
490
+ "text": [
491
+ "GaMMA catalog:\n"
492
+ ]
493
+ },
494
+ {
495
+ "data": {
496
+ "text/html": [
497
+ "<div>\n",
498
+ "<style scoped>\n",
499
+ " .dataframe tbody tr th:only-of-type {\n",
500
+ " vertical-align: middle;\n",
501
+ " }\n",
502
+ "\n",
503
+ " .dataframe tbody tr th {\n",
504
+ " vertical-align: top;\n",
505
+ " }\n",
506
+ "\n",
507
+ " .dataframe thead th {\n",
508
+ " text-align: right;\n",
509
+ " }\n",
510
+ "</style>\n",
511
+ "<table border=\"1\" class=\"dataframe\">\n",
512
+ " <thead>\n",
513
+ " <tr style=\"text-align: right;\">\n",
514
+ " <th></th>\n",
515
+ " <th>time</th>\n",
516
+ " <th>magnitude</th>\n",
517
+ " <th>sigma_time</th>\n",
518
+ " <th>sigma_amp</th>\n",
519
+ " <th>cov_time_amp</th>\n",
520
+ " <th>gamma_score</th>\n",
521
+ " <th>num_picks</th>\n",
522
+ " <th>num_p_picks</th>\n",
523
+ " <th>num_s_picks</th>\n",
524
+ " <th>event_index</th>\n",
525
+ " <th>longitude</th>\n",
526
+ " <th>latitude</th>\n",
527
+ " <th>depth_km</th>\n",
528
+ " </tr>\n",
529
+ " </thead>\n",
530
+ " <tbody>\n",
531
+ " <tr>\n",
532
+ " <th>0</th>\n",
533
+ " <td>2019-07-04T17:58:02.566</td>\n",
534
+ " <td>999</td>\n",
535
+ " <td>0.344259</td>\n",
536
+ " <td>0</td>\n",
537
+ " <td>0</td>\n",
538
+ " <td>56.970255</td>\n",
539
+ " <td>57</td>\n",
540
+ " <td>29</td>\n",
541
+ " <td>28</td>\n",
542
+ " <td>1</td>\n",
543
+ " <td>-117.503559</td>\n",
544
+ " <td>35.70536</td>\n",
545
+ " <td>12.578723</td>\n",
546
+ " </tr>\n",
547
+ " </tbody>\n",
548
+ "</table>\n",
549
+ "</div>"
550
+ ],
551
+ "text/plain": [
552
+ " time magnitude sigma_time sigma_amp cov_time_amp \\\n",
553
+ "0 2019-07-04T17:58:02.566 999 0.344259 0 0 \n",
554
+ "\n",
555
+ " gamma_score num_picks num_p_picks num_s_picks event_index longitude \\\n",
556
+ "0 56.970255 57 29 28 1 -117.503559 \n",
557
+ "\n",
558
+ " latitude depth_km \n",
559
+ "0 35.70536 12.578723 "
560
+ ]
561
+ },
562
+ "metadata": {},
563
+ "output_type": "display_data"
564
+ },
565
+ {
566
+ "name": "stdout",
567
+ "output_type": "stream",
568
+ "text": [
569
+ "GaMMA association:\n"
570
+ ]
571
+ },
572
+ {
573
+ "data": {
574
+ "text/html": [
575
+ "<div>\n",
576
+ "<style scoped>\n",
577
+ " .dataframe tbody tr th:only-of-type {\n",
578
+ " vertical-align: middle;\n",
579
+ " }\n",
580
+ "\n",
581
+ " .dataframe tbody tr th {\n",
582
+ " vertical-align: top;\n",
583
+ " }\n",
584
+ "\n",
585
+ " .dataframe thead th {\n",
586
+ " text-align: right;\n",
587
+ " }\n",
588
+ "</style>\n",
589
+ "<table border=\"1\" class=\"dataframe\">\n",
590
+ " <thead>\n",
591
+ " <tr style=\"text-align: right;\">\n",
592
+ " <th></th>\n",
593
+ " <th>station_id</th>\n",
594
+ " <th>phase_time</th>\n",
595
+ " <th>phase_score</th>\n",
596
+ " <th>phase_type</th>\n",
597
+ " <th>dt</th>\n",
598
+ " <th>event_index</th>\n",
599
+ " <th>gamma_score</th>\n",
600
+ " </tr>\n",
601
+ " </thead>\n",
602
+ " <tbody>\n",
603
+ " <tr>\n",
604
+ " <th>0</th>\n",
605
+ " <td>CI.CCC..BH</td>\n",
606
+ " <td>2019-07-04T17:58:07.368000</td>\n",
607
+ " <td>0.952</td>\n",
608
+ " <td>P</td>\n",
609
+ " <td>0.01</td>\n",
610
+ " <td>1</td>\n",
611
+ " <td>0.667284</td>\n",
612
+ " </tr>\n",
613
+ " <tr>\n",
614
+ " <th>1</th>\n",
615
+ " <td>CI.CCC..BH</td>\n",
616
+ " <td>2019-07-04T17:58:10.978000</td>\n",
617
+ " <td>0.891</td>\n",
618
+ " <td>S</td>\n",
619
+ " <td>0.01</td>\n",
620
+ " <td>1</td>\n",
621
+ " <td>0.362202</td>\n",
622
+ " </tr>\n",
623
+ " <tr>\n",
624
+ " <th>2</th>\n",
625
+ " <td>CI.CCC..HH</td>\n",
626
+ " <td>2019-07-04T17:58:07.398000</td>\n",
627
+ " <td>0.952</td>\n",
628
+ " <td>P</td>\n",
629
+ " <td>0.01</td>\n",
630
+ " <td>1</td>\n",
631
+ " <td>0.631032</td>\n",
632
+ " </tr>\n",
633
+ " <tr>\n",
634
+ " <th>3</th>\n",
635
+ " <td>CI.CCC..HH</td>\n",
636
+ " <td>2019-07-04T17:58:11.008000</td>\n",
637
+ " <td>0.798</td>\n",
638
+ " <td>S</td>\n",
639
+ " <td>0.01</td>\n",
640
+ " <td>1</td>\n",
641
+ " <td>0.294299</td>\n",
642
+ " </tr>\n",
643
+ " <tr>\n",
644
+ " <th>4</th>\n",
645
+ " <td>CI.CLC..BH</td>\n",
646
+ " <td>2019-07-04T17:58:05.478000</td>\n",
647
+ " <td>0.959</td>\n",
648
+ " <td>P</td>\n",
649
+ " <td>0.01</td>\n",
650
+ " <td>1</td>\n",
651
+ " <td>0.491822</td>\n",
652
+ " </tr>\n",
653
+ " <tr>\n",
654
+ " <th>...</th>\n",
655
+ " <td>...</td>\n",
656
+ " <td>...</td>\n",
657
+ " <td>...</td>\n",
658
+ " <td>...</td>\n",
659
+ " <td>...</td>\n",
660
+ " <td>...</td>\n",
661
+ " <td>...</td>\n",
662
+ " </tr>\n",
663
+ " <tr>\n",
664
+ " <th>57</th>\n",
665
+ " <td>CI.WRC2..HH</td>\n",
666
+ " <td>2019-07-04T17:58:08.038000</td>\n",
667
+ " <td>0.983</td>\n",
668
+ " <td>P</td>\n",
669
+ " <td>0.01</td>\n",
670
+ " <td>1</td>\n",
671
+ " <td>0.617376</td>\n",
672
+ " </tr>\n",
673
+ " <tr>\n",
674
+ " <th>58</th>\n",
675
+ " <td>CI.WRC2..HH</td>\n",
676
+ " <td>2019-07-04T17:58:12.048000</td>\n",
677
+ " <td>0.803</td>\n",
678
+ " <td>S</td>\n",
679
+ " <td>0.01</td>\n",
680
+ " <td>1</td>\n",
681
+ " <td>0.859684</td>\n",
682
+ " </tr>\n",
683
+ " <tr>\n",
684
+ " <th>59</th>\n",
685
+ " <td>CI.WRV2..EH</td>\n",
686
+ " <td>2019-07-04T17:58:10.948000</td>\n",
687
+ " <td>0.959</td>\n",
688
+ " <td>P</td>\n",
689
+ " <td>0.01</td>\n",
690
+ " <td>1</td>\n",
691
+ " <td>0.573461</td>\n",
692
+ " </tr>\n",
693
+ " <tr>\n",
694
+ " <th>60</th>\n",
695
+ " <td>CI.WRV2..EH</td>\n",
696
+ " <td>2019-07-04T17:58:17.068000</td>\n",
697
+ " <td>0.551</td>\n",
698
+ " <td>S</td>\n",
699
+ " <td>0.01</td>\n",
700
+ " <td>1</td>\n",
701
+ " <td>0.877037</td>\n",
702
+ " </tr>\n",
703
+ " <tr>\n",
704
+ " <th>61</th>\n",
705
+ " <td>CI.WVP2..EH</td>\n",
706
+ " <td>2019-07-04T17:58:09.578000</td>\n",
707
+ " <td>0.352</td>\n",
708
+ " <td>P</td>\n",
709
+ " <td>0.01</td>\n",
710
+ " <td>1</td>\n",
711
+ " <td>0.676099</td>\n",
712
+ " </tr>\n",
713
+ " </tbody>\n",
714
+ "</table>\n",
715
+ "<p>62 rows × 7 columns</p>\n",
716
+ "</div>"
717
+ ],
718
+ "text/plain": [
719
+ " station_id phase_time phase_score phase_type dt \\\n",
720
+ "0 CI.CCC..BH 2019-07-04T17:58:07.368000 0.952 P 0.01 \n",
721
+ "1 CI.CCC..BH 2019-07-04T17:58:10.978000 0.891 S 0.01 \n",
722
+ "2 CI.CCC..HH 2019-07-04T17:58:07.398000 0.952 P 0.01 \n",
723
+ "3 CI.CCC..HH 2019-07-04T17:58:11.008000 0.798 S 0.01 \n",
724
+ "4 CI.CLC..BH 2019-07-04T17:58:05.478000 0.959 P 0.01 \n",
725
+ ".. ... ... ... ... ... \n",
726
+ "57 CI.WRC2..HH 2019-07-04T17:58:08.038000 0.983 P 0.01 \n",
727
+ "58 CI.WRC2..HH 2019-07-04T17:58:12.048000 0.803 S 0.01 \n",
728
+ "59 CI.WRV2..EH 2019-07-04T17:58:10.948000 0.959 P 0.01 \n",
729
+ "60 CI.WRV2..EH 2019-07-04T17:58:17.068000 0.551 S 0.01 \n",
730
+ "61 CI.WVP2..EH 2019-07-04T17:58:09.578000 0.352 P 0.01 \n",
731
+ "\n",
732
+ " event_index gamma_score \n",
733
+ "0 1 0.667284 \n",
734
+ "1 1 0.362202 \n",
735
+ "2 1 0.631032 \n",
736
+ "3 1 0.294299 \n",
737
+ "4 1 0.491822 \n",
738
+ ".. ... ... \n",
739
+ "57 1 0.617376 \n",
740
+ "58 1 0.859684 \n",
741
+ "59 1 0.573461 \n",
742
+ "60 1 0.877037 \n",
743
+ "61 1 0.676099 \n",
744
+ "\n",
745
+ "[62 rows x 7 columns]"
746
+ ]
747
+ },
748
+ "metadata": {},
749
+ "output_type": "display_data"
750
+ }
751
+ ],
752
+ "source": [
753
+ "# GAMMA_API_URL = \"http://127.0.0.1:8001\"\n",
754
+ "GAMMA_API_URL = \"https://ai4eps-gamma.hf.space\"\n",
755
+ "\n",
756
+ "stations_json = station_locs.to_dict(orient=\"records\")\n",
757
+ "\n",
758
+ "config = {}\n",
759
+ "config[\"use_amplitude\"] = False\n",
760
+ "response = requests.post(f'{GAMMA_API_URL}/predict/', json= {\"picks\": {\"data\": phasenet_picks},\n",
761
+ " \"stations\": {\"data\": stations_json},\n",
762
+ " \"config\": config})\n",
763
+ "\n",
764
+ "if response.status_code == 200:\n",
765
+ " result = response.json()\n",
766
+ " events_gamma = result[\"events\"]\n",
767
+ " picks_gamma = result[\"picks\"]\n",
768
+ " print(\"GaMMA catalog:\")\n",
769
+ " display(pd.DataFrame(events_gamma))\n",
770
+ " print(\"GaMMA association:\")\n",
771
+ " display(pd.DataFrame(picks_gamma))\n",
772
+ "else:\n",
773
+ " print(f\"Request failed with status code: {response.status_code}\")\n",
774
+ " print(f\"Error message: {response.text}\")"
775
+ ]
776
+ },
777
+ {
778
+ "cell_type": "code",
779
+ "execution_count": 13,
780
+ "metadata": {
781
+ "id": "QlsjyoCtLFAr"
782
+ },
783
+ "outputs": [
784
+ {
785
+ "data": {
786
+ "text/plain": [
787
+ "<matplotlib.collections.PathCollection at 0x306ca0910>"
788
+ ]
789
+ },
790
+ "execution_count": 13,
791
+ "metadata": {},
792
+ "output_type": "execute_result"
793
+ },
794
+ {
795
+ "data": {
796
+ "image/png": "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V43N9qzrpZNPcyQOACA0uOg23MTESfeslj54TCpcK53SUbrit77S0hSknC/duVT692+l8hKpyyDpgtudTgUAOMFcxhjjdIhg8Hq98ng8KikpkdvtdjoOAABogIbuvzklBAAArEdhAQAA1qOwAAAA61FYAACA9SgsAADAehQWAABgPQoLAACwHoUFAABYj8ICAACsR2EBAADWo7AAAADrUVgAAID1KCwAAMB6FBYAAGA9CgsAALAehQUAAFiPwgIAAKxHYQEAANajsAAAAOtRWAAAgPUoLAAAwHoUFgAAYD0KCwAAsF6jCsv06dOVkZEht9stt9utzMxMvfvuu/7HR48eLZfLFXDr1atXg9efnZ0tl8ula6+9tjGxAABAhItpzMIpKSmaMmWKOnbsKEmaM2eOhgwZory8PJ111lmSpAEDBmjWrFn+58TFxTVo3d98843uv/9+XXzxxY2JBAAAmoBGFZZBgwYF3J80aZKmT5+uZcuW+QtLfHy82rVr16gQVVVVGjFihCZOnKhPPvlExcXFjXo+AACIbMd8DUtVVZWys7NVVlamzMxM/3hubq6SkpLUqVMn3Xbbbfruu++Ouq7HH39cbdq00ZgxYxr8+hUVFfJ6vQE3AAAQmRp1hEWS8vPzlZmZqfLycrVs2VILFixQ165dJUkDBw7UjTfeqLS0NG3evFkTJkxQ3759tXr1asXHx9e6vv/85z966aWXtGbNmkblmDx5siZOnNjY+AAAIAy5jDGmMU/Yv3+/tmzZouLiYs2fP18zZszQokWL/KXlcIWFhUpLS1N2draGDh1a4/HS0lJlZGTo+eef18CBAyX5LtwtLi7Wm2++WW+OiooKVVRU+O97vV6lpqaqpKREbre7MW8JAAA4xOv1yuPxHHX/3egjLHFxcf6Lbnv06KGVK1fqmWee0Ysvvlhj2eTkZKWlpWnDhg21rmvTpk0qKCgIuDamurraFywmRl999ZXOOOOMWp8bHx9f51EbAAAQWRpdWI5kjAk40nG4Xbt2aevWrUpOTq718c6dOys/Pz9g7JFHHlFpaameeeYZpaamHm88AAAQARpVWMaPH6+BAwcqNTVVpaWlys7OVm5urnJycrRnzx499thjuv7665WcnKyCggKNHz9erVu31nXXXedfx8iRI9WhQwdNnjxZCQkJOvvsswNeo1WrVpJUYxwAADRd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mJiooUOHBownJyerurraf79ly5aaNm2aLrzwQkVFRentt9/WsGHDNGfOHP30pz+V5NtI5s6dq2HDhqm8vFyVlZUaPHiwnnvuOf96mjdvrvT0dMXGxkqSioqKFBcXp5NOOing9du2bauioiL//XHjxuncc8/VSSedpBUrVujhhx/W5s2bNWPGjKDPyfFwej4boqioSElJSTXGk5KSAubcaeEwlxLb5rHO565du/Tb3/5WY8eO9Y+Fy7Yphcd8SmyfjZ3P559/Xr/61a9UVlamzp076/3331dcXJyk8No+6+Tk4Z2j0VEOw6Wnp5u77777mNZ99913m27duvnvf/755yY5Odn8/ve/N2vXrjU5OTmmW7du5pZbbqlzHXPnzjVxcXE1xi+//HIzduzYOp/3xhtvGElm586dx5T9WNk+n4er6zTGpEmTTKdOnWos37FjRzN58uRjyn4sImEua8O2eXQlJSWmZ8+eZsCAAWb//v3+cVu2TWMiYz5rw/ZZv+LiYrN+/XqzaNEiM2jQIHPuueeaffv2GWPs2j6PVdgWlo8//thIMmvWrDmmdf/tb38zCQkJ/vs//elPzQ033BCwzCeffGIkme3bt9e6jg8//NBIMt9//33AeEZGhvnNb35T52tv27atxrnEULB9Pg9X1072pZdeMh6Pp8byHo/HzJw585iyH4tImMvasG3WP59er9dkZmaafv36+XcEB9mybRoTGfNZG7bPo/99P6iiosI0b97cvPrqq8YYu7bPYxW217C89NJLOu+889S9e/djen5eXp6Sk5P99/fu3auoqMDpiI6OliSZOn5u6bzzzlNsbKzef/99/1hhYaE+++wz9e7du97XlhTw+k6zYT4bIjMzUyUlJVqxYoV/bPny5SopKal3zkMpXOayrteW2DZr4/V6dcUVVyguLk5vv/22EhISAh4Ph21TCp/5rOu1JbbPhjLGqKKiQlL4bJ/1crAs1aq0tNTk5eWZvLw8I8lMmzbN5OXlmW+++ca/TElJiWnevLmZPn16ret46KGHTFZWlv/+7Nmzzdy5c80XX3xh1q1bZ6ZOnWpiY2PNtGnT/MvMmjXLxMTEmOeff95s2rTJLF682PTo0cNccMEF/mWWL19u0tPTzbZt2/xjP//5z01KSor54IMPzKeffmr69u1runfvbiorK40xxixZssT/Hr7++mszb9480759ezN48OCgzVl9wm0+CwsLTV5envnrX/9qJJmPP/7Y5OXlmV27dvmXGTBggMnIyDBLly41S5cuNd26dTPXXHNNUOarPpE2l2ybDZ9Pr9drevbsabp162Y2btxoCgsL/beDf9eNcW7bNCby5pPts+HzuWnTJvO73/3OrFq1ynzzzTdmyZIlZsiQIebkk082O3bs8D/Pye0zGKwrLAcPXx95GzVqlH+ZF1980TRr1swUFxfXuo5Ro0aZSy+91H9/9uzZpkuXLqZ58+YmMTHRnHfeeeaVV16p8bxnn33WdO3a1TRr1swkJyebESNGBOwADmbbvHmzf2zfvn3m7rvvNieffLJp1qyZueaaa8yWLVv8j69evdr07NnTeDwek5CQYNLT082jjz5qysrKjn2SGiHc5vPRRx+tNe+sWbP8y+zatcuMGDHCJCYmmsTERDNixIgGne44XpE2l2ybDZ/PurIeOedObZv1ZQzX+WT7bPh8fvvtt2bgwIEmKSnJxMbGmpSUFDN8+PAaH1d2cvsMBpcxQT6mDAAAEGRhew0LAABoOigsAADAehQWAABgPQoLAACwHoUFAABYj8ICAACsR2EBAADWo7AAAADrUVgAAID1KCwAAMB6FBYAAGA9CgsAALDe/wencCRbdtkiPgAAAABJRU5ErkJggg==",
797
+ "text/plain": [
798
+ "<Figure size 640x480 with 1 Axes>"
799
+ ]
800
+ },
801
+ "metadata": {},
802
+ "output_type": "display_data"
803
+ }
804
+ ],
805
+ "source": [
806
+ "events_ = pd.DataFrame(result[\"events\"])\n",
807
+ "picks_ = pd.DataFrame(result[\"picks\"])\n",
808
+ "picks_[\"phase_time\"] = pd.to_datetime(picks_[\"phase_time\"])\n",
809
+ "picks_ = picks_.merge(station_locs[[\"station_id\", \"longitude\", \"latitude\"]], on=\"station_id\")\n",
810
+ "\n",
811
+ "plt.figure()\n",
812
+ "mapping_color = lambda x: f\"C{x}\" if x!= -1 else \"black\"\n",
813
+ "plt.scatter(picks_[\"phase_time\"], picks_[\"latitude\"], c=picks_[\"event_index\"].apply(mapping_color), s=10)"
814
+ ]
815
+ },
816
+ {
817
+ "cell_type": "markdown",
818
+ "metadata": {
819
+ "id": "Cz-fBlTmwkl2"
820
+ },
821
+ "source": [
822
+ "## Compare with official catalog"
823
+ ]
824
+ },
825
+ {
826
+ "cell_type": "code",
827
+ "execution_count": 14,
828
+ "metadata": {
829
+ "id": "q-EW2OPo51qr"
830
+ },
831
+ "outputs": [
832
+ {
833
+ "name": "stdout",
834
+ "output_type": "stream",
835
+ "text": [
836
+ "Origin\n",
837
+ "\t resource_id: ResourceIdentifier(id=\"smi:service.iris.edu/fdsnws/event/1/query?originid=39384936\")\n",
838
+ "\t time: UTCDateTime(2019, 7, 4, 17, 58, 2, 620000)\n",
839
+ "\t longitude: -117.516998\n",
840
+ "\t latitude: 35.700832\n",
841
+ "\t depth: 2770.0\n",
842
+ "\t creation_info: CreationInfo(author='ci,us')\n",
843
+ "Magnitude\n",
844
+ "\t resource_id: ResourceIdentifier(id=\"smi:service.iris.edu/fdsnws/event/1/query?magnitudeid=195120172\")\n",
845
+ "\t mag: 3.29\n",
846
+ "\t magnitude_type: 'Ml'\n",
847
+ "\t creation_info: CreationInfo(author='CI')\n"
848
+ ]
849
+ }
850
+ ],
851
+ "source": [
852
+ "event = events[0]\n",
853
+ "print(event.origins[0])\n",
854
+ "print(event.magnitudes[0])"
855
+ ]
856
+ }
857
+ ],
858
+ "metadata": {
859
+ "colab": {
860
+ "provenance": []
861
+ },
862
+ "kernelspec": {
863
+ "display_name": "Python 3",
864
+ "name": "python3"
865
+ },
866
+ "language_info": {
867
+ "codemirror_mode": {
868
+ "name": "ipython",
869
+ "version": 3
870
+ },
871
+ "file_extension": ".py",
872
+ "mimetype": "text/x-python",
873
+ "name": "python",
874
+ "nbconvert_exporter": "python",
875
+ "pygments_lexer": "ipython3",
876
+ "version": "3.10.12"
877
+ }
878
+ },
879
+ "nbformat": 4,
880
+ "nbformat_minor": 0
881
+ }