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 return False 

41 

42 return False 

43 

44 

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

50 

51 

52def detect_pyrocko_events(first512): 

53 try: 

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

55 except UnicodeDecodeError: 

56 return False 

57 

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 

64 

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 

72 

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

74 ok += 1 

75 continue 

76 

77 return False 

78 

79 return ok > 2 

80 

81 

82def detect(first512): 

83 if detect_pyrocko_stations(first512): 

84 return 'pyrocko_stations' 

85 

86 elif detect_pyrocko_events(first512): 

87 return 'pyrocko_events' 

88 

89 return None 

90 

91 

92def float_or_none(s): 

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

94 return None 

95 else: 

96 return float(s) 

97 

98 

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

100 if format == 'pyrocko_stations': 

101 return iload_pyrocko_stations(file_path, segment, content) 

102 

103 if format == 'pyrocko_events': 

104 return iload_pyrocko_events(file_path, segment, content) 

105 

106 

107def iload_pyrocko_stations(file_path, segment, content): 

108 

109 inut = 0 

110 tmin = None 

111 tmax = None 

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

113 

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

125 

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) 

132 

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) 

141 

142 yield nut 

143 inut += 1 

144 

145 have_station = True 

146 

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

152 

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

158 

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) 

165 

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) 

175 

176 yield nut 

177 inut += 1 

178 

179 else: 

180 raise Exception('invalid syntax') 

181 

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

186 

187 

188def iload_pyrocko_events(file_path, segment, content): 

189 from pyrocko import model as pmodel 

190 

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) 

198 

199 if 'event' in content: 

200 nut.content = ev 

201 

202 yield nut