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 return False
42 return False
45g_event_keys = set('''
46name region catalog magnitude_type latitude longitude magnitude depth duration
47north_shift east_shift mnn mee mdd mne mnd med strike1 dip1 rake1 strike2 dip2
48rake2 duration time tags moment
49'''.split())
52def detect_pyrocko_events(first512):
53 try:
54 first512 = first512.decode('utf-8')
55 except UnicodeDecodeError:
56 return False
58 lines = first512.splitlines()[:-1]
59 ok = 0
60 for line in lines:
61 line = line.strip()
62 if not line or line.startswith('#'):
63 continue
65 t = line.split(' = ', 1)
66 if len(t) == 2:
67 if t[0].strip() in g_event_keys:
68 ok += 1
69 continue
70 else:
71 return False
73 if line.startswith('---'):
74 ok += 1
75 continue
77 return False
79 return ok > 2
82def detect(first512):
83 if detect_pyrocko_stations(first512):
84 return 'pyrocko_stations'
86 elif detect_pyrocko_events(first512):
87 return 'pyrocko_events'
89 return None
92def float_or_none(s):
93 if s.lower() == 'nan':
94 return None
95 else:
96 return float(s)
99def iload(format, file_path, segment, content):
100 if format == 'pyrocko_stations':
101 return iload_pyrocko_stations(file_path, segment, content)
103 if format == 'pyrocko_events':
104 return iload_pyrocko_events(file_path, segment, content)
107def iload_pyrocko_stations(file_path, segment, content):
109 inut = 0
110 tmin = None
111 tmax = None
112 with open(file_path, 'r') as f:
114 have_station = False
115 for (iline, line) in enumerate(f):
116 try:
117 toks = line.split(None, 5)
118 if len(toks) == 5 or len(toks) == 6:
119 net, sta, loc = toks[0].split('.')
120 lat, lon, elevation, depth = [float(x) for x in toks[1:5]]
121 if len(toks) == 5:
122 description = u''
123 else:
124 description = str(toks[5])
126 nut = model.make_station_nut(
127 file_segment=0,
128 file_element=inut,
129 codes=model.CodesNSL(net, sta, loc),
130 tmin=tmin,
131 tmax=tmax)
133 if 'station' in content:
134 nut.content = model.Station(
135 lat=lat,
136 lon=lon,
137 elevation=elevation,
138 depth=depth,
139 description=description,
140 **nut.station_kwargs)
142 yield nut
143 inut += 1
145 have_station = True
147 elif len(toks) == 4 and have_station:
148 cha = toks[0]
149 azi = float_or_none(toks[1])
150 dip = float_or_none(toks[2])
151 gain = float(toks[3])
153 if gain != 1.0:
154 logger.warning(
155 '%s.%s.%s.%s gain value from stations '
156 'file ignored - please check' % (
157 net, sta, loc, cha))
159 nut = model.make_channel_nut(
160 file_segment=0,
161 file_element=inut,
162 codes=model.CodesNSLCE(net, sta, loc, cha, ''),
163 tmin=tmin,
164 tmax=tmax)
166 if 'channel' in content:
167 nut.content = model.Channel(
168 lat=lat,
169 lon=lon,
170 elevation=elevation,
171 depth=depth,
172 azimuth=azi,
173 dip=dip,
174 **nut.channel_kwargs)
176 yield nut
177 inut += 1
179 else:
180 raise Exception('invalid syntax')
182 except Exception as e:
183 logger.warning(
184 'skipping invalid station/channel definition: %s '
185 '(line: %i, file: %s' % (str(e), iline, file_path))
188def iload_pyrocko_events(file_path, segment, content):
189 from pyrocko import model as pmodel
191 for iev, ev in enumerate(pmodel.Event.load_catalog(file_path)):
192 nut = model.make_event_nut(
193 file_segment=0,
194 file_element=iev,
195 codes=model.CodesX(ev.catalog or ''),
196 tmin=ev.time,
197 tmax=ev.time)
199 if 'event' in content:
200 nut.content = ev
202 yield nut