1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6from __future__ import absolute_import, print_function
8import logging
9from builtins import str as newstr
11from pyrocko.io.io_common import get_stats, touch # noqa
12from ... import model
14logger = logging.getLogger('psq.io.textfiles')
17def provided_formats():
18 return ['pyrocko_stations', 'pyrocko_events']
21def detect_pyrocko_stations(first512):
22 try:
23 first512 = first512.decode('utf-8')
24 except UnicodeDecodeError:
25 return False
27 for line in first512.splitlines():
28 t = line.split(None, 5)
29 if len(t) in (5, 6):
30 if len(t[0].split('.')) != 3:
31 return False
33 try:
34 lat, lon, ele, dep = map(float, t[1:5])
35 if lat < -90. or 90 < lat:
36 return False
37 if lon < -180. or 180 < lon:
38 return False
40 return True
42 except Exception:
43 raise
44 return False
46 return False
49g_event_keys = set('''
50name region catalog magnitude_type latitude longitude magnitude depth duration
51north_shift east_shift mnn mee mdd mne mnd med strike1 dip1 rake1 strike2 dip2
52rake2 duration time tags moment
53'''.split())
56def detect_pyrocko_events(first512):
57 try:
58 first512 = first512.decode('utf-8')
59 except UnicodeDecodeError:
60 return False
62 lines = first512.splitlines()[:-1]
63 ok = 0
64 for line in lines:
65 line = line.strip()
66 if not line or line.startswith('#'):
67 continue
69 t = line.split(' = ', 1)
70 if len(t) == 2:
71 if t[0].strip() in g_event_keys:
72 ok += 1
73 continue
74 else:
75 return False
77 if line.startswith('---'):
78 ok += 1
79 continue
81 return False
83 return ok > 2
86def detect(first512):
87 if detect_pyrocko_stations(first512):
88 return 'pyrocko_stations'
90 elif detect_pyrocko_events(first512):
91 return 'pyrocko_events'
93 return None
96def float_or_none(s):
97 if s.lower() == 'nan':
98 return None
99 else:
100 return float(s)
103def iload(format, file_path, segment, content):
104 if format == 'pyrocko_stations':
105 return iload_pyrocko_stations(file_path, segment, content)
107 if format == 'pyrocko_events':
108 return iload_pyrocko_events(file_path, segment, content)
111def iload_pyrocko_stations(file_path, segment, content):
113 inut = 0
114 tmin = None
115 tmax = None
116 with open(file_path, 'r') as f:
118 have_station = False
119 for (iline, line) in enumerate(f):
120 try:
121 toks = line.split(None, 5)
122 if len(toks) == 5 or len(toks) == 6:
123 net, sta, loc = toks[0].split('.')
124 lat, lon, elevation, depth = [float(x) for x in toks[1:5]]
125 if len(toks) == 5:
126 description = u''
127 else:
128 description = newstr(toks[5])
130 agn = ''
132 nut = model.make_station_nut(
133 file_segment=0,
134 file_element=inut,
135 agency=agn,
136 network=net,
137 station=sta,
138 location=loc,
139 tmin=tmin,
140 tmax=tmax)
142 if 'station' in content:
143 nut.content = model.Station(
144 lat=lat,
145 lon=lon,
146 elevation=elevation,
147 depth=depth,
148 description=description,
149 **nut.station_kwargs)
151 yield nut
152 inut += 1
154 have_station = True
156 elif len(toks) == 4 and have_station:
157 cha = toks[0]
158 azi = float_or_none(toks[1])
159 dip = float_or_none(toks[2])
160 gain = float(toks[3])
162 if gain != 1.0:
163 logger.warning(
164 '%s.%s.%s.%s gain value from stations '
165 'file ignored - please check' % (
166 net, sta, loc, cha))
168 nut = model.make_channel_nut(
169 file_segment=0,
170 file_element=inut,
171 agency=agn,
172 network=net,
173 station=sta,
174 location=loc,
175 channel=cha,
176 tmin=tmin,
177 tmax=tmax)
179 if 'channel' in content:
180 nut.content = model.Channel(
181 lat=lat,
182 lon=lon,
183 elevation=elevation,
184 depth=depth,
185 azimuth=azi,
186 dip=dip,
187 **nut.channel_kwargs)
189 yield nut
190 inut += 1
192 else:
193 raise Exception('invalid syntax')
195 except Exception as e:
196 logger.warning(
197 'skipping invalid station/channel definition: %s '
198 '(line: %i, file: %s' % (str(e), iline, file_path))
201def iload_pyrocko_events(file_path, segment, content):
202 from pyrocko import model as pmodel
204 for iev, ev in enumerate(pmodel.Event.load_catalog(file_path)):
205 nut = model.make_event_nut(
206 file_segment=0,
207 file_element=iev,
208 name=ev.name or '',
209 tmin=ev.time,
210 tmax=ev.time)
212 if 'event' in content:
213 nut.content = ev
215 yield nut