forked from yannikbehr/SRL_2015
-
Notifications
You must be signed in to change notification settings - Fork 0
/
delayeew.py
236 lines (199 loc) · 8.48 KB
/
delayeew.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
#!/usr/bin/env python
"""
Compute theoretical alert delays or P-wave traveltimes.
Created on Jan 22, 2015
@author: behry
"""
import os
import sys
sys.path.append(os.path.join(os.environ['HOME'], 'mypy'))
import progressbar as pg
import numpy as np
import pyproj
import ipdb
class NetworkInfo:
"""
Dummy implementation for a class that returns station names
and coordinates, and network codes.
"""
def __init__(self):
self.lat = []
self.lon = []
self.nm = []
self.nw = []
self.size = 0
def read(self):
pass
def get_lat(self):
pass
def get_lon(self):
pass
def get_names(self):
pass
def get_networkcodes(self):
pass
class DelayObs:
"""
Dummy class to load processing latencies.
"""
def __init__(self):
pass
def get_pick_delays(self):
pass
def get_pick_default(self):
pass
def get_envelope_default(self):
pass
def get_envelope_delays(self):
pass
def get_associator_delays(self):
pass
def get_magnitude_delays(self):
pass
class DelayException(Exception):
pass
class DelayEEW:
def __init__(self):
pass
def compute(self, networkinfo, elon, elat, edep, vp=6.5, vs=3.5, nnst=6,
procdelay=False, target=None, nmaps=500,
resultsfn='p_wave_tt_6_stations.npz', datadir='./data',
latencies=None, vp3d=False):
# If given a target location (lon,lat) it will also compute
# the lead time from any potential epicenter to the target site
if target is not None:
tln, tlt = target
# get the station locations
networks = networkinfo.get_networks()
# get the delay measurement distributions:
# pkdel = pick delays
# envdel = envelope delays
# ascdel = associator/locator delays
# magdel = magnitude delays
# pkdefault = pick default delay
# envdefault = envelope default delay
# Note pkdel and envdel have to be Python dictionaries that have
# a Numpy array of delay measurements for every station name key
# ascdel and magdel are simply Numpy arrays containing delay
# observations
# pkdefault and envdefault are Python dictionaries that contain a
# default delay value for every network name key. These default values
# are used if a station is in the list of stations returned by
# networkinfo but does not have delay observations in pkdel and envdel
if procdelay and latencies is not None:
pkdel = latencies.get_pick_delays()
envdel = latencies.get_envelope_delays()
ascdel = latencies.get_associator_delays()
magdel = latencies.get_magnitude_delays()
pkdefault = latencies.get_pick_default()
envdefault = latencies.get_envelope_default()
# do we have a grid or a set of points?
if elon.shape != elat.shape or elon.shape != edep.shape:
raise DelayException("elon, elat, and edep must have the same shape!")
outshape = [nmaps]
for _s in elon.shape:
outshape.append(_s)
lat = elat.ravel()
lon = elon.ravel()
dep = edep.ravel()
ngp = lon.size
ttP = np.zeros(outshape)
ttPtmp = np.zeros(ngp)
tstarget = ttPtmp.copy()
g = pyproj.Geod(ellps='sphere')
# Setup progressbar
widgets = ['tt: ', pg.Percentage(), ' ', pg.Bar('#'),
' ', pg.ETA()]
pbar = pg.ProgressBar(widgets=widgets, maxval=nmaps * ngp).start()
no_env_dl = []
no_pk_dl = []
# loop over samples (Monte-Carlo simulation)
for nm in range(nmaps):
idx = 0
# loop over earthquake locations
for _lat, _lon, _dep in zip(lat, lon, dep):
pbar.update(nm * ngp + idx)
min_dt = 1.e38
# loop over networks; all stations within a network are
# considered for delay computations but only the fastest alert
# is stored
for net in networks.keys():
if len(networks[net]['lat']) < 1:
continue
stlat = networks[net]['lat']
stlon = networks[net]['lon']
nwcode = np.array(networks[net]['nw'])
names = np.array(networks[net]['nm'])
maxnstat = min(10, len(stlat))
nnst = min(nnst, len(stlat))
# An option to used traveltimes from a 3D model instead
# of a homogeneous halfspace; only works on my computer
# at the moment
if vp3d:
datadir = './data/ttime_ch/'
fin = os.path.join(datadir, "%.4f_%.4f_%.1f.npy" % \
(_lat, _lon, _dep))
if not os.path.isfile(fin):
raise DelayException('File %s does not exist!' % fin)
a = np.load(fin)
pt = a['ttime'][:, 0]
dt = max(pt[0:nnst])
stat_names = a['name']
else:
# Find the <nnst> nearest stations
lats = np.ones((len(stlat),)) * _lat
lons = np.ones((len(stlon),)) * _lon
az, baz, dist = g.inv(lons, lats, stlon, stlat)
dist_sorted = np.sort(dist)
stat_names = names[np.argsort(dist)]
dz = np.ones((maxnstat,)) * _dep
pt = np.sqrt(dz * dz + dist_sorted[0:maxnstat] / 1000. * dist_sorted[0:maxnstat] / 1000.) / vp
dt = max(pt[0:nnst])
if target is not None:
azt, bazt, distt = g.inv(_lon, _lat, tln, tlt)
distt /= 1000.
tstarget[idx] = np.sqrt(distt * distt + _dep * _dep) / vs
# Add delays
# Note: if a close by station has very long delays, the
# algorithm will pick one of the next further stations
# if they can send data before the closer station
if procdelay:
pk_delays = []
env_delays = []
for stat in stat_names[0:maxnstat]:
if stat in pkdel.keys():
pk_delays.append(pkdel[stat][np.random.randint(0, len(pkdel[stat]))])
else:
if stat not in no_pk_dl:
no_pk_dl.append(stat)
pk_delays.append(pkdefault[net])
if stat in envdel.keys():
env_delays.append(envdel[stat][np.random.randint(0, len(envdel[stat]))])
else:
if stat not in no_env_dl:
no_env_dl.append(stat)
env_delays.append(envdefault[net])
if len(pk_delays) != maxnstat or len(env_delays) != maxnstat:
raise DelayException('Number of delays is not equal to %d' % nnst)
temp = np.sort(pt + np.array(pk_delays)) + ascdel[np.random.randint(0, len(ascdel))]
origin_delay = max(temp[0:nnst])
waveform_delay = min(pt + np.array(env_delays))
dt = max(origin_delay, waveform_delay) + magdel[np.random.randint(0, len(magdel))]
if dt < min_dt:
min_dt = dt
ttPtmp[idx] = min_dt
idx += 1
ttP[nm] = ttPtmp.reshape(elon.shape)
tstarget = tstarget.reshape(elon.shape)
# store the results for plotting
if resultsfn is not None:
np.savez(resultsfn, ttP=ttP, tstarget=tstarget, lat=elat, lon=elon,
dep=edep)
pbar.finish()
print "No envelope delay data available for the following stations:"
print ' '.join(no_env_dl)
print "No pick delay info available for the following stations:"
print ' '.join(no_pk_dl)
return elat, elon, edep, ttP, tstarget
if __name__ == '__main__':
pass