1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6from __future__ import absolute_import, print_function
8from pyrocko.io.io_common import get_stats, touch # noqa
9from pyrocko import trace
10from ... import model
13km = 1000.
16def provided_formats():
17 return ['sac']
20def detect(first512):
21 from pyrocko.io import sac
23 if sac.detect(first512):
24 return 'sac'
25 else:
26 return None
29def agg(*ds):
30 out = {}
31 for d in ds:
32 out.update(d)
34 return out
37def nonetoempty(x):
38 if x is None:
39 return x
40 else:
41 return x.strip()
44def iload(format, file_path, segment, content):
45 assert format == 'sac'
47 from pyrocko.io import sac
49 load_data = 'waveform' in content
51 s = sac.SacFile(file_path, load_data=load_data)
53 codes = dict(
54 agency='',
55 network=nonetoempty(s.knetwk),
56 station=nonetoempty(s.kstnm),
57 location=nonetoempty(s.khole),
58 channel=nonetoempty(s.kcmpnm))
60 tmin = s.get_ref_time() + s.b
61 tmax = tmin + s.delta * s.npts
63 tspan = dict(
64 tmin=tmin,
65 tmax=tmax,
66 deltat=s.delta)
68 inut = 0
69 nut = model.make_waveform_nut(
70 file_segment=0,
71 file_element=inut,
72 **agg(codes, tspan))
74 if 'waveform' in content:
75 nut.content = trace.Trace(
76 ydata=s.data[0],
77 **nut.waveform_kwargs)
79 yield nut
80 inut += 1
82 if None not in (s.stla, s.stlo):
83 position = dict(
84 lat=s.stla,
85 lon=s.stlo,
86 elevation=s.stel,
87 depth=s.stdp)
89 codes_without_channel = codes.copy()
90 del codes_without_channel['channel']
91 nut = model.make_station_nut(
92 file_segment=0,
93 file_element=inut,
94 **agg(codes_without_channel, tspan))
96 if 'station' in content:
97 nut.content = model.Station(
98 **agg(position, nut.station_kwargs))
100 yield nut
101 inut += 1
103 dip = None
104 if s.cmpinc is not None:
105 dip = s.cmpinc - 90.
107 nut = model.make_channel_nut(
108 file_segment=0,
109 file_element=inut,
110 **agg(codes, tspan))
112 if 'channel' in content:
113 nut.content = model.Channel(
114 azimuth=s.cmpaz,
115 dip=dip,
116 **agg(position, nut.channel_kwargs))
118 yield nut
119 inut += 1
121 if None not in (s.evla, s.evlo, s.o):
122 etime = s.get_ref_time() + s.o
123 depth = None
124 if s.evdp is not None:
125 depth = s.evdp # * km # unclear specs
127 nut = model.make_event_nut(
128 name=nonetoempty(s.kevnm),
129 file_segment=0,
130 file_element=inut,
131 tmin=etime,
132 tmax=etime)
134 if 'event' in content:
135 nut.content = model.Event(
136 lat=s.evla,
137 lon=s.evlo,
138 depth=depth,
139 magnitude=s.mag,
140 **nut.event_kwargs)
142 yield nut
143 inut += 1