1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6import logging 

7 

8from pyrocko.io.io_common import get_stats, touch # noqa 

9from ... import model 

10 

11logger = logging.getLogger('psq.io.textfiles') 

12 

13 

14def provided_formats(): 

15 return ['pyrocko_stations', 'pyrocko_events'] 

16 

17 

18def detect_pyrocko_stations(first512): 

19 try: 

20 first512 = first512.decode('utf-8') 

21 except UnicodeDecodeError: 

22 return False 

23 

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 

29 

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 

36 

37 return True 

38 

39 except Exception: 

40 raise 

41 return False 

42 

43 return False 

44 

45 

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()) 

51 

52 

53def detect_pyrocko_events(first512): 

54 try: 

55 first512 = first512.decode('utf-8') 

56 except UnicodeDecodeError: 

57 return False 

58 

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 

65 

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 

73 

74 if line.startswith('---'): 

75 ok += 1 

76 continue 

77 

78 return False 

79 

80 return ok > 2 

81 

82 

83def detect(first512): 

84 if detect_pyrocko_stations(first512): 

85 return 'pyrocko_stations' 

86 

87 elif detect_pyrocko_events(first512): 

88 return 'pyrocko_events' 

89 

90 return None 

91 

92 

93def float_or_none(s): 

94 if s.lower() == 'nan': 

95 return None 

96 else: 

97 return float(s) 

98 

99 

100def iload(format, file_path, segment, content): 

101 if format == 'pyrocko_stations': 

102 return iload_pyrocko_stations(file_path, segment, content) 

103 

104 if format == 'pyrocko_events': 

105 return iload_pyrocko_events(file_path, segment, content) 

106 

107 

108def iload_pyrocko_stations(file_path, segment, content): 

109 

110 inut = 0 

111 tmin = None 

112 tmax = None 

113 with open(file_path, 'r') as f: 

114 

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]) 

126 

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) 

133 

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) 

142 

143 yield nut 

144 inut += 1 

145 

146 have_station = True 

147 

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]) 

153 

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)) 

159 

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) 

166 

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) 

176 

177 yield nut 

178 inut += 1 

179 

180 else: 

181 raise Exception('invalid syntax') 

182 

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)) 

187 

188 

189def iload_pyrocko_events(file_path, segment, content): 

190 from pyrocko import model as pmodel 

191 

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) 

199 

200 if 'event' in content: 

201 nut.content = ev 

202 

203 yield nut