DASPy-toolbox 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. DASPy_toolbox-1.0.0.dist-info/LICENSE.txt +1 -0
  2. DASPy_toolbox-1.0.0.dist-info/METADATA +85 -0
  3. DASPy_toolbox-1.0.0.dist-info/RECORD +49 -0
  4. DASPy_toolbox-1.0.0.dist-info/WHEEL +5 -0
  5. DASPy_toolbox-1.0.0.dist-info/entry_points.txt +2 -0
  6. DASPy_toolbox-1.0.0.dist-info/top_level.txt +1 -0
  7. daspy/__init__.py +4 -0
  8. daspy/advanced_tools/__init__.py +0 -0
  9. daspy/advanced_tools/channel.py +354 -0
  10. daspy/advanced_tools/decomposition.py +165 -0
  11. daspy/advanced_tools/denoising.py +276 -0
  12. daspy/advanced_tools/fdct.py +789 -0
  13. daspy/advanced_tools/strain2vel.py +245 -0
  14. daspy/basic_tools/__init__.py +0 -0
  15. daspy/basic_tools/filter.py +257 -0
  16. daspy/basic_tools/freqattributes.py +117 -0
  17. daspy/basic_tools/preprocessing.py +238 -0
  18. daspy/basic_tools/visualization.py +186 -0
  19. daspy/core/__init__.py +4 -0
  20. daspy/core/collection.py +279 -0
  21. daspy/core/dasdatetime.py +72 -0
  22. daspy/core/example.pkl +0 -0
  23. daspy/core/make_example.py +32 -0
  24. daspy/core/read.py +544 -0
  25. daspy/core/section.py +1319 -0
  26. daspy/core/write.py +282 -0
  27. daspy/seismic_detection/__init__.py +1 -0
  28. daspy/seismic_detection/calc_travel_time.py +23 -0
  29. daspy/seismic_detection/core.py +119 -0
  30. daspy/seismic_detection/detection.py +12 -0
  31. daspy/seismic_detection/gamma/__init__.py +13 -0
  32. daspy/seismic_detection/gamma/_base.py +549 -0
  33. daspy/seismic_detection/gamma/_bayesian_mixture.py +875 -0
  34. daspy/seismic_detection/gamma/_gaussian_mixture.py +866 -0
  35. daspy/seismic_detection/gamma/app.py +192 -0
  36. daspy/seismic_detection/gamma/seismic_ops.py +478 -0
  37. daspy/seismic_detection/gamma/utils.py +512 -0
  38. daspy/seismic_detection/location.py +266 -0
  39. daspy/seismic_detection/magnitude.py +43 -0
  40. daspy/seismic_detection/phase_picking.py +67 -0
  41. daspy/structure_imaging/__init__.py +0 -0
  42. daspy/structure_imaging/ambient_noise.py +4 -0
  43. daspy/structure_imaging/dispersion.py +27 -0
  44. daspy/structure_imaging/fault_zone.py +59 -0
  45. daspy/structure_imaging/inversion.py +6 -0
  46. daspy/traffic_monitoring/JamDetection.py +6 -0
  47. daspy/traffic_monitoring/SpeedMeasurement.py +6 -0
  48. daspy/traffic_monitoring/VehicleDetection.py +6 -0
  49. daspy/traffic_monitoring/__init__.py +0 -0
@@ -0,0 +1,512 @@
1
+ import multiprocessing as mp
2
+ import platform
3
+ from collections import Counter
4
+ from datetime import datetime
5
+
6
+ import numpy as np
7
+ import pandas as pd
8
+ from scipy.sparse.csgraph import minimum_spanning_tree
9
+ from sklearn.cluster import DBSCAN
10
+
11
+ from ._bayesian_mixture import BayesianGaussianMixture
12
+ from ._gaussian_mixture import GaussianMixture
13
+ from .seismic_ops import calc_amp, calc_time, initialize_eikonal
14
+
15
+ to_seconds = lambda t: t.timestamp(tz="UTC")
16
+ from_seconds = lambda t: pd.Timestamp.utcfromtimestamp(t).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3]
17
+ # to_seconds = lambda t: datetime.strptime(t, "%Y-%m-%dT%H:%M:%S.%f").timestamp()
18
+ # from_seconds = lambda t: [datetime.utcfromtimestamp(x).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] for x in t]
19
+
20
+
21
+ # def estimate_station_spacing(stations):
22
+ def estimate_eps(stations, vp, sigma=3.0):
23
+ X = stations[["x(km)", "y(km)", "z(km)"]].values
24
+ D = np.sqrt(((X[:, np.newaxis, :] - X[np.newaxis, :, :]) ** 2).sum(axis=-1))
25
+ Tcsr = minimum_spanning_tree(D).toarray()
26
+
27
+ # Tcsr = Tcsr[Tcsr > 0]
28
+ # # mean = np.median(Tcsr)
29
+ # mean = np.mean(Tcsr)
30
+ # std = np.std(Tcsr)
31
+ # eps = (mean + sigma * std) / vp
32
+
33
+ eps = np.max(Tcsr) / vp * 1.5
34
+
35
+ return eps
36
+
37
+
38
+ def convert_picks_csv(picks, stations, config):
39
+ # t = picks["timestamp"].apply(lambda x: x.timestamp()).to_numpy()
40
+ if type(picks["timestamp"].iloc[0]) is str:
41
+ picks.loc[:, "timestamp"] = picks["timestamp"].apply(lambda x: datetime.fromisoformat(x))
42
+ t = (
43
+ picks["timestamp"]
44
+ .apply(lambda x: x.tz_convert("UTC").timestamp() if x.tzinfo is not None else x.tz_localize("UTC").timestamp())
45
+ .to_numpy()
46
+ )
47
+ # t = picks["timestamp"].apply(lambda x: x.timestamp()).to_numpy()
48
+ timestamp0 = np.min(t)
49
+ t = t - timestamp0
50
+ if config["use_amplitude"]:
51
+ a = picks["amp"].apply(lambda x: np.log10(x * 1e2)).to_numpy() ##cm/s
52
+ data = np.stack([t, a]).T
53
+ else:
54
+ data = t[:, np.newaxis]
55
+ meta = stations.merge(picks["id"], how="right", on="id", validate="one_to_many")
56
+ locs = meta[config["dims"]].to_numpy()
57
+ phase_type = picks["type"].apply(lambda x: x.lower()).to_numpy()
58
+ phase_weight = picks["prob"].to_numpy()[:, np.newaxis]
59
+ pick_station_id = picks.apply(lambda x: x.id + "_" + x.type, axis=1).to_numpy()
60
+ nan_idx = meta.isnull().any(axis=1)
61
+ return (
62
+ data[~nan_idx],
63
+ locs[~nan_idx],
64
+ phase_type[~nan_idx],
65
+ phase_weight[~nan_idx],
66
+ picks.index.to_numpy()[~nan_idx],
67
+ pick_station_id[~nan_idx],
68
+ timestamp0,
69
+ )
70
+
71
+
72
+ def association(picks, stations, config, event_idx0=0, method="BGMM", **kwargs):
73
+ data, locs, phase_type, phase_weight, pick_idx, pick_station_id, timestamp0 = convert_picks_csv(
74
+ picks, stations, config
75
+ )
76
+
77
+ if len(data) < config["min_picks_per_eq"]:
78
+ return [], []
79
+
80
+ vel = config["vel"] if "vel" in config else {"p": 6.0, "s": 6.0 / 1.73}
81
+ if ("eikonal" not in config) or (config["eikonal"] is None):
82
+ config["eikonal"] = None
83
+ else:
84
+ config["eikonal"] = initialize_eikonal(config["eikonal"])
85
+
86
+ if ("use_dbscan" in config) and config["use_dbscan"]:
87
+ # db = DBSCAN(eps=config["dbscan_eps"], min_samples=config["dbscan_min_samples"]).fit(data[:, 0:1])
88
+ db = DBSCAN(eps=config["dbscan_eps"], min_samples=config["dbscan_min_samples"]).fit(
89
+ np.hstack([data[:, 0:1], locs[:, :2] / np.average(vel["p"])])
90
+ )
91
+ labels = db.labels_
92
+ unique_labels = set(labels)
93
+ unique_labels = unique_labels.difference([-1])
94
+ else:
95
+ labels = np.zeros(len(data))
96
+ unique_labels = [0]
97
+
98
+ if "ncpu" not in config:
99
+ config["ncpu"] = max(1, min(len(unique_labels) // 4, min(32, mp.cpu_count() - 1)))
100
+ else:
101
+ config["ncpu"] = min(mp.cpu_count(), config["ncpu"])
102
+
103
+ if config["ncpu"] == 1:
104
+ print(f"Associating {len(data)} picks with {config['ncpu']} CPUs")
105
+ event_idx = 0
106
+ events, assignment = [], []
107
+ for unique_label in list(unique_labels):
108
+ events_, assignment_ = associate(
109
+ unique_label,
110
+ labels,
111
+ data,
112
+ locs,
113
+ phase_type,
114
+ phase_weight,
115
+ pick_idx,
116
+ pick_station_id,
117
+ config,
118
+ timestamp0,
119
+ vel,
120
+ method,
121
+ event_idx,
122
+ )
123
+ event_idx += len(events_)
124
+ events.extend(events_)
125
+ assignment.extend(assignment_)
126
+ else:
127
+ manager = mp.Manager()
128
+ lock = manager.Lock()
129
+ # event_idx0 - 1 as event_idx is increased before use
130
+ event_idx = manager.Value("i", event_idx0 - 1)
131
+
132
+ print(f"Associating {len(unique_labels)} clusters with {config['ncpu']} CPUs")
133
+
134
+ # the following sort and shuffle is to make sure jobs are distributed evenly
135
+ counter = Counter(labels)
136
+ unique_labels = sorted(unique_labels, key=lambda x: counter[x], reverse=True)
137
+ np.random.shuffle(unique_labels)
138
+
139
+ # the default chunk_size is len(unique_labels)//(config["ncpu"]*4), which makes some jobs very heavy
140
+ chunk_size = max(len(unique_labels) // (config["ncpu"] * 20), 1)
141
+
142
+ # Check for OS to start a child process in multiprocessing
143
+ # https://superfastpython.com/multiprocessing-context-in-python/
144
+ if platform.system().lower() in ["darwin", "windows"]:
145
+ context = "spawn"
146
+ else:
147
+ context = "fork"
148
+
149
+ with mp.get_context(context).Pool(config["ncpu"]) as p:
150
+ results = p.starmap(
151
+ associate,
152
+ [
153
+ [
154
+ k,
155
+ labels,
156
+ data,
157
+ locs,
158
+ phase_type,
159
+ phase_weight,
160
+ pick_idx,
161
+ pick_station_id,
162
+ config,
163
+ timestamp0,
164
+ vel,
165
+ method,
166
+ event_idx,
167
+ lock,
168
+ ]
169
+ for k in unique_labels
170
+ ],
171
+ chunksize=chunk_size,
172
+ )
173
+ # resuts is a list of tuples, each tuple contains two lists events and assignment
174
+ # here we flatten the list of tuples into two lists
175
+ events, assignment = [], []
176
+ for each_events, each_assignment in results:
177
+ events.extend(each_events)
178
+ assignment.extend(each_assignment)
179
+
180
+ return events, assignment # , event_idx.value
181
+
182
+
183
+ def associate(
184
+ k,
185
+ labels,
186
+ data,
187
+ locs,
188
+ phase_type,
189
+ phase_weight,
190
+ pick_idx,
191
+ pick_station_id,
192
+ config,
193
+ timestamp0,
194
+ vel,
195
+ method,
196
+ event_idx,
197
+ lock=None,
198
+ ):
199
+ print(".", end="")
200
+
201
+ data_ = data[labels == k]
202
+ locs_ = locs[labels == k]
203
+ phase_type_ = phase_type[labels == k]
204
+ phase_weight_ = phase_weight[labels == k]
205
+ pick_idx_ = pick_idx[labels == k]
206
+ pick_station_id_ = pick_station_id[labels == k]
207
+
208
+ max_num_event = max(Counter(pick_station_id_).values())
209
+
210
+ if len(pick_idx_) < max(3, config["min_picks_per_eq"]):
211
+ return [], []
212
+
213
+ time_range = max(data_[:, 0].max() - data_[:, 0].min(), 1)
214
+ if config["use_amplitude"]:
215
+ amp_range = max(data_[:, 1].max() - data_[:, 1].min(), 1)
216
+
217
+ ## initialization with [1,1,1] horizontal points and N time points
218
+ centers_init = init_centers(config, data_, locs_, time_range, max_num_event)
219
+
220
+ ## run clustering
221
+ # mean_precision_prior = 0.01 / time_range
222
+ if "covariance_prior" in config:
223
+ covariance_prior_pre = config["covariance_prior"]
224
+ else:
225
+ # covariance_prior_pre = [5.0, 2.0]
226
+ ## TODO: design a smark way to set covariance_prior
227
+ x_std = np.std(locs_[:, 0])
228
+ y_std = np.std(locs_[:, 1])
229
+ t_std = np.std(data_[:, 0])
230
+ ## option 1
231
+ # scaler = max(np.sqrt(x_std**2 + y_std**2) / 6.0 , 0.1)
232
+ ## option 2
233
+ # scaler = max(np.sqrt(x_std**2 + y_std**2) / 6.0 / t_std, 0.1) * 10
234
+ ## option 3
235
+ # d, v = 50, 6.0
236
+ # scaler = max((np.exp(np.sqrt(x_std**2 + y_std**2)/d) - 1)/(np.exp(1) - 1) * d / v / t_std, 0.2) * 10
237
+ ## option 4
238
+ rstd = np.sqrt(x_std**2 + y_std**2)
239
+ scaler = max(10.0, (rstd/6.0)*(rstd/60.0)) # 6.0 km/s, 60 km
240
+ if config["use_amplitude"]:
241
+ # covariance_prior_pre = [time_range * 10.0, amp_range * 10.0]
242
+ covariance_prior_pre = [scaler, scaler]
243
+ else:
244
+ # covariance_prior_pre = [time_range * 10.0]
245
+ covariance_prior_pre = [scaler]
246
+ # print(f"covariance_prior_pre: {covariance_prior_pre}")
247
+ if config["use_amplitude"]:
248
+ covariance_prior = np.array([[covariance_prior_pre[0], 0.0], [0.0, covariance_prior_pre[1]]])
249
+ else:
250
+ covariance_prior = np.array([[covariance_prior_pre[0]]])
251
+ data_ = data_[:, 0:1]
252
+
253
+ if method == "BGMM":
254
+ gmm = BayesianGaussianMixture(
255
+ n_components=len(centers_init),
256
+ weight_concentration_prior=1.0 / len(centers_init),
257
+ # mean_precision_prior=mean_precision_prior,
258
+ covariance_prior=covariance_prior,
259
+ init_params="centers",
260
+ centers_init=centers_init.copy(),
261
+ station_locs=locs_,
262
+ phase_type=phase_type_,
263
+ phase_weight=phase_weight_,
264
+ vel=vel,
265
+ eikonal=config["eikonal"],
266
+ bounds=config["bfgs_bounds"],
267
+ ).fit(data_)
268
+ elif method == "GMM":
269
+ gmm = GaussianMixture(
270
+ n_components=len(centers_init) + 1,
271
+ init_params="centers",
272
+ centers_init=centers_init.copy(),
273
+ station_locs=locs_,
274
+ phase_type=phase_type_,
275
+ phase_weight=phase_weight_,
276
+ vel=vel,
277
+ eikonal=config["eikonal"],
278
+ bounds=config["bfgs_bounds"],
279
+ dummy_comp=True,
280
+ dummy_prob=1 / (1 * np.sqrt(2 * np.pi)) * np.exp(-1 / 2),
281
+ dummy_quantile=0.1,
282
+ ).fit(data_)
283
+ else:
284
+ raise (f"Unknown method {method}; Should be 'BGMM' or 'GMM'")
285
+
286
+ ## run prediction
287
+ pred = gmm.predict(data_)
288
+ prob = np.exp(gmm.score_samples(data_))
289
+ prob_matrix = gmm.predict_proba(data_)
290
+ prob_eq = prob_matrix.sum(axis=0)
291
+ # prob = prob_matrix[range(len(data_)), pred]
292
+ # score = gmm.score(data_)
293
+ # score_sample = gmm.score_samples(data_)
294
+
295
+ ## filtering
296
+ events = []
297
+ assignment = []
298
+
299
+ for i in range(len(centers_init)):
300
+ tmp_data = data_[pred == i]
301
+ tmp_locs = locs_[pred == i]
302
+ tmp_pick_station_id = pick_station_id_[pred == i]
303
+ tmp_phase_type = phase_type_[pred == i]
304
+ if (len(tmp_data) == 0) or (len(tmp_data) < config["min_picks_per_eq"]):
305
+ continue
306
+ # idx_filter = np.ones(len(tmp_data)).astype(bool)
307
+
308
+ ## filter by time
309
+ t_ = calc_time(
310
+ gmm.centers_[i : i + 1, : len(config["dims"]) + 1],
311
+ tmp_locs,
312
+ tmp_phase_type,
313
+ vel=vel,
314
+ eikonal=config["eikonal"],
315
+ )
316
+ diff_t = np.abs(t_ - tmp_data[:, 0:1])
317
+ idx_t = (diff_t < config["max_sigma11"]).squeeze(axis=1)
318
+ idx_filter = idx_t
319
+ if len(tmp_data[idx_filter]) < config["min_picks_per_eq"]:
320
+ continue
321
+
322
+ ## filter multiple picks at the same station
323
+ unique_sta_id = {}
324
+ for j, k in enumerate(tmp_pick_station_id):
325
+ if (k not in unique_sta_id) or (diff_t[j] < unique_sta_id[k][1]):
326
+ unique_sta_id[k] = (j, diff_t[j])
327
+ idx_s = np.zeros(len(idx_t)).astype(bool) ## based on station
328
+ for k in unique_sta_id:
329
+ idx_s[unique_sta_id[k][0]] = True
330
+ idx_filter = idx_filter & idx_s
331
+ if len(tmp_data[idx_filter]) < config["min_picks_per_eq"]:
332
+ continue
333
+ gmm.covariances_[i, 0, 0] = np.mean((diff_t[idx_t]) ** 2)
334
+
335
+ ## filter by amplitude
336
+ if config["use_amplitude"]:
337
+ a_ = calc_amp(
338
+ gmm.centers_[i : i + 1, len(config["dims"]) + 1 : len(config["dims"]) + 2],
339
+ gmm.centers_[i : i + 1, : len(config["dims"]) + 1],
340
+ tmp_locs,
341
+ )
342
+ diff_a = np.abs(a_ - tmp_data[:, 1:2])
343
+ idx_a = (diff_a < config["max_sigma22"]).squeeze()
344
+ idx_filter = idx_filter & idx_a
345
+ if len(tmp_data[idx_filter]) < config["min_picks_per_eq"]:
346
+ continue
347
+
348
+ if "max_sigma12" in config:
349
+ idx_cov = np.abs(gmm.covariances_[i, 0, 1]) < config["max_sigma12"]
350
+ idx_filter = idx_filter & idx_cov
351
+ if len(tmp_data[idx_filter]) < config["min_picks_per_eq"]:
352
+ continue
353
+
354
+ gmm.covariances_[i, 1, 1] = np.mean((diff_a[idx_a]) ** 2)
355
+
356
+ if "min_p_picks_per_eq" in config:
357
+ if len(tmp_data[idx_filter & (tmp_phase_type == "p")]) < config["min_p_picks_per_eq"]:
358
+ continue
359
+ if "min_s_picks_per_eq" in config:
360
+ if len(tmp_data[idx_filter & (tmp_phase_type == "s")]) < config["min_s_picks_per_eq"]:
361
+ continue
362
+
363
+ if lock is not None:
364
+ with lock:
365
+ if not isinstance(event_idx, int):
366
+ event_idx.value += 1
367
+ event_idx_value = event_idx.value
368
+ else:
369
+ event_idx += 1
370
+ event_idx_value = event_idx
371
+ else:
372
+ if not isinstance(event_idx, int):
373
+ event_idx.value += 1
374
+ event_idx_value = event_idx.value
375
+ else:
376
+ event_idx += 1
377
+ event_idx_value = event_idx
378
+
379
+ event = {
380
+ # "time": from_seconds(gmm.centers_[i, len(config["dims"])]),
381
+ "time": datetime.utcfromtimestamp(gmm.centers_[i, len(config["dims"])] + timestamp0).isoformat(
382
+ timespec="milliseconds"
383
+ ),
384
+ # "time(s)": gmm.centers_[i, len(config["dims"])],
385
+ "magnitude": gmm.centers_[i, len(config["dims"]) + 1] if config["use_amplitude"] else 999,
386
+ "sigma_time": np.sqrt(gmm.covariances_[i, 0, 0]),
387
+ "sigma_amp": np.sqrt(gmm.covariances_[i, 1, 1]) if config["use_amplitude"] else 0,
388
+ "cov_time_amp": gmm.covariances_[i, 0, 1] if config["use_amplitude"] else 0,
389
+ "gamma_score": prob_eq[i],
390
+ "num_picks": len(tmp_data[idx_filter]),
391
+ "num_p_picks": len(tmp_data[idx_filter & (tmp_phase_type == "p")]),
392
+ "num_s_picks": len(tmp_data[idx_filter & (tmp_phase_type == "s")]),
393
+ "event_index": event_idx_value,
394
+ }
395
+ for j, k in enumerate(config["dims"]): ## add location
396
+ event[k] = gmm.centers_[i, j]
397
+ events.append(event)
398
+
399
+ for pi, pr in zip(pick_idx_[pred == i][idx_filter], prob):
400
+ assignment.append((pi, event_idx_value, pr))
401
+
402
+ if (event_idx_value + 1) % 100 == 0:
403
+ print(f"\nAssociated {event_idx_value + 1} events")
404
+ return events, assignment
405
+
406
+
407
+ # def init_centers(config, data_, locs_, time_range, max_num_event=1):
408
+ # """
409
+ # max_num_event: maximum number of events at one station
410
+ # """
411
+
412
+ # if "initial_points" in config:
413
+ # initial_points = config["initial_points"]
414
+ # if not isinstance(initial_points, list):
415
+ # initial_points = [initial_points, initial_points, initial_points]
416
+ # else:
417
+ # initial_points = [1, 1, 1]
418
+
419
+ # if (np.prod(initial_points) * max_num_event * config["oversample_factor"]) > len(data_):
420
+ # initial_points = [1, 1, 1]
421
+
422
+ # x_init = np.linspace(config["x(km)"][0], config["x(km)"][1], initial_points[0] + 2)[1:-1]
423
+ # y_init = np.linspace(config["y(km)"][0], config["y(km)"][1], initial_points[1] + 2)[1:-1]
424
+ # z_init = np.linspace(config["z(km)"][0], config["z(km)"][1], initial_points[2] + 2)[1:-1]
425
+ # # z_init = np.linspace(config["z(km)"][0], config["z(km)"][1], initial_points[2]) + 1.0
426
+
427
+ # ## manually set initial points
428
+ # if "x_init" in config:
429
+ # x_init = np.array(config["x_init"])
430
+ # if "y_init" in config:
431
+ # y_init = np.array(config["y_init"])
432
+ # if "z_init" in config:
433
+ # z_init = np.array(config["z_init"])
434
+
435
+ # x_init = np.broadcast_to(x_init[:, np.newaxis, np.newaxis], initial_points).reshape(-1)
436
+ # y_init = np.broadcast_to(y_init[np.newaxis, :, np.newaxis], initial_points).reshape(-1)
437
+ # z_init = np.broadcast_to(z_init[np.newaxis, np.newaxis, :], initial_points).reshape(-1)
438
+
439
+ # ## I found it helpful to add a point at the center of the area
440
+ # if (initial_points[0] == 2) and (initial_points[1] == 2):
441
+ # x_init = np.append(x_init, np.mean(config["x(km)"]))
442
+ # y_init = np.append(y_init, np.mean(config["y(km)"]))
443
+ # z_init = np.append(z_init, 0)
444
+
445
+ # num_xyz_init = len(x_init)
446
+
447
+ # # num_sta = len(np.unique(locs_, axis=0))
448
+ # # num_t_init = max(np.round(len(data_) / num_sta / num_xyz_init * config["oversample_factor"]), 1)
449
+ # # num_t_init = min(int(num_t_init), max(len(data_) // num_xyz_init, 1))
450
+ # num_t_init = min(max(int(max_num_event * config["oversample_factor"]), 1), max(len(data_) // num_xyz_init, 1))
451
+ # t_init = np.sort(data_[:, 0])[:: max(len(data_) // num_t_init, 1)][:num_t_init]
452
+ # # t_init = np.linspace(
453
+ # # data_[:, 0].min() - 0.1 * time_range,
454
+ # # data_[:, 0].max() + 0.1 * time_range,
455
+ # # num_t_init)
456
+
457
+ # x_init = np.broadcast_to(x_init[:, np.newaxis], (num_xyz_init, num_t_init)).reshape(-1)
458
+ # y_init = np.broadcast_to(y_init[:, np.newaxis], (num_xyz_init, num_t_init)).reshape(-1)
459
+ # z_init = np.broadcast_to(z_init[:, np.newaxis], (num_xyz_init, num_t_init)).reshape(-1)
460
+ # t_init = np.broadcast_to(t_init[np.newaxis, :], (num_xyz_init, num_t_init)).reshape(-1)
461
+
462
+ # if config["dims"] == ["x(km)", "y(km)", "z(km)"]:
463
+ # centers_init = np.vstack([x_init, y_init, z_init, t_init]).T
464
+ # elif config["dims"] == ["x(km)", "y(km)"]:
465
+ # centers_init = np.vstack([x_init, y_init, t_init]).T
466
+ # elif config["dims"] == ["x(km)"]:
467
+ # centers_init = np.vstack([x_init, t_init]).T
468
+ # else:
469
+ # raise (ValueError("Unsupported dims"))
470
+
471
+ # if config["use_amplitude"]:
472
+ # centers_init = np.hstack([centers_init, 1.0 * np.ones((len(centers_init), 1))]) # init magnitude to 1.0
473
+
474
+ # return centers_init
475
+
476
+ def init_centers(config, data_, locs_, time_range, max_num_event=1):
477
+ """
478
+ max_num_event: maximum number of events at one station
479
+ """
480
+
481
+ if "initial_points" in config:
482
+ initial_points = config["initial_points"]
483
+ if not isinstance(initial_points, list):
484
+ initial_points = [initial_points, initial_points, initial_points]
485
+ else:
486
+ initial_points = [1, 1, 1]
487
+
488
+ num_t_init = min(max(int(max_num_event * config["oversample_factor"]), 1), len(data_))
489
+
490
+ index = np.argsort(data_[:, 0])[:: max(len(data_) // num_t_init, 1)][:num_t_init]
491
+ t_init = data_[index, 0]
492
+ x_init = locs_[:, 0][index]
493
+ y_init = locs_[:, 1][index]
494
+ # x_init, y_init = np.mean(locs_[:, 0]), np.mean(locs_[:, 1])
495
+ # x_init = np.broadcast_to(x_init, (num_t_init)).reshape(-1)
496
+ # y_init = np.broadcast_to(y_init, (num_t_init)).reshape(-1)
497
+ z_init = np.linspace(config["z(km)"][0], config["z(km)"][1], initial_points[2] + 2)[1:-1]
498
+ z_init = np.broadcast_to(z_init, (num_t_init)).reshape(-1)
499
+
500
+ if config["dims"] == ["x(km)", "y(km)", "z(km)"]:
501
+ centers_init = np.vstack([x_init, y_init, z_init, t_init]).T
502
+ elif config["dims"] == ["x(km)", "y(km)"]:
503
+ centers_init = np.vstack([x_init, y_init, t_init]).T
504
+ elif config["dims"] == ["x(km)"]:
505
+ centers_init = np.vstack([x_init, t_init]).T
506
+ else:
507
+ raise (ValueError("Unsupported dims"))
508
+
509
+ if config["use_amplitude"]:
510
+ centers_init = np.hstack([centers_init, 1.0 * np.ones((len(centers_init), 1))]) # init magnitude to 1.0
511
+
512
+ return centers_init