Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/client/isc.py: 85%
108 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 06:59 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-06 06:59 +0000
1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Client to get earthquake catalog information from
8`ISC <http://www.isc.ac.uk/>`_.
9'''
11import logging
13from pyrocko import util
14from pyrocko.util import urlopen
15from pyrocko.io import quakeml
16from .base_catalog import EarthquakeCatalog
18logger = logging.getLogger('pyrocko.client.isc')
20km = 1000.
23class ISCError(Exception):
24 pass
27class ISCBlocked(ISCError):
28 pass
31class ISC(EarthquakeCatalog):
32 '''
33 Interfacing the catalog of the Internation Seismological Centre (ISC).
34 '''
36 def __init__(self, catalog=None):
37 self.events = {}
39 def flush(self):
40 self.events = {}
42 def append_time_params(self, a, time_range):
43 date_start_s, tstart_s = util.time_to_str(
44 time_range[0], format='%Y-%m-%d %H:%M:%S').split()
45 date_end_s, tend_s = util.time_to_str(
46 time_range[1], format='%Y-%m-%d %H:%M:%S').split()
47 date_start_s = date_start_s.split('-')
48 date_end_s = date_end_s.split('-')
50 a('start_year=%s' % date_start_s[0])
51 a('start_month=%s' % date_start_s[1])
52 a('start_day=%s' % date_start_s[2])
53 a('start_time=%s' % tstart_s)
55 a('end_year=%s' % date_end_s[0])
56 a('end_month=%s' % date_end_s[1])
57 a('end_day=%s' % date_end_s[2])
58 a('end_time=%s' % tend_s)
60 def iter_event_names(
61 self,
62 time_range=None,
63 magmin=None,
64 magmax=None,
65 latmin=-90.,
66 latmax=90.,
67 lonmin=-180.,
68 lonmax=180.):
69 p = []
70 a = p.append
72 a('out_format=CATQuakeML')
73 a('request=REVIEWED')
74 a('searchshape=RECT')
76 self.append_time_params(a, time_range)
78 if magmin:
79 a('min_mag=%g' % magmin)
80 if magmax:
81 a('max_mag=%g' % magmax)
83 a('bot_lat=%g' % latmin)
84 a('top_lat=%g' % latmax)
85 a('left_lon=%g' % lonmin)
86 a('right_lon=%g' % lonmax)
87 url = 'http://www.isc.ac.uk/cgi-bin/web-db-v4?' + '&'.join(p)
89 logger.debug('Opening URL: %s' % url)
90 page = urlopen(url).read().decode()
91 logger.debug('Received page (%i bytes)' % len(page))
93 if 'The search could not be run due to problems' in page:
94 logger.warning('%s\nurl: %s' % (page, url))
95 return
96 elif 'No events were found.' in page:
97 logger.info('No events were found.')
98 events = []
99 else:
100 try:
101 data = quakeml.QuakeML.load_xml(string=page)
102 except Exception:
103 if page[:500].find(
104 'Please try again in a few minutes') != -1:
106 raise ISCBlocked(
107 'Apparently, we have queried ISC too eagerly:\n'
108 + '-' * 79 + '\n' + page + '\n' + '-' * 79)
109 else:
110 raise ISCError(
111 "Couldn't parse XML results from ISC:\n"
112 + '-' * 79 + '\n' + page + '\n' + '-' * 79)
114 events = data.get_pyrocko_events()
116 for ev in events:
117 self.events[ev.name] = ev
119 for ev in events:
120 if time_range[0] <= ev.time and ev.time <= time_range[1]:
121 yield ev.name
123 def get_event(self, name):
124 if name not in self.events:
125 t = self._name_to_date(name)
126 for name2 in self.iter_event_names(
127 time_range=(t-24*60*60, t+24*60*60)):
129 if name2 == name:
130 break
132 return self.events[name]
134 def get_phase_markers(self, time_range, station_codes, phases):
135 '''
136 Download phase picks from ISC catalog and return them as a list
137 of `pyrocko.gui.PhaseMarker` instances.
139 :param time_range: Tuple with (tmin tmax)
140 :param station_codes: List with ISC station codes
141 (see http://www.isc.ac.uk/cgi-bin/stations?lista).
142 If `station_codes` is 'global', query all ISC stations.
143 :param phases: List of seismic phases. (e.g. ['P', 'PcP']
144 '''
146 p = []
147 a = p.append
149 a('out_format=QuakeML')
150 a('request=STNARRIVALS')
151 if station_codes == 'global':
152 a('stnsearch=GLOBAL')
153 else:
154 a('stnsearch=STN')
155 a('sta_list=%s' % ','.join(station_codes))
157 a('phaselist=%s' % ','.join(phases))
159 self.append_time_params(a, time_range)
161 url = 'http://www.isc.ac.uk/cgi-bin/web-db-v4?' + '&'.join(p)
163 logger.debug('Opening URL: %s' % url)
164 page = urlopen(url)
165 page = page.read().decode()
167 if 'No stations were found.' in page:
168 logger.info('No stations were found.')
169 return []
171 logger.debug('Received page (%i bytes)' % len(page))
173 data = quakeml.QuakeML.load_xml(string=page)
175 markers = data.get_pyrocko_phase_markers()
176 markers = self.replace_isc_codes(markers)
178 return markers
180 def replace_isc_codes(self, markers):
181 for m in markers:
182 new_nslc_ids = []
183 for (n, s, l_, c) in m.get_nslc_ids():
184 l_ = l_.replace('--', '')
185 c = c.replace('???', '*')
186 new_nslc_ids.append((n, s, l_, c))
187 m.nslc_ids = new_nslc_ids
189 return markers
191 def _name_to_date(self, name):
192 ds = name[-23:]
193 t = util.str_to_time(ds, format='%Y-%m-%d_%H-%M-%S.3FRAC')
194 return t