crimeacs commited on
Commit
639fbda
·
1 Parent(s): 636d133

Added channel order input

Browse files
Gradio_app.ipynb CHANGED
@@ -2,14 +2,14 @@
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
- "execution_count": 17,
6
  "metadata": {},
7
  "outputs": [
8
  {
9
  "name": "stdout",
10
  "output_type": "stream",
11
  "text": [
12
- "Running on local URL: http://127.0.0.1:7864\n",
13
  "\n",
14
  "To create a public link, set `share=True` in `launch()`.\n"
15
  ]
@@ -17,7 +17,7 @@
17
  {
18
  "data": {
19
  "text/html": [
20
- "<div><iframe src=\"http://127.0.0.1:7864/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
21
  ],
22
  "text/plain": [
23
  "<IPython.core.display.HTML object>"
@@ -30,7 +30,7 @@
30
  "data": {
31
  "text/plain": []
32
  },
33
- "execution_count": 17,
34
  "metadata": {},
35
  "output_type": "execute_result"
36
  },
@@ -38,215 +38,7 @@
38
  "name": "stdout",
39
  "output_type": "stream",
40
  "text": [
41
- "Starting to download inventory\n",
42
- "Finished downloading inventory\n",
43
- "Processing CI.CCC...\n",
44
- "Downloading waveform for CI_CCC_2019-07-04T17:33:40.494920Z\n",
45
- "Skipping CI_CCC_2019-07-04T17:33:40.494920Z\n",
46
- "Processing CI.CLC...\n",
47
- "Processing CI.JRC2...\n",
48
- "Reading cached waveform\n",
49
- "Added CI.JRC2 to the list of waveforms\n",
50
- "Processing CI.LRL...\n",
51
- "Reading cached waveform\n",
52
- "Added CI.LRL to the list of waveforms\n",
53
- "Processing CI.MPM...\n",
54
- "Reading cached waveform\n",
55
- "Processing CI.Q0072...\n",
56
- "Reading cached waveform\n",
57
- "Processing CI.SLA...\n",
58
- "Reading cached waveform\n",
59
- "Added CI.SLA to the list of waveforms\n",
60
- "Processing CI.SRT...\n",
61
- "Reading cached waveform\n",
62
- "Added CI.SRT to the list of waveforms\n",
63
- "Processing CI.TOW2...\n",
64
- "Reading cached waveform\n",
65
- "Added CI.TOW2 to the list of waveforms\n",
66
- "Processing CI.WBM...\n",
67
- "Downloading waveform for CI_WBM_2019-07-04T17:33:40.063616Z\n",
68
- "Skipping CI_WBM_2019-07-04T17:33:40.063616Z\n",
69
- "Processing CI.WCS2...\n",
70
- "Downloading waveform for CI_WCS2_2019-07-04T17:33:40.200958Z\n",
71
- "Skipping CI_WCS2_2019-07-04T17:33:40.200958Z\n",
72
- "Processing CI.WMF...\n",
73
- "Reading cached waveform\n",
74
- "Added CI.WMF to the list of waveforms\n",
75
- "Processing CI.WNM...\n",
76
- "Reading cached waveform\n",
77
- "Processing CI.WRC2...\n",
78
- "Downloading waveform for CI_WRC2_2019-07-04T17:33:38.698099Z\n",
79
- "Skipping CI_WRC2_2019-07-04T17:33:38.698099Z\n",
80
- "Processing CI.WRV2...\n",
81
- "Reading cached waveform\n",
82
- "Processing CI.WVP2...\n",
83
- "Downloading waveform for CI_WVP2_2019-07-04T17:33:39.650402Z\n",
84
- "Skipping CI_WVP2_2019-07-04T17:33:39.650402Z\n",
85
- "Processing NP.1809...\n",
86
- "Reading cached waveform\n",
87
- "Processing NP.5419...\n",
88
- "Reading cached waveform\n",
89
- "Processing PB.B916...\n",
90
- "Reading cached waveform\n",
91
- "Processing PB.B917...\n",
92
- "Reading cached waveform\n",
93
- "Processing PB.B918...\n",
94
- "Reading cached waveform\n",
95
- "Processing PB.B921...\n",
96
- "Reading cached waveform\n",
97
- "Starting to run predictions\n"
98
- ]
99
- },
100
- {
101
- "name": "stderr",
102
- "output_type": "stream",
103
- "text": [
104
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:273: FutureWarning: The input object of type 'Tensor' is an array-like implementing one of the corresponding protocols (`__array__`, `__array_interface__` or `__array_struct__`); but not a sequence (or 0-D). In the future, this object will be coerced as if it was first converted using `np.array(obj)`. To retain the old behaviour, you have to either modify the type 'Tensor', or assign to an empty array created with `np.empty(correct_shape, dtype=object)`.\n",
105
- " waveforms = np.array(waveforms)[selection_indexes]\n",
106
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:273: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.\n",
107
- " waveforms = np.array(waveforms)[selection_indexes]\n",
108
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:280: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
109
- " waveforms = [torch.tensor(waveform) for waveform in waveforms]\n"
110
- ]
111
- },
112
- {
113
- "name": "stdout",
114
- "output_type": "stream",
115
- "text": [
116
- "Starting plotting 3 waveforms\n",
117
- "Fetching topography\n",
118
- "Plotting topo\n"
119
- ]
120
- },
121
- {
122
- "name": "stderr",
123
- "output_type": "stream",
124
- "text": [
125
- "/Users/anovosel/miniconda3/envs/phasehunter/lib/python3.11/site-packages/bmi_topography/api_key.py:49: UserWarning: You are using a demo key to fetch data from OpenTopography, functionality will be limited. See https://bmi-topography.readthedocs.io/en/latest/#api-key for more information.\n",
126
- " warnings.warn(\n"
127
- ]
128
- },
129
- {
130
- "name": "stdout",
131
- "output_type": "stream",
132
- "text": [
133
- "Plotting waveform 1/3\n",
134
- "Station 35.98249, -117.80885 has P velocity 4.13660431013202 and S velocity 2.2622770044299756\n",
135
- "Plotting waveform 2/3\n"
136
- ]
137
- },
138
- {
139
- "name": "stderr",
140
- "output_type": "stream",
141
- "text": [
142
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:365: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.\n",
143
- " output_picks = output_picks.append(pd.DataFrame({'station_name': [names[i]],\n",
144
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:365: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.\n",
145
- " output_picks = output_picks.append(pd.DataFrame({'station_name': [names[i]],\n"
146
- ]
147
- },
148
- {
149
- "name": "stdout",
150
- "output_type": "stream",
151
- "text": [
152
- "Station 35.69235, -117.75051 has P velocity 3.4155476453388767 and S velocity 1.67967367867923\n",
153
- "Plotting waveform 3/3\n",
154
- "Station 36.11758, -117.85486 has P velocity 4.745724852828504 and S velocity 2.6483289549749593\n",
155
- "Plotting stations\n"
156
- ]
157
- },
158
- {
159
- "name": "stderr",
160
- "output_type": "stream",
161
- "text": [
162
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:365: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.\n",
163
- " output_picks = output_picks.append(pd.DataFrame({'station_name': [names[i]],\n",
164
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:385: UserWarning: FixedFormatter should only be used together with FixedLocator\n",
165
- " ax[i].set_xticklabels(ax[i].get_xticks(), rotation = 50)\n"
166
- ]
167
- },
168
- {
169
- "name": "stdout",
170
- "output_type": "stream",
171
- "text": [
172
- " station_name st_lat st_lon starttime p_phase, s \\\n",
173
- "0 CI.JRC2 35.98249 -117.80885 2019-07-04T17:33:39.947494Z 7.320212 \n",
174
- "1 CI.SRT 35.69235 -117.75051 2019-07-04T17:33:38.029990Z 4.532020 \n",
175
- "2 CI.WMF 36.11758 -117.85486 2019-07-04T17:33:41.867962Z 9.504385 \n",
176
- "\n",
177
- " p_uncertainty, s s_phase, s s_uncertainty, s velocity_p, km/s \\\n",
178
- "0 0.020417 13.385108 0.028439 4.136604 \n",
179
- "1 0.017490 9.215676 0.019568 3.415548 \n",
180
- "2 0.015920 17.031569 0.046738 4.745725 \n",
181
- "\n",
182
- " velocity_s, km/s \n",
183
- "0 2.262277 \n",
184
- "1 1.679674 \n",
185
- "2 2.648329 \n"
186
- ]
187
- },
188
- {
189
- "name": "stderr",
190
- "output_type": "stream",
191
- "text": [
192
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:503: MatplotlibDeprecationWarning: Unable to determine Axes to steal space for Colorbar. Using gca(), but will raise in the future. Either provide the *cax* argument to use as the Axes for the Colorbar, provide the *ax* argument to steal space from it, or add *mappable* to an Axes.\n",
193
- " plt.colorbar(m)\n"
194
- ]
195
- },
196
- {
197
- "name": "stdout",
198
- "output_type": "stream",
199
- "text": [
200
- " station_name st_lat st_lon starttime p_phase, s \\\n",
201
- "0 CI.JRC2 35.98249 -117.80885 2019-07-04T17:33:39.947494Z 7.320212 \n",
202
- "1 CI.SRT 35.69235 -117.75051 2019-07-04T17:33:38.029990Z 4.532020 \n",
203
- "2 CI.WMF 36.11758 -117.85486 2019-07-04T17:33:41.867962Z 9.504385 \n",
204
- "\n",
205
- " p_uncertainty, s s_phase, s s_uncertainty, s velocity_p, km/s \\\n",
206
- "0 0.020417 13.385108 0.028439 4.136604 \n",
207
- "1 0.017490 9.215676 0.019568 3.415548 \n",
208
- "2 0.015920 17.031569 0.046738 4.745725 \n",
209
- "\n",
210
- " velocity_s, km/s \n",
211
- "0 2.262277 \n",
212
- "1 1.679674 \n",
213
- "2 2.648329 \n"
214
- ]
215
- },
216
- {
217
- "name": "stderr",
218
- "output_type": "stream",
219
- "text": [
220
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:503: MatplotlibDeprecationWarning: Unable to determine Axes to steal space for Colorbar. Using gca(), but will raise in the future. Either provide the *cax* argument to use as the Axes for the Colorbar, provide the *ax* argument to steal space from it, or add *mappable* to an Axes.\n",
221
- " plt.colorbar(m)\n"
222
- ]
223
- },
224
- {
225
- "name": "stdout",
226
- "output_type": "stream",
227
- "text": [
228
- " station_name st_lat st_lon starttime p_phase, s \\\n",
229
- "0 CI.JRC2 35.98249 -117.80885 2019-07-04T17:33:39.947494Z 7.320212 \n",
230
- "1 CI.SRT 35.69235 -117.75051 2019-07-04T17:33:38.029990Z 4.532020 \n",
231
- "2 CI.WMF 36.11758 -117.85486 2019-07-04T17:33:41.867962Z 9.504385 \n",
232
- "\n",
233
- " p_uncertainty, s s_phase, s s_uncertainty, s velocity_p, km/s \\\n",
234
- "0 0.020417 13.385108 0.028439 4.136604 \n",
235
- "1 0.017490 9.215676 0.019568 3.415548 \n",
236
- "2 0.015920 17.031569 0.046738 4.745725 \n",
237
- "\n",
238
- " velocity_s, km/s \n",
239
- "0 2.262277 \n",
240
- "1 1.679674 \n",
241
- "2 2.648329 \n"
242
- ]
243
- },
244
- {
245
- "name": "stderr",
246
- "output_type": "stream",
247
- "text": [
248
- "/var/folders/_g/3q5q8_dj0ydcpktxlwxb5vrh0000gq/T/ipykernel_3502/4124724611.py:503: MatplotlibDeprecationWarning: Unable to determine Axes to steal space for Colorbar. Using gca(), but will raise in the future. Either provide the *cax* argument to use as the Axes for the Colorbar, provide the *ax* argument to steal space from it, or add *mappable* to an Axes.\n",
249
- " plt.colorbar(m)\n"
250
  ]
251
  }
252
  ],
@@ -302,17 +94,41 @@
302
  " \n",
303
  " return resampled_waveform\n",
304
  "\n",
305
- "def make_prediction(waveform, sampling_rate):\n",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
306
  " waveform = np.load(waveform)\n",
307
  " print('Loaded', waveform.shape)\n",
308
  "\n",
309
  " if len(waveform.shape) == 1:\n",
310
  " waveform = waveform.reshape(1, waveform.shape[0])\n",
311
- " print('Reshaped', waveform.shape)\n",
 
 
 
312
  " if sampling_rate != 100:\n",
313
  " waveform = resample_waveform(waveform, sampling_rate, 100)\n",
314
  " print('Resampled', waveform.shape)\n",
315
  "\n",
 
316
  " orig_waveform = waveform[:, :6000].copy()\n",
317
  " processed_input = prepare_waveform(waveform)\n",
318
  "\n",
@@ -326,12 +142,12 @@
326
  " return processed_input, p_phase, s_phase, orig_waveform\n",
327
  "\n",
328
  "\n",
329
- "def mark_phases(waveform, uploaded_file, p_thres, s_thres, sampling_rate):\n",
330
  "\n",
331
  " if uploaded_file is not None:\n",
332
  " waveform = uploaded_file.name\n",
333
  "\n",
334
- " processed_input, p_phase, s_phase, orig_waveform = make_prediction(waveform, sampling_rate)\n",
335
  "\n",
336
  " # Create a plot of the waveform with the phases marked\n",
337
  " if sum(processed_input[0][2] == 0): #if input is 1C\n",
@@ -506,10 +322,12 @@
506
  " if len(waveforms) == 0:\n",
507
  " print('No waveforms found')\n",
508
  " fig, ax = plt.subplots()\n",
509
- " ax.text(0.5,0.5,'No waveforms found')\n",
 
510
  " fig.canvas.draw();\n",
511
  " image = np.array(fig.canvas.renderer.buffer_rgba())\n",
512
  " plt.close(fig)\n",
 
513
  " output_picks = pd.DataFrame()\n",
514
  " output_picks.to_csv('data/picks.csv', index=False)\n",
515
  " output_csv = 'data/picks.csv'\n",
@@ -833,13 +651,16 @@
833
  " info=\"Sampling rate of the waveform\",\n",
834
  " interactive=True,\n",
835
  " )\n",
 
 
 
836
  "\n",
837
  " button = gr.Button(\"Predict phases\")\n",
838
  " outputs = gr.Image(label='Waveform with Phases Marked', type='numpy', interactive=False)\n",
839
  " \n",
840
  " button.click(mark_phases, inputs=[inputs, upload, \n",
841
  " P_thres_inputs, S_thres_inputs,\n",
842
- " sampling_rate_inputs], \n",
843
  " outputs=outputs) \n",
844
  " with gr.Tab(\"Select earthquake from catalogue\"):\n",
845
  "\n",
@@ -971,60 +792,77 @@
971
  },
972
  {
973
  "cell_type": "code",
974
- "execution_count": 24,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
975
  "metadata": {},
976
  "outputs": [
977
  {
978
  "data": {
979
  "text/plain": [
980
- "[<matplotlib.lines.Line2D at 0x14eb2da90>]"
981
  ]
982
  },
983
- "execution_count": 24,
984
  "metadata": {},
985
  "output_type": "execute_result"
986
  },
987
  {
988
  "data": {
989
- "image/png": "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lMjYDJmIsI8IkXawRoTI2AyZiPC4R6QdvC4gMjZjJiLMRIg0gzUiRMZm0ESEiLSDiQiRkRk0EWFlMJFW8NdIZGwGTUSISCucPAwRGRqPAESkqiNIVzsEIlIRExEiIiJSDRMRIiIiUg0TESIiIlINExEiIiJSDRMRIiIiUg0TESIiIlKNIRMRjuNIRESkDYZMRIiIiEgbmIgQERGRapiIEBERkWqYiBAREZFqmIgQERGRapiIEBERkWqYiBAREZFqmIgQERGRapiIEBERkWqYiBAREZFqmIgQERGRapiIEBERkWqMmYjwqXdERESaYMxEhIiIiDSBiQgRERGphokIERERqYaJCBEREamGiQgRERGphokIERERqcaYiYgkqR0BERERwaiJiOBAIkRERFpgzESEiIiINIGJCBEREanGmIkI+4gQERFpgjETEfYRISIi0gRjJiJ86h0REZEmGDQRISIiIi1gIkJERESqMWgiwqYZIiIiLYhZIvLMM89AkiRMnDgxVkUSERGRxsUkEfnjjz/w1ltv4fTTT49FcURERKQTiicilZWVGDNmDN555x1kZmYqXRwRERHpiOKJyPjx4zFq1CgMHz486Lw2mw3l5eVeL2WwjwgREREAxJvV7S5qUXLlc+bMwZo1a/DHH3+ENH9+fj6eeOIJJUMiIiKiOmb88wxVy1csDSooKMDdd9+NTz75BAkJCSEtM3nyZJSVlXleBQUFSoVHREREANpmJatavmI1IqtXr0ZJSQn69u3rmeZ0OrF06VK89tprsNlsMJvNXstYrVZYrValQiIiIqJ61H78mmKJyLBhw7BhwwavaTfffDO6dOmCBx98sEESElPsIkJERKQJiiUiqamp6NGjh9e05ORkZGVlNZhORERE6pCgbpWIQUdWJSIiIi1Q9K6Z+hYvXhzL4oiIiCgItfuIGLNGRLCTCBERkRYYMxEhIiIiTWAiQkREZGAqt8wwESEiIiL1GDQRYR8RIiIiAKpXiRg0ESEiIiItYCJCRERkYBzQTBVsmiEiItICgyYiREREBHBAMyIiIjIwJiJEREQGxnFE1MAh3omIiDTBmIkIERERAQAklTuJMBEhIiIi1TARISIiMjD2EVED+4gQERFpgjETESIiIgLAcUSIiIjIwJiIEBERGRifNaMCic+aISIicmPTDBEREaklPTFO1fKZiBAR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F2w2G/dVHcOGDcOGDRuwbt06z6t///4YM2aM5/+5r/yrrKzErl270Lx5c36v6hk8eHCDIQa2b9+ONm3aANDJ8T3q7q46M2fOHGG1WsWMGTPE5s2bxa233ioyMjK8elc3RhUVFWLt2rVi7dq1AoB48cUXxdq1a8Vff/0lhHDf3pWRkSG++uorsX79enHZZZf5vL2rT58+YsWKFeLXX38VnTp18rq9q7S0VOTm5oobbrhBbNy4UcyZM0ckJSXp6vbdO+64Q6Snp4vFixd73Tp4/Phxzzy33367aN26tfj555/FqlWrxKBBg8SgQYM879feOnjBBReIdevWifnz54umTZv6vHXw/vvvF1u2bBGvv/66Lm8dnDRpkliyZInYs2ePWL9+vZg0aZKQJEn8+OOPQgjuq0Dq3jUjBPdVXffdd59YvHix2LNnj/jtt9/E8OHDRXZ2tigpKRFCcF/VtXLlSmGxWMTTTz8tduzYIT755BORlJQkPv74Y888Wj++Gy4REUKIV199VbRu3VrEx8eLAQMGiOXLl6sdkuJ++eUXAaDBa+zYsUII9y1eU6ZMEbm5ucJqtYphw4aJbdu2ea3jyJEj4tprrxUpKSkiLS1N3HzzzaKiosJrnj///FOcffbZwmq1ipYtW4pnnnkmVpsoC1/7CID44IMPPPNUV1eLO++8U2RmZoqkpCRx+eWXi4MHD3qtZ+/evWLkyJEiMTFRZGdni/vuu0/Y7XaveX755RfRu3dvER8fL9q3b+9Vhl7885//FG3atBHx8fGiadOmYtiwYZ4kRAjuq0DqJyLcV6dcffXVonnz5iI+Pl60bNlSXH311V7jYnBfefvmm29Ejx49hNVqFV26dBFvv/221/taP75LQggRXZ0KERERUWQM1UeEiIiItIWJCBEREamGiQgRERGphokIERERqYaJCBEREamGiQgRERGphokIERERqYaJCBEREamGiQgRERGphokIERERqYaJCBEREamGiQgRERGp5v8Bjf6vxL9TJoUAAAAASUVORK5CYII=",
990
  "text/plain": [
991
  "<Figure size 640x480 with 1 Axes>"
992
  ]
993
  },
994
  "metadata": {},
995
  "output_type": "display_data"
996
- },
997
- {
998
- "name": "stderr",
999
- "output_type": "stream",
1000
- "text": [
1001
- "Traceback (most recent call last):\n",
1002
- " File \"/usr/local/lib/python3.9/site-packages/gradio/routes.py\", line 393, in run_predict\n",
1003
- " output = await app.get_blocks().process_api(\n",
1004
- " File \"/usr/local/lib/python3.9/site-packages/gradio/blocks.py\", line 1108, in process_api\n",
1005
- " result = await self.call_function(\n",
1006
- " File \"/usr/local/lib/python3.9/site-packages/gradio/blocks.py\", line 915, in call_function\n",
1007
- " prediction = await anyio.to_thread.run_sync(\n",
1008
- " File \"/usr/local/lib/python3.9/site-packages/anyio/to_thread.py\", line 31, in run_sync\n",
1009
- " return await get_asynclib().run_sync_in_worker_thread(\n",
1010
- " File \"/usr/local/lib/python3.9/site-packages/anyio/_backends/_asyncio.py\", line 937, in run_sync_in_worker_thread\n",
1011
- " return await future\n",
1012
- " File \"/usr/local/lib/python3.9/site-packages/anyio/_backends/_asyncio.py\", line 867, in run\n",
1013
- " result = context.run(func, *args)\n",
1014
- " File \"/var/folders/ky/4j6xbvhs5m583jflkhyzxf9h0000gn/T/ipykernel_9385/3876498698.py\", line 76, in mark_phases\n",
1015
- " waveform = resample_waveform(waveform, sampling_rate, 100)\n",
1016
- " File \"/var/folders/ky/4j6xbvhs5m583jflkhyzxf9h0000gn/T/ipykernel_9385/3876498698.py\", line 46, in resample_waveform\n",
1017
- " resampled_length = int(waveform.shape[-1] * resampling_ratio)\n",
1018
- "AttributeError: 'str' object has no attribute 'shape'\n"
1019
- ]
1020
  }
1021
  ],
1022
  "source": [
1023
- "a = np.load(\"test.npy\") \n",
1024
- "plt.plot(a)\n",
1025
- "\n",
1026
- "b = resample_waveform(a, 200, 100)\n",
1027
- "plt.plot(b)"
1028
  ]
1029
  },
1030
  {
@@ -1038,102 +876,27 @@
1038
  },
1039
  {
1040
  "cell_type": "code",
1041
- "execution_count": 2,
1042
  "metadata": {},
1043
  "outputs": [
1044
  {
1045
- "data": {
1046
- "text/plain": [
1047
- "['DEFAULT_TEMP_DIR',\n",
1048
- " '__abstractmethods__',\n",
1049
- " '__class__',\n",
1050
- " '__delattr__',\n",
1051
- " '__dict__',\n",
1052
- " '__dir__',\n",
1053
- " '__doc__',\n",
1054
- " '__eq__',\n",
1055
- " '__format__',\n",
1056
- " '__ge__',\n",
1057
- " '__getattribute__',\n",
1058
- " '__getstate__',\n",
1059
- " '__gt__',\n",
1060
- " '__hash__',\n",
1061
- " '__init__',\n",
1062
- " '__init_subclass__',\n",
1063
- " '__le__',\n",
1064
- " '__lt__',\n",
1065
- " '__module__',\n",
1066
- " '__ne__',\n",
1067
- " '__new__',\n",
1068
- " '__reduce__',\n",
1069
- " '__reduce_ex__',\n",
1070
- " '__repr__',\n",
1071
- " '__setattr__',\n",
1072
- " '__sizeof__',\n",
1073
- " '__slots__',\n",
1074
- " '__str__',\n",
1075
- " '__subclasshook__',\n",
1076
- " '__weakref__',\n",
1077
- " '_abc_impl',\n",
1078
- " '_id',\n",
1079
- " '_skip_init_processing',\n",
1080
- " '_style',\n",
1081
- " 'as_example',\n",
1082
- " 'attach_load_event',\n",
1083
- " 'base64_to_temp_file_if_needed',\n",
1084
- " 'change',\n",
1085
- " 'clear',\n",
1086
- " 'deserialize',\n",
1087
- " 'download_temp_copy_if_needed',\n",
1088
- " 'elem_classes',\n",
1089
- " 'elem_id',\n",
1090
- " 'file_count',\n",
1091
- " 'file_types',\n",
1092
- " 'get_block_name',\n",
1093
- " 'get_config',\n",
1094
- " 'get_expected_parent',\n",
1095
- " 'get_load_fn_and_initial_value',\n",
1096
- " 'get_specific_update',\n",
1097
- " 'hash_base64',\n",
1098
- " 'hash_file',\n",
1099
- " 'hash_url',\n",
1100
- " 'info',\n",
1101
- " 'interactive',\n",
1102
- " 'label',\n",
1103
- " 'load_event',\n",
1104
- " 'load_event_to_attach',\n",
1105
- " 'make_temp_copy_if_needed',\n",
1106
- " 'parent',\n",
1107
- " 'postprocess',\n",
1108
- " 'preprocess',\n",
1109
- " 'render',\n",
1110
- " 'root',\n",
1111
- " 'root_url',\n",
1112
- " 'save_uploaded_file',\n",
1113
- " 'select',\n",
1114
- " 'selectable',\n",
1115
- " 'serialize',\n",
1116
- " 'set_event_trigger',\n",
1117
- " 'share_token',\n",
1118
- " 'show_label',\n",
1119
- " 'style',\n",
1120
- " 'temp_files',\n",
1121
- " 'test_input',\n",
1122
- " 'type',\n",
1123
- " 'unrender',\n",
1124
- " 'update',\n",
1125
- " 'upload',\n",
1126
- " 'value',\n",
1127
- " 'visible']"
1128
- ]
1129
- },
1130
- "execution_count": 2,
1131
- "metadata": {},
1132
- "output_type": "execute_result"
1133
  }
1134
  ],
1135
  "source": [
1136
- "dir(output_csv)"
 
 
 
 
 
 
 
 
1137
  ]
1138
  },
1139
  {
 
2
  "cells": [
3
  {
4
  "cell_type": "code",
5
+ "execution_count": 44,
6
  "metadata": {},
7
  "outputs": [
8
  {
9
  "name": "stdout",
10
  "output_type": "stream",
11
  "text": [
12
+ "Running on local URL: http://127.0.0.1:7872\n",
13
  "\n",
14
  "To create a public link, set `share=True` in `launch()`.\n"
15
  ]
 
17
  {
18
  "data": {
19
  "text/html": [
20
+ "<div><iframe src=\"http://127.0.0.1:7872/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
21
  ],
22
  "text/plain": [
23
  "<IPython.core.display.HTML object>"
 
30
  "data": {
31
  "text/plain": []
32
  },
33
+ "execution_count": 44,
34
  "metadata": {},
35
  "output_type": "execute_result"
36
  },
 
38
  "name": "stdout",
39
  "output_type": "stream",
40
  "text": [
41
+ "Loaded (1, 28412)\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  ]
43
  }
44
  ],
 
94
  " \n",
95
  " return resampled_waveform\n",
96
  "\n",
97
+ "def sort_channels_to_ZNE(waveform, channels):\n",
98
+ " # Input:\n",
99
+ " # waveform: a 2D numpy array with shape (3, n), where n is the number of samples\n",
100
+ " # channels: a list or tuple of 3 strings representing the channel order, e.g. ('N', 'Z', 'E')\n",
101
+ " channels = list(channels)\n",
102
+ "\n",
103
+ " if len(channels) != 3 or set(channels) != {'Z', 'N', 'E'}:\n",
104
+ " raise ValueError(\"Invalid channel input. It should be a permutation of 'Z', 'N', and 'E'.\")\n",
105
+ "\n",
106
+ " # Find the indices of the Z, N, and E channels\n",
107
+ " z_index = channels.index('Z')\n",
108
+ " n_index = channels.index('N')\n",
109
+ " e_index = channels.index('E')\n",
110
+ " \n",
111
+ " print(z_index, n_index, e_index)\n",
112
+ " # Sort the channels to ZNE\n",
113
+ " sorted_waveform = waveform[[z_index, n_index, e_index], :]\n",
114
+ " \n",
115
+ " return sorted_waveform\n",
116
+ "\n",
117
+ "def make_prediction(waveform, sampling_rate, order):\n",
118
  " waveform = np.load(waveform)\n",
119
  " print('Loaded', waveform.shape)\n",
120
  "\n",
121
  " if len(waveform.shape) == 1:\n",
122
  " waveform = waveform.reshape(1, waveform.shape[0])\n",
123
+ "\n",
124
+ " elif waveform.shape[0] == 3:\n",
125
+ " waveform = sort_channels_to_ZNE(waveform, order)\n",
126
+ "\n",
127
  " if sampling_rate != 100:\n",
128
  " waveform = resample_waveform(waveform, sampling_rate, 100)\n",
129
  " print('Resampled', waveform.shape)\n",
130
  "\n",
131
+ "\n",
132
  " orig_waveform = waveform[:, :6000].copy()\n",
133
  " processed_input = prepare_waveform(waveform)\n",
134
  "\n",
 
142
  " return processed_input, p_phase, s_phase, orig_waveform\n",
143
  "\n",
144
  "\n",
145
+ "def mark_phases(waveform, uploaded_file, p_thres, s_thres, sampling_rate, order):\n",
146
  "\n",
147
  " if uploaded_file is not None:\n",
148
  " waveform = uploaded_file.name\n",
149
  "\n",
150
+ " processed_input, p_phase, s_phase, orig_waveform = make_prediction(waveform, sampling_rate, order)\n",
151
  "\n",
152
  " # Create a plot of the waveform with the phases marked\n",
153
  " if sum(processed_input[0][2] == 0): #if input is 1C\n",
 
322
  " if len(waveforms) == 0:\n",
323
  " print('No waveforms found')\n",
324
  " fig, ax = plt.subplots()\n",
325
+ " # prints \"No waveforms found\" on the plot aligned at center and vertically\n",
326
+ " ax.text(0.5,0.5,'No waveforms found', horizontalalignment='center', verticalalignment='center', transform=ax.transAxes)\n",
327
  " fig.canvas.draw();\n",
328
  " image = np.array(fig.canvas.renderer.buffer_rgba())\n",
329
  " plt.close(fig)\n",
330
+ "\n",
331
  " output_picks = pd.DataFrame()\n",
332
  " output_picks.to_csv('data/picks.csv', index=False)\n",
333
  " output_csv = 'data/picks.csv'\n",
 
651
  " info=\"Sampling rate of the waveform\",\n",
652
  " interactive=True,\n",
653
  " )\n",
654
+ " order_input = gr.Text(value='ZNE', \n",
655
+ " label='Channel order', \n",
656
+ " info='Order of the channels in the waveform file (e.g. ZNE)')\n",
657
  "\n",
658
  " button = gr.Button(\"Predict phases\")\n",
659
  " outputs = gr.Image(label='Waveform with Phases Marked', type='numpy', interactive=False)\n",
660
  " \n",
661
  " button.click(mark_phases, inputs=[inputs, upload, \n",
662
  " P_thres_inputs, S_thres_inputs,\n",
663
+ " sampling_rate_inputs, order_input], \n",
664
  " outputs=outputs) \n",
665
  " with gr.Tab(\"Select earthquake from catalogue\"):\n",
666
  "\n",
 
792
  },
793
  {
794
  "cell_type": "code",
795
+ "execution_count": 34,
796
+ "metadata": {},
797
+ "outputs": [
798
+ {
799
+ "data": {
800
+ "text/plain": [
801
+ "array([[53, 52, 28, ..., 0, 0, 0]], dtype=int32)"
802
+ ]
803
+ },
804
+ "execution_count": 34,
805
+ "metadata": {},
806
+ "output_type": "execute_result"
807
+ },
808
+ {
809
+ "name": "stdout",
810
+ "output_type": "stream",
811
+ "text": [
812
+ "Loaded (1, 25412)\n",
813
+ "Reshaped (1, 25412)\n"
814
+ ]
815
+ },
816
+ {
817
+ "name": "stderr",
818
+ "output_type": "stream",
819
+ "text": [
820
+ "No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.\n"
821
+ ]
822
+ },
823
+ {
824
+ "name": "stdout",
825
+ "output_type": "stream",
826
+ "text": [
827
+ "Loaded (1, 25412)\n",
828
+ "Reshaped (1, 25412)\n"
829
+ ]
830
+ }
831
+ ],
832
+ "source": [
833
+ "np.load('test_no_p.npy')"
834
+ ]
835
+ },
836
+ {
837
+ "cell_type": "code",
838
+ "execution_count": 33,
839
  "metadata": {},
840
  "outputs": [
841
  {
842
  "data": {
843
  "text/plain": [
844
+ "[<matplotlib.lines.Line2D at 0x1ccb9acd0>]"
845
  ]
846
  },
847
+ "execution_count": 33,
848
  "metadata": {},
849
  "output_type": "execute_result"
850
  },
851
  {
852
  "data": {
853
+ "image/png": "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9+61HnfccYc1LxgMavTo0erRo4cKCgr08MMPa+7cuXrmmWesNitWrNCNN96oSZMmafXq1Ro/frzGjx+vdevW2bE5OA0MWgYARIrtp6V37NhRKSkpjc574YUXVFNTo2effVYej0cDBgxQYWGhHnnkEU2ePFmS9Nhjj2nMmDGaMWOGJOnBBx9Ubm6unnjiCT399NMR2w4AANBy2b6HZ/78+erSpYuGDh2qhx9+WHV1dda8/Px8jRw5Uh6Px3ouOztbmzdv1sGDB602WVlZIcvMzs5Wfn5+ZDYAAAC0eLbu4fmP//gPXXjhhercubNWrFihWbNmae/evXrkkUckSYFAQL169Qp5TXJysjWvU6dOCgQC1nPfbhMIBE643urqalVXV1vTwWCwuTYJp4HT0gEAkdLse3hmzpx53EDk7z42bdokScrJydGoUaM0ePBg3X777frTn/6kxx9/PCSMhMO8efPk9/utR1paWljXBwAA7NXse3juuusu3XLLLSdt07t370afz8jIUF1dnXbs2KH09HSlpKSouLg4pM2x6WPjfk7U5kTjgiRp1qxZysnJsaaDwSChxwYMWgYAREqzB57ExEQlJiae0WsLCwvldruVlJQkScrMzNR9992n2tpaxcTESJJyc3OVnp6uTp06WW3y8vI0ffp0azm5ubnKzMw84Xq8Xq+8Xu8Z1QgAAFof2wYt5+fn69FHH9WaNWv01Vdf6YUXXtCdd96pn/70p1aYuemmm+TxeDRp0iStX79eL7/8sh577LGQvTO//OUvtXjxYv3pT3/Spk2bNHfuXK1atUrTpk2za9MAAEALY9ugZa/Xq5deeklz585VdXW1evXqpTvvvDMkzPj9fr333nuaOnWqhg0bpoSEBM2ePds6JV2SLrvsMv3973/X/fffr1/96lc699xztWjRIg0cONCOzQIAAC2QyxjOlQkGg/L7/SovL5fP57O7nFar58y3Tqv9xT076dXbLwtTNQAApzud32/br8MDAAAQbgQeAADgeAQeAADgeAQe2CbF387uEgAAbQSBB7YYOzBFs3/U3+4yAABthO13S0fb9NRPh9ldAgCgDWEPDwAAcDwCD5oN98YCALRUBB40m8/uyzrp/BnZ6RGqBACAUAQeNJuEDie/IWviKeYDABAuBB4AAOB4BB4AAOB4BB5EjFGbv08tAMAmBB4AAOB4BB4AAOB4BB5ETKc4j90lAADaKG4tgYjJOj9ZEzN7aEhavN2lAADaGAIPIsbtduk31wy0uwwAQBvEIS0AAOB4BB4AAOB4BB4AAOB4BB4AAOB4BB4AAOB4BB4AAOB4BB4AAOB4BB4AAOB4BB4AAOB4BB40q/aeKLtLAADgOAQeNKt+XX12lwAAwHEIPAAAwPEIPAAAwPEIPAAAwPEIPAAAwPEIPAAAwPEIPAAAwPEIPAAAwPEIPAAAwPGi7S4Aznbt0G7yt4vR+KHd7C4FANCGEXgQVr7YaM29eoDdZQAA2jgOaQEAAMcj8AAAAMcj8CCsRqUn2V0CAAAEHoTXqPREu0sAAIDAg+Z1+/f7WH8P7R4vl8tlYzUAABxF4EGz+mH/ZLtLAADgOAQeAADgeAQeAADgeAQeAADgeAQeAADgeAQeAADgeAQeAADgeGELPL/73e902WWXKS4uTvHx8Y22KSoq0rhx4xQXF6ekpCTNmDFDdXV1IW2WLVumCy+8UF6vV3379tXChQuPW86CBQvUs2dPxcbGKiMjQ59++mkYtggAALRWYQs8NTU1+slPfqIpU6Y0Or++vl7jxo1TTU2NVqxYoeeff14LFy7U7NmzrTbbt2/XuHHjdPnll6uwsFDTp0/Xz3/+c7377rtWm5dfflk5OTmaM2eOPv/8cw0ZMkTZ2dkqKSkJ16YBAIBWxmWMMeFcwcKFCzV9+nSVlZWFPP/OO+/oRz/6kfbs2aPk5KMXq3v66ad17733at++ffJ4PLr33nv11ltvad26ddbrbrjhBpWVlWnx4sWSpIyMDF188cV64oknJEkNDQ1KS0vTHXfcoZkzZzapxmAwKL/fr/Lycvl8vmbY6rat58y3JEkXdo/Xa7/4ns3VAACc6nR+v20bw5Ofn69BgwZZYUeSsrOzFQwGtX79eqtNVlZWyOuys7OVn58v6ehepIKCgpA2brdbWVlZVpvGVFdXKxgMhjwAAIBz2RZ4AoFASNiRZE0HAoGTtgkGgzpy5Ij279+v+vr6RtscW0Zj5s2bJ7/fbz3S0tKaY5MAAEALdVqBZ+bMmXK5XCd9bNq0KVy1NptZs2apvLzceuzcudPukgAAQBhFn07ju+66S7fccstJ2/Tu3btJy0pJSTnubKri4mJr3rH/Hnvu2218Pp/atWunqKgoRUVFNdrm2DIa4/V65fV6m1QnAABo/U4r8CQmJioxMbFZVpyZmanf/e53KikpUVJSkiQpNzdXPp9P/fv3t9q8/fbbIa/Lzc1VZmamJMnj8WjYsGHKy8vT+PHjJR0dtJyXl6dp06Y1S504cy6Xy+4SAACQFMYxPEVFRSosLFRRUZHq6+tVWFiowsJCVVZWSpJGjx6t/v376+abb9aaNWv07rvv6v7779fUqVOtvS+33367vvrqK91zzz3atGmTnnzySb3yyiu68847rfXk5OToP//zP/X8889r48aNmjJlig4dOqRbb701XJuGJgrzCYAAADTZae3hOR2zZ8/W888/b00PHTpUkrR06VKNGjVKUVFRevPNNzVlyhRlZmaqffv2mjhxoh544AHrNb169dJbb72lO++8U4899pjOOecc/dd//Zeys7OtNtdff7327dun2bNnKxAI6IILLtDixYuPG8gMAADarrBfh6c14Do8zYvr8AAAIqFVXIcHAAAgUgg8CBsGLQMAWgoCDwAAcDwCDwAAcDwCDwAAcDwCDwAAcDwCD8KGIcsAgJaCwAMAAByPwAMAAByPwIOwafOX8AYAtBgEHgAA4HgEHoQNg5YBAC0FgQcAADgegQcAADgegQcAADgegQcAADgegQdh42LUMgCghSDwAAAAxyPwAAAAxyPwAAAAxyPwoNlFu48O3sns3cXmSgAAOCra7gLgPEvvHqUPvtynn1x0jt2lAAAgicCDMEjrHKefXtrD7jIAALBwSAsAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADgegQcAADged0uXZIyRJAWDQZsrAQAATXXsd/vY7/jJEHgkVVRUSJLS0tJsrgQAAJyuiooK+f3+k7ZxmabEIodraGjQnj171LFjR7lcrmZddjAYVFpamnbu3Cmfz9esy3Y6+u7s0H9njr47c/Td2aH/To8xRhUVFUpNTZXbffJROuzhkeR2u3XOOeeEdR0+n4837xmi784O/Xfm6LszR9+dHfqv6U61Z+cYBi0DAADHI/AAAADHI/CEmdfr1Zw5c+T1eu0updWh784O/Xfm6LszR9+dHfovfBi0DAAAHI89PAAAwPEIPAAAwPEIPAAAwPEIPAAAwPEIPGG2YMEC9ezZU7GxscrIyNCnn35qd0kRNXfuXLlcrpBHv379rPlVVVWaOnWqunTpog4dOui6665TcXFxyDKKioo0btw4xcXFKSkpSTNmzFBdXV1Im2XLlunCCy+U1+tV3759tXDhwkhsXrNavny5rrrqKqWmpsrlcmnRokUh840xmj17trp27ap27dopKytLW7ZsCWlTWlqqCRMmyOfzKT4+XpMmTVJlZWVIm7Vr12rEiBGKjY1VWlqaHnrooeNqefXVV9WvXz/FxsZq0KBBevvtt5t9e5vbqfrvlltuOe69OGbMmJA2bbX/5s2bp4svvlgdO3ZUUlKSxo8fr82bN4e0ieRntTV9bzal70aNGnXce+/2228PadMW+y7iDMLmpZdeMh6Pxzz77LNm/fr15rbbbjPx8fGmuLjY7tIiZs6cOWbAgAFm79691mPfvn3W/Ntvv92kpaWZvLw8s2rVKnPppZeayy67zJpfV1dnBg4caLKysszq1avN22+/bRISEsysWbOsNl999ZWJi4szOTk5ZsOGDebxxx83UVFRZvHixRHd1rP19ttvm/vuu8+89tprRpJ5/fXXQ+bPnz/f+P1+s2jRIrNmzRpz9dVXm169epkjR45YbcaMGWOGDBliPvnkE/Phhx+avn37mhtvvNGaX15ebpKTk82ECRPMunXrzIsvvmjatWtn/vrXv1ptPv74YxMVFWUeeughs2HDBnP//febmJgY88UXX4S9D87Gqfpv4sSJZsyYMSHvxdLS0pA2bbX/srOzzXPPPWfWrVtnCgsLzZVXXmm6d+9uKisrrTaR+qy2tu/NpvTd97//fXPbbbeFvPfKy8ut+W217yKNwBNGl1xyiZk6dao1XV9fb1JTU828efNsrCqy5syZY4YMGdLovLKyMhMTE2NeffVV67mNGzcaSSY/P98Yc/RHzO12m0AgYLV56qmnjM/nM9XV1cYYY+655x4zYMCAkGVff/31Jjs7u5m3JnK++4Pd0NBgUlJSzMMPP2w9V1ZWZrxer3nxxReNMcZs2LDBSDKfffaZ1eadd94xLpfL7N692xhjzJNPPmk6depk9Z0xxtx7770mPT3dmv63f/s3M27cuJB6MjIyzL//+7836zaG04kCzzXXXHPC19B/3ygpKTGSzAcffGCMiexntbV/b36374w5Gnh++ctfnvA19F1kcEgrTGpqalRQUKCsrCzrObfbraysLOXn59tYWeRt2bJFqamp6t27tyZMmKCioiJJUkFBgWpra0P6qF+/furevbvVR/n5+Ro0aJCSk5OtNtnZ2QoGg1q/fr3V5tvLONbGSf28fft2BQKBkO30+/3KyMgI6av4+HhddNFFVpusrCy53W6tXLnSajNy5Eh5PB6rTXZ2tjZv3qyDBw9abZzan8uWLVNSUpLS09M1ZcoUHThwwJpH/32jvLxcktS5c2dJkfusOuF787t9d8wLL7yghIQEDRw4ULNmzdLhw4etefRdZHDz0DDZv3+/6uvrQ97AkpScnKxNmzbZVFXkZWRkaOHChUpPT9fevXv1m9/8RiNGjNC6desUCATk8XgUHx8f8prk5GQFAgFJUiAQaLQPj807WZtgMKgjR46oXbt2Ydq6yDm2rY1t57f7ISkpKWR+dHS0OnfuHNKmV69exy3j2LxOnTqdsD+PLaO1GjNmjH784x+rV69e2rZtm371q19p7Nixys/PV1RUFP33Lw0NDZo+fbq+973vaeDAgZIUsc/qwYMHW/X3ZmN9J0k33XSTevToodTUVK1du1b33nuvNm/erNdee00SfRcpBB6E1dixY62/Bw8erIyMDPXo0UOvvPKKI4IIWo8bbrjB+nvQoEEaPHiw+vTpo2XLlumKK66wsbKWZerUqVq3bp0++ugju0tpdU7Ud5MnT7b+HjRokLp27aorrrhC27ZtU58+fSJdZpvFIa0wSUhIUFRU1HFnMRQXFyslJcWmquwXHx+v8847T1u3blVKSopqampUVlYW0ubbfZSSktJoHx6bd7I2Pp/PMaHq2Lae7P2UkpKikpKSkPl1dXUqLS1tlv502vu2d+/eSkhI0NatWyXRf5I0bdo0vfnmm1q6dKnOOecc6/lIfVZb8/fmifquMRkZGZIU8t5ry30XKQSeMPF4PBo2bJjy8vKs5xoaGpSXl6fMzEwbK7NXZWWltm3bpq5du2rYsGGKiYkJ6aPNmzerqKjI6qPMzEx98cUXIT9Eubm58vl86t+/v9Xm28s41sZJ/dyrVy+lpKSEbGcwGNTKlStD+qqsrEwFBQVWmyVLlqihocH6gs3MzNTy5ctVW1trtcnNzVV6ero6depktXF6f0rSrl27dODAAXXt2lVS2+4/Y4ymTZum119/XUuWLDnusF2kPqut8XvzVH3XmMLCQkkKee+1xb6LOLtHTTvZSy+9ZLxer1m4cKHZsGGDmTx5somPjw8Zie90d911l1m2bJnZvn27+fjjj01WVpZJSEgwJSUlxpijp7p2797dLFmyxKxatcpkZmaazMxM6/XHTtccPXq0KSwsNIsXLzaJiYmNnq45Y8YMs3HjRrNgwYJWeVp6RUWFWb16tVm9erWRZB555BGzevVq8/XXXxtjjp6WHh8fb9544w2zdu1ac8011zR6WvrQoUPNypUrzUcffWTOPffckNOqy8rKTHJysrn55pvNunXrzEsvvWTi4uKOO606Ojra/PGPfzQbN240c+bMafGnVRtz8v6rqKgwd999t8nPzzfbt28377//vrnwwgvNueeea6qqqqxltNX+mzJlivH7/WbZsmUhp04fPnzYahOpz2pr+948Vd9t3brVPPDAA2bVqlVm+/bt5o033jC9e/c2I0eOtJbRVvsu0gg8Yfb444+b7t27G4/HYy655BLzySef2F1SRF1//fWma9euxuPxmG7dupnrr7/ebN261Zp/5MgR84tf/MJ06tTJxMXFmWuvvdbs3bs3ZBk7duwwY8eONe3atTMJCQnmrrvuMrW1tSFtli5dai644ALj8XhM7969zXPPPReJzWtWS5cuNZKOe0ycONEYc/TU9F//+tcmOTnZeL1ec8UVV5jNmzeHLOPAgQPmxhtvNB06dDA+n8/ceuutpqKiIqTNmjVrzPDhw43X6zXdunUz8+fPP66WV155xZx33nnG4/GYAQMGmLfeeits291cTtZ/hw8fNqNHjzaJiYkmJibG9OjRw9x2223H/RC01f5rrN8khXyOIvlZbU3fm6fqu6KiIjNy5EjTuXNn4/V6Td++fc2MGTNCrsNjTNvsu0hzGWNM5PYnAQAARB5jeAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOMReAAAgOP9/yWvYymBlXynAAAAAElFTkSuQmCC",
854
  "text/plain": [
855
  "<Figure size 640x480 with 1 Axes>"
856
  ]
857
  },
858
  "metadata": {},
859
  "output_type": "display_data"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
860
  }
861
  ],
862
  "source": [
863
+ "a = np.load(\"data/sample/sample_1.npy\") \n",
864
+ "np.save('test_no_p.npy', a[:, 3000:])\n",
865
+ "plt.plot(a[0])\n"
 
 
866
  ]
867
  },
868
  {
 
876
  },
877
  {
878
  "cell_type": "code",
879
+ "execution_count": 37,
880
  "metadata": {},
881
  "outputs": [
882
  {
883
+ "name": "stdout",
884
+ "output_type": "stream",
885
+ "text": [
886
+ "1 0 2\n"
887
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
888
  }
889
  ],
890
  "source": [
891
+ "import numpy as np\n",
892
+ "\n",
893
+ "\n",
894
+ "\n",
895
+ "# Example usage:\n",
896
+ "waveform = np.random.rand(3, 100) # A random waveform with 3 channels and 100 samples\n",
897
+ "channels = 'NZE'\n",
898
+ "\n",
899
+ "sorted_waveform = sort_channels_to_ZNE(waveform, channels)"
900
  ]
901
  },
902
  {
app.py CHANGED
@@ -49,17 +49,41 @@ def resample_waveform(waveform, original_freq, target_freq):
49
 
50
  return resampled_waveform
51
 
52
- def make_prediction(waveform, sampling_rate):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  waveform = np.load(waveform)
54
  print('Loaded', waveform.shape)
55
 
56
  if len(waveform.shape) == 1:
57
  waveform = waveform.reshape(1, waveform.shape[0])
58
- print('Reshaped', waveform.shape)
 
 
 
59
  if sampling_rate != 100:
60
  waveform = resample_waveform(waveform, sampling_rate, 100)
61
  print('Resampled', waveform.shape)
62
 
 
63
  orig_waveform = waveform[:, :6000].copy()
64
  processed_input = prepare_waveform(waveform)
65
 
@@ -73,12 +97,12 @@ def make_prediction(waveform, sampling_rate):
73
  return processed_input, p_phase, s_phase, orig_waveform
74
 
75
 
76
- def mark_phases(waveform, uploaded_file, p_thres, s_thres, sampling_rate):
77
 
78
  if uploaded_file is not None:
79
  waveform = uploaded_file.name
80
 
81
- processed_input, p_phase, s_phase, orig_waveform = make_prediction(waveform, sampling_rate)
82
 
83
  # Create a plot of the waveform with the phases marked
84
  if sum(processed_input[0][2] == 0): #if input is 1C
@@ -253,10 +277,12 @@ def predict_on_section(client_name, timestamp, eq_lat, eq_lon, radius_km, source
253
  if len(waveforms) == 0:
254
  print('No waveforms found')
255
  fig, ax = plt.subplots()
256
- ax.text(0.5,0.5,'No waveforms found')
 
257
  fig.canvas.draw();
258
  image = np.array(fig.canvas.renderer.buffer_rgba())
259
  plt.close(fig)
 
260
  output_picks = pd.DataFrame()
261
  output_picks.to_csv('data/picks.csv', index=False)
262
  output_csv = 'data/picks.csv'
@@ -580,13 +606,16 @@ with gr.Blocks() as demo:
580
  info="Sampling rate of the waveform",
581
  interactive=True,
582
  )
 
 
 
583
 
584
  button = gr.Button("Predict phases")
585
  outputs = gr.Image(label='Waveform with Phases Marked', type='numpy', interactive=False)
586
 
587
  button.click(mark_phases, inputs=[inputs, upload,
588
  P_thres_inputs, S_thres_inputs,
589
- sampling_rate_inputs],
590
  outputs=outputs)
591
  with gr.Tab("Select earthquake from catalogue"):
592
 
 
49
 
50
  return resampled_waveform
51
 
52
+ def sort_channels_to_ZNE(waveform, channels):
53
+ # Input:
54
+ # waveform: a 2D numpy array with shape (3, n), where n is the number of samples
55
+ # channels: a list or tuple of 3 strings representing the channel order, e.g. ('N', 'Z', 'E')
56
+ channels = list(channels)
57
+
58
+ if len(channels) != 3 or set(channels) != {'Z', 'N', 'E'}:
59
+ raise ValueError("Invalid channel input. It should be a permutation of 'Z', 'N', and 'E'.")
60
+
61
+ # Find the indices of the Z, N, and E channels
62
+ z_index = channels.index('Z')
63
+ n_index = channels.index('N')
64
+ e_index = channels.index('E')
65
+
66
+ print(z_index, n_index, e_index)
67
+ # Sort the channels to ZNE
68
+ sorted_waveform = waveform[[z_index, n_index, e_index], :]
69
+
70
+ return sorted_waveform
71
+
72
+ def make_prediction(waveform, sampling_rate, order):
73
  waveform = np.load(waveform)
74
  print('Loaded', waveform.shape)
75
 
76
  if len(waveform.shape) == 1:
77
  waveform = waveform.reshape(1, waveform.shape[0])
78
+
79
+ elif waveform.shape[0] == 3:
80
+ waveform = sort_channels_to_ZNE(waveform, order)
81
+
82
  if sampling_rate != 100:
83
  waveform = resample_waveform(waveform, sampling_rate, 100)
84
  print('Resampled', waveform.shape)
85
 
86
+
87
  orig_waveform = waveform[:, :6000].copy()
88
  processed_input = prepare_waveform(waveform)
89
 
 
97
  return processed_input, p_phase, s_phase, orig_waveform
98
 
99
 
100
+ def mark_phases(waveform, uploaded_file, p_thres, s_thres, sampling_rate, order):
101
 
102
  if uploaded_file is not None:
103
  waveform = uploaded_file.name
104
 
105
+ processed_input, p_phase, s_phase, orig_waveform = make_prediction(waveform, sampling_rate, order)
106
 
107
  # Create a plot of the waveform with the phases marked
108
  if sum(processed_input[0][2] == 0): #if input is 1C
 
277
  if len(waveforms) == 0:
278
  print('No waveforms found')
279
  fig, ax = plt.subplots()
280
+ # prints "No waveforms found" on the plot aligned at center and vertically
281
+ ax.text(0.5,0.5,'No waveforms found', horizontalalignment='center', verticalalignment='center', transform=ax.transAxes)
282
  fig.canvas.draw();
283
  image = np.array(fig.canvas.renderer.buffer_rgba())
284
  plt.close(fig)
285
+
286
  output_picks = pd.DataFrame()
287
  output_picks.to_csv('data/picks.csv', index=False)
288
  output_csv = 'data/picks.csv'
 
606
  info="Sampling rate of the waveform",
607
  interactive=True,
608
  )
609
+ order_input = gr.Text(value='ZNE',
610
+ label='Channel order',
611
+ info='Order of the channels in the waveform file (e.g. ZNE)')
612
 
613
  button = gr.Button("Predict phases")
614
  outputs = gr.Image(label='Waveform with Phases Marked', type='numpy', interactive=False)
615
 
616
  button.click(mark_phases, inputs=[inputs, upload,
617
  P_thres_inputs, S_thres_inputs,
618
+ sampling_rate_inputs, order_input],
619
  outputs=outputs)
620
  with gr.Tab("Select earthquake from catalogue"):
621
 
data/cached/AK_CAPN_2023-04-10T17:33:40.015179Z.mseed ADDED
Binary file (44.5 kB). View file
 
data/cached/AV_KENI_2023-04-10T17:33:41.392981Z.mseed ADDED
Binary file (43 kB). View file
 
data/cached/CI_SLA_2023-04-10T17:33:40.190746Z.mseed ADDED
Binary file (62 kB). View file
 
data/cached/GS_CA09_2023-04-10T17:33:38.249774Z.mseed ADDED
Binary file (28.2 kB). View file
 
data/cached/PB_B916_2023-04-10T17:33:42.213172Z.mseed ADDED
Binary file (26.6 kB). View file
 
data/cached/PB_B917_2023-04-10T17:33:42.616354Z.mseed ADDED
Binary file (13.8 kB). View file
 
data/cached/PB_B921_2023-04-10T17:33:39.103517Z.mseed ADDED
Binary file (13.8 kB). View file
 
data/picks.csv CHANGED
@@ -1,4 +1 @@
1
- station_name,starttime,"p_phase, s","p_uncertainty, s","s_phase, s","s_uncertainty, s","velocity_p, km/s","velocity_s, km/s"
2
- CI.SRT,2019-07-04T17:33:38.029990Z,5.195954322814941,0.4883878491818905,11.277575492858887,1.6350263357162476,2.9791118172972846,1.3725759526093728
3
- CI.JRC2,2019-07-04T17:33:39.947494Z,7.11562442779541,0.4898720048367977,13.208794593811035,1.644418090581894,4.255539668245224,2.29247429065224
4
- CI.WMF,2019-07-04T17:33:41.867962Z,9.043024063110352,0.4864034615457058,15.146604537963867,1.6339519992470741,4.987844305676596,2.9779080827144124
 
1
+
 
 
 
test_no_p.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:02e7a0fb5c2125a130b63c6de3e20a5349228fbc47eb4298ff41f42daef708d8
3
+ size 101776