/
readrotate.py
146 lines (105 loc) · 4.43 KB
/
readrotate.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
import numpy as np
from obspy import read
from obspy.signal.polarization import flinn
from obspy.signal.trigger import zDetect, triggerOnset, plotTrigger
import datetime as dt
def calc_geoinc(trace,metric=True):
"""docstring for calc_geoinc"""
stla=trace.stats.sac.stla
stlo=trace.stats.sac.stlo
stdp=trace.stats.sac.stdp
evla=trace.stats.sac.evla
evlo=trace.stats.sac.evlo
evdp=trace.stats.sac.evdp
if metric:
baz=np.rad2deg(np.arctan2((evlo-stlo),(evla-stla)))
EpiDist = np.sqrt((evlo-stlo)**2. + (evla-stla)**2.)
inc = np.rad2deg(np.arctan(EpiDist/ (evdp-stdp)))
HypoDist = np.sqrt((evdp-stdp)**2. + EpiDist**2)
if baz<0.:
baz=baz+360.
azi=np.mod(baz+180.0,360.0)
inc=np.mod(inc+180.0,180.)
return azi,inc,baz,HypoDist,EpiDist,stdp
def fixchannels(st):
"""docstring for fixchannels"""
for trace in st:
if len(trace.stats.channel)==1:
trace.stats.channel='BS'+trace.stats.channel
pass
def readandrotate(stem,stns='*',ext='[E,N,Z]'):
"""
Reads in sac files and rotates to ray-frame
stem: string providing path to sac files without the extension
e.g.: 'path/to/sac/sacfile'
stns: either '*' for all stations in array, or list of stations
e.g.: '[001,002,003]'
ext: extensions corresponding to 3C data
e.g.: '[BHE,BHN,BHZ]'
"""
# Read in files
st = read(stem+'.'+stns+'.'+ext)
# fix the chgannel components if they are not 3 characters long (stupidly required for rotating)
fixchannels(st)
# copy stream
strot = st.copy()
for station in [tr.stats.station for tr in strot.select(component="Z")]:
sttmp = strot.select(station=station)
azi,inc,baz,hypodist,epidist,stdp=calc_geoinc(sttmp[0])
sttmp.rotate('ZNE->LQT',back_azimuth=baz,inclination=inc)
return strot
def picker(st):
"""docstring for picker"""
s_picks=[np.nan]*2
df = st[0].stats.sampling_rate
npts = st[0].stats.npts
for i,cmp in enumerate(['L','Q','T']):
tmp=st.select(component=cmp)
trace=tmp[0]
# calculate cft of zDetect for 20 sample window
cft=zDetect(trace,20)
#mincft=min(cft)
maxcft=max(cft)
#meancft=mean(cft)
#print mincft,maxcft,(maxcft+mincft)/2,meancft
if cmp=='L': # P-trace: care less about this one, go ahead and pick
picks=triggerOnset(cft,0,0)
# plotTrigger(trace, cft, 0, 0)
p_pick=np.nan
for pick,end in picks:
if npts-pick<100:
break
else:
stcut = st.copy()
# cut trace from pick to 100 samples past pick
startcut=stcut[0].stats.starttime+dt.timedelta(seconds= pick/df)
endcut=startcut + dt.timedelta(seconds=100/df)
stcut = stcut.slice(startcut,endcut)
stcut.sort()
azi,inc,lin,plan=flinn(stcut)
#print "inc, lin =", inc, lin
if inc<40 and lin>0.6:
# good enough for a p-pick
p_pick=pick
break
else: # S-traces: only pick if the signal is relatively large
s_picks[i-1]=np.nan
if maxcft>6:
picks=triggerOnset(cft,4,1)
for pick,end in picks:
if npts-pick<100:
break
else:
stcut =st.copy()
# cut trace from pick to 100 samples past pick
startcut=stcut[0].stats.starttime+dt.timedelta(seconds= pick/df)
endcut=startcut + dt.timedelta(seconds=100/df)
stcut = stcut.slice(startcut,endcut)
stcut.sort()
azi,inc,lin,plan=flinn(stcut)
if inc>50 and lin>0.75:
# good enough for an s-pick
s_picks[i-1]=pick
break
s_pick=np.nanmin(s_picks)
return (p_pick-50)/df,[(i-50)/df for i in s_picks]