1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5from __future__ import absolute_import, division 

6 

7import logging 

8 

9from pyrocko import util 

10from pyrocko.util import urlopen 

11from pyrocko.io import quakeml 

12from .base_catalog import EarthquakeCatalog 

13 

14logger = logging.getLogger('pyrocko.client.isc') 

15 

16km = 1000. 

17 

18 

19class ISC(EarthquakeCatalog): 

20 ''' 

21 Interfacing the catalog of the Internation Seismological Centre (ISC). 

22 ''' 

23 

24 def __init__(self, catalog=None): 

25 self.events = {} 

26 

27 def flush(self): 

28 self.events = {} 

29 

30 def append_time_params(self, a, time_range): 

31 date_start_s, tstart_s = util.time_to_str( 

32 time_range[0], format='%Y-%m-%d %H:%M:%S').split() 

33 date_end_s, tend_s = util.time_to_str( 

34 time_range[1], format='%Y-%m-%d %H:%M:%S').split() 

35 date_start_s = date_start_s.split('-') 

36 date_end_s = date_end_s.split('-') 

37 

38 a('start_year=%s' % date_start_s[0]) 

39 a('start_month=%s' % date_start_s[1]) 

40 a('start_day=%s' % date_start_s[2]) 

41 a('start_time=%s' % tstart_s) 

42 

43 a('end_year=%s' % date_end_s[0]) 

44 a('end_month=%s' % date_end_s[1]) 

45 a('end_day=%s' % date_end_s[2]) 

46 a('end_time=%s' % tend_s) 

47 

48 def iter_event_names( 

49 self, 

50 time_range=None, 

51 magmin=None, 

52 magmax=None, 

53 latmin=-90., 

54 latmax=90., 

55 lonmin=-180., 

56 lonmax=180.): 

57 p = [] 

58 a = p.append 

59 

60 a('out_format=CATQuakeML') 

61 a('request=REVIEWED') 

62 a('searchshape=RECT') 

63 

64 self.append_time_params(a, time_range) 

65 

66 if magmin: 

67 a('min_mag=%g' % magmin) 

68 if magmax: 

69 a('max_mag=%g' % magmax) 

70 

71 a('bot_lat=%g' % latmin) 

72 a('top_lat=%g' % latmax) 

73 a('left_lon=%g' % lonmin) 

74 a('right_lon=%g' % lonmax) 

75 url = 'http://www.isc.ac.uk/cgi-bin/web-db-v4?' + '&'.join(p) 

76 

77 logger.debug('Opening URL: %s' % url) 

78 page = urlopen(url).read().decode() 

79 logger.debug('Received page (%i bytes)' % len(page)) 

80 

81 if 'The search could not be run due to problems' in page: 

82 logger.warning('%s\nurl: %s' % (page, url)) 

83 return 

84 elif 'No events were found.' in page: 

85 logger.info('No events were found.') 

86 events = [] 

87 else: 

88 data = quakeml.QuakeML.load_xml(string=page) 

89 events = data.get_pyrocko_events() 

90 

91 for ev in events: 

92 self.events[ev.name] = ev 

93 

94 for ev in events: 

95 if time_range[0] <= ev.time and ev.time <= time_range[1]: 

96 yield ev.name 

97 

98 def get_event(self, name): 

99 if name not in self.events: 

100 t = self._name_to_date(name) 

101 for name2 in self.iter_event_names( 

102 time_range=(t-24*60*60, t+24*60*60)): 

103 

104 if name2 == name: 

105 break 

106 

107 return self.events[name] 

108 

109 def get_phase_markers(self, time_range, station_codes, phases): 

110 ''' 

111 Download phase picks from ISC catalog and return them as a list 

112 of `pyrocko.gui.PhaseMarker` instances. 

113 

114 :param time_range: Tuple with (tmin tmax) 

115 :param station_codes: List with ISC station codes 

116 (see http://www.isc.ac.uk/cgi-bin/stations?lista). 

117 If `station_codes` is 'global', query all ISC stations. 

118 :param phases: List of seismic phases. (e.g. ['P', 'PcP'] 

119 ''' 

120 

121 p = [] 

122 a = p.append 

123 

124 a('out_format=QuakeML') 

125 a('request=STNARRIVALS') 

126 if station_codes == 'global': 

127 a('stnsearch=GLOBAL') 

128 else: 

129 a('stnsearch=STN') 

130 a('sta_list=%s' % ','.join(station_codes)) 

131 

132 a('phaselist=%s' % ','.join(phases)) 

133 

134 self.append_time_params(a, time_range) 

135 

136 url = 'http://www.isc.ac.uk/cgi-bin/web-db-v4?' + '&'.join(p) 

137 

138 logger.debug('Opening URL: %s' % url) 

139 page = urlopen(url) 

140 page = page.read().decode() 

141 

142 if 'No stations were found.' in page: 

143 logger.info('No stations were found.') 

144 return [] 

145 

146 logger.debug('Received page (%i bytes)' % len(page)) 

147 

148 data = quakeml.QuakeML.load_xml(string=page) 

149 

150 markers = data.get_pyrocko_phase_markers() 

151 markers = self.replace_isc_codes(markers) 

152 

153 return markers 

154 

155 def replace_isc_codes(self, markers): 

156 for m in markers: 

157 new_nslc_ids = [] 

158 for (n, s, l_, c) in m.get_nslc_ids(): 

159 l_ = l_.replace('--', '') 

160 c = c.replace('???', '*') 

161 new_nslc_ids.append((n, s, l_, c)) 

162 m.nslc_ids = new_nslc_ids 

163 

164 return markers 

165 

166 def _name_to_date(self, name): 

167 ds = name[-23:] 

168 t = util.str_to_time(ds, format='%Y-%m-%d_%H-%M-%S.3FRAC') 

169 return t