1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6import logging
8from pyrocko.io.io_common import get_stats, touch # noqa
9from ... import model
11logger = logging.getLogger('psq.io.textfiles')
14def provided_formats():
15 return ['pyrocko_stations', 'pyrocko_events']
18def detect_pyrocko_stations(first512):
19 try:
20 first512 = first512.decode('utf-8')
21 except UnicodeDecodeError:
22 return False
24 for line in first512.splitlines():
25 t = line.split(None, 5)
26 if len(t) in (5, 6):
27 if len(t[0].split('.')) != 3:
28 return False
30 try:
31 lat, lon, ele, dep = map(float, t[1:5])
32 if lat < -90. or 90 < lat:
33 return False
34 if lon < -180. or 180 < lon:
35 return False
37 return True
39 except Exception:
40 raise
41 return False
43 return False
46g_event_keys = set('''
47name region catalog magnitude_type latitude longitude magnitude depth duration
48north_shift east_shift mnn mee mdd mne mnd med strike1 dip1 rake1 strike2 dip2
49rake2 duration time tags moment
50'''.split())
53def detect_pyrocko_events(first512):
54 try:
55 first512 = first512.decode('utf-8')
56 except UnicodeDecodeError:
57 return False
59 lines = first512.splitlines()[:-1]
60 ok = 0
61 for line in lines:
62 line = line.strip()
63 if not line or line.startswith('#'):
64 continue
66 t = line.split(' = ', 1)
67 if len(t) == 2:
68 if t[0].strip() in g_event_keys:
69 ok += 1
70 continue
71 else:
72 return False
74 if line.startswith('---'):
75 ok += 1
76 continue
78 return False
80 return ok > 2
83def detect(first512):
84 if detect_pyrocko_stations(first512):
85 return 'pyrocko_stations'
87 elif detect_pyrocko_events(first512):
88 return 'pyrocko_events'
90 return None
93def float_or_none(s):
94 if s.lower() == 'nan':
95 return None
96 else:
97 return float(s)
100def iload(format, file_path, segment, content):
101 if format == 'pyrocko_stations':
102 return iload_pyrocko_stations(file_path, segment, content)
104 if format == 'pyrocko_events':
105 return iload_pyrocko_events(file_path, segment, content)
108def iload_pyrocko_stations(file_path, segment, content):
110 inut = 0
111 tmin = None
112 tmax = None
113 with open(file_path, 'r') as f:
115 have_station = False
116 for (iline, line) in enumerate(f):
117 try:
118 toks = line.split(None, 5)
119 if len(toks) == 5 or len(toks) == 6:
120 net, sta, loc = toks[0].split('.')
121 lat, lon, elevation, depth = [float(x) for x in toks[1:5]]
122 if len(toks) == 5:
123 description = u''
124 else:
125 description = str(toks[5])
127 nut = model.make_station_nut(
128 file_segment=0,
129 file_element=inut,
130 codes=model.CodesNSL(net, sta, loc),
131 tmin=tmin,
132 tmax=tmax)
134 if 'station' in content:
135 nut.content = model.Station(
136 lat=lat,
137 lon=lon,
138 elevation=elevation,
139 depth=depth,
140 description=description,
141 **nut.station_kwargs)
143 yield nut
144 inut += 1
146 have_station = True
148 elif len(toks) == 4 and have_station:
149 cha = toks[0]
150 azi = float_or_none(toks[1])
151 dip = float_or_none(toks[2])
152 gain = float(toks[3])
154 if gain != 1.0:
155 logger.warning(
156 '%s.%s.%s.%s gain value from stations '
157 'file ignored - please check' % (
158 net, sta, loc, cha))
160 nut = model.make_channel_nut(
161 file_segment=0,
162 file_element=inut,
163 codes=model.CodesNSLCE(net, sta, loc, cha, ''),
164 tmin=tmin,
165 tmax=tmax)
167 if 'channel' in content:
168 nut.content = model.Channel(
169 lat=lat,
170 lon=lon,
171 elevation=elevation,
172 depth=depth,
173 azimuth=azi,
174 dip=dip,
175 **nut.channel_kwargs)
177 yield nut
178 inut += 1
180 else:
181 raise Exception('invalid syntax')
183 except Exception as e:
184 logger.warning(
185 'skipping invalid station/channel definition: %s '
186 '(line: %i, file: %s' % (str(e), iline, file_path))
189def iload_pyrocko_events(file_path, segment, content):
190 from pyrocko import model as pmodel
192 for iev, ev in enumerate(pmodel.Event.load_catalog(file_path)):
193 nut = model.make_event_nut(
194 file_segment=0,
195 file_element=iev,
196 codes=model.CodesX(ev.catalog or ''),
197 tmin=ev.time,
198 tmax=ev.time)
200 if 'event' in content:
201 nut.content = ev
203 yield nut